OSDN Git Service

initial commit
authorTakuya ASADA <syuu@dokukino.com>
Mon, 16 Aug 2010 06:52:22 +0000 (15:52 +0900)
committerTakuya ASADA <syuu@dokukino.com>
Mon, 16 Aug 2010 06:52:22 +0000 (15:52 +0900)
1002 files changed:
src/kerberosV/CVS/Entries [new file with mode: 0644]
src/kerberosV/CVS/Repository [new file with mode: 0644]
src/kerberosV/CVS/Root [new file with mode: 0644]
src/kerberosV/Makefile [new file with mode: 0644]
src/kerberosV/Makefile.inc [new file with mode: 0644]
src/kerberosV/README [new file with mode: 0644]
src/kerberosV/doc/CVS/Entries [new file with mode: 0644]
src/kerberosV/doc/CVS/Repository [new file with mode: 0644]
src/kerberosV/doc/CVS/Root [new file with mode: 0644]
src/kerberosV/doc/Makefile [new file with mode: 0644]
src/kerberosV/doc/obj [new symlink]
src/kerberosV/include/CVS/Entries [new file with mode: 0644]
src/kerberosV/include/CVS/Repository [new file with mode: 0644]
src/kerberosV/include/CVS/Root [new file with mode: 0644]
src/kerberosV/include/config.h [new file with mode: 0644]
src/kerberosV/include/crypto-headers.h [new file with mode: 0644]
src/kerberosV/include/krb5-types.h [new file with mode: 0644]
src/kerberosV/include/print_version.h [new file with mode: 0644]
src/kerberosV/include/roken.h [new file with mode: 0644]
src/kerberosV/include/version.h [new file with mode: 0644]
src/kerberosV/libexec/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/Makefile [new file with mode: 0644]
src/kerberosV/libexec/Makefile.inc [new file with mode: 0644]
src/kerberosV/libexec/hprop/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/hprop/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/hprop/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/hprop/Makefile [new file with mode: 0644]
src/kerberosV/libexec/hprop/obj [new symlink]
src/kerberosV/libexec/hpropd/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/hpropd/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/hpropd/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/hpropd/Makefile [new file with mode: 0644]
src/kerberosV/libexec/hpropd/obj [new symlink]
src/kerberosV/libexec/ipropd-master/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/ipropd-master/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/ipropd-master/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/ipropd-master/Makefile [new file with mode: 0644]
src/kerberosV/libexec/ipropd-master/obj [new symlink]
src/kerberosV/libexec/ipropd-slave/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/ipropd-slave/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/ipropd-slave/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/ipropd-slave/Makefile [new file with mode: 0644]
src/kerberosV/libexec/ipropd-slave/obj [new symlink]
src/kerberosV/libexec/kadmind/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/kadmind/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/kadmind/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/kadmind/Makefile [new file with mode: 0644]
src/kerberosV/libexec/kadmind/obj [new symlink]
src/kerberosV/libexec/kdc/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/kdc/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/kdc/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/kdc/Makefile [new file with mode: 0644]
src/kerberosV/libexec/kdc/obj [new symlink]
src/kerberosV/libexec/kfd/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/kfd/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/kfd/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/kfd/Makefile [new file with mode: 0644]
src/kerberosV/libexec/kpasswdd/CVS/Entries [new file with mode: 0644]
src/kerberosV/libexec/kpasswdd/CVS/Repository [new file with mode: 0644]
src/kerberosV/libexec/kpasswdd/CVS/Root [new file with mode: 0644]
src/kerberosV/libexec/kpasswdd/Makefile [new file with mode: 0644]
src/kerberosV/libexec/kpasswdd/obj [new symlink]
src/kerberosV/openbsd-vers/CVS/Entries [new file with mode: 0644]
src/kerberosV/openbsd-vers/CVS/Repository [new file with mode: 0644]
src/kerberosV/openbsd-vers/CVS/Root [new file with mode: 0644]
src/kerberosV/openbsd-vers/print_version.c [new file with mode: 0644]
src/kerberosV/src/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/CVS/Root [new file with mode: 0644]
src/kerberosV/src/ChangeLog [new file with mode: 0644]
src/kerberosV/src/ChangeLog.1998 [new file with mode: 0644]
src/kerberosV/src/ChangeLog.1999 [new file with mode: 0644]
src/kerberosV/src/ChangeLog.2000 [new file with mode: 0644]
src/kerberosV/src/ChangeLog.2001 [new file with mode: 0644]
src/kerberosV/src/ChangeLog.2002 [new file with mode: 0644]
src/kerberosV/src/ChangeLog.2003 [new file with mode: 0644]
src/kerberosV/src/ChangeLog.2004 [new file with mode: 0644]
src/kerberosV/src/Makefile.am [new file with mode: 0644]
src/kerberosV/src/Makefile.am.common [new file with mode: 0644]
src/kerberosV/src/Makefile.in [new file with mode: 0644]
src/kerberosV/src/NEWS [new file with mode: 0644]
src/kerberosV/src/README [new file with mode: 0644]
src/kerberosV/src/TODO [new file with mode: 0644]
src/kerberosV/src/TODO-1.0 [new file with mode: 0644]
src/kerberosV/src/TODO-shadow [new file with mode: 0644]
src/kerberosV/src/acconfig.h [new file with mode: 0644]
src/kerberosV/src/acinclude.m4 [new file with mode: 0644]
src/kerberosV/src/aclocal.m4 [new file with mode: 0644]
src/kerberosV/src/admin/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/admin/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/admin/CVS/Root [new file with mode: 0644]
src/kerberosV/src/admin/ChangeLog [new file with mode: 0644]
src/kerberosV/src/admin/add.c [new file with mode: 0644]
src/kerberosV/src/admin/change.c [new file with mode: 0644]
src/kerberosV/src/admin/copy.c [new file with mode: 0644]
src/kerberosV/src/admin/get.c [new file with mode: 0644]
src/kerberosV/src/admin/ktutil-commands.in [new file with mode: 0644]
src/kerberosV/src/admin/ktutil.8 [new file with mode: 0644]
src/kerberosV/src/admin/ktutil.c [new file with mode: 0644]
src/kerberosV/src/admin/ktutil_locl.h [new file with mode: 0644]
src/kerberosV/src/admin/list.c [new file with mode: 0644]
src/kerberosV/src/admin/purge.c [new file with mode: 0644]
src/kerberosV/src/admin/remove.c [new file with mode: 0644]
src/kerberosV/src/admin/rename.c [new file with mode: 0644]
src/kerberosV/src/appl/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/appl/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/appl/CVS/Root [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/CVS/Root [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/ChangeLog [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/afslog.1 [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/afslog.c [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/pagsh.1 [new file with mode: 0644]
src/kerberosV/src/appl/afsutil/pagsh.c [new file with mode: 0644]
src/kerberosV/src/appl/login/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/appl/login/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/appl/login/CVS/Root [new file with mode: 0644]
src/kerberosV/src/appl/login/limits_conf.c [new file with mode: 0644]
src/kerberosV/src/appl/popper/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/appl/popper/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/appl/popper/CVS/Root [new file with mode: 0644]
src/kerberosV/src/appl/popper/auth_gssapi.c [new file with mode: 0644]
src/kerberosV/src/appl/popper/auth_krb4.c [new file with mode: 0644]
src/kerberosV/src/appl/popper/pop_auth.h [new file with mode: 0644]
src/kerberosV/src/appl/su/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/appl/su/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/appl/su/CVS/Root [new file with mode: 0644]
src/kerberosV/src/appl/su/su.1 [new file with mode: 0644]
src/kerberosV/src/appl/test/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/appl/test/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/appl/test/CVS/Root [new file with mode: 0644]
src/kerberosV/src/appl/test/common.c [new file with mode: 0644]
src/kerberosV/src/appl/test/gss_common.c [new file with mode: 0644]
src/kerberosV/src/appl/test/gss_common.h [new file with mode: 0644]
src/kerberosV/src/appl/test/gssapi_client.c [new file with mode: 0644]
src/kerberosV/src/appl/test/gssapi_server.c [new file with mode: 0644]
src/kerberosV/src/appl/test/http_client.c [new file with mode: 0644]
src/kerberosV/src/appl/test/nt_gss_client.c [new file with mode: 0644]
src/kerberosV/src/appl/test/nt_gss_common.c [new file with mode: 0644]
src/kerberosV/src/appl/test/nt_gss_common.h [new file with mode: 0644]
src/kerberosV/src/appl/test/nt_gss_server.c [new file with mode: 0644]
src/kerberosV/src/appl/test/tcp_client.c [new file with mode: 0644]
src/kerberosV/src/appl/test/tcp_server.c [new file with mode: 0644]
src/kerberosV/src/appl/test/test_locl.h [new file with mode: 0644]
src/kerberosV/src/appl/test/uu_client.c [new file with mode: 0644]
src/kerberosV/src/appl/test/uu_server.c [new file with mode: 0644]
src/kerberosV/src/cf/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/cf/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/cf/CVS/Root [new file with mode: 0644]
src/kerberosV/src/cf/check-symbols.sh [new file with mode: 0644]
src/kerberosV/src/cf/largefile.m4 [new file with mode: 0644]
src/kerberosV/src/cf/pthreads.m4 [new file with mode: 0644]
src/kerberosV/src/cf/vararray.m4 [new file with mode: 0644]
src/kerberosV/src/cf/win32.m4 [new file with mode: 0644]
src/kerberosV/src/compile [new file with mode: 0755]
src/kerberosV/src/config.guess [new file with mode: 0644]
src/kerberosV/src/config.sub [new file with mode: 0644]
src/kerberosV/src/doc/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/doc/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/doc/CVS/Root [new file with mode: 0644]
src/kerberosV/src/doc/ack.texi [new file with mode: 0644]
src/kerberosV/src/doc/apps.texi [new file with mode: 0644]
src/kerberosV/src/doc/heimdal.info [new file with mode: 0644]
src/kerberosV/src/doc/heimdal.info-1 [new file with mode: 0644]
src/kerberosV/src/doc/heimdal.info-2 [new file with mode: 0644]
src/kerberosV/src/doc/heimdal.texi [new file with mode: 0644]
src/kerberosV/src/doc/init-creds [new file with mode: 0644]
src/kerberosV/src/doc/install.texi [new file with mode: 0644]
src/kerberosV/src/doc/intro.texi [new file with mode: 0644]
src/kerberosV/src/doc/kerberos4.texi [new file with mode: 0644]
src/kerberosV/src/doc/latin1.tex [new file with mode: 0644]
src/kerberosV/src/doc/layman.asc [new file with mode: 0644]
src/kerberosV/src/doc/mdate-sh [new file with mode: 0644]
src/kerberosV/src/doc/migration.texi [new file with mode: 0644]
src/kerberosV/src/doc/misc.texi [new file with mode: 0644]
src/kerberosV/src/doc/programming.texi [new file with mode: 0644]
src/kerberosV/src/doc/setup.texi [new file with mode: 0644]
src/kerberosV/src/doc/whatis.texi [new file with mode: 0644]
src/kerberosV/src/doc/win2k.texi [new file with mode: 0644]
src/kerberosV/src/etc/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/etc/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/etc/CVS/Root [new file with mode: 0644]
src/kerberosV/src/etc/services.append [new file with mode: 0644]
src/kerberosV/src/include/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/include/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/include/CVS/Root [new file with mode: 0644]
src/kerberosV/src/include/bits.c [new file with mode: 0644]
src/kerberosV/src/include/config.h.in [new file with mode: 0644]
src/kerberosV/src/include/make_crypto.c [new file with mode: 0644]
src/kerberosV/src/include/stamp-h.in [new file with mode: 0644]
src/kerberosV/src/kadmin/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/kadmin/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/kadmin/CVS/Root [new file with mode: 0644]
src/kerberosV/src/kadmin/ChangeLog [new file with mode: 0644]
src/kerberosV/src/kadmin/add-random-users.c [new file with mode: 0644]
src/kerberosV/src/kadmin/ank.c [new file with mode: 0644]
src/kerberosV/src/kadmin/cpw.c [new file with mode: 0644]
src/kerberosV/src/kadmin/del.c [new file with mode: 0644]
src/kerberosV/src/kadmin/del_enctype.c [new file with mode: 0644]
src/kerberosV/src/kadmin/dump-format.txt [new file with mode: 0644]
src/kerberosV/src/kadmin/dump.c [new file with mode: 0644]
src/kerberosV/src/kadmin/ext.c [new file with mode: 0644]
src/kerberosV/src/kadmin/get.c [new file with mode: 0644]
src/kerberosV/src/kadmin/init.c [new file with mode: 0644]
src/kerberosV/src/kadmin/kadm_conn.c [new file with mode: 0644]
src/kerberosV/src/kadmin/kadmin-commands.in [new file with mode: 0644]
src/kerberosV/src/kadmin/kadmin.8 [new file with mode: 0644]
src/kerberosV/src/kadmin/kadmin.c [new file with mode: 0644]
src/kerberosV/src/kadmin/kadmin_locl.h [new file with mode: 0644]
src/kerberosV/src/kadmin/kadmind.8 [new file with mode: 0644]
src/kerberosV/src/kadmin/kadmind.c [new file with mode: 0644]
src/kerberosV/src/kadmin/load.c [new file with mode: 0644]
src/kerberosV/src/kadmin/mod.c [new file with mode: 0644]
src/kerberosV/src/kadmin/pw_quality.c [new file with mode: 0644]
src/kerberosV/src/kadmin/random_password.c [new file with mode: 0644]
src/kerberosV/src/kadmin/rename.c [new file with mode: 0644]
src/kerberosV/src/kadmin/server.c [new file with mode: 0644]
src/kerberosV/src/kadmin/stash.c [new file with mode: 0644]
src/kerberosV/src/kadmin/util.c [new file with mode: 0644]
src/kerberosV/src/kadmin/version4.c [new file with mode: 0644]
src/kerberosV/src/kcm/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/kcm/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/kcm/CVS/Root [new file with mode: 0644]
src/kerberosV/src/kcm/Makefile.am [new file with mode: 0644]
src/kerberosV/src/kcm/Makefile.in [new file with mode: 0644]
src/kerberosV/src/kcm/acl.c [new file with mode: 0644]
src/kerberosV/src/kcm/acquire.c [new file with mode: 0644]
src/kerberosV/src/kcm/cache.c [new file with mode: 0644]
src/kerberosV/src/kcm/client.c [new file with mode: 0644]
src/kerberosV/src/kcm/config.c [new file with mode: 0644]
src/kerberosV/src/kcm/connect.c [new file with mode: 0644]
src/kerberosV/src/kcm/cursor.c [new file with mode: 0644]
src/kerberosV/src/kcm/events.c [new file with mode: 0644]
src/kerberosV/src/kcm/glue.c [new file with mode: 0644]
src/kerberosV/src/kcm/headers.h [new file with mode: 0644]
src/kerberosV/src/kcm/kcm.8 [new file with mode: 0644]
src/kerberosV/src/kcm/kcm_locl.h [new file with mode: 0644]
src/kerberosV/src/kcm/kcm_protos.h [new file with mode: 0644]
src/kerberosV/src/kcm/log.c [new file with mode: 0644]
src/kerberosV/src/kcm/main.c [new file with mode: 0644]
src/kerberosV/src/kcm/protocol.c [new file with mode: 0644]
src/kerberosV/src/kcm/renew.c [new file with mode: 0644]
src/kerberosV/src/kdc/524.c [new file with mode: 0644]
src/kerberosV/src/kdc/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/kdc/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/kdc/CVS/Root [new file with mode: 0644]
src/kerberosV/src/kdc/config.c [new file with mode: 0644]
src/kerberosV/src/kdc/connect.c [new file with mode: 0644]
src/kerberosV/src/kdc/headers.h [new file with mode: 0644]
src/kerberosV/src/kdc/hprop.8 [new file with mode: 0644]
src/kerberosV/src/kdc/hprop.c [new file with mode: 0644]
src/kerberosV/src/kdc/hprop.h [new file with mode: 0644]
src/kerberosV/src/kdc/hpropd.8 [new file with mode: 0644]
src/kerberosV/src/kdc/hpropd.c [new file with mode: 0644]
src/kerberosV/src/kdc/kadb.h [new file with mode: 0644]
src/kerberosV/src/kdc/kaserver.c [new file with mode: 0644]
src/kerberosV/src/kdc/kdc.8 [new file with mode: 0644]
src/kerberosV/src/kdc/kdc_locl.h [new file with mode: 0644]
src/kerberosV/src/kdc/kerberos4.c [new file with mode: 0644]
src/kerberosV/src/kdc/kerberos5.c [new file with mode: 0644]
src/kerberosV/src/kdc/kstash.8 [new file with mode: 0644]
src/kerberosV/src/kdc/kstash.c [new file with mode: 0644]
src/kerberosV/src/kdc/log.c [new file with mode: 0644]
src/kerberosV/src/kdc/main.c [new file with mode: 0644]
src/kerberosV/src/kdc/misc.c [new file with mode: 0644]
src/kerberosV/src/kdc/mit_dump.c [new file with mode: 0644]
src/kerberosV/src/kdc/pkinit.c [new file with mode: 0644]
src/kerberosV/src/kdc/rx.h [new file with mode: 0644]
src/kerberosV/src/kdc/string2key.8 [new file with mode: 0644]
src/kerberosV/src/kdc/string2key.c [new file with mode: 0644]
src/kerberosV/src/kdc/v4_dump.c [new file with mode: 0644]
src/kerberosV/src/kpasswd/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/kpasswd/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/kpasswd/CVS/Root [new file with mode: 0644]
src/kerberosV/src/kpasswd/kpasswd-generator.c [new file with mode: 0644]
src/kerberosV/src/kpasswd/kpasswd.1 [new file with mode: 0644]
src/kerberosV/src/kpasswd/kpasswd.c [new file with mode: 0644]
src/kerberosV/src/kpasswd/kpasswd_locl.h [new file with mode: 0644]
src/kerberosV/src/kpasswd/kpasswdd.8 [new file with mode: 0644]
src/kerberosV/src/kpasswd/kpasswdd.c [new file with mode: 0644]
src/kerberosV/src/kuser/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/kuser/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/kuser/CVS/Root [new file with mode: 0644]
src/kerberosV/src/kuser/copy_cred_cache.1 [new file with mode: 0644]
src/kerberosV/src/kuser/copy_cred_cache.c [new file with mode: 0644]
src/kerberosV/src/kuser/generate-requests.c [new file with mode: 0644]
src/kerberosV/src/kuser/kauth_options.c [new file with mode: 0644]
src/kerberosV/src/kuser/kdecode_ticket.c [new file with mode: 0644]
src/kerberosV/src/kuser/kdestroy.1 [new file with mode: 0644]
src/kerberosV/src/kuser/kdestroy.c [new file with mode: 0644]
src/kerberosV/src/kuser/kgetcred.1 [new file with mode: 0644]
src/kerberosV/src/kuser/kgetcred.c [new file with mode: 0644]
src/kerberosV/src/kuser/kinit.1 [new file with mode: 0644]
src/kerberosV/src/kuser/kinit.c [new file with mode: 0644]
src/kerberosV/src/kuser/kinit_options.c [new file with mode: 0644]
src/kerberosV/src/kuser/klist.1 [new file with mode: 0644]
src/kerberosV/src/kuser/klist.c [new file with mode: 0644]
src/kerberosV/src/kuser/kuser_locl.h [new file with mode: 0644]
src/kerberosV/src/kuser/kverify.c [new file with mode: 0644]
src/kerberosV/src/lib/45/45_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/45/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/45/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/45/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/45/get_ad_tkt.c [new file with mode: 0644]
src/kerberosV/src/lib/45/mk_req.c [new file with mode: 0644]
src/kerberosV/src/lib/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/asn1/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/asn1/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/asn1/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/asn1/asn1-common.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/asn1_err.et [new file with mode: 0644]
src/kerberosV/src/lib/asn1/asn1_print.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/check-common.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/check-common.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/check-der.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/check-gen.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_cmp.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_copy.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_free.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_get.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_length.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/der_put.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_copy.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_decode.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_encode.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_free.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_length.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/gen_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/hash.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/hash.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/k5.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/asn1/lex.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/lex.l [new file with mode: 0644]
src/kerberosV/src/lib/asn1/libasn1.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/main.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/parse.y [new file with mode: 0644]
src/kerberosV/src/lib/asn1/pkinit.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/asn1/rfc2459.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/asn1/setchgpw2.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/asn1/symbol.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/symbol.h [new file with mode: 0644]
src/kerberosV/src/lib/asn1/timegm.c [new file with mode: 0644]
src/kerberosV/src/lib/asn1/x509.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/com_err/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/com_err/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/com_err/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/com_err/com_err.c [new file with mode: 0644]
src/kerberosV/src/lib/com_err/com_err.h [new file with mode: 0644]
src/kerberosV/src/lib/com_err/com_right.h [new file with mode: 0644]
src/kerberosV/src/lib/com_err/error.c [new file with mode: 0644]
src/kerberosV/src/lib/des/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/des/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/des/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/des/DESperate.txt [new file with mode: 0644]
src/kerberosV/src/lib/des/aes.c [new file with mode: 0644]
src/kerberosV/src/lib/des/aes.h [new file with mode: 0644]
src/kerberosV/src/lib/des/des-tables.h [new file with mode: 0644]
src/kerberosV/src/lib/des/gen-des.pl [new file with mode: 0644]
src/kerberosV/src/lib/des/rc2.c [new file with mode: 0644]
src/kerberosV/src/lib/des/rc2.h [new file with mode: 0644]
src/kerberosV/src/lib/des/rc2test.c [new file with mode: 0644]
src/kerberosV/src/lib/des/rc4.c [new file with mode: 0644]
src/kerberosV/src/lib/des/rctest.c [new file with mode: 0644]
src/kerberosV/src/lib/des/rijndael-alg-fst.c [new file with mode: 0644]
src/kerberosV/src/lib/des/rijndael-alg-fst.h [new file with mode: 0644]
src/kerberosV/src/lib/des/ui.c [new file with mode: 0644]
src/kerberosV/src/lib/editline/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/editline/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/editline/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/editline/edit_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/8003.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/ChangeLog [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/accept_sec_context.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/acquire_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/add_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/add_oid_set_member.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/address_to_krb5addr.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/arcfour.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/arcfour.h [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/canonicalize_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/ccache_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/cfx.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/cfx.h [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/compare_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/compat.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/context_time.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/copy_ccache.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/create_emtpy_oid_set.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/decapsulate.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/delete_sec_context.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/display_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/display_status.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/duplicate_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/encapsulate.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/export_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/export_sec_context.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/external.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/get_mic.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/gss_acquire_cred.3 [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/gssapi.3 [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/gssapi.h [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/gssapi_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/import_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/import_sec_context.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/indicate_mechs.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/init.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/init_sec_context.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/inquire_context.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/inquire_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/inquire_cred_by_mech.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/inquire_mechs_for_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/inquire_names_for_mech.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/process_context_token.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/release_buffer.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/release_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/release_name.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/release_oid_set.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/sequence.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/spkm.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/spnego.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/test_acquire_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/test_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/test_oid_set_member.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/test_sequence.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/ticket_flags.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/unwrap.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/v1.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/verify_mic.c [new file with mode: 0644]
src/kerberosV/src/lib/gssapi/wrap.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/hdb/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/hdb/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/hdb/common.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/convert_db.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/db.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/db3.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb-ldap.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb-private.h [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb-protos.h [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb.asn1 [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb.h [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb.schema [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb_err.et [new file with mode: 0644]
src/kerberosV/src/lib/hdb/hdb_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/hdb/keys.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/keytab.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/libasn1.h [new file with mode: 0644]
src/kerberosV/src/lib/hdb/mkey.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/ndbm.c [new file with mode: 0644]
src/kerberosV/src/lib/hdb/print.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/ChangeLog [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/acl.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/ad.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/admin.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/bump_pw_expire.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/check-cracklib.pl [new file with mode: 0755]
src/kerberosV/src/lib/kadm5/chpass_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/chpass_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/client_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/common_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/context_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/create_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/create_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/default_keys.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/delete_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/delete_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/destroy_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/destroy_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/dump_log.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/ent_setup.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/error.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/flush.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/flush_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/flush_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/free.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/get_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/get_princs_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/get_princs_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/get_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/init_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/init_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/iprop.8 [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/iprop.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/ipropd_master.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/ipropd_slave.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/kadm5-private.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/kadm5-protos.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/kadm5-pwcheck.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/kadm5_err.et [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/kadm5_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/kadm5_pwcheck.3 [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/keys.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/log.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/marshall.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/modify_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/modify_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/password_quality.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/private.h [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/privs_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/privs_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/randkey_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/randkey_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/rename_c.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/rename_s.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/replay_log.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/sample_passwd_check.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/send_recv.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/server_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/set_keys.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/set_modifier.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/test_pw_quality.c [new file with mode: 0644]
src/kerberosV/src/lib/kadm5/truncate_log.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/kafs/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/kafs/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/kafs/ChangeLog [new file with mode: 0644]
src/kerberosV/src/lib/kafs/README.dlfcn [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afskrb.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afskrb5.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afsl.exp [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afslib.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afslib.exp [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afssys.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/afssysdefs.h [new file with mode: 0644]
src/kerberosV/src/lib/kafs/common.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/dlfcn.c [new file with mode: 0644]
src/kerberosV/src/lib/kafs/dlfcn.h [new file with mode: 0644]
src/kerberosV/src/lib/kafs/kafs.3 [new file with mode: 0644]
src/kerberosV/src/lib/kafs/kafs.h [new file with mode: 0644]
src/kerberosV/src/lib/kafs/kafs_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/kafs/roken_rename.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/krb5/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/krb5/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/krb5/acache.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/acl.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/add_et_list.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/addr_families.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/address.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/aes-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/aname_to_localname.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/appdefault.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/asn1_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/auth_context.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/build_ap_req.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/build_auth.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/cache.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/changepw.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/codec.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/config_file.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/config_file_netinfo.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/constants.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/context.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/convert_creds.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/copy_host_realm.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/crc.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/creds.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/crypto.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/data.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/derived-key-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/dump_config.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/eai_to_heim_errno.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/error_string.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/expand_hostname.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/fcache.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/free.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/free_host_realm.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/generate_seq_number.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/generate_subkey.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_addrs.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_default_principal.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_default_realm.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_for_creds.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_host_realm.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_in_tkt.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_in_tkt_pw.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_in_tkt_with_keytab.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_in_tkt_with_skey.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/get_port.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/heim_err.et [new file with mode: 0644]
src/kerberosV/src/lib/krb5/heim_threads.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/init_creds.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/init_creds_pw.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/k524_err.et [new file with mode: 0644]
src/kerberosV/src/lib/krb5/kcm.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/kcm.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/kerberos.8 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keyblock.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keytab.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keytab_any.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keytab_file.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keytab_keyfile.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keytab_krb4.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/keytab_memory.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5-private.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5-protos.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5-v4compat.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5.conf.5 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb524_convert_creds_kdc.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_425_conv_principal.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_acl_match_file.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_address.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_aname_to_localname.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_appdefault.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_auth_context.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_c_make_checksum.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_ccache.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_ccapi.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_check_transited.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_compare_creds.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_config.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_context.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_create_checksum.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_creds.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_crypto_init.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_data.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_eai_to_heim_errno.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_encrypt.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_err.et [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_expand_hostname.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_find_padata.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_generate_random_block.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_get_all_client_addrs.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_get_credentials.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_get_forwarded_creds.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_get_in_cred.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_get_init_creds.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_get_krbhst.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_getportbyname.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_init_context.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_is_thread_safe.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_keyblock.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_keytab.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_krbhst_init.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_kuserok.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_mk_safe.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_openlog.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_parse_name.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_principal.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_rcache.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_rd_error.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_rd_safe.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_set_default_realm.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_set_password.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_storage.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_string_to_key.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_ticket.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_timeofday.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_unparse_name.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_verify_init_creds.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_verify_user.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krb5_warn.3 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krbhst-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/krbhst.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/kuserok.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/log.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mcache.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/misc.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mit_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mk_error.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mk_priv.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mk_rep.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mk_req.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mk_req_ext.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/mk_safe.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/n-fold-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/n-fold.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/name-45-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/net_read.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/net_write.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/padata.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/parse-name-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/pkinit.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/principal.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/prog_setup.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/prompter_posix.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/rd_cred.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/rd_error.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/rd_priv.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/rd_rep.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/rd_req.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/rd_safe.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/read_message.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/recvauth.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/replay.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/send_to_kdc.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/sendauth.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/set_default_realm.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/sock_principal.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/store-int.h [new file with mode: 0644]
src/kerberosV/src/lib/krb5/store-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/store.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/store_emem.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/store_fd.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/store_mem.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/string-to-key-test.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_acl.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_addr.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_alname.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_cc.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_config.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_crypto.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_get_addrs.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_keytab.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_kuserok.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_mem.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/test_time.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/ticket.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/time.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/transited.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/v4_glue.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/verify_init.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/verify_krb5_conf.8 [new file with mode: 0644]
src/kerberosV/src/lib/krb5/verify_krb5_conf.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/verify_user.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/version.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/warn.c [new file with mode: 0644]
src/kerberosV/src/lib/krb5/write_message.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/roken/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/roken/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/roken/ChangeLog [new file with mode: 0644]
src/kerberosV/src/lib/roken/acconfig.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/base64-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/base64.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/base64.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/bswap.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/chown.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/closefrom.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/compile [new file with mode: 0644]
src/kerberosV/src/lib/roken/concat.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/config.h.in [new file with mode: 0644]
src/kerberosV/src/lib/roken/copyhostent.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/daemon.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/ecalloc.3 [new file with mode: 0644]
src/kerberosV/src/lib/roken/ecalloc.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/emalloc.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/environment.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/eread.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/erealloc.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/err.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/err.hin [new file with mode: 0644]
src/kerberosV/src/lib/roken/errx.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/esetenv.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/estrdup.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/ewrite.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/fchown.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/flock.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/fnmatch.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/fnmatch.hin [new file with mode: 0644]
src/kerberosV/src/lib/roken/freeaddrinfo.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/freehostent.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/gai_strerror.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/get_default_username.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/get_window_size.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getaddrinfo-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getaddrinfo.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getaddrinfo_hostspec.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getarg.3 [new file with mode: 0644]
src/kerberosV/src/lib/roken/getarg.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getarg.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/getcap.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getcwd.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getdtablesize.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getegid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/geteuid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getgid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/gethostname.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getifaddrs.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getipnodebyaddr.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getipnodebyname.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getnameinfo.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getnameinfo_verified.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getopt.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getprogname.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/gettimeofday.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getuid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/getusershell.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/glob.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/glob.hin [new file with mode: 0644]
src/kerberosV/src/lib/roken/h_errno.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/hex-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/hex.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/hex.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/hostent_find_fqdn.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/hstrerror.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/ifaddrs.hin [new file with mode: 0644]
src/kerberosV/src/lib/roken/inet_aton.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/inet_ntop.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/inet_pton.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/initgroups.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/innetgr.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/install-sh [new file with mode: 0644]
src/kerberosV/src/lib/roken/iruserok.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/issuid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/k_getpwnam.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/k_getpwuid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/localtime_r.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/lstat.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/make-print-version.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/memmove.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/mini_inetd.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/missing [new file with mode: 0644]
src/kerberosV/src/lib/roken/mkinstalldirs [new file with mode: 0644]
src/kerberosV/src/lib/roken/mkstemp.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/ndbm_wrap.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/ndbm_wrap.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/net_read.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/net_write.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_bytes-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_bytes.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_bytes.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_reply-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_time-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_time.3 [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_time.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_time.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_units.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/parse_units.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/print_version.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/putenv.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/rcmd.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/readv.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/realloc.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/recvmsg.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/resolve-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/resolve.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/resolve.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/resource.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/roken-common.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/roken.awk [new file with mode: 0644]
src/kerberosV/src/lib/roken/roken.h.in [new file with mode: 0644]
src/kerberosV/src/lib/roken/roken_gethostby.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/rtbl.3 [new file with mode: 0644]
src/kerberosV/src/lib/roken/rtbl.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/rtbl.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/sendmsg.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/setegid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/setenv.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/seteuid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/setprogname.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/signal.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/simple_exec.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/socket.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strcasecmp.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strcollect.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strlcat.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strlcpy.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strlwr.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strncasecmp.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strndup.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strnlen.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strpftime-test.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strptime.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strsep.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strsep_copy.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strtok_r.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/strupr.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/swab.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/test-mem.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/test-mem.h [new file with mode: 0644]
src/kerberosV/src/lib/roken/test-readenv.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/timeval.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/tm2time.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/unsetenv.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/unvis.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/verify.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/verr.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/verrx.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/vis.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/vis.hin [new file with mode: 0644]
src/kerberosV/src/lib/roken/vsyslog.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/vwarn.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/vwarnx.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/warn.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/warnerr.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/warnx.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/write_pid.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/writev.c [new file with mode: 0644]
src/kerberosV/src/lib/roken/xdbm.h [new file with mode: 0644]
src/kerberosV/src/lib/sl/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/sl/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/sl/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/sl/ChangeLog [new file with mode: 0644]
src/kerberosV/src/lib/sl/lex.l [new file with mode: 0644]
src/kerberosV/src/lib/sl/make_cmds.c [new file with mode: 0644]
src/kerberosV/src/lib/sl/make_cmds.h [new file with mode: 0644]
src/kerberosV/src/lib/sl/parse.y [new file with mode: 0644]
src/kerberosV/src/lib/sl/roken_rename.h [new file with mode: 0644]
src/kerberosV/src/lib/sl/sl.c [new file with mode: 0644]
src/kerberosV/src/lib/sl/sl.h [new file with mode: 0644]
src/kerberosV/src/lib/sl/sl_locl.h [new file with mode: 0644]
src/kerberosV/src/lib/sl/slc-gram.y [new file with mode: 0644]
src/kerberosV/src/lib/sl/slc-lex.l [new file with mode: 0644]
src/kerberosV/src/lib/sl/slc.h [new file with mode: 0644]
src/kerberosV/src/lib/sl/ss.c [new file with mode: 0644]
src/kerberosV/src/lib/sl/ss.h [new file with mode: 0644]
src/kerberosV/src/lib/vers/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/lib/vers/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/lib/vers/CVS/Root [new file with mode: 0644]
src/kerberosV/src/lib/vers/ChangeLog [new file with mode: 0644]
src/kerberosV/src/lib/vers/make-print-version.c [new file with mode: 0644]
src/kerberosV/src/lib/vers/print_version.c [new file with mode: 0644]
src/kerberosV/src/lib/vers/vers.h [new file with mode: 0644]
src/kerberosV/src/tools/CVS/Entries [new file with mode: 0644]
src/kerberosV/src/tools/CVS/Repository [new file with mode: 0644]
src/kerberosV/src/tools/CVS/Root [new file with mode: 0644]
src/kerberosV/src/tools/build.sh [new file with mode: 0644]
src/kerberosV/src/tools/kdc-log-analyze.pl [new file with mode: 0755]
src/kerberosV/src/tools/krb5-config.1 [new file with mode: 0644]
src/kerberosV/src/tools/krb5-config.in [new file with mode: 0644]
src/kerberosV/src/ylwrap [new file with mode: 0755]
src/kerberosV/usr.bin/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/Makefile.inc [new file with mode: 0644]
src/kerberosV/usr.bin/afslog/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/afslog/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/afslog/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/afslog/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/afslog/obj [new symlink]
src/kerberosV/usr.bin/kauth/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/kauth/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/kauth/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/kauth/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/kauth/obj [new symlink]
src/kerberosV/usr.bin/kdestroy/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/kdestroy/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/kdestroy/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/kdestroy/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/kdestroy/obj [new symlink]
src/kerberosV/usr.bin/kf/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/kf/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/kf/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/kf/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/kinit/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/kinit/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/kinit/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/kinit/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/kinit/obj [new symlink]
src/kerberosV/usr.bin/klist/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/klist/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/klist/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/klist/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/klist/obj [new symlink]
src/kerberosV/usr.bin/pagsh/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/pagsh/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/pagsh/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/pagsh/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/pagsh/obj [new symlink]
src/kerberosV/usr.bin/string2key/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/string2key/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/string2key/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/string2key/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/string2key/obj [new symlink]
src/kerberosV/usr.bin/verify_krb5_conf/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.bin/verify_krb5_conf/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.bin/verify_krb5_conf/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.bin/verify_krb5_conf/Makefile [new file with mode: 0644]
src/kerberosV/usr.bin/verify_krb5_conf/obj [new symlink]
src/kerberosV/usr.sbin/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.sbin/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.sbin/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.sbin/Makefile [new file with mode: 0644]
src/kerberosV/usr.sbin/Makefile.inc [new file with mode: 0644]
src/kerberosV/usr.sbin/kadmin/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.sbin/kadmin/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.sbin/kadmin/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.sbin/kadmin/Makefile [new file with mode: 0644]
src/kerberosV/usr.sbin/kadmin/obj [new symlink]
src/kerberosV/usr.sbin/kstash/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.sbin/kstash/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.sbin/kstash/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.sbin/kstash/Makefile [new file with mode: 0644]
src/kerberosV/usr.sbin/kstash/obj [new symlink]
src/kerberosV/usr.sbin/ktutil/CVS/Entries [new file with mode: 0644]
src/kerberosV/usr.sbin/ktutil/CVS/Repository [new file with mode: 0644]
src/kerberosV/usr.sbin/ktutil/CVS/Root [new file with mode: 0644]
src/kerberosV/usr.sbin/ktutil/Makefile [new file with mode: 0644]
src/kerberosV/usr.sbin/ktutil/obj [new symlink]

diff --git a/src/kerberosV/CVS/Entries b/src/kerberosV/CVS/Entries
new file mode 100644 (file)
index 0000000..307e1a7
--- /dev/null
@@ -0,0 +1,10 @@
+/Makefile/1.13/Sun Apr 30 10:22:00 2006//
+/Makefile.inc/1.10/Fri Apr 14 08:28:54 2006//
+/README/1.15/Sun May 11 21:58:24 2003//
+D/doc////
+D/include////
+D/libexec////
+D/openbsd-vers////
+D/src////
+D/usr.bin////
+D/usr.sbin////
diff --git a/src/kerberosV/CVS/Repository b/src/kerberosV/CVS/Repository
new file mode 100644 (file)
index 0000000..82e0e0f
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV
diff --git a/src/kerberosV/CVS/Root b/src/kerberosV/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/Makefile b/src/kerberosV/Makefile
new file mode 100644 (file)
index 0000000..7830d0b
--- /dev/null
@@ -0,0 +1,5 @@
+# $OpenBSD: Makefile,v 1.13 2006/04/30 10:22:00 biorn Exp $
+
+SUBDIR = usr.bin libexec usr.sbin doc
+
+.include <bsd.subdir.mk>
diff --git a/src/kerberosV/Makefile.inc b/src/kerberosV/Makefile.inc
new file mode 100644 (file)
index 0000000..b3f8ee2
--- /dev/null
@@ -0,0 +1,24 @@
+# $OpenBSD: Makefile.inc,v 1.10 2006/04/14 08:28:54 biorn Exp $
+
+KRB5DIR        = ${.CURDIR}/${KRBDEPTH}
+KRB5SRC        = ${.CURDIR}/${KRBDEPTH}/src
+
+CFLAGS += -DHAVE_CONFIG_H -DBINDIR=\"/usr/bin\" -DSBINDIR=\"/usr/sbin\"\
+          -DLIBEXECDIR=\"/usr/libexec\" -DSYSCONFDIR=\"/etc/kerberosV\" \
+          -I${DESTDIR}/usr/include/kerberosV \
+          -I${KRB5DIR}/include -I${KRB5SRC}/lib/roken\
+          -I${KRB5SRC}/include -I${KRB5SRC}/lib/sl  \
+          -I${KRB5SRC}/lib/krb5
+CFLAGS+=       -Wall
+.include <bsd.own.mk>                          # for 'NOPIC' definition
+.if !defined(NOPIC)
+CFLAGS += -DHAVE_DLOPEN
+.endif
+
+PRINTVER=      print_version.c
+ROKENSRC=      ${KRB5SRC}/lib/roken
+
+.PATH: ${KRB5SRC}/man
+.PATH: ${KRB5DIR}/openbsd-vers
+
+COMPILE_ET     = /usr/bin/compile_et
diff --git a/src/kerberosV/README b/src/kerberosV/README
new file mode 100644 (file)
index 0000000..5c4a3a4
--- /dev/null
@@ -0,0 +1,15 @@
+Documentation
+=============
+
+The 'heimdal' infopage has information about how to set up a Kerberos
+realm etc. There are also a number of manpages with reference information.
+
+
+BSD Auth
+========
+
+There's also a BSD Authentication login script in src/libexec/login_krb5,
+that is used to enable Kerberos authentication in login, sshd, xdm etc.
+
+Refer to login.conf(5), login(1), login_krb5(8) and login_krb5-or-pwd(8)
+for more information on how to enable them.
diff --git a/src/kerberosV/doc/CVS/Entries b/src/kerberosV/doc/CVS/Entries
new file mode 100644 (file)
index 0000000..c01f853
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.6/Sat Aug 30 01:16:30 2008//
+D
diff --git a/src/kerberosV/doc/CVS/Repository b/src/kerberosV/doc/CVS/Repository
new file mode 100644 (file)
index 0000000..687f489
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/doc
diff --git a/src/kerberosV/doc/CVS/Root b/src/kerberosV/doc/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/doc/Makefile b/src/kerberosV/doc/Makefile
new file mode 100644 (file)
index 0000000..8ac6236
--- /dev/null
@@ -0,0 +1,38 @@
+# $Id: Makefile,v 1.6 2008/08/30 01:16:30 brad Exp $
+
+KRBDEPTH=..
+.include "../Makefile.inc"
+
+.PATH: ${KRB5SRC}/doc
+
+MAKEINFO = /usr/bin/makeinfo
+INSTALL-INFO = /usr/bin/install-info
+
+infodir = ${DESTDIR}/usr/share/info
+
+INSTALL = /usr/bin/install
+
+info = heimdal.info
+
+SRCS =         heimdal.texi intro.texi install.texi setup.texi kerberos4.texi
+
+
+all: $(info)
+
+install: $(info)
+       $(INSTALL-INFO) ${.OBJDIR}/$(info) $(infodir)/dir
+       ${INSTALL} ${INSTALL_COPY} -m 444 -o ${BINOWN} -g ${BINGRP} -p ${.OBJDIR}/$(info) $(infodir)
+
+$(info): $(SRCS)
+       ${MAKEINFO} --no-split -I${KRB5SRC}/doc -o ${.OBJDIR}/$@ ${KRB5SRC}/doc/heimdal.texi
+
+clean:
+       (cd ${.OBJDIR} ; rm -f *.aux *.cp *.cps *.dvi *.fn *.ky *.log *.pg *.toc *.tp *.vr *.info *.info-[0-9])
+
+cleandir: clean
+
+
+.PHONY: install all clean cleandir
+
+.include <bsd.obj.mk>
+.include <bsd.subdir.mk>
diff --git a/src/kerberosV/doc/obj b/src/kerberosV/doc/obj
new file mode 120000 (symlink)
index 0000000..7e6773c
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/doc
\ No newline at end of file
diff --git a/src/kerberosV/include/CVS/Entries b/src/kerberosV/include/CVS/Entries
new file mode 100644 (file)
index 0000000..d432b32
--- /dev/null
@@ -0,0 +1,7 @@
+/crypto-headers.h/1.2/Fri Apr 14 08:28:55 2006//
+/krb5-types.h/1.2/Sun May 11 03:49:07 2003//
+/print_version.h/1.5/Wed Apr 26 20:40:37 2006//
+/roken.h/1.10/Fri Oct 29 16:25:42 2004//
+/version.h/1.5/Fri Apr 14 08:28:55 2006//
+/config.h/1.13/Mon May 31 05:18:28 2010//
+D
diff --git a/src/kerberosV/include/CVS/Repository b/src/kerberosV/include/CVS/Repository
new file mode 100644 (file)
index 0000000..74cf96e
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/include
diff --git a/src/kerberosV/include/CVS/Root b/src/kerberosV/include/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/include/config.h b/src/kerberosV/include/config.h
new file mode 100644 (file)
index 0000000..c20f588
--- /dev/null
@@ -0,0 +1,1491 @@
+/* include/config.h.  Generated by configure.  */
+/* include/config.h.in.  Generated from configure.in by autoheader.  */
+
+#ifdef BUILD_KRB5_LIB
+#ifndef KRB5_LIB_FUNCTION
+#ifdef _WIN32_
+#define KRB5_LIB_FUNCTION _export _stdcall
+#else
+#define KRB5_LIB_FUNCTION
+#endif
+#endif
+#endif
+
+
+#ifdef BUILD_ROKEN_LIB
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32_
+#define ROKEN_LIB_FUNCTION _export _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+#endif
+
+
+#ifndef RCSID
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
+#endif
+
+/* Maximum values on all known systems */
+#define MaxHostNameLen (64+4)
+#define MaxPathLen (1024+4)
+
+
+
+/* Define if you want authentication support in telnet. */
+#define AUTHENTICATION 1
+
+/* path to bin */
+#define BINDIR "/usr/bin"
+
+/* Define if realloc(NULL) doesn't work. */
+/* #undef BROKEN_REALLOC */
+
+/* Define if you want support for DCE/DFS PAG's. */
+/* #undef DCE */
+
+/* Define if you want to use DES encryption in telnet. */
+#define DES_ENCRYPTION 1
+
+/* Define this to enable diagnostics in telnet. */
+#define DIAGNOSTICS 1
+
+/* Define if you want have a thread safe libraries */
+/* #undef ENABLE_PTHREAD_SUPPORT */
+
+/* Define if you want encryption support in telnet. */
+#define ENCRYPTION 1
+
+/* define if sys/param.h defines the endiness */
+#define ENDIANESS_IN_SYS_PARAM_H 1
+
+/* Define this if you want support for broken ENV_{VAR,VAL} telnets. */
+/* #undef ENV_HACK */
+
+/* define if prototype of gethostbyaddr is compatible with struct hostent
+   *gethostbyaddr(const void *, size_t, int) */
+#define GETHOSTBYADDR_PROTO_COMPATIBLE 1
+
+/* define if prototype of gethostbyname is compatible with struct hostent
+   *gethostbyname(const char *) */
+#define GETHOSTBYNAME_PROTO_COMPATIBLE 1
+
+/* define if prototype of getservbyname is compatible with struct servent
+   *getservbyname(const char *, const char *) */
+#define GETSERVBYNAME_PROTO_COMPATIBLE 1
+
+/* define if prototype of getsockname is compatible with int getsockname(int,
+   struct sockaddr*, socklen_t*) */
+#define GETSOCKNAME_PROTO_COMPATIBLE 1
+
+/* Define if you have the `altzone' variable. */
+/* #undef HAVE_ALTZONE */
+
+/* Define to 1 if you have the <arpa/ftp.h> header file. */
+#define HAVE_ARPA_FTP_H 1
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#define HAVE_ARPA_NAMESER_H 1
+
+/* Define to 1 if you have the <arpa/telnet.h> header file. */
+#define HAVE_ARPA_TELNET_H 1
+
+/* Define to 1 if you have the `asnprintf' function. */
+/* #undef HAVE_ASNPRINTF */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the `atexit' function. */
+#define HAVE_ATEXIT 1
+
+/* Define to 1 if you have the <bind/bitypes.h> header file. */
+/* #undef HAVE_BIND_BITYPES_H */
+
+/* Define to 1 if you have the <bsdsetjmp.h> header file. */
+/* #undef HAVE_BSDSETJMP_H */
+
+/* Define to 1 if you have the `bswap16' function. */
+/* #undef HAVE_BSWAP16 */
+
+/* Define to 1 if you have the `bswap32' function. */
+/* #undef HAVE_BSWAP32 */
+
+/* Define to 1 if you have the <capability.h> header file. */
+/* #undef HAVE_CAPABILITY_H */
+
+/* Define to 1 if you have the `cap_set_proc' function. */
+/* #undef HAVE_CAP_SET_PROC */
+
+/* Define to 1 if you have the `cgetent' function. */
+#define HAVE_CGETENT 1
+
+/* Define if you have the function `chown'. */
+#define HAVE_CHOWN 1
+
+/* Define if you have the function `closefrom'. */
+#define HAVE_CLOSEFROM 1
+
+/* Define to 1 if you have the <config.h> header file. */
+/* #undef HAVE_CONFIG_H */
+
+/* Define if you have the function `copyhostent'. */
+/* #undef HAVE_COPYHOSTENT */
+
+/* Define to 1 if you have the `crypt' function. */
+#define HAVE_CRYPT 1
+
+/* Define to 1 if you have the <crypt.h> header file. */
+/* #undef HAVE_CRYPT_H */
+
+/* Define to 1 if you have the <curses.h> header file. */
+#define HAVE_CURSES_H 1
+
+/* Define if you have the function `daemon'. */
+#define HAVE_DAEMON 1
+
+/* define if you have a berkeley db1/2 library */
+#define HAVE_DB1 1
+
+/* define if you have a berkeley db3/4 library */
+/* #undef HAVE_DB3 */
+
+/* Define to 1 if you have the <db3/db.h> header file. */
+/* #undef HAVE_DB3_DB_H */
+
+/* Define to 1 if you have the <db4/db.h> header file. */
+/* #undef HAVE_DB4_DB_H */
+
+/* Define to 1 if you have the `dbm_firstkey' function. */
+#define HAVE_DBM_FIRSTKEY 1
+
+/* Define to 1 if you have the <dbm.h> header file. */
+#define HAVE_DBM_H 1
+
+/* Define to 1 if you have the `dbopen' function. */
+#define HAVE_DBOPEN 1
+
+/* Define to 1 if you have the <db_185.h> header file. */
+/* #undef HAVE_DB_185_H */
+
+/* Define to 1 if you have the `db_create' function. */
+/* #undef HAVE_DB_CREATE */
+
+/* Define to 1 if you have the <db.h> header file. */
+#define HAVE_DB_H 1
+
+/* define if you have ndbm compat in db */
+/* #undef HAVE_DB_NDBM */
+
+/* Define to 1 if you have the declaration of `altzone', and to 0 if you
+   don't. */
+/* #undef HAVE_DECL_ALTZONE */
+
+/* Define to 1 if you have the declaration of `environ', and to 0 if you
+   don't. */
+#define HAVE_DECL_ENVIRON 0
+
+/* Define to 1 if you have the declaration of `h_errlist', and to 0 if you
+   don't. */
+#define HAVE_DECL_H_ERRLIST 0
+
+/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
+   don't. */
+#define HAVE_DECL_H_ERRNO 1
+
+/* Define to 1 if you have the declaration of `h_nerr', and to 0 if you don't.
+   */
+#define HAVE_DECL_H_NERR 0
+
+/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't.
+   */
+#define HAVE_DECL_OPTARG 1
+
+/* Define to 1 if you have the declaration of `opterr', and to 0 if you don't.
+   */
+#define HAVE_DECL_OPTERR 1
+
+/* Define to 1 if you have the declaration of `optind', and to 0 if you don't.
+   */
+#define HAVE_DECL_OPTIND 1
+
+/* Define to 1 if you have the declaration of `optopt', and to 0 if you don't.
+   */
+#define HAVE_DECL_OPTOPT 1
+
+/* Define to 1 if you have the declaration of `timezone', and to 0 if you
+   don't. */
+#define HAVE_DECL_TIMEZONE 1
+
+/* Define to 1 if you have the declaration of `_res', and to 0 if you don't.
+   */
+#define HAVE_DECL__RES 0
+
+/* Define to 1 if you have the declaration of `__progname', and to 0 if you
+   don't. */
+#define HAVE_DECL___PROGNAME 0
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#define HAVE_DIRENT_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the `dlopen' function. */
+/* #undef HAVE_DLOPEN 1 */
+
+/* Define to 1 if you have the `dn_expand' function. */
+#define HAVE_DN_EXPAND 1
+
+/* Define to 1 if you have the `door_create' function. */
+/* #undef HAVE_DOOR_CREATE */
+
+/* Define if you have the function `ecalloc'. */
+/* #undef HAVE_ECALLOC */
+
+/* Define to 1 if you have the `el_init' function. */
+#define HAVE_EL_INIT 1
+
+/* Define if you have the function `emalloc'. */
+/* #undef HAVE_EMALLOC */
+
+/* Define if you have the function `erealloc'. */
+/* #undef HAVE_EREALLOC */
+
+/* Define if you have the function `err'. */
+#define HAVE_ERR 1
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define if you have the function `errx'. */
+#define HAVE_ERRX 1
+
+/* Define to 1 if you have the <err.h> header file. */
+#define HAVE_ERR_H 1
+
+/* Define if you have the function `estrdup'. */
+/* #undef HAVE_ESTRDUP */
+
+/* Define if you have the function `fchown'. */
+#define HAVE_FCHOWN 1
+
+/* Define to 1 if you have the `fcntl' function. */
+#define HAVE_FCNTL 1
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define if you have the function `flock'. */
+#define HAVE_FLOCK 1
+
+/* Define if you have the function `fnmatch'. */
+#define HAVE_FNMATCH 1
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#define HAVE_FNMATCH_H 1
+
+/* Define if el_init takes four arguments. */
+#define HAVE_FOUR_VALUED_EL_INIT 1
+
+/* define if krb_put_int takes four arguments. */
+/* #undef HAVE_FOUR_VALUED_KRB_PUT_INT */
+
+/* Define to 1 if you have the `freeaddrinfo' function. */
+#define HAVE_FREEADDRINFO 1
+
+/* Define if you have the function `freehostent'. */
+/* #undef HAVE_FREEHOSTENT */
+
+/* Define to 1 if you have the `gai_strerror' function. */
+#define HAVE_GAI_STRERROR 1
+
+/* Define to 1 if you have the <gdbm/ndbm.h> header file. */
+/* #undef HAVE_GDBM_NDBM_H */
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the `getconfattr' function. */
+/* #undef HAVE_GETCONFATTR */
+
+/* Define if you have the function `getcwd'. */
+#define HAVE_GETCWD 1
+
+/* Define if you have the function `getdtablesize'. */
+#define HAVE_GETDTABLESIZE 1
+
+/* Define if you have the function `getegid'. */
+#define HAVE_GETEGID 1
+
+/* Define if you have the function `geteuid'. */
+#define HAVE_GETEUID 1
+
+/* Define if you have the function `getgid'. */
+#define HAVE_GETGID 1
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#define HAVE_GETHOSTBYNAME 1
+
+/* Define to 1 if you have the `gethostbyname2' function. */
+#define HAVE_GETHOSTBYNAME2 1
+
+/* Define if you have the function `gethostname'. */
+#define HAVE_GETHOSTNAME 1
+
+/* Define if you have the function `getifaddrs'. */
+#define HAVE_GETIFADDRS 1
+
+/* Define if you have the function `getipnodebyaddr'. */
+/* #undef HAVE_GETIPNODEBYADDR */
+
+/* Define if you have the function `getipnodebyname'. */
+/* #undef HAVE_GETIPNODEBYNAME */
+
+/* Define to 1 if you have the `getlogin' function. */
+#define HAVE_GETLOGIN 1
+
+/* Define if you have a working getmsg. */
+/* #undef HAVE_GETMSG */
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#define HAVE_GETNAMEINFO 1
+
+/* Define if you have the function `getopt'. */
+#define HAVE_GETOPT 1
+
+/* Define to 1 if you have the `getpagesize' function. */
+#define HAVE_GETPAGESIZE 1
+
+/* Define to 1 if you have the `getpeereid' function. */
+#define HAVE_GETPEEREID 1
+
+/* Define to 1 if you have the `getpeerucred' function. */
+/* #undef HAVE_GETPEERUCRED */
+
+/* Define to 1 if you have the `getprogname' function. */
+/* #undef HAVE_GETPROGNAME */
+
+/* Define to 1 if you have the `getpwnam_r' function. */
+/* #undef HAVE_GETPWNAM_R */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define to 1 if you have the `getsockopt' function. */
+#define HAVE_GETSOCKOPT 1
+
+/* Define to 1 if you have the `getspnam' function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define if you have the function `gettimeofday'. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the `getudbnam' function. */
+/* #undef HAVE_GETUDBNAM */
+
+/* Define if you have the function `getuid'. */
+#define HAVE_GETUID 1
+
+/* Define if you have the function `getusershell'. */
+#define HAVE_GETUSERSHELL 1
+
+/* define if you have a glob() that groks GLOB_BRACE, GLOB_NOCHECK,
+   GLOB_QUOTE, GLOB_TILDE, and GLOB_LIMIT */
+#define HAVE_GLOB 1
+
+/* Define to 1 if you have the `grantpt' function. */
+/* #undef HAVE_GRANTPT */
+
+/* Define to 1 if you have the <grp.h> header file. */
+#define HAVE_GRP_H 1
+
+/* Define to 1 if you have the `hstrerror' function. */
+#define HAVE_HSTRERROR 1
+
+/* Define if you have the `h_errlist' variable. */
+#define HAVE_H_ERRLIST 1
+
+/* Define if you have the `h_errno' variable. */
+#define HAVE_H_ERRNO 1
+
+/* Define if you have the `h_nerr' variable. */
+#define HAVE_H_NERR 1
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#define HAVE_IFADDRS_H 1
+
+/* Define if you have the in6addr_loopback variable */
+#define HAVE_IN6ADDR_LOOPBACK 1
+
+/* define */
+#define HAVE_INET_ATON 1
+
+/* define */
+#define HAVE_INET_NTOP 1
+
+/* define */
+#define HAVE_INET_PTON 1
+
+/* Define if you have the function `initgroups'. */
+#define HAVE_INITGROUPS 1
+
+/* Define to 1 if you have the `initstate' function. */
+#define HAVE_INITSTATE 1
+
+/* Define if you have the function `innetgr'. */
+#define HAVE_INNETGR 1
+
+/* Define to 1 if the system has the type `int16_t'. */
+#define HAVE_INT16_T 1
+
+/* Define to 1 if the system has the type `int32_t'. */
+#define HAVE_INT32_T 1
+
+/* Define to 1 if the system has the type `int64_t'. */
+#define HAVE_INT64_T 1
+
+/* Define to 1 if the system has the type `int8_t'. */
+#define HAVE_INT8_T 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <io.h> header file. */
+/* #undef HAVE_IO_H */
+
+/* Define if you have IPv6. */
+#define HAVE_IPV6 1
+
+/* Define if you have the function `iruserok'. */
+#define HAVE_IRUSEROK 1
+
+/* Define to 1 if you have the `issetugid' function. */
+#define HAVE_ISSETUGID 1
+
+/* Define if you want to use the Kerberos Credentials Manager. */
+/* #undef HAVE_KCM */
+
+/* Define to 1 if you have the `krb_disable_debug' function. */
+/* #undef HAVE_KRB_DISABLE_DEBUG */
+
+/* Define to 1 if you have the `krb_enable_debug' function. */
+/* #undef HAVE_KRB_ENABLE_DEBUG */
+
+/* Define to 1 if you have the `krb_get_kdc_time_diff' function. */
+/* #undef HAVE_KRB_GET_KDC_TIME_DIFF */
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+/* #undef HAVE_KRB_GET_OUR_IP_FOR_REALM */
+
+/* Define to 1 if you have the `krb_kdctimeofday' function. */
+/* #undef HAVE_KRB_KDCTIMEOFDAY */
+
+/* Define to 1 if you have the <libutil.h> header file. */
+/* #undef HAVE_LIBUTIL_H */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the `loadquery' function. */
+/* #undef HAVE_LOADQUERY */
+
+/* Define if you have the function `localtime_r'. */
+#define HAVE_LOCALTIME_R 1
+
+/* Define to 1 if you have the `logout' function. */
+#define HAVE_LOGOUT 1
+
+/* Define to 1 if you have the `logwtmp' function. */
+#define HAVE_LOGWTMP 1
+
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
+/* Define if you have the function `lstat'. */
+#define HAVE_LSTAT 1
+
+/* Define to 1 if you have the <maillock.h> header file. */
+/* #undef HAVE_MAILLOCK_H */
+
+/* Define if you have the function `memmove'. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define if you have the function `mkstemp'. */
+#define HAVE_MKSTEMP 1
+
+/* Define to 1 if you have the `mktime' function. */
+#define HAVE_MKTIME 1
+
+/* Define to 1 if you have a working `mmap' system call. */
+#define HAVE_MMAP 1
+
+/* define if you have a ndbm library */
+#define HAVE_NDBM 1
+
+/* Define to 1 if you have the <ndbm.h> header file. */
+#define HAVE_NDBM_H 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netgroup.h> header file. */
+#define HAVE_NETGROUP_H 1
+
+/* Define to 1 if you have the <netinet6/in6.h> header file. */
+/* #undef HAVE_NETINET6_IN6_H */
+
+/* Define to 1 if you have the <netinet6/in6_var.h> header file. */
+/* #undef HAVE_NETINET6_IN6_VAR_H */
+
+/* Define to 1 if you have the <netinet/in6.h> header file. */
+/* #undef HAVE_NETINET_IN6_H */
+
+/* Define to 1 if you have the <netinet/in6_machtypes.h> header file. */
+/* #undef HAVE_NETINET_IN6_MACHTYPES_H */
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#define HAVE_NETINET_IN_SYSTM_H 1
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#define HAVE_NETINET_IP_H 1
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define if you want to use Netinfo instead of krb5.conf. */
+/* #undef HAVE_NETINFO */
+
+/* Define to 1 if you have the <netinfo/ni.h> header file. */
+/* #undef HAVE_NETINFO_NI_H */
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#define HAVE_NET_IF_H 1
+
+/* Define if NDBM really is DB (creates files *.db) */
+#define HAVE_NEW_DB 1
+
+/* define if you have hash functions like md4_finito() */
+/* #undef HAVE_OLD_HASH_NAMES */
+
+/* Define to 1 if you have the `on_exit' function. */
+/* #undef HAVE_ON_EXIT */
+
+/* Define to 1 if you have the `openpty' function. */
+#define HAVE_OPENPTY 1
+
+/* define to use openssl's libcrypto */
+#define HAVE_OPENSSL 1
+
+/* Define to enable basic OSF C2 support. */
+/* #undef HAVE_OSFC2 */
+
+/* Define to 1 if you have the <paths.h> header file. */
+#define HAVE_PATHS_H 1
+
+/* Define to 1 if you have the `pidfile' function. */
+#define HAVE_PIDFILE 1
+
+/* Define to 1 if you have the `poll' function. */
+#define HAVE_POLL 1
+
+/* Define to 1 if you have the <poll.h> header file. */
+#define HAVE_POLL_H 1
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#define HAVE_PTHREAD_H 1
+
+/* Define to 1 if you have the `ptsname' function. */
+/* #undef HAVE_PTSNAME */
+
+/* Define to 1 if you have the <pty.h> header file. */
+/* #undef HAVE_PTY_H */
+
+/* Define if you have the function `putenv'. */
+#define HAVE_PUTENV 1
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#define HAVE_PWD_H 1
+
+/* Define to 1 if you have the `rand' function. */
+#define HAVE_RAND 1
+
+/* Define to 1 if you have the `random' function. */
+#define HAVE_RANDOM 1
+
+/* Define if you have the function `rcmd'. */
+#define HAVE_RCMD 1
+
+/* Define if you have a readline compatible library. */
+#define HAVE_READLINE 1
+
+/* Define if you have the function `readv'. */
+#define HAVE_READV 1
+
+/* Define if you have the function `recvmsg'. */
+#define HAVE_RECVMSG 1
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#define HAVE_RESOLV_H 1
+
+/* Define to 1 if you have the `res_nsearch' function. */
+/* #undef HAVE_RES_NSEARCH */
+
+/* Define to 1 if you have the `res_search' function. */
+#define HAVE_RES_SEARCH 1
+
+/* Define to 1 if you have the `revoke' function. */
+#define HAVE_REVOKE 1
+
+/* Define to 1 if you have the <rpcsvc/ypclnt.h> header file. */
+#define HAVE_RPCSVC_YPCLNT_H 1
+
+/* Define to 1 if you have the <sac.h> header file. */
+/* #undef HAVE_SAC_H */
+
+/* Define to 1 if the system has the type `sa_family_t'. */
+#define HAVE_SA_FAMILY_T 1
+
+/* Define to 1 if you have the <security/pam_modules.h> header file. */
+/* #undef HAVE_SECURITY_PAM_MODULES_H */
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define if you have the function `sendmsg'. */
+#define HAVE_SENDMSG 1
+
+/* Define if you have the function `setegid'. */
+#define HAVE_SETEGID 1
+
+/* Define if you have the function `setenv'. */
+#define HAVE_SETENV 1
+
+/* Define if you have the function `seteuid'. */
+#define HAVE_SETEUID 1
+
+/* Define to 1 if you have the `setitimer' function. */
+#define HAVE_SETITIMER 1
+
+/* Define to 1 if you have the `setlim' function. */
+/* #undef HAVE_SETLIM */
+
+/* Define to 1 if you have the `setlogin' function. */
+#define HAVE_SETLOGIN 1
+
+/* Define to 1 if you have the `setpcred' function. */
+/* #undef HAVE_SETPCRED */
+
+/* Define to 1 if you have the `setpgid' function. */
+#define HAVE_SETPGID 1
+
+/* Define to 1 if you have the `setproctitle' function. */
+#define HAVE_SETPROCTITLE 1
+
+/* Define to 1 if you have the `setprogname' function. */
+/* #undef HAVE_SETPROGNAME */
+
+/* Define to 1 if you have the `setregid' function. */
+#define HAVE_SETREGID 1
+
+/* Define to 1 if you have the `setresgid' function. */
+#define HAVE_SETRESGID 1
+
+/* Define to 1 if you have the `setresuid' function. */
+#define HAVE_SETRESUID 1
+
+/* Define to 1 if you have the `setreuid' function. */
+#define HAVE_SETREUID 1
+
+/* Define to 1 if you have the `setsid' function. */
+#define HAVE_SETSID 1
+
+/* Define to 1 if you have the `setsockopt' function. */
+#define HAVE_SETSOCKOPT 1
+
+/* Define to 1 if you have the `setstate' function. */
+#define HAVE_SETSTATE 1
+
+/* Define to 1 if you have the `setutent' function. */
+/* #undef HAVE_SETUTENT */
+
+/* Define to 1 if you have the `sgi_getcapabilitybyname' function. */
+/* #undef HAVE_SGI_GETCAPABILITYBYNAME */
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#define HAVE_SGTTY_H 1
+
+/* Define to 1 if you have the <shadow.h> header file. */
+/* #undef HAVE_SHADOW_H */
+
+/* Define to 1 if you have the <siad.h> header file. */
+/* #undef HAVE_SIAD_H */
+
+/* Define to 1 if you have the `sigaction' function. */
+#define HAVE_SIGACTION 1
+
+/* Define to 1 if you have the <signal.h> header file. */
+#define HAVE_SIGNAL_H 1
+
+/* define if you have a working snprintf */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#define HAVE_SOCKLEN_T 1
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#define HAVE_SSIZE_T 1
+
+/* Define to 1 if you have the <standards.h> header file. */
+/* #undef HAVE_STANDARDS_H */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+/* #undef HAVE_STDINT_H */
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have the function `strcasecmp'. */
+#define HAVE_STRCASECMP 1
+
+/* Define if you have the function `strdup'. */
+#define HAVE_STRDUP 1
+
+/* Define if you have the function `strerror'. */
+#define HAVE_STRERROR 1
+
+/* Define if you have the function `strftime'. */
+#define HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define if you have the function `strlcat'. */
+#define HAVE_STRLCAT 1
+
+/* Define if you have the function `strlcpy'. */
+#define HAVE_STRLCPY 1
+
+/* Define if you have the function `strlwr'. */
+/* #undef HAVE_STRLWR */
+
+/* Define if you have the function `strncasecmp'. */
+#define HAVE_STRNCASECMP 1
+
+/* Define if you have the function `strndup'. */
+#define HAVE_STRNDUP 1
+
+/* Define if you have the function `strnlen'. */
+#define HAVE_STRNLEN 1
+
+/* Define to 1 if you have the <stropts.h> header file. */
+/* #undef HAVE_STROPTS_H */
+
+/* Define if you have the function `strptime'. */
+#define HAVE_STRPTIME 1
+
+/* Define if you have the function `strsep'. */
+#define HAVE_STRSEP 1
+
+/* Define if you have the function `strsep_copy'. */
+/* #undef HAVE_STRSEP_COPY */
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the `strsvis' function. */
+/* #undef HAVE_STRSVIS */
+
+/* Define if you have the function `strtok_r'. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if the system has the type `struct addrinfo'. */
+#define HAVE_STRUCT_ADDRINFO 1
+
+/* Define to 1 if the system has the type `struct ifaddrs'. */
+#define HAVE_STRUCT_IFADDRS 1
+
+/* Define to 1 if the system has the type `struct iovec'. */
+#define HAVE_STRUCT_IOVEC 1
+
+/* Define to 1 if the system has the type `struct msghdr'. */
+#define HAVE_STRUCT_MSGHDR 1
+
+/* Define to 1 if the system has the type `struct sockaddr'. */
+#define HAVE_STRUCT_SOCKADDR 1
+
+/* Define if struct sockaddr has field sa_len. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* define if you have struct spwd */
+/* #undef HAVE_STRUCT_SPWD */
+
+/* Define if struct tm has field tm_gmtoff. */
+#define HAVE_STRUCT_TM_TM_GMTOFF 1
+
+/* Define if struct tm has field tm_zone. */
+#define HAVE_STRUCT_TM_TM_ZONE 1
+
+/* Define if struct utmpx has field ut_exit. */
+/* #undef HAVE_STRUCT_UTMPX_UT_EXIT */
+
+/* Define if struct utmpx has field ut_syslen. */
+/* #undef HAVE_STRUCT_UTMPX_UT_SYSLEN */
+
+/* Define if struct utmp has field ut_addr. */
+/* #undef HAVE_STRUCT_UTMP_UT_ADDR */
+
+/* Define if struct utmp has field ut_host. */
+/* #undef HAVE_STRUCT_UTMP_UT_HOST */
+
+/* Define if struct utmp has field ut_id. */
+/* #undef HAVE_STRUCT_UTMP_UT_ID */
+
+/* Define if struct utmp has field ut_pid. */
+/* #undef HAVE_STRUCT_UTMP_UT_PID */
+
+/* Define if struct utmp has field ut_type. */
+/* #undef HAVE_STRUCT_UTMP_UT_TYPE */
+
+/* Define if struct utmp has field ut_user. */
+/* #undef HAVE_STRUCT_UTMP_UT_USER */
+
+/* define if struct winsize is declared in sys/termios.h */
+#define HAVE_STRUCT_WINSIZE 1
+
+/* Define to 1 if you have the `strunvis' function. */
+#define HAVE_STRUNVIS 1
+
+/* Define if you have the function `strupr'. */
+/* #undef HAVE_STRUPR */
+
+/* Define to 1 if you have the `strvis' function. */
+#define HAVE_STRVIS 1
+
+/* Define to 1 if you have the `strvisx' function. */
+#define HAVE_STRVISX 1
+
+/* Define to 1 if you have the `svis' function. */
+/* #undef HAVE_SVIS */
+
+/* Define if you have the function `swab'. */
+#define HAVE_SWAB 1
+
+/* Define to 1 if you have the `sysconf' function. */
+#define HAVE_SYSCONF 1
+
+/* Define to 1 if you have the `sysctl' function. */
+#define HAVE_SYSCTL 1
+
+/* Define to 1 if you have the `syslog' function. */
+#define HAVE_SYSLOG 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+/* #undef HAVE_SYS_BITYPES_H */
+
+/* Define to 1 if you have the <sys/bswap.h> header file. */
+/* #undef HAVE_SYS_BSWAP_H */
+
+/* Define to 1 if you have the <sys/capability.h> header file. */
+/* #undef HAVE_SYS_CAPABILITY_H */
+
+/* Define to 1 if you have the <sys/category.h> header file. */
+/* #undef HAVE_SYS_CATEGORY_H */
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#define HAVE_SYS_FILE_H 1
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#define HAVE_SYS_FILIO_H 1
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#define HAVE_SYS_MMAN_H 1
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#define HAVE_SYS_PARAM_H 1
+
+/* Define to 1 if you have the <sys/proc.h> header file. */
+#define HAVE_SYS_PROC_H 1
+
+/* Define to 1 if you have the <sys/ptyio.h> header file. */
+/* #undef HAVE_SYS_PTYIO_H */
+
+/* Define to 1 if you have the <sys/ptyvar.h> header file. */
+/* #undef HAVE_SYS_PTYVAR_H */
+
+/* Define to 1 if you have the <sys/pty.h> header file. */
+/* #undef HAVE_SYS_PTY_H */
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#define HAVE_SYS_SELECT_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/stream.h> header file. */
+/* #undef HAVE_SYS_STREAM_H */
+
+/* Define to 1 if you have the <sys/stropts.h> header file. */
+/* #undef HAVE_SYS_STROPTS_H */
+
+/* Define to 1 if you have the <sys/strtty.h> header file. */
+/* #undef HAVE_SYS_STRTTY_H */
+
+/* Define to 1 if you have the <sys/str_tty.h> header file. */
+/* #undef HAVE_SYS_STR_TTY_H */
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#define HAVE_SYS_SYSCALL_H 1
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#define HAVE_SYS_SYSCTL_H 1
+
+/* Define to 1 if you have the <sys/termio.h> header file. */
+/* #undef HAVE_SYS_TERMIO_H */
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#define HAVE_SYS_TIMEB_H 1
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+#define HAVE_SYS_TIMES_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/tty.h> header file. */
+#define HAVE_SYS_TTY_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#define HAVE_SYS_UIO_H 1
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#define HAVE_SYS_UN_H 1
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#define HAVE_SYS_UTSNAME_H 1
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#define HAVE_SYS_WAIT_H 1
+
+/* Define to 1 if you have the <termcap.h> header file. */
+#define HAVE_TERMCAP_H 1
+
+/* Define to 1 if you have the <termios.h> header file. */
+#define HAVE_TERMIOS_H 1
+
+/* Define to 1 if you have the <termio.h> header file. */
+/* #undef HAVE_TERMIO_H */
+
+/* Define to 1 if you have the <term.h> header file. */
+#define HAVE_TERM_H 1
+
+/* Define to 1 if you have the `tgetent' function. */
+#define HAVE_TGETENT 1
+
+/* Define to 1 if you have the `timegm' function. */
+#define HAVE_TIMEGM 1
+
+/* Define if you have the `timezone' variable. */
+#define HAVE_TIMEZONE 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <tmpdir.h> header file. */
+/* #undef HAVE_TMPDIR_H */
+
+/* Define to 1 if you have the `ttyname' function. */
+#define HAVE_TTYNAME 1
+
+/* Define to 1 if you have the `ttyslot' function. */
+#define HAVE_TTYSLOT 1
+
+/* Define to 1 if you have the <udb.h> header file. */
+/* #undef HAVE_UDB_H */
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#define HAVE_UINT16_T 1
+
+/* Define to 1 if the system has the type `uint32_t'. */
+#define HAVE_UINT32_T 1
+
+/* Define to 1 if the system has the type `uint64_t'. */
+#define HAVE_UINT64_T 1
+
+/* Define to 1 if the system has the type `uint8_t'. */
+#define HAVE_UINT8_T 1
+
+/* Define to 1 if you have the `umask' function. */
+#define HAVE_UMASK 1
+
+/* Define to 1 if you have the `uname' function. */
+#define HAVE_UNAME 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `unlockpt' function. */
+/* #undef HAVE_UNLOCKPT */
+
+/* Define if you have the function `unsetenv'. */
+#define HAVE_UNSETENV 1
+
+/* Define to 1 if you have the `unvis' function. */
+#define HAVE_UNVIS 1
+
+/* Define to 1 if you have the <userconf.h> header file. */
+/* #undef HAVE_USERCONF_H */
+
+/* Define to 1 if you have the <usersec.h> header file. */
+/* #undef HAVE_USERSEC_H */
+
+/* Define to 1 if you have the <util.h> header file. */
+#define HAVE_UTIL_H 1
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+/* #undef HAVE_UTMPX_H */
+
+/* Define to 1 if you have the <utmp.h> header file. */
+#define HAVE_UTMP_H 1
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#define HAVE_U_INT16_T 1
+
+/* Define to 1 if the system has the type `u_int32_t'. */
+#define HAVE_U_INT32_T 1
+
+/* Define to 1 if the system has the type `u_int64_t'. */
+#define HAVE_U_INT64_T 1
+
+/* Define to 1 if the system has the type `u_int8_t'. */
+#define HAVE_U_INT8_T 1
+
+/* Define to 1 if you have the `vasnprintf' function. */
+/* #undef HAVE_VASNPRINTF */
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define if you have the function `verr'. */
+#define HAVE_VERR 1
+
+/* Define if you have the function `verrx'. */
+#define HAVE_VERRX 1
+
+/* Define to 1 if you have the `vhangup' function. */
+/* #undef HAVE_VHANGUP */
+
+/* Define to 1 if you have the `vis' function. */
+#define HAVE_VIS 1
+
+/* Define to 1 if you have the <vis.h> header file. */
+/* #undef HAVE_VIS_H */
+
+/* define if you have a working vsnprintf */
+#define HAVE_VSNPRINTF 1
+
+/* Define if you have the function `vsyslog'. */
+#define HAVE_VSYSLOG 1
+
+/* Define if you have the function `vwarn'. */
+#define HAVE_VWARN 1
+
+/* Define if you have the function `vwarnx'. */
+#define HAVE_VWARNX 1
+
+/* Define if you have the function `warn'. */
+#define HAVE_WARN 1
+
+/* Define if you have the function `warnx'. */
+#define HAVE_WARNX 1
+
+/* Define if you have the function `writev'. */
+#define HAVE_WRITEV 1
+
+/* define if struct winsize has ws_xpixel */
+#define HAVE_WS_XPIXEL 1
+
+/* define if struct winsize has ws_ypixel */
+#define HAVE_WS_YPIXEL 1
+
+/* Define to 1 if you have the `XauFileName' function. */
+#define HAVE_XAUFILENAME 1
+
+/* Define to 1 if you have the `XauReadAuth' function. */
+#define HAVE_XAUREADAUTH 1
+
+/* Define to 1 if you have the `XauWriteAuth' function. */
+#define HAVE_XAUWRITEAUTH 1
+
+/* Define to 1 if you have the `yp_get_default_domain' function. */
+#define HAVE_YP_GET_DEFAULT_DOMAIN 1
+
+/* Define to 1 if you have the `_getpty' function. */
+/* #undef HAVE__GETPTY */
+
+/* Define if you have the `_res' variable. */
+#define HAVE__RES 1
+
+/* Define to 1 if you have the `_scrsize' function. */
+/* #undef HAVE__SCRSIZE */
+
+/* define if your compiler has __attribute__ */
+#define HAVE___ATTRIBUTE__ 1
+
+/* Define if you have the `__progname' variable. */
+#define HAVE___PROGNAME 1
+
+/* Define if you have the hesiod package. */
+/* #undef HESIOD */
+
+/* Define if you are running IRIX 4. */
+/* #undef IRIX4 */
+
+/* Define if you have the krb4 package. */
+/* #undef KRB4 */
+
+/* Enable Kerberos 5 support in applications. */
+#define KRB5 1
+
+/* Define if krb_mk_req takes const char * */
+/* #undef KRB_MK_REQ_CONST */
+
+/* This is the krb4 sendauth version. */
+/* #undef KRB_SENDAUTH_VERS */
+
+/* Define to zero if your krb.h doesn't */
+/* #undef KRB_VERIFY_NOT_SECURE */
+
+/* Define to one if your krb.h doesn't */
+/* #undef KRB_VERIFY_SECURE */
+
+/* Define to two if your krb.h doesn't */
+/* #undef KRB_VERIFY_SECURE_FAIL */
+
+/* path to lib */
+#define LIBDIR "/usr/lib"
+
+/* path to libexec */
+#define LIBEXECDIR "/usr/libexec"
+
+/* path to localstate */
+#define LOCALSTATEDIR "/var/heimdal"
+
+/* define if the system is missing a prototype for asnprintf() */
+#define NEED_ASNPRINTF_PROTO 1
+
+/* define if the system is missing a prototype for asprintf() */
+/* #undef NEED_ASPRINTF_PROTO */
+
+/* define if the system is missing a prototype for crypt() */
+/* #undef NEED_CRYPT_PROTO */
+
+/* define if the system is missing a prototype for daemon() */
+#define NEED_DAEMON_PROTO 1
+
+/* define if the system is missing a prototype for gethostname() */
+/* #undef NEED_GETHOSTNAME_PROTO */
+
+/* define if the system is missing a prototype for getusershell() */
+/* #undef NEED_GETUSERSHELL_PROTO */
+
+/* define if the system is missing a prototype for glob() */
+/* #undef NEED_GLOB_PROTO */
+
+/* define if the system is missing a prototype for hstrerror() */
+/* #undef NEED_HSTRERROR_PROTO */
+
+/* define if the system is missing a prototype for inet_aton() */
+/* #undef NEED_INET_ATON_PROTO */
+
+/* define if the system is missing a prototype for mkstemp() */
+/* #undef NEED_MKSTEMP_PROTO */
+
+/* define if the system is missing a prototype for setenv() */
+/* #undef NEED_SETENV_PROTO */
+
+/* define if the system is missing a prototype for snprintf() */
+#define NEED_SNPRINTF_PROTO 1
+
+/* define if the system is missing a prototype for strndup() */
+#undef NEED_STRNDUP_PROTO
+
+/* define if the system is missing a prototype for strsep() */
+/* #undef NEED_STRSEP_PROTO */
+
+/* define if the system is missing a prototype for strsvis() */
+#define NEED_STRSVIS_PROTO 1
+
+/* define if the system is missing a prototype for strtok_r() */
+/* #undef NEED_STRTOK_R_PROTO */
+
+/* define if the system is missing a prototype for strunvis() */
+#define NEED_STRUNVIS_PROTO 1
+
+/* define if the system is missing a prototype for strvisx() */
+#define NEED_STRVISX_PROTO 1
+
+/* define if the system is missing a prototype for strvis() */
+#define NEED_STRVIS_PROTO 1
+
+/* define if the system is missing a prototype for svis() */
+#define NEED_SVIS_PROTO 1
+
+/* define if the system is missing a prototype for unsetenv() */
+/* #undef NEED_UNSETENV_PROTO */
+
+/* define if the system is missing a prototype for unvis() */
+#define NEED_UNVIS_PROTO 1
+
+/* define if the system is missing a prototype for vasnprintf() */
+#define NEED_VASNPRINTF_PROTO 1
+
+/* define if the system is missing a prototype for vasprintf() */
+/* #undef NEED_VASPRINTF_PROTO */
+
+/* define if the system is missing a prototype for vis() */
+#define NEED_VIS_PROTO 1
+
+/* define if the system is missing a prototype for vsnprintf() */
+#define NEED_VSNPRINTF_PROTO 1
+
+/* Define if you don't want to use mmap. */
+/* #undef NO_MMAP */
+
+/* Define this to enable old environment option in telnet. */
+#define OLD_ENVIRON 1
+
+/* Define if you have the openldap package. */
+/* #undef OPENLDAP */
+
+/* Define if you want support for hdb ldap module */
+/* #undef OPENLDAP_MODULE */
+
+/* define if prototype of openlog is compatible with void openlog(const char
+   *, int, int) */
+#define OPENLOG_PROTO_COMPATIBLE 1
+
+/* Define if you want OTP support in applications. */
+#define OTP 1
+
+/* Name of package */
+#define PACKAGE "heimdal"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "heimdal-bugs@pdc.kth.se"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "Heimdal"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "Heimdal 0.7.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "heimdal"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.7.1"
+
+/* Define to enable PKINIT. */
+/* #undef PKINIT */
+
+/* Define if getlogin has POSIX flavour (and not BSD). */
+/* #undef POSIX_GETLOGIN */
+
+/* Define if getpwnam_r has POSIX flavour. */
+/* #undef POSIX_GETPWNAM_R */
+
+/* Define if you have the readline package. */
+/* #undef READLINE */
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#define RETSIGTYPE void
+
+/* path to sbin */
+#define SBINDIR "/usr/sbin"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define if you have streams ptys. */
+/* #undef STREAMSPTY */
+
+/* Define to what version of SunOS you are running. */
+/* #undef SunOS */
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Version number of package */
+#define VERSION "0.7.1"
+
+/* Define if signal handlers return void. */
+#define VOID_RETSIGTYPE 1
+
+/* define if target is big endian */
+/* #undef WORDS_BIGENDIAN */
+
+/* Define to 1 if the X Window System is missing or not being used. */
+/* #undef X_DISPLAY_MISSING */
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to enable extensions on glibc-based systems such as Linux. */
+#define _GNU_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef gid_t */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define this to what the type mode_t should be. */
+/* #undef mode_t */
+
+/* Define to `long' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef pid_t */
+
+/* Define this to what the type sig_atomic_t should be. */
+/* #undef sig_atomic_t */
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+/* #undef uid_t */
+
+#if defined(HAVE_FOUR_VALUED_KRB_PUT_INT) || !defined(KRB4)
+#define KRB_PUT_INT(F, T, L, S) krb_put_int((F), (T), (L), (S))
+#else
+#define KRB_PUT_INT(F, T, L, S) krb_put_int((F), (T), (S))
+#endif
+
+
+
+#if defined(ENCRYPTION) && !defined(AUTHENTICATION)
+#define AUTHENTICATION 1
+#endif
+
+/* Set this to the default system lead string for telnetd
+ * can contain %-escapes: %s=sysname, %m=machine, %r=os-release
+ * %v=os-version, %t=tty, %h=hostname, %d=date and time
+ */
+/* #undef USE_IM */
+
+/* Used with login -p */
+/* #undef LOGIN_ARGS */
+
+/* set this to a sensible login */
+#ifndef LOGIN_PATH
+#define LOGIN_PATH BINDIR "/login"
+#endif
+
+
+#ifdef ROKEN_RENAME
+#include "roken_rename.h"
+#endif
+
+#ifndef HAVE_KRB_KDCTIMEOFDAY
+#define krb_kdctimeofday(X) gettimeofday((X), NULL)
+#endif
+
+#ifndef HAVE_KRB_GET_KDC_TIME_DIFF
+#define krb_get_kdc_time_diff() (0)
+#endif
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#ifdef BROKEN_REALLOC
+#define realloc(X, Y) rk_realloc((X), (Y))
+#endif
+
+
+#if ENDIANESS_IN_SYS_PARAM_H
+#  include <sys/types.h>
+#  include <sys/param.h>
+#  if BYTE_ORDER == BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+#  endif
+#endif
+
+
+#if _AIX
+#define _ALL_SOURCE
+/* XXX this is gross, but kills about a gazillion warnings */
+struct ether_addr;
+struct sockaddr;
+struct sockaddr_dl;
+struct sockaddr_in;
+#endif
+
+
+/* IRIX 4 braindamage */
+#if IRIX == 4 && !defined(__STDC__)
+#define __STDC__ 0
+#endif
+
diff --git a/src/kerberosV/include/crypto-headers.h b/src/kerberosV/include/crypto-headers.h
new file mode 100644 (file)
index 0000000..93289b4
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __crypto_headers_h__
+#define __crypto_headers_h__
+#define OPENSSL_DES_LIBDES_COMPATIBILITY
+#include <openssl/des.h>
+#include <openssl/rc4.h>
+#include <openssl/rc2.h>
+#include <openssl/md4.h>
+#include <openssl/md5.h>
+#include <openssl/sha.h>
+#include <openssl/aes.h>
+#include <openssl/ui.h>
+#endif /* __crypto_headers_h__ */
diff --git a/src/kerberosV/include/krb5-types.h b/src/kerberosV/include/krb5-types.h
new file mode 100644 (file)
index 0000000..9d61bcb
--- /dev/null
@@ -0,0 +1,16 @@
+/* krb5-types.h -- this file was generated for i386-unknown-openbsd2.7 by
+                   $Id: krb5-types.h,v 1.2 2003/05/11 03:49:07 hin Exp $ */
+
+#ifndef __krb5_types_h__
+#define __krb5_types_h__
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <sys/socket.h>
+
+
+typedef socklen_t krb5_socklen_t;
+#include <unistd.h>
+typedef ssize_t krb5_ssize_t;
+
+#endif /* __krb5_types_h__ */
diff --git a/src/kerberosV/include/print_version.h b/src/kerberosV/include/print_version.h
new file mode 100644 (file)
index 0000000..e038cb0
--- /dev/null
@@ -0,0 +1 @@
+#define VERSIONLIST { "heimdal-0.7.2/OpenBSD", }
diff --git a/src/kerberosV/include/roken.h b/src/kerberosV/include/roken.h
new file mode 100644 (file)
index 0000000..9b53b81
--- /dev/null
@@ -0,0 +1,233 @@
+/* This is an OS dependent, generated file */
+
+
+#ifndef __ROKEN_H__
+#define __ROKEN_H__
+
+/* -*- C -*- */
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: roken.h.in,v 1.159 2001/08/21 15:32:05 assar Exp $ */
+/* $Id: roken.h,v 1.10 2004/10/29 16:25:42 biorn Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+
+#include <sys/param.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <grp.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <err.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <time.h>
+
+#include <paths.h>
+
+
+#define ROKEN_LIB_FUNCTION
+
+#include <roken-common.h>
+
+ROKEN_CPP_START
+
+
+
+
+
+
+
+
+
+
+int asnprintf (char **ret, size_t max_sz, const char *format, ...)
+     __attribute__ ((format (printf, 3, 4)));
+
+int vasnprintf (char **ret, size_t max_sz, const char *format, va_list ap)
+     __attribute__((format (printf, 3, 0)));
+
+
+char * strndup(const char *old, size_t sz);
+
+char * strlwr(char *);
+
+size_t strnlen(const char*, size_t);
+
+
+ssize_t strsep_copy(const char**, const char*, char*, size_t);
+
+
+
+
+char * strupr(char *);
+
+
+
+
+
+
+
+
+
+
+
+#include <pwd.h>
+struct passwd *k_getpwnam (const char *user);
+struct passwd *k_getpwuid (uid_t uid);
+
+const char *get_default_username (void);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define bswap32 swap32
+#define bswap16 swap16
+
+
+time_t tm2time (struct tm tm, int local);
+
+int unix_verify_user(char *user, char *password);
+
+void mini_inetd (int port);
+
+int roken_concat (char *s, size_t len, ...);
+
+size_t roken_mconcat (char **s, size_t max_len, ...);
+
+int roken_vconcat (char *s, size_t len, va_list args);
+
+size_t roken_vmconcat (char **s, size_t max_len, va_list args);
+
+ssize_t net_write (int fd, const void *buf, size_t nbytes);
+
+ssize_t net_read (int fd, void *buf, size_t nbytes);
+
+int issuid(void);
+
+
+int get_window_size(int fd, struct winsize *);
+
+
+
+extern char **environ;
+
+struct hostent *
+getipnodebyname (const char *name, int af, int flags, int *error_num);
+
+struct hostent *
+getipnodebyaddr (const void *src, size_t len, int af, int *error_num);
+
+void
+freehostent (struct hostent *h);
+
+struct hostent *
+copyhostent (const struct hostent *h);
+
+
+
+
+
+
+
+
+int
+getnameinfo_verified(const struct sockaddr *sa, socklen_t salen,
+                    char *host, size_t hostlen,
+                    char *serv, size_t servlen,
+                    int flags);
+
+int roken_getaddrinfo_hostspec(const char *, int, struct addrinfo **); 
+int roken_getaddrinfo_hostspec2(const char *, int, int, struct addrinfo **);
+
+
+
+void *emalloc (size_t);
+void *ecalloc(size_t num, size_t sz);
+void *erealloc (void *, size_t);
+char *estrdup (const char *);
+
+/*
+ * kludges and such
+ */
+
+int roken_gethostby_setup(const char*, const char*);
+struct hostent* roken_gethostbyname(const char*);
+struct hostent* roken_gethostbyaddr(const void*, size_t, int);
+
+#define roken_getservbyname(x,y) getservbyname(x,y)
+
+#define roken_openlog(a,b,c) openlog(a,b,c)
+
+#define roken_getsockname(a,b,c) getsockname(a,b,c)
+
+void setprogname(const char *argv0);
+
+const char *getprogname(void);
+
+void set_progname(char *argv0);
+const char *get_progname(void);
+
+ROKEN_CPP_END
+#define ROKEN_VERSION 0.6.3
+
+#endif /* __ROKEN_H__ */
diff --git a/src/kerberosV/include/version.h b/src/kerberosV/include/version.h
new file mode 100644 (file)
index 0000000..a54c20b
--- /dev/null
@@ -0,0 +1,2 @@
+char *heimdal_long_version = "@(#)$Version: heimdal-0.7.2/OpenBSD";
+char *heimdal_version = "heimdal-0.7.2/OpenBSD";
diff --git a/src/kerberosV/libexec/CVS/Entries b/src/kerberosV/libexec/CVS/Entries
new file mode 100644 (file)
index 0000000..e791a7c
--- /dev/null
@@ -0,0 +1,10 @@
+/Makefile/1.5/Mon Jul 14 16:14:43 2003//
+/Makefile.inc/1.1/Fri May 25 08:19:39 2001//
+D/hprop////
+D/hpropd////
+D/ipropd-master////
+D/ipropd-slave////
+D/kadmind////
+D/kdc////
+D/kfd////
+D/kpasswdd////
diff --git a/src/kerberosV/libexec/CVS/Repository b/src/kerberosV/libexec/CVS/Repository
new file mode 100644 (file)
index 0000000..514cc4e
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec
diff --git a/src/kerberosV/libexec/CVS/Root b/src/kerberosV/libexec/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/Makefile b/src/kerberosV/libexec/Makefile
new file mode 100644 (file)
index 0000000..e252623
--- /dev/null
@@ -0,0 +1,7 @@
+# $OpenBSD: Makefile,v 1.5 2003/07/14 16:14:43 mho Exp $
+
+# kfd - not imported?
+
+SUBDIR=        kdc kadmind hprop hpropd ipropd-master ipropd-slave kpasswdd
+
+.include <bsd.subdir.mk>
diff --git a/src/kerberosV/libexec/Makefile.inc b/src/kerberosV/libexec/Makefile.inc
new file mode 100644 (file)
index 0000000..7dc0e13
--- /dev/null
@@ -0,0 +1,3 @@
+# $OpenBSD: Makefile.inc,v 1.1 2001/05/25 08:19:39 hin Exp $
+
+BINDIR=/usr/libexec
diff --git a/src/kerberosV/libexec/hprop/CVS/Entries b/src/kerberosV/libexec/hprop/CVS/Entries
new file mode 100644 (file)
index 0000000..a39576e
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.7/Mon Jul 14 16:14:43 2003//
+D
diff --git a/src/kerberosV/libexec/hprop/CVS/Repository b/src/kerberosV/libexec/hprop/CVS/Repository
new file mode 100644 (file)
index 0000000..9a6ea0e
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/hprop
diff --git a/src/kerberosV/libexec/hprop/CVS/Root b/src/kerberosV/libexec/hprop/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/hprop/Makefile b/src/kerberosV/libexec/hprop/Makefile
new file mode 100644 (file)
index 0000000..1ccd606
--- /dev/null
@@ -0,0 +1,21 @@
+# $OpenBSD: Makefile,v 1.7 2003/07/14 16:14:43 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  hprop
+MAN=   ${PROG}.8
+
+SRCS=  hprop.c mit_dump.c v4_dump.c hprop.h kadb.h
+SRCS+= ${PRINTVER}
+SRCS+= tm2time.c
+
+.PATH: ${KRB5SRC}/kdc
+.PATH: ${ROKENSRC}
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/lib/kadm5
+
+DPADD+= ${LIBKADM5SRV} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkadm5srv -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/hprop/obj b/src/kerberosV/libexec/hprop/obj
new file mode 120000 (symlink)
index 0000000..7c02823
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/hprop
\ No newline at end of file
diff --git a/src/kerberosV/libexec/hpropd/CVS/Entries b/src/kerberosV/libexec/hpropd/CVS/Entries
new file mode 100644 (file)
index 0000000..a39576e
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.7/Mon Jul 14 16:14:43 2003//
+D
diff --git a/src/kerberosV/libexec/hpropd/CVS/Repository b/src/kerberosV/libexec/hpropd/CVS/Repository
new file mode 100644 (file)
index 0000000..f047d87
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/hpropd
diff --git a/src/kerberosV/libexec/hpropd/CVS/Root b/src/kerberosV/libexec/hpropd/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/hpropd/Makefile b/src/kerberosV/libexec/hpropd/Makefile
new file mode 100644 (file)
index 0000000..bcdb4b6
--- /dev/null
@@ -0,0 +1,21 @@
+# $OpenBSD: Makefile,v 1.7 2003/07/14 16:14:43 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  hpropd
+MAN=   ${PROG}.8
+
+SRCS=  hpropd.c
+SRCS+= ${PRINTVER}
+SRCS+= mini_inetd.c socket.c tm2time.c 
+
+.PATH: ${KRB5SRC}/kdc
+.PATH: ${ROKENSRC}
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/lib/kadm5
+
+DPADD+= ${LIBKADM5SRV} ${LIBKRB5} ${LIBCRYPTO} ${LIBDES}
+LDADD+=        -lkadm5srv -lkrb5 -lcrypto -ldes
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/hpropd/obj b/src/kerberosV/libexec/hpropd/obj
new file mode 120000 (symlink)
index 0000000..8bdcb28
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/hpropd
\ No newline at end of file
diff --git a/src/kerberosV/libexec/ipropd-master/CVS/Entries b/src/kerberosV/libexec/ipropd-master/CVS/Entries
new file mode 100644 (file)
index 0000000..52e4db8
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.8/Sun Apr 23 20:46:55 2006//
+D
diff --git a/src/kerberosV/libexec/ipropd-master/CVS/Repository b/src/kerberosV/libexec/ipropd-master/CVS/Repository
new file mode 100644 (file)
index 0000000..321bda0
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/ipropd-master
diff --git a/src/kerberosV/libexec/ipropd-master/CVS/Root b/src/kerberosV/libexec/ipropd-master/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/ipropd-master/Makefile b/src/kerberosV/libexec/ipropd-master/Makefile
new file mode 100644 (file)
index 0000000..2e42815
--- /dev/null
@@ -0,0 +1,23 @@
+# $OpenBSD: Makefile,v 1.8 2006/04/23 20:46:55 biorn Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  ipropd-master
+MAN=   iprop.8
+MLINKS+=iprop.8 ipropd-master.8
+MLINKS+=iprop.8 ipropd-slave.8
+
+SRCS=  ipropd_master.c
+SRCS+= ${PRINTVER}
+SRCS+= rtbl.c
+
+.PATH: ${KRB5SRC}/lib/kadm5
+.PATH: ${ROKENSRC}
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5
+
+DPADD+= ${LIBKADM5SRV} ${LIBKRB5} ${LIBCRYPTO} ${LIBUTIL} ${LIBDES}
+LDADD+=        -lkadm5srv -lkrb5 -lcrypto -lutil -ldes
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/ipropd-master/obj b/src/kerberosV/libexec/ipropd-master/obj
new file mode 120000 (symlink)
index 0000000..af46c41
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/ipropd-master
\ No newline at end of file
diff --git a/src/kerberosV/libexec/ipropd-slave/CVS/Entries b/src/kerberosV/libexec/ipropd-slave/CVS/Entries
new file mode 100644 (file)
index 0000000..ea6c74f
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.9/Sun Apr 23 20:46:55 2006//
+D
diff --git a/src/kerberosV/libexec/ipropd-slave/CVS/Repository b/src/kerberosV/libexec/ipropd-slave/CVS/Repository
new file mode 100644 (file)
index 0000000..205ffb3
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/ipropd-slave
diff --git a/src/kerberosV/libexec/ipropd-slave/CVS/Root b/src/kerberosV/libexec/ipropd-slave/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/ipropd-slave/Makefile b/src/kerberosV/libexec/ipropd-slave/Makefile
new file mode 100644 (file)
index 0000000..39c791f
--- /dev/null
@@ -0,0 +1,19 @@
+# $OpenBSD: Makefile,v 1.9 2006/04/23 20:46:55 biorn Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  ipropd-slave
+NOMAN=
+
+SRCS=  ipropd_slave.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/lib/kadm5
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/lib/kadm5
+
+DPADD+= ${LIBKADM5SRV} ${LIBKRB5} ${LIBCRYPTO} ${LIBUTIL} ${LIBDES}
+LDADD+=        -lkadm5srv -lkrb5 -lcrypto -lutil -ldes
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/ipropd-slave/obj b/src/kerberosV/libexec/ipropd-slave/obj
new file mode 120000 (symlink)
index 0000000..8725f7d
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/ipropd-slave
\ No newline at end of file
diff --git a/src/kerberosV/libexec/kadmind/CVS/Entries b/src/kerberosV/libexec/kadmind/CVS/Entries
new file mode 100644 (file)
index 0000000..9208eaa
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.12/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/libexec/kadmind/CVS/Repository b/src/kerberosV/libexec/kadmind/CVS/Repository
new file mode 100644 (file)
index 0000000..70c870f
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/kadmind
diff --git a/src/kerberosV/libexec/kadmind/CVS/Root b/src/kerberosV/libexec/kadmind/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/kadmind/Makefile b/src/kerberosV/libexec/kadmind/Makefile
new file mode 100644 (file)
index 0000000..3099137
--- /dev/null
@@ -0,0 +1,21 @@
+# $OpenBSD: Makefile,v 1.12 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kadmind
+MAN=   ${PROG}.8
+
+SRCS=  kadmind.c server.c kadm_conn.c
+SRCS+= ${PRINTVER}
+SRCS+= mini_inetd.c socket.c
+
+.PATH: ${KRB5SRC}/kadmin
+.PATH: ${ROKENSRC}
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/kdc
+
+DPADD+=        ${LIBKADM5SRV} ${LIBKRB5} ${LIBDES} ${LIBCRYPTO} ${LIBUTIL}
+LDADD+=        -lkadm5srv -lkrb5 -ldes -lcrypto -lutil
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/kadmind/obj b/src/kerberosV/libexec/kadmind/obj
new file mode 120000 (symlink)
index 0000000..d1cf7cc
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/kadmind
\ No newline at end of file
diff --git a/src/kerberosV/libexec/kdc/CVS/Entries b/src/kerberosV/libexec/kdc/CVS/Entries
new file mode 100644 (file)
index 0000000..3606a3c
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.12/Fri Apr 14 08:28:55 2006//
+D
diff --git a/src/kerberosV/libexec/kdc/CVS/Repository b/src/kerberosV/libexec/kdc/CVS/Repository
new file mode 100644 (file)
index 0000000..0ad2aca
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/kdc
diff --git a/src/kerberosV/libexec/kdc/CVS/Root b/src/kerberosV/libexec/kdc/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/kdc/Makefile b/src/kerberosV/libexec/kdc/Makefile
new file mode 100644 (file)
index 0000000..8a9b199
--- /dev/null
@@ -0,0 +1,31 @@
+# $OpenBSD: Makefile,v 1.12 2006/04/14 08:28:55 biorn Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kdc
+MAN=   ${PROG}.8
+
+SRCS=  524.c \
+       config.c \
+       connect.c \
+       kaserver.c \
+       kdc_locl.h \
+       kerberos5.c \
+       kerberos4.c \
+       log.c \
+       main.c \
+       misc.c \
+       rx.h
+SRCS+= ${PRINTVER}
+SRCS+= parse_bytes.c
+
+.PATH: ${KRB5SRC}/kdc
+.PATH: ${ROKENSRC}
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/kdc
+
+DPADD+=        ${LIBKRB5} ${LIBDES} ${LIBCRYPTO} ${LIBUTIL}
+LDADD+=        -lkrb5 -ldes -lcrypto -lutil
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/kdc/obj b/src/kerberosV/libexec/kdc/obj
new file mode 120000 (symlink)
index 0000000..7f8f9b6
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/kdc
\ No newline at end of file
diff --git a/src/kerberosV/libexec/kfd/CVS/Entries b/src/kerberosV/libexec/kfd/CVS/Entries
new file mode 100644 (file)
index 0000000..4ca2ee8
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.5/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/libexec/kfd/CVS/Repository b/src/kerberosV/libexec/kfd/CVS/Repository
new file mode 100644 (file)
index 0000000..2d7c6ba
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/kfd
diff --git a/src/kerberosV/libexec/kfd/CVS/Root b/src/kerberosV/libexec/kfd/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/kfd/Makefile b/src/kerberosV/libexec/kfd/Makefile
new file mode 100644 (file)
index 0000000..9c84bd0
--- /dev/null
@@ -0,0 +1,18 @@
+# $OpenBSD: Makefile,v 1.5 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kfd
+MAN=   ${PROG}.8
+
+SRCS=  kfd.c
+
+.PATH: ${KRB5SRC}/appl/kf
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5
+
+DPADD+=        ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/kpasswdd/CVS/Entries b/src/kerberosV/libexec/kpasswdd/CVS/Entries
new file mode 100644 (file)
index 0000000..720ec48
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.10/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/libexec/kpasswdd/CVS/Repository b/src/kerberosV/libexec/kpasswdd/CVS/Repository
new file mode 100644 (file)
index 0000000..1d3645d
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/libexec/kpasswdd
diff --git a/src/kerberosV/libexec/kpasswdd/CVS/Root b/src/kerberosV/libexec/kpasswdd/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/libexec/kpasswdd/Makefile b/src/kerberosV/libexec/kpasswdd/Makefile
new file mode 100644 (file)
index 0000000..57a5d44
--- /dev/null
@@ -0,0 +1,19 @@
+# $OpenBSD: Makefile,v 1.10 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kpasswdd
+MAN=   ${PROG}.8
+
+SRCS=  kpasswdd.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/kpasswd
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/lib/kadm5
+
+DPADD+=        ${LIBKADM5SRV} ${LIBKRB5} ${LIBDES} ${LIBCRYPTO} ${LIBUTIL}
+LDADD+=        -lkadm5srv -lkrb5 -ldes -lcrypto -lutil
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/libexec/kpasswdd/obj b/src/kerberosV/libexec/kpasswdd/obj
new file mode 120000 (symlink)
index 0000000..c85909b
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/libexec/kpasswdd
\ No newline at end of file
diff --git a/src/kerberosV/openbsd-vers/CVS/Entries b/src/kerberosV/openbsd-vers/CVS/Entries
new file mode 100644 (file)
index 0000000..315d677
--- /dev/null
@@ -0,0 +1,2 @@
+/print_version.c/1.3/Fri Apr 14 08:28:55 2006//
+D
diff --git a/src/kerberosV/openbsd-vers/CVS/Repository b/src/kerberosV/openbsd-vers/CVS/Repository
new file mode 100644 (file)
index 0000000..2a6b4e8
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/openbsd-vers
diff --git a/src/kerberosV/openbsd-vers/CVS/Root b/src/kerberosV/openbsd-vers/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/openbsd-vers/print_version.c b/src/kerberosV/openbsd-vers/print_version.c
new file mode 100644 (file)
index 0000000..d1fb46e
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1998 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#if 0
+RCSID("$Id: print_version.c,v 1.3 2006/04/14 08:28:55 biorn Exp $");
+#endif
+
+#include <stdio.h>
+
+
+#define VERSIONLIST            { "heimdal-0.7.2/OpenBSD", }
+#define PACKAGE_BUGREPORT      "bugs@openbsd.org"
+
+char *__progname;
+
+void
+print_version(const char *progname)
+{
+    const char *package_list = VERSIONLIST;
+    
+    if(progname == NULL)
+       progname = __progname;
+    
+    if(*package_list == '\0')
+       package_list = "no version information";
+    fprintf(stderr, "%s (%s)\n", progname, package_list);
+    fprintf(stderr, "Copyright 1999-2004 Kungliga Tekniska Högskolan\n");
+    fprintf(stderr, "Send bug-reports to %s\n", PACKAGE_BUGREPORT);
+}
diff --git a/src/kerberosV/src/CVS/Entries b/src/kerberosV/src/CVS/Entries
new file mode 100644 (file)
index 0000000..4a44e22
--- /dev/null
@@ -0,0 +1,36 @@
+/ChangeLog/1.1.1.7/Fri Apr 14 07:31:11 2006//
+/ChangeLog.1998/1.1.1.1/Fri May 25 07:44:22 2001//
+/ChangeLog.1999/1.1.1.1/Fri May 25 07:44:24 2001//
+/ChangeLog.2000/1.1.1.1/Fri May 25 07:44:26 2001//
+/ChangeLog.2001/1.1.1.1/Sun May 11 02:14:14 2003//
+/ChangeLog.2002/1.1.1.1/Sun May 11 02:14:14 2003//
+/ChangeLog.2003/1.1.1.1/Fri Apr 14 07:31:16 2006//
+/ChangeLog.2004/1.1.1.1/Fri Apr 14 07:31:16 2006//
+/Makefile.am/1.1.1.2/Fri Apr 14 07:31:16 2006//
+/Makefile.am.common/1.1.1.2/Fri Oct 29 15:55:17 2004//
+/Makefile.in/1.1.1.5/Fri Apr 14 07:31:50 2006//
+/NEWS/1.1.1.5/Fri Apr 14 07:31:17 2006//
+/README/1.1.1.1/Fri May 25 07:44:26 2001//
+/TODO/1.1.1.4/Fri Apr 14 07:31:17 2006//
+/TODO-1.0/1.1.1.3/Fri Apr 14 07:31:17 2006//
+/TODO-shadow/1.1.1.1/Wed Feb  6 08:51:43 2002//
+/acconfig.h/1.1.1.3/Wed Feb  6 08:51:43 2002//
+/acinclude.m4/1.1.1.2/Fri Apr 14 07:31:17 2006//
+/aclocal.m4/1.4/Fri Apr 14 08:15:03 2006//
+/compile/1.1.1.1/Fri Oct 29 15:55:22 2004//
+/config.guess/1.9/Sun Apr 17 10:07:33 2005//
+/config.sub/1.1.1.2/Fri Oct 29 15:55:18 2004//
+/ylwrap/1.1.1.1/Fri Apr 14 07:31:50 2006//
+D/admin////
+D/appl////
+D/cf////
+D/doc////
+D/etc////
+D/include////
+D/kadmin////
+D/kcm////
+D/kdc////
+D/kpasswd////
+D/kuser////
+D/lib////
+D/tools////
diff --git a/src/kerberosV/src/CVS/Repository b/src/kerberosV/src/CVS/Repository
new file mode 100644 (file)
index 0000000..94fdb9c
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src
diff --git a/src/kerberosV/src/CVS/Root b/src/kerberosV/src/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/ChangeLog b/src/kerberosV/src/ChangeLog
new file mode 100644 (file)
index 0000000..a228b4f
--- /dev/null
@@ -0,0 +1,1162 @@
+2006-02-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Release 0.7.2
+
+       * lib/krb5/Makefile.am: install krb5_set_password.3
+       
+       * tools/krb5-config.in: Depend on LIB_dlopen
+
+       * tools/Makefile.am: Depend on LIB_dlopen
+
+       * lib/krb5/rd_req.c: 1.60: (krb5_verify_ap_re2): check timestamp
+       in authenticator
+
+       * kcm/connect.c: 1.18: (kcm_loop): Use HAVE_DOOR_CREATE, not
+       HAVE_DOORS.  1.17: (update_client_creds): in case there is no
+       UCRED_VERSION, skip LOCAL_PEERCRED
+
+       * lib/krb5/keytab_memory.c: 1.8: (mkt_remove_entry): realloc can
+       return NULL on success in the case 0 entries are allocated, From
+       Andrew Bartlet
+       
+2005-11-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kcm/headers.h: 1.7: Maybe include <sys/param.h>.
+       
+2005-10-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * configure.in: 1.378: Check for <sys/ucred.h>.
+       
+       * kcm/headers.h: 1.6: Maybe include <sys/param.h>.  1.5: include
+       <sys/ucred.h>
+       
+2005-10-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_encrypt.3: 1.16: Fix mdoc for
+       krb5_encrypt_EncryptedData, Johnny Lam <jlam@pkgsrc.org>
+       
+2005-10-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/rd_cred.c: 1.26: (krb5_rd_cred): try both the session
+       key and the sender subkey. Both RFC1510 and RFC4120 say that you
+       have to use the session key, Heimdal uses subkey.
+       
+2005-10-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kcm/connect.c: 1.16: * kcm/connect.c: fix arguments to kcm_log()
+       when reporting sendmsg() error * kcm/connect.c: don't send socket
+       address in msghdr, it returns an already connected error on Linux
+       
+2005-10-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: Rename private to opt_private.
+
+       * lib/krb5/init_creds.c: Rename private to opt_private.
+
+       * lib/krb5/krb5.h: 1.238: (krb5_get_init_creds_opt): rename
+       element private to opt_private to make c++ picky compilers less
+       upset.
+       
+2005-09-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * Release 0.7.1
+
+       * lib/krb5/kuserok.c: 1.14: (check_directory): use passed
+       directory name
+
+2005-08-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/crypto.c: 1.124: (wrapped_length): the underived
+       encrypted types checksum are all unkeyed (matches the code in
+       encrypt_internal() and encrypt_internal_special())
+
+2005-08-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/db3.c: 1.16: (DB_open): catch errors from the d->open
+       calls instead of letting them slip though to d->cursor. Bug
+       repport from Andrew Bartlett <abartlet@samba.org> 1.15: (DB_open):
+       in case of error, close database
+
+2005-08-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/mkey.c (hdb_seal_key_mkey): if mknvo isn't set, the
+       caller want the latest mkvno, go search for it.
+
+2005-07-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/524.c: 1.32: Always include <krb5-v4compat.h>.
+
+2005-07-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_cred.c: 1.108: (krb5_get_credentials_with_flags):
+       only call krb5_cc_retrieve_cred once, and plug memory leak.
+
+       * lib/krb5/rd_cred.c (krb5_rd_cred): don't leak memory
+
+2005-06-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Release 0.7
+
+       * kdc/kerberos5.c (make_etype_info2_entry): NUL terminate the
+       string
+
+       * lib/krb5/cache.c: 1.70: (_krb5_expand_default_cc_name): replace
+       strndup with inline copy
+
+       * kdc/kerberos5.c: 1.176: replace strndup with inline copy, free
+       data on failure
+
+2005-06-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: TESTS += test_mem libkrb5_la_SOURCES +=
+       kcm.h
+       
+       * kuser/kinit.c (main): catch KRB5_CONFIG_BADFORMAT from
+       krb5_init_context
+
+       * kdc/main.c (main): catch KRB5_CONFIG_BADFORMAT from
+       krb5_init_context
+
+       * lib/krb5/verify_krb5_conf.c (main): catch KRB5_CONFIG_BADFORMAT
+       from krb5_init_context From: Mathias Feiler
+       <feiler@uni-hohenheim.de>
+
+       * lib/krb5/verify_krb5_conf.c: Add more missig entires, from
+       Mathias Feiler <feiler@uni-hohenheim.de>
+
+2005-06-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c (pk_principal_from_X509): remember to free
+       KRB5PrincipalName
+
+       * lib/krb5/log.c (krb5_closelog): free all content in
+       krb5_log_facility
+
+2005-06-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/524.c: init kvno to please gcc
+
+       * kdc/kaserver.c (do_authenticate): check return value from
+       unparse_auth_args
+
+2005-06-07  Dave Love  <fx@gnu.org>
+
+       * doc/setup.texi: Spelling.
+       
+       * doc/programming.texi: Spelling.
+
+2005-06-02  Dave Love  <fx@gnu.org>
+
+       * kcm/connect.c (kcm_door_server): Make static.
+
+       * kcm/kcm_locl.h (disallow_getting_krbtgt): Declare.
+
+2005-06-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/mit_dump.c (mit_prop_dump): cast argument to
+       krb5_parse_principal to avoid warning
+
+       * kdc/mit_dump.c: rename KRB5_TL_MOD_PRINC to
+       mit_KRB5_TL_MOD_PRINC to hint its a constant originating from mit
+       codebase
+
+2005-06-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/store.c: If we are allocating 0 entires, avoid failing
+       if ALLOC returns NULL
+
+       * lib/krb5/verify_krb5_conf.c: Check for [kdc]v4-realm
+       
+       * lib/krb5/cache.c: When returning a new error code, set error
+       string.
+
+2005-05-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/keytab_file.c: Adapt to changed signature of
+       _krb5_xunlock, clear more error string where needed.
+
+       * lib/krb5/fcache.c (_krb5_xunlock): catch the error and turn it
+       into something sensable
+
+2005-05-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * kdc/kerberos5.c (tgs_make_reply): copy ok-as-delegate flag from
+       server entry to encrypted ticket flags
+
+2005-05-30  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/connect.c: rename sendlength to prependlength (which
+       hopefully better represents its purpose), and change type to
+       krb5_boolean
+
+       * kdc/connect.c: log signal causing exit
+       
+       * kdc/main.c (sigterm): set exit_flag to signal causing exit;
+       (main): trap SIGXCPU
+
+2005-05-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kcm/kcm.8: document --disallow-getting-krbtgt and --door-path
+
+       * kcm/protocol.c (kcm_op_retrieve): check server for krbtgt, not
+       client
+
+       * kcm/main.c: ignore SIGPIPE
+
+       * kcm/protocol.c: Add option to disallow getting krbtgt out from
+       from KCM. KCM will do the fetching part itself.
+       
+       * kcm/config.c: Add option to disallow getting krbtgt out from
+       from KCM. KCM will do the fetching part itself.
+
+2005-05-30  Luke Howard <lukeh@padl.com>
+
+       * kcm/events.c: if credentials have expired when attempting
+       to renew, attempt to reacquire them using initial creds
+
+2005-05-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_principal.3: Spelling, from Björn Sandell
+       
+       * doc/setup.texi: spelling, from Björn Sandell
+
+       * lib/krb5/name-45-test.c: XXX don't run the test unless the
+       machine is in kth.se or su.se because it depends on local resolver
+       configuration.
+
+       * lib/hdb/hdb.c: provde RTLD_NOW and RTLD_GLOBAL if they don't
+       exists
+
+       * kcm/connect.c: fix doors support, fix signedness warnings
+
+       * kcm/config.c: add --door-path=
+       
+       * configure.in: comment what the "detect doors on solaris"
+       fragment tries to do
+
+       * kcm/acquire.c (generate_random_pw): fix signed-ness warnings
+
+       * kcm/connect.c (update_client_creds): fix compile error in the
+       getpeerucred case
+
+       * lib/krb5/test_cc.c: change format for expantion variables in
+       default_cc_name to %{variable} to not confuse them with shell
+       ditto
+
+       * kcm/headers.h: Maybe include <door.h>.
+
+       * kcm/kcm_locl.h: add extern door_path;
+
+       * configure.in: detect doors using door_create
+       
+       * kcm/Makefile.am: add dependcy on kcm_protos.h add lib depency on
+       LIB_door_create
+
+       * lib/krb5/kcm.h: add _PATH_KCM_DOOR, default path to kcm door
+
+       * lib/krb5/kcm.c: use [libdefaults]kcm_door to find the door to
+       kcm
+
+       * lib/krb5/Makefile.am: libkrb5_la_LIBADD += LIB_door_create
+       
+       * lib/krb5/krb5_locl.h: Maybe include <sys/mman.h>, maybe include
+       <door.h>.
+
+       * lib/krb5/kcm.c (kcm_send_request): add support for doing a door
+       call to kcm
+
+       * lib/asn1: prefix Der_class with ASN1_C_ to avoid problems with
+       system headerfiles that pollute the name space
+
+       * kcm/kcm.8: change format for expantion variables in
+       default_cc_name to %{variable} to not confuse them with shell
+       ditto
+
+       * lib/krb5/krb5.conf.5: change format for expantion variables in
+       default_cc_name to %{variable} to not confuse them with shell
+       ditto
+
+       * lib/krb5/cache.c (_krb5_expand_default_cc_name): change format
+       for expantion variables to %{variable} to not confuse them with
+       shell ditto
+       
+       * kcm/connect.c: add LOCAL_PEERCRED and experimental doors support
+
+2005-05-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/kf/kfd.c: case uid_t to unsigned long in printf format
+
+2005-05-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_auth_context.3: remove trailing space
+
+2005-05-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kcm/connect.c (do_request): use sendmsg to send the reply
+       
+       * fix-export: add make_proto for kcm/kcm_protos.h
+       
+       * kcm/kcm_locl.h: remove prototypes and add <kcm_protos.h>
+
+       * kcm/Makefile.am (kcm_SOURCES): add headerfiles
+       (kcm_protos.h): generate prototypes
+
+       * kcm/protocol.c: fix error in last commit, use right function
+
+       * kcm/headers.h: include <ucred.h> if we have getpeerucred
+
+       * configure.in: check for functions getpeerucred and getpeereid
+
+       * kcm/connect.c (update_client_creds): add support for
+       getpeerucred and getpeereid
+
+       * lib/krb5/kcm.c (kcm_alloc): allow kcm socket to be configured by
+       [libdefaults]kcm_socket=/path
+
+2005-05-24  David Love  <fx@gnu.org>
+
+       * kcm/kcm.8: KRB5CCNAME needs an literal uid, not ${uid}, spelling
+
+2005-05-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kcm/protocol.c: Merge the description and function jumptables
+       into one structure.  Use the length of the array when checking if
+       opcode is value, not a constant.
+
+       * kcm/kcm_locl.h: struct kcm_op: jumptable structure
+
+       * kcm/main.c: move declaration of detach_from_console away from
+       here to kcm_locl.h, Don't test HAVE_DAEMON since roken supplies it.
+       
+       * kcm/kcm_locl.h: move declaration of detach_from_console here
+       
+       * kdc/config.c: Don't test HAVE_DAEMON since roken supplies it.
+       
+2005-05-23  Dave Love  <fx@gnu.org>
+
+       * kcm/config.c: Don't test HAVE_DAEMON since roken supplies it.
+
+       * kdc/main.c: Don't test HAVE_DAEMON since roken supplies it.
+
+2005-05-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_keytab.3: document WRFILE and JAVA14
+
+2005-05-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krbhst.c (srv_get_hosts): if srv_get_hosts failes,
+       return and ignore the error
+
+       * lib/krb5/krbhst.c (srv_find_realm): make sure `res' and `count'
+       have good values
+       
+       * lib/krb5/test_keytab.c: tests all keytab format
+       
+2005-05-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c (_krb5_pk_rd_pa_reply): non non asn1 decoding
+       errors, fail. Make sure we free memory on error.
+       (pk_verify_chain_standard): make sure we provide good errors.
+
+       * lib/krb5/verify_krb5_conf.c: add missing options, prompted by
+       James F. Hranicky mail to heimdal-discuss
+
+       * lib/krb5/verify_krb5_conf.c: add pkinit and password quailty
+       check options
+
+       * lib/krb5/pkinit.c (pk_verify_chain_standard): store better error
+       message in the context for certificate errors.
+       
+       * lib/krb5/keytab.c (krb5_kt_free_entry): zero out content of all
+       krb5_free_x_content like functions to make sure data doesnt get
+       reused, idea from Wynn Wilkes <wwilkes@vintela.com>
+
+       * configure.in: depend on automake 1.8, we don't test anything
+       older
+
+       * lib/krb5/init_creds_pw.c (process_pa_data_to_md): add comment
+       that the caller always free out_md; remove comment about memory,
+       it doesn't happen.
+       (init_cred_loop): free ctx->as_req.padata when its reset (From Wynn
+       Wilkes <wwilkes@vintela.com>), move a comment close the the code
+
+       * lib/krb5/keytab_krb4.c (fkt_remove_entry): need to call
+       krb5_kt_free_entry after each krb5_kt_next_entry.
+
+       * lib/krb5/keytab_file.c (fkt_remove_entry): need to call
+       krb5_kt_free_entry after each fkt_next_entry_int. From: Wynn
+       Wilkes <wwilkes@vintela.com>
+
+2005-05-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: TESTS += test_keytab
+
+       * lib/krb5/keytab_krb4.c (krb4_kt_remove_entry): plug memory leaks,
+       avoid crashing on empty keytab
+
+       * lib/krb5/krb5_keytab.3: document behavior of
+       krb5_kt_remove_entry
+
+       * lib/krb5/keytab_memory.c (mkt_remove_entry): check if there
+       isn't any entries in the keytab before removing any since that
+       leads to bad pointer arithmetic and crashing. From: Wynn Wilkes
+       <wwilkes@vintela.com>.  Make the function return KRB5_KT_NOTFOUND
+       if the entry wasn't in the keytab (just like the filebased
+       keytab).
+
+       * lib/krb5/test_keytab.c: test memory corruption in MEMORY keytab
+
+       * lib/krb5{addr_families,context,creds,free,keyblock,
+       mit_glue,rd_error}.c:zero out content of all krb5_free_x_content
+       like functions to make sure data doesnt get reused, idea from
+       Wynn Wilkes <wwilkes@vintela.com>
+
+       * lib/krb5/krb5_get_credentials.3: document KRB5_GC_EXPIRED_OK
+       
+       * lib/krb5/krb5.3: add krb5_cc_new_unique
+
+2005-05-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/fcache.c (fcc_get_first): check return value from
+       malloc, memset the structure, make sure cursor doesn't point to
+       freed memory on failure.  From: Wynn Wilkes <wwilkes@vintela.com>
+
+       * lib/krb5/krb5_auth_context.3: document
+       KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED
+
+       * lib/krb5/get_cred.c: Remove expired credentials, based on
+       patches and comments from Anders Magnusson <ragge@ltu.se> and Wynn
+       Wilkes <wwilkes@vintela.com>
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): honor
+       KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED and create unencrypted
+       (ENCTYPE_NULL) credentials. for use with old mit server and java based
+       ones as they can't handle encrypted KRB-CRED. Note that the option
+       needs to turned on because if the consumer sends the KRB-CRED in
+       clear bad things will happen.
+
+       * lib/krb5/context.c (krb5_init_context): register krb5_javakt_ops
+
+       * lib/krb5/krb5.h: KRB5_GC_EXPIRED_OK: expired credentials is ok
+       to return from krb5_get_credentials.
+       KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED: make forward credentials
+       be unencrypted, for compatibility with mit kerberos and java
+       kerberos. krb5_javakt_ops: export
+
+2005-05-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/keytab_file.c: Add new keytab file format JAVA14 that
+       doesn't the use extended kvnos, as hinted, this is needed for
+       Java's Kerberos implementation.
+
+2005-05-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: handle pkinit-9, pkinit-19, and pkinit-25
+       enckey, still no DH
+       
+       * kdc/pkinit.c: handle pkinit-9, pkinit-19, and pkinit-25 enckey,
+       still no DH
+
+       * kdc/kerberos5.c (as_rep): search for pkinit-9, pkinit-19, and
+       pkinit-25 pa-data, return empty pkinit pa-data in the
+       PREAUTH_REQUIRED krb-error
+
+       * doc/ack.texi: add pkinit people
+
+       * lib/krb5/krb5_storage.3: document krb5_storage_is_flags
+
+       * lib/krb5/{krb5_compare_creds.3,krb5_get_init_creds.3,
+       krb5_krbhst_init.3,krb5_storage.3}:
+       make more pretty, from Björn Sandell
+
+2005-05-09  Dave Love  <fx@gnu.org>
+
+       * doc/setup.texi: Fix and clarify password quality check examples.
+       
+2005-05-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/kuserok.c (krb5_kuserok): use POSIX_GETPWNAM_R instead
+       of HAVE_GETPWNAM_R From: Dave Love <d.love@dl.ac.uk>
+
+2005-05-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/addr_families.c (krb5_print_address): catch when the
+       unknown adress don't fit. From Björn Sandell <biorn@dce.chalmers.se>
+
+2005-05-05  Dave Love  <d.love@dl.ac.uk>
+
+       * configure.in: fix type right test, include <termios.h> for
+       sys/strtty.h, not sys/ptyvar.h
+       
+2005-05-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: spelling
+
+2005-05-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: expand on what "trailing component" means
+       
+2005-05-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/rd_cred.c: put address comparison in separate function
+       
+       * lib/krb5/krb5_kuserok.3: check the user's ~/.k5login.d directory
+       for access files, all of which is handled like the regular
+       ~/.k5login
+
+       * lib/krb5/kuserok.c: check the user's ~/.k5login.d directory for
+       access files, all of which is handled like the regular ~/.k5login
+       
+2005-05-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/ack.texi: Clearify what version of libdes we are using and
+       who's code in it we are using.
+       
+       * kcm/kcm.8: more text about usage
+       
+       * kcm/Makefile.am: man_MANS += kcm.8
+
+       * kcm/kcm.8: initial manpage
+
+       * configure.in: if we have a $srcdir/lib/asn1/pkcs12.asn1, define
+       PKINIT
+       
+2005-05-02  Dave Love  <fx@gnu.org>
+
+       * configure.in: sys/tty.h (for sys/ptyvar.h) might need termios.h.
+
+2005-05-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * tools/krb5-config.in: add com_err to required libs
+       
+       * lib/krb5/pkinit.c (krb5_ui_method_read_string): use the fill in
+       length
+
+       * lib/krb5/init_creds_pw.c: Now that we fixed the signed-ness of
+       nonce for windows, remove the code that removed the signed
+       bit. Instead add comment that they still need to be the same
+       (Kerberos protocol nonce and pk-init nonce) for Windows.
+       
+2005-05-02  David Love  <fx@gnu.org>
+
+       * lib/krb5/crypto.c: Don't declare des_salt &c as static with
+       incomplete type (invalid in c89, at least).
+       
+2005-05-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_locl.h: include <crypt.h>
+
+2005-05-02  David Love  <fx@gnu.org>
+
+       * kcm/connect.c (init_socket): rename variable sun to un to avoid
+       namespace collision.
+       (handle_stream): Cast arg of krb5_warnx.
+
+2005-04-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: if we are using PKINIT, strip of the
+       highest bit to make windows PK-INIT happy. Also make the nonces
+       the same, again for windows, they are using pk-init-9.
+       
+       XXX check if it isn't the that nonce is an unsigned variable so
+       its just a asn1 mismatch.
+
+       * kdc/pkinit.c: pass a NULL prompter data to _krb5_pk_load_openssl_id
+       
+       * kuser/kinit.c: krb5_get_init_creds_opt_set_pkinit
+       
+       * lib/krb5/pkinit.c: Pass prompter data to the prompter function,
+       implement a UI prompter function wrapping the kerberos prompter
+       function so that the the OpenSSL ENGINE can ask for a password
+       when loading the private key. From: Douglas E. Engert
+
+       * lib/krb5: add <err.h> in test programs
+       
+       * configure.in: sys/ptyvar.h might need <sys/tty.h>
+       
+       * lib/krb5/Makefile.am: use LIB_com_err for libkrb5.la
+
+2005-04-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/Makefile.am: use $(LIB_com_err)
+       
+2005-04-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/context.c (krb5_set_config_files): ignore permission
+       denied on configuration files, user might not be allowed to read
+       /var/heimdal/kdc.conf
+
+2005-04-26  Dave Love  <fx@gnu.org>
+
+       * lib/krb5/krb5_locl.h: define _POSIX_PTHREAD_SEMANTICS so we get
+       posix getpwnam_r
+
+2005-04-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/gen_glue.c: switch the units variable to a
+       function. gcc-4.1 needs the size of the structure if its defined
+       as extern struct units foo_units[] an we don't want to include
+       <parse_units.h> in the generate headerfile
+
+2005-04-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb.schema: add EQUALITY rule for krb5ValidStart,
+       krb5ValidEnd, krb5PasswordEnd From Howard Chu
+
+2005-04-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/whatis.texi: comment out docbook stuff for now
+       
+       * kuser/klist.c: use strlcpy
+       
+       * doc/ack.texi: we no longer use eay libdes, make acknowledgment
+       still be there, but claim that we no longer use it. Mark editline
+       to be a modified version as required by the license.
+       
+       * lib/krb5/pkinit.c: use the unexported oid_to_enctype function
+       
+       * lib/krb5/crypto.c: unexport the oid_to_enctype function, not for
+       external consumers
+
+       * kdc/Makefile.am: always add kaserver
+       
+       * lib/krb5/krb5_ccache.3: document krb5_cc_new_unique
+
+       * lib/krb5/cache.c (krb5_cc_new_unique): new function to create a
+       new credential cache
+
+       * kdc/headers.h: don't include kerberos 4 headers here
+
+       * kdc/hpropd.c: include kerberos 4 headers here
+
+       * kdc/connect.c: add kaserver support independ of having krb4
+       support
+       
+       * kdc/config.c: add kaserver support unconditionally, make kdc
+       only fail to start when there are no v4 realm configured and
+       krb4/kaserver is turned on
+
+       * kdc/kaserver.c: Use the new Kerberos 4 functions in libkrb5 and
+       so kaserver support is always compiled in (still default disabled)
+       
+       * lib/krb5/v4_glue.c: simplify error handling
+
+       * doc/whatis.texi: add docbook version macro of @sub
+       
+       * doc/heimdal.texi: change the wrapping around the Top node to
+       ifnottex, make html generation work
+
+       * lib/krb5/krb5_krbhst_init.3: spelling, from Björn Sandell
+       <biorn@dce.chalmers.se>
+
+       * lib/krb5/krb5_get_krbhst.3: spelling, from Björn Sandell
+       <biorn@dce.chalmers.se>
+
+       * lib/krb5/krb5_data.3: spelling, from Björn Sandell
+       <biorn@dce.chalmers.se>
+
+       * lib/krb5/krb5_aname_to_localname.3: spelling, from Björn Sandell
+       <biorn@dce.chalmers.se>
+
+       * lib/krb5/krb5_address.3: spelling, from Björn Sandell
+       <biorn@dce.chalmers.se>
+
+2005-04-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/config.c: Use the new Kerberos 4 functions in libkrb5 and so
+       kerberos 4 is always compiled in (still default disabled)
+
+       * kdc/kerberos4.c: Use the new Kerberos 4 functions in libkrb5 and
+       so kerberos 4 is always compiled in (still default disabled)
+
+       * lib/krb5/krb5_locl.h: forward declaration of _krb5_krb_auth_data
+       
+       * lib/krb5/convert_creds.c: Move the kerberos v4 replacement
+       functions to v4_glue.c
+
+       * lib/krb5/v4_glue.c: Implement enough of kerberos 4 protocol to
+       be a KDC, move the v4 bits over here
+       
+       * lib/krb5/krb5-v4compat.h: add more v4 defines
+       
+2005-04-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswdd.c: Support multi-realms databases, requires
+       that all the realms are configured on the KDC in krb5.conf with
+       [libdefaults]default_realm stanzas.
+
+2005-04-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c: spell succeeded correctly, From Sean Chittenden
+
+       * lib/krb5/addr_families.c: catch two more snprintf problems
+       
+2005-04-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/Makefile.am: this lib include com_err, add -com_err to
+       CHECK_SYMBOLS
+
+       * appl/test/http_client.c: cast ssize_t to unsigned long, fix
+       printf format
+
+2005-04-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/kuserok.c: use asprintf to avoid truncating pathnames
+       
+       * lib/krb5/get_host_realm.c: check return value of snprintf
+       
+       * lib/krb5/test_addr.c: check address truncation
+       
+       * lib/krb5/addr_families.c: check return values from snprintf and
+       clean up semantics of ret_len
+
+       * lib/krb5/krb5_address.3: clarify what ret_len is in
+       krb5_print_address
+
+       * lib/krb5/test_kuserok.c: add --version and --help
+       
+       * lib/krb5/kuserok.c: use getpwnamn_r if it exists
+
+       * lib/krb5/Makefile.am: noinst_PROGRAMS += test_kuserok
+
+       * lib/krb5/test_kuserok.c: test program for krb5_kuserok
+
+2005-04-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/acache.c (acc_resolve): if open_default_ccache failed
+       with ccErrCCacheNotFound try again with create_default_ccache,
+       this fixes the problem where the security server apperenly haven't
+       started yet on Mac OS X
+       
+       * lib/krb5/get_default_principal.c
+       (_krb5_get_default_principal_local): add, for use of functions
+       that in ccache layer to avoid recursive calls.
+       
+       * lib/hdb/hdb-ldap.c: drop <ctype.h>, no longer use any of the is*
+       macros in this file
+
+       * include/make_crypto.c: cast to unsigned char to make sure its
+       not negative when passing it to is* functions
+
+2005-04-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/programming.texi: remove manpage macro, add some more
+       references to manpages
+
+       * doc/heimdal.texi: define manpage macro
+       
+       * doc/setup.texi: document new password policy code
+       
+       * kpasswd/kpasswdd.c: add verifier libraries with
+       kadm5_add_passwd_quality_verifier
+
+       * lib/krb5/krb5_keyblock.3: document krb5_keyblock_init
+       
+2005-04-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kaserver.c: AUTHENTICATE and AUTHENTICATE_V2 is almost the
+       same, and clients
+       (klog) can deal with that the kaserver returns the same thing for
+       both
+
+       * lib/krb5/keyblock.c: Add krb5_keyblock_init to allocate an fill
+       in a keyblock from key data.
+       
+2005-04-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * configure.in: rk_WIN32_EXPORT for roken
+
+2005-04-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * appl/test/gssapi_server.c: print out client principla of
+       delegated credential
+
+2005-04-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c (process_pa_data_to_key): also check
+       for KRB5_PADATA_PK_AS_REP_19, From: Douglas Engert
+
+2005-04-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * .cvsignore: ignore more generate files
+       
+2005-04-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/check-der.c: use size_t, print size_t by casting to
+       unsigned long
+       
+       * lib/krb5/test_crypto.c: print size_t by casting to unsigned long
+       
+       * lib/krb5/acache.c: Argument to create_new_ccache is a principal,
+       not a credential cache name.  Clean up lossage related to this
+       problem.
+
+       * lib/hdb/Makefile.am: CHECK_SYMBOLS += HDBFlags2int
+       
+       * lib/krb5/addr_families.c
+       (krb5_address_prefixlen_boundary,krb5_free_address):
+       use find_atype when we are dealing with a kerberos address type
+
+       * lib/krb5/aes-test.c: size_t vs int + fix printf
+       
+       * lib/krb5/pkinit.c: Since the decode can't make out the diffrence
+       between PA-PK-AS-REP-19 and PA-PK-AS-REQ-Win2k, try harder to
+       verify both cases
+
+2005-04-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/test/uu_client.c: print size_t by casting to unsigned long
+       
+2005-04-01 Johan Danielsson <joda@pdc.kth.se>
+
+       * kdc/kerberos4.c (do_version4): check client and server max_life
+       
+       * kdc/kaserver.c (do_getticket): check client max_life
+       
+2005-03-31  Love  <lha@kth.se>
+
+       * lib/krb5/verify_krb5_conf.c: const poison
+
+       * lib/krb5/test_alname.c: const poison
+
+       * lib/asn1/main.c: const poison
+
+       * lib/krb5/test_addr.c: test parse IPv6 RANGE addresses
+
+       * lib/krb5/addr_families.c: implement mask boundary for IPv6
+
+       * lib/asn1/gen.c: avoid const string warnings steming from
+       writeable-string
+
+2005-03-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: TESTS += test_addr
+
+       * lib/krb5/test_addr.c: simple test for addresses
+       
+       * lib/krb5/addr_families.c: make RANGE parse prefixlen style
+       addresses too, fix printing of RANGE addresses, add
+       krb5_address_prefixlen_boundary
+
+       * lib/krb5/krb5_keytab.3: stop memory leak in example, expand on
+       wildcards
+
+2005-03-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_principal.3: spelling, from Tomas Olsson
+
+       * lib/krb5/krb5_warn.3: spelling, from Tomas Olsson
+
+2005-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/acache.c: add mutex for global variables, clean up
+       returned error codes, implement storing addresses into the ccapi
+
+       * appl/test/gssapi_server.c: free memory, make error strings match
+       
+       * appl/test/gssapi_server.c: use print_gss_name, print server name
+       too
+
+       * appl/test/gss_common.h (print_gss_name): common code for
+       printing gss name
+
+       * appl/test/gss_common.c (print_gss_name): common code for
+       printing gss name
+
+       * appl/test/http_client.c: Make constent with rest of the gssapi
+       test programs
+
+2005-03-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/keys.c: AES is enabled by default, remove ifdefs
+       
+       * lib/krb5/crypto.c: AES is enabled by default, remove ifdefs
+       
+       * lib/krb5/aes-test.c: use hex encoder from roken AES is enabled
+       by default, remove ifdefs
+
+       * kdc/kerberos5.c: AES is enabled by default, remove ifdefs
+
+2005-03-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: Add some text about modifying the database
+       
+2005-03-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: widen lifetime/renewal warning text field, also
+       make use of unparse_time_approx, no need to be specific to the
+       second when ticket needs to be renewed or their lifetime.
+
+       * doc/heimdal.texi: copyright maintenance, drop eay, use updated
+       UCB license
+
+       * lib/krb5/crypto.c: more static and unsigned issues
+
+       * lib/krb5/crypto.c: fix signedness issues, prompted by report of
+       Magnus Ahltorp
+
+2005-03-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_keytab.3: more text about how to free returned
+       resources
+
+2005-03-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: handle the -25 generation path
+
+       * lib/krb5/pkinit.c: use KRB5_PADATA_PK_AS_REQ_19
+       
+       * lib/krb5/pkinit.c: fold in pk-init-25 asn1 changes
+       
+2005-03-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: use generated oid's
+       
+       * lib/krb5/pkinit.c: use generated oid's
+       
+2005-03-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: update to the asn1 structures used in -25's
+
+       * lib/krb5/pkinit.c: update to the asn1 structures used in -25's
+
+2005-03-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/hdb/hdb-ldap.c: use the newly written hex function from
+       roken and remove the old implementation
+
+2005-03-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/test/http_client.c: allow specifing port to connect to
+
+2005-02-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: bump version to 21:0:4
+
+       * lib/hdb/Makefile.am: bump version to 8:0:1
+       
+       * lib/asn1/Makefile.am: bump version to 7:0:1
+
+2005-02-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/crypto.c (DES_string_to_key_int): must check for weak
+       keys after doing the DES_cbc_cksum
+
+2005-02-19  Luke Howard  <lukeh@padl.com>
+
+       * lib/krb5/krbhst.c: set KD_CONFIG after calling
+         config_get_hosts() in kpasswd_get_next()
+         From: Wynn Wilkes <wynnw@vintela.com>
+
+2005-02-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/db3.c (DB_open): correct the check for O_RDONLY
+       From: Chaskiel M Grundman <cg2v@andrew.cmu.edu>
+
+2005-02-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/crypto.c (krb5_random_to_key): cast size_t to int to
+       make %d work
+
+2005-02-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/keytab.c (krb5_kt_get_entry): tell what enctype the
+       caller requested to provide the user with a glue what the caller
+       was asking for.
+
+2005-02-05  Luke Howard  <lukeh@padl.com>
+
+       * lib/krb5/kcm.c: add _krb5_kcm_is_running, _krb5_kcm_noop
+
+       * kcm/acquire.c: don't leak salt if keyproc called multiple
+         times
+
+       * kcm/config.c: allow KCM system ccache to be configured from
+         krb5.conf, in the system_ccache stanza of [kcm]
+
+2005-02-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kcm/protocol.c: use -1 as the invalid pid number
+
+       * kcm/connect.c: support SCM_CREDS (for NetBSD)
+
+       * kcm/Makefile.am: LDADD += LIB_pidfile
+       
+       * kcm/connect.c: make it possible to build on systems without
+       SO_PEERCRED (still doesn't work)
+
+       * kcm/config.c: cast argument to isdigit to unsigned char
+       
+       * lib/krb5/krb5.conf.5: document large_msg_size
+
+       * lib/krb5/context.c (init_context_from_config_file): init
+       large_msg_size to 6000
+
+       * lib/krb5/krb5.h (krb5_context_data): add large_msg_size,
+       threshold where we start to use transport protocols without tiny
+       max data transport sizes.
+
+       * lib/krb5/kcm.h: drop prototypes, they all live in krb5-private.h
+       by now
+
+2005-02-02  Luke Howard  <lukeh@padl.com>
+
+       * configure.in: generate kcm/Makefile
+
+       * Makefile.am: recurse into kcm/ if KCM defined
+
+       * kcm: add KCM daemon
+
+2005-02-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/send_to_kdc.c (send_and_recv_udp): make private again
+
+       * lib/krb5/kcm.c: use AF_UNIX like the rest of the codebase, add
+       some more error strings
+
+2005-02-02  Luke Howard  <lukeh@padl.com>
+
+       * configure.in: add --enable-kcm option for Kerberos
+         Credentials Manager (KCM)
+
+       * lib/krb5/Makefile.am: add kcm.c
+
+       * lib/krb5/cache.c: use cc_retrieve_cred if present rather
+         than enumerating ccache
+
+       * lib/krb5/context.c: register KCM cc_ops
+
+       * lib/krb5/get_cred.c: pass all options to cc_retrieve_cred
+
+       * lib/krb5/init_creds_pw.c: add krb5_get_init_creds_keyblock
+
+       * lib/krb5/kcm.[ch]: add initial implementation of KCM
+         client library
+
+       * lib/krb5/krb5.h: fix cc_retrieve prototype, add KCM cc_ops
+
+       * lib/krb5/send_to_kdc.c: add _krb5_send_and_recv_tcp
+
+       * lib/krb5/store.c: add krb5_store_creds_tag, krb5_ret_creds_tag
+
+2005-01-24  Luke Howard  <lukeh@padl.com>
+
+       * lib/krb5/init_creds_pw.c: allow NULL in_options to be passed
+         krb5_get_init_creds_password()
+
+       * kdc/kerberos5.c: don't crash when logging no server etype
+         support if client == NULL
+
+2005-01-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kstash.c: s/random_key/random_key_flag/, From Dave Love
+       <d.love@dl.ac.uk>
+
+2005-01-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/apps.texi: Texinfo fixes. Text about irix 6.5 using
+       PAM. From: Dave Love <d.love@dl.ac.uk>
+
+2005-01-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c: cast argument to isdigit to
+       unsigned char
+
+       * lib/krb5/keytab_keyfile.c: cast argument to toupper to unsigned
+       char
+
+       * lib/asn1/hash.c (hashcaseadd): cast argument to toupper to
+       unsigned char
+
+       * appl/kf/kfd.c (kfd_match_version): cast argument to islower to
+       unsigned char
+
+       * lib/krb5/krb5.3: drop krb5_{checksum,enctype}_is_disabled
+
+       * lib/krb5/krb5_encrypt.3: drop krb5_enctype_is_disabled, more
+       text about krb5_enctype_valid
+
+       * lib/krb5/krb5_create_checksum.3: drop
+       krb5_checksum_is_disabled
+
+       * lib/krb5/crypto.c: drop krb5_{checksum,enctype}_isdisabled
+       
+       * lib/krb5/context.c: krb5_enctype_is_disabled is the same thing
+       as krb5_enctype_valid, so use the later since its older and the
+       api doesn't really need another entry point
+
+       * lib/krb5/rd_req.c: krb5_enctype_is_disabled is the same thing as
+       krb5_enctype_valid, so use the later since its older and the api
+       doesn't really need another entry point
+
+       * kdc/kerberos5.c: krb5_enctype_is_disabled is the same thing as
+       krb5_enctype_valid, so use the later since its older and the api
+       doesn't really need another entry point
+
+2005-01-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswdd.8: document --addresses, controls what
+       addresses kpasswd should listen too
+
+       * kpasswd/kpasswdd.c: add --addresses, controls what addresses
+       kpasswd should listen too
+
+       * lib/krb5/addr_families.c (krb5_parse_address): filter out dup
+       addresses from getaddrinfo
+
+       * kpasswd/kpasswd.1: document -c
+
+       * kpasswd/kpasswd.c: allow specifying a credential cache to use
+       for the admin principal
+
+       * include/bits.c: constify to avoid warning with -Wwrite-string
+       
+       * NEWS: add 0.6.2 and 0.6.3 items
+       
+       * lib/krb5/krb5_keyblock.3: document krb5_generate_subkey_extended
+
+       * lib/krb5/krb5_is_thread_safe.3: document function
+
+       * lib/krb5/Makefile.am (man_MANS) += krb5_is_thread_safe.3
+       
+       * lib/krb5/context.c (krb5_is_thread_safe): return TRUE is the
+       library was compiled with multithreading support. If not,
+       application must global lock the library, it it uses threads that
+       call kerberos functions at the same time.
+       
+2005-01-05  Luke Howard  <lukeh@padl.com>
+
+       * lib/krb5/auth_context.c: use krb5_generate_subkey_extended()
+
+       * lib/krb5/appdefault.c: remove redundant KRB5_LIB_FUNCTION
+
+       * lib/krb5/build_auth.c: support for enctype negotiation
+         (client sends EtypeList in Authenticator authz data)
+
+       * lib/krb5/context.c: mutex should be destroyed last in
+         krb5_free_context()
+
+       * lib/krb5/generate_subkey.c: add krb5_generate_subkey_extended(),
+         set *subkey to NULL if key geneartion fails
+
+       * lib/krb5/krb5.h: add KRB5_KU_PA_SERVER_REFERRAL_DATA
+
+       * lib/krb5/mk_req_ext.c: support ETYPE_ARCFOUR_HMAC_MD5_56
+
+       * lib/krb5/rd_req.c: support for enctype negotiation
+         (client sends EtypeList in Authenticator authz data)
+
+2005-01-04  Luke Howard  <lukeh@padl.com>
+
+       * lib/asn1/k5.asn1: add authorization data types for enctype
+       negotiation implementation
+
+2005-01-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/changepw.c (change_password_loop): on failing to find a
+       kdc, set result_code to KRB5_KPASSWD_HARDERROR
+       
+2005-01-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/heimdal.texi: Happy New Year
+       
diff --git a/src/kerberosV/src/ChangeLog.1998 b/src/kerberosV/src/ChangeLog.1998
new file mode 100644 (file)
index 0000000..f26dba7
--- /dev/null
@@ -0,0 +1,3201 @@
+Sat Dec  5 19:49:34 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/context.c: remove ktype_is_etype
+
+       * lib/krb5/crypto.c, lib/krb5/krb5.h, acconfig.h: NEW_DES3_CODE
+
+       * configure.in: fix for AIX install; better tests for AIX dynamic
+       AFS libs; `--enable-new-des3-code'
+
+Tue Dec  1 14:44:44 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * appl/afsutil/Makefile.am: link with extra libs for aix
+
+       * kuser/Makefile.am: link with extra libs for aix
+
+Sun Nov 29 01:56:21 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_addrs.c (krb5_get_all_server_addrs): add.  almost
+       the same as krb5_get_all_client_addrs except that it includes
+       loopback addresses
+
+       * kdc/connect.c (init_socket): bind to a particular address
+       (init_sockets): get all local addresses and bind to them all
+
+       * lib/krb5/addr_families.c (addr2sockaddr, print_addr): new
+       methods
+       (find_af, find_atype): new functions.  use them.
+
+       * configure.in: add hesiod
+
+Wed Nov 25 11:37:48 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/krb5_err.et: add some codes from kerberos-revisions-03
+
+Mon Nov 23 12:53:48 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/log.c: rename delete -> remove
+
+       * lib/kadm5/delete_s.c: rename delete -> remove
+
+       * lib/hdb/common.c: rename delete -> remove
+
+Sun Nov 22 12:26:26 1998  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: check for environ and `struct spwd'
+
+Sun Nov 22 11:42:45 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/kerberos5.c (as_rep): set keytype to sess_ktype if
+       ktype_is_etype
+
+       * lib/krb5/encrypt.c (krb5_keytype_to_etypes): zero terminate
+       etypes
+       (em): sort entries
+
+Sun Nov 22 06:54:48 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/init_creds_pw.c: more type correctness
+
+       * lib/krb5/get_cred.c: re-structure code.  remove limits on ASN1
+       generated bits.
+
+Sun Nov 22 01:49:50 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * kdc/hprop.c (v4_prop): fix bogus indexing
+
+Sat Nov 21 21:39:20 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/verify_init.c (fail_verify_is_ok): new function
+       (krb5_verify_init_creds): if we cannot get a ticket for
+       host/`hostname` and fail_verify_is_ok just return.  use
+       krb5_rd_req
+
+Sat Nov 21 23:12:27 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/free.c (krb5_xfree): new function
+
+       * lib/krb5/creds.c (krb5_free_creds_contents): new function
+
+       * lib/krb5/context.c: more type correctness
+
+       * lib/krb5/checksum.c: more type correctness
+
+       * lib/krb5/auth_context.c (krb5_auth_con_init): more type
+       correctness
+
+       * lib/asn1/der_get.c (der_get_length): fix test of len
+       (der_get_tag): more type correctness
+
+       * kuser/klist.c (usage): void-ize
+
+       * admin/ktutil.c (kt_remove): some more type correctness.
+
+Sat Nov 21 16:49:20 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * kuser/klist.c: try to list enctypes as keytypes
+
+       * kuser/kinit.c: remove extra `--cache' option, add `--enctypes'
+       to set list of enctypes to use
+
+       * kadmin/load.c: load strings as hex
+
+       * kadmin/dump.c: dump hex as string is possible
+
+       * admin/ktutil.c: use print_version()
+
+       * configure.in, acconfig.h: test for hesiod
+
+Sun Nov 15 17:28:19 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/crypto.c: add some crypto debug code
+
+       * lib/krb5/get_in_tkt.c (_krb5_extract_ticket): don't use fixed
+       buffer when encoding ticket
+
+       * lib/krb5/auth_context.c (re-)implement `krb5_auth_setenctype'
+
+       * kdc/kerberos5.c: allow mis-match of tgt session key, and service
+       session key
+
+       * admin/ktutil.c: keytype -> enctype
+
+Fri Nov 13 05:35:48 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.h (KRB5_TGS_NAME, KRB5_TGS_NAME_SIZE): added
+       
+Sat Nov  7 19:56:31 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_cred.c (add_cred): add termination NULL pointer
+
+Mon Nov  2 01:15:06 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_req.c: adapt to new crypto api
+
+       * lib/krb5/rd_rep.c: adapt to new crypto api
+
+       * lib/krb5/rd_priv.c: adopt to new crypto api
+
+       * lib/krb5/rd_cred.c: adopt to new crypto api
+
+       * lib/krb5/principal.c: ENOMEM -> ERANGE
+
+       * lib/krb5/mk_safe.c: cleanup and adopt to new crypto api
+
+       * lib/krb5/mk_req_ext.c: adopt to new crypto api
+
+       * lib/krb5/mk_req.c: get enctype from auth_context keyblock
+
+       * lib/krb5/mk_rep.c: cleanup and adopt to new crypto api
+
+       * lib/krb5/mk_priv.c: adopt to new crypto api
+
+       * lib/krb5/keytab.c: adopt to new crypto api
+
+       * lib/krb5/get_in_tkt_with_skey.c: adopt to new crypto api
+
+       * lib/krb5/get_in_tkt_with_keytab.c: adopt to new crypto api
+
+       * lib/krb5/get_in_tkt_pw.c: adopt to new crypto api
+
+       * lib/krb5/get_in_tkt.c: adopt to new crypto api
+
+       * lib/krb5/get_cred.c: adopt to new crypto api
+
+       * lib/krb5/generate_subkey.c: use new crypto api
+
+       * lib/krb5/context.c: rename etype functions to enctype ditto
+
+       * lib/krb5/build_auth.c: use new crypto api
+
+       * lib/krb5/auth_context.c: remove enctype and cksumtype from
+       auth_context
+
+Mon Nov  2 01:15:06 1998  Assar Westerlund  <assar@sics.se>
+
+       * kdc/connect.c (handle_udp, handle_tcp): correct type of `n'
+
+Tue Sep 15 18:41:38 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * admin/ktutil.c: fix printing of unrecognized keytypes
+
+Tue Sep 15 17:02:33 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/kadm5/set_keys.c: add KEYTYPE_USE_AFS3_SALT to keytype if
+       using AFS3 salt
+
+Tue Aug 25 23:30:52 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc): care about
+       `use_admin_kdc'
+
+       * lib/krb5/changepw.c (get_kdc_address): use
+       krb5_get_krb_admin_hst
+
+       * lib/krb5/krbhst.c (krb5_get_krb_admin_hst): new function
+
+       * lib/krb5/krb5.h (krb5_context_data): add `use_admin_kdc'
+
+       * lib/krb5/context.c (krb5_get_use_admin_kdc,
+       krb5_set_use_admin_kdc): new functions
+
+Tue Aug 18 22:24:12 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/crypto.c: remove all calls to abort(); check return
+       value from _key_schedule;
+       (RSA_MD[45]_DES_verify): zero tmp and res;
+       (RSA_MD5_DES3_{verify,checksum}): implement
+
+Mon Aug 17 20:18:46 1998  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos4.c (swap32): conditionalize
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_internal): new function
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm): if the hostname
+       returned from gethostby*() isn't a FQDN, try with the original
+       hostname
+
+       * lib/krb5/get_cred.c (make_pa_tgs_req): use krb5_mk_req_internal
+       and correct key usage
+
+       * lib/krb5/crypto.c (verify_checksum): make static
+
+       * admin/ktutil.c (kt_list): use krb5_enctype_to_string
+
+Sun Aug 16 20:57:56 1998  Assar Westerlund  <assar@sics.se>
+
+       * kadmin/cpw.c (do_cpw_entry): use asprintf for the prompt
+
+       * kadmin/ank.c (ank): print principal name in prompt
+
+       * lib/krb5/crypto.c (hmac): always allocate space for checksum.
+       never trust c.checksum.length
+       (_get_derived_key): try to return the derived key
+
+Sun Aug 16 19:48:42 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/crypto.c (hmac): fix some peculiarities and bugs
+       (get_checksum_key): assume usage is `formatted'
+       (create_checksum,verify_checksum): moved the guts of the krb5_*
+       functions here, both take `formatted' key-usages
+       (encrypt_internal_derived): fix various bogosities
+       (derive_key): drop key_type parameter (already given by the
+       encryption_type)
+
+       * kdc/kerberos5.c (check_flags): handle case where client is NULL
+
+       * kdc/connect.c (process_request): return zero after processing
+       kerberos 4 request
+
+Sun Aug 16 18:38:15 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/crypto.c: merge x-*.[ch] into one file
+
+       * lib/krb5/cache.c: remove residual from krb5_ccache_data
+
+Fri Aug 14 16:28:23 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/x-crypto.c (derive_key): move DES3 specific code to
+       separate function (will eventually end up someplace else)
+
+       * lib/krb5/x-crypto.c (krb5_string_to_key_derived): allocate key
+
+       * configure.in, acconfig.h: test for four valued krb_put_int
+
+Thu Aug 13 23:46:29 1998  Assar Westerlund  <assar@emma.pdc.kth.se>
+
+       * Release 0.0t
+
+Thu Aug 13 22:40:17 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/config_file.c (parse_binding): remove trailing
+       whitespace
+
+Wed Aug 12 20:15:11 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/x-checksum.c (krb5_verify_checksum): pass checksum type
+       to krb5_create_checksum
+
+       * lib/krb5/x-key.c: implement DES3_string_to_key_derived; fix a
+       few typos
+
+Wed Aug  5 12:39:54 1998  Assar Westerlund  <assar@emma.pdc.kth.se>
+
+       * Release 0.0s
+
+Thu Jul 30 23:12:17 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_error.c (krb5_mk_error): realloc until you die
+
+Thu Jul 23 19:49:03 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kdc_locl.h: proto for `get_des_key'
+
+       * configure.in: test for four valued el_init
+
+       * kuser/klist.c: keytype -> enctype
+
+       * kpasswd/kpasswdd.c (change): use new `krb5_string_to_key*'
+
+       * kdc/hprop.c (v4_prop, ka_convert): convert to a set of keys
+
+       * kdc/kaserver.c: use `get_des_key'
+
+       * kdc/524.c: use new crypto api
+
+       * kdc/kerberos4.c: use new crypto api
+
+       * kdc/kerberos5.c: always treat keytypes as enctypes; use new
+       crypto api
+
+       * kdc/kstash.c: adapt to new crypto api
+
+       * kdc/string2key.c: adapt to new crypto api
+
+       * admin/srvconvert.c: add keys for all possible enctypes
+
+       * admin/ktutil.c: keytype -> enctype
+
+       * lib/gssapi/init_sec_context.c: get enctype from auth_context
+       keyblock
+
+       * lib/hdb/hdb.c: remove hdb_*_keytype2key
+
+       * lib/kadm5/set_keys.c: adapt to new crypto api
+
+       * lib/kadm5/rename_s.c: adapt to new crypto api
+
+       * lib/kadm5/get_s.c: adapt to new crypto api
+
+       * lib/kadm5/create_s.c: add keys for des-cbc-crc, des-cbc-md4,
+       des-cbc-md5, and des3-cbc-sha1
+
+       * lib/krb5/heim_err.et: error message for unsupported salt
+
+       * lib/krb5/codec.c: short-circuit these functions, since they are
+       not needed any more
+
+       * lib/krb5/rd_safe.c: cleanup and adapt to new crypto api
+
+Mon Jul 13 23:00:59 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc): don't advance
+       hostent->h_addr_list, use a copy instead
+
+Mon Jul 13 15:00:31 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/config_file.c (parse_binding, parse_section): make sure
+       everything is ok before adding to linked list
+
+       * lib/krb5/config_file.c: skip ws before checking for comment
+
+Wed Jul  8 10:45:45 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/asn1/k5.asn1: hmac-sha1-des3 = 12
+
+Tue Jun 30 18:08:05 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc): do not close the
+       unopened file
+
+       * lib/krb5/mk_priv.c: realloc correctly
+
+       * lib/krb5/get_addrs.c (find_all_addresses): init j
+
+       * lib/krb5/context.c (krb5_init_context): print error if parsing
+       of config file produced an error.
+
+       * lib/krb5/config_file.c (parse_list, krb5_config_parse_file):
+       ignore more spaces
+
+       * lib/krb5/codec.c (krb5_encode_EncKrbCredPart,
+       krb5_encode_ETYPE_INFO): initialize `ret'
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): realloc
+       correctly
+
+       * lib/kadm5/set_keys.c (_kadm5_set_keys): initialize `ret'
+
+       * lib/kadm5/init_c.c (get_cred_cache): try to do the right thing
+       with default_client
+
+       * kuser/kinit.c (main): initialize `ticket_life'
+
+       * kdc/kerberos5.c (get_pa_etype_info): initialize `ret'
+       (tgs_rep2): initialize `krbtgt'
+
+       * kdc/connect.c (do_request): check for errors from `sendto'
+
+       * kdc/524.c (do_524): initialize `ret'
+
+       * kadmin/util.c (foreach_principal): don't clobber `ret'
+
+       * kadmin/del.c (del_entry): don't apply on zeroth argument
+
+       * kadmin/cpw.c (do_cpw_entry): initialize `ret'
+
+Sat Jun 13 04:14:01 1998  Assar Westerlund  <assar@juguete.sics.se>
+
+       * Release 0.0r
+
+Sun Jun  7 04:13:14 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c: fall-back definition of
+       IN6_ADDR_V6_TO_V4
+
+       * configure.in: only set CFLAGS if it wasn't set look for
+       dn_expand and res_search
+
+Mon Jun  1 21:28:07 1998  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: remove duplicate seteuid
+
+Sat May 30 00:19:51 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/convert_creds.c: import _krb_time_to_life, to avoid
+       runtime dependencies on libkrb with some shared library
+       implementations
+
+Fri May 29 00:09:02 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kuser/kinit_options.c: Default options for kinit.
+
+       * kuser/kauth_options.c: Default options for kauth.
+
+       * kuser/kinit.c: Implement lots a new options.
+
+       * kdc/kerberos5.c (check_tgs_flags): make sure kdc-req-body->rtime
+       is not NULL; set endtime to min of new starttime + old_life, and
+       requested endtime
+
+       * lib/krb5/init_creds_pw.c (get_init_creds_common): if the
+       forwardable or proxiable flags are set in options, set the
+       kdc-flags to the value specified, and not always to one
+
+Thu May 28 21:28:06 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c: Optionally compare client address to addresses
+       in ticket.
+
+       * kdc/connect.c: Pass client address to as_rep() and tgs_rep().
+
+       * kdc/config.c: Add check_ticket_addresses, and
+       allow_null_ticket_addresses variables.
+
+Tue May 26 14:03:42 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/kadm5/create_s.c: possibly make DES keys version 4 salted
+
+       * lib/kadm5/set_keys.c: check config file for kadmin/use_v4_salt
+       before zapping version 4 salts
+
+Sun May 24 05:22:17 1998  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0q
+
+       * lib/krb5/aname_to_localname.c: new file
+
+       * lib/gssapi/init_sec_context.c (repl_mutual): no output token
+
+       * lib/gssapi/display_name.c (gss_display_name): zero terminate
+       output.
+
+Sat May 23 19:11:07 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/gssapi/display_status.c: new file
+
+       * Makefile.am: send -I to aclocal
+
+       * configure.in: remove duplicate setenv
+
+Sat May 23 04:55:19 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kadmin/util.c (foreach_principal): Check for expression before
+       wading through the whole database.
+
+       * kadmin/kadmin.c: Pass NULL password to
+       kadm5_*_init_with_password.
+
+       * lib/kadm5/init_c.c: Implement init_with_{skey,creds}*. Make use
+       of `password' parameter to init_with_password.
+
+       * lib/kadm5/init_s.c: implement init_with_{skey,creds}*
+
+       * lib/kadm5/server.c: Better arguments for
+       kadm5_init_with_password.
+
+Sat May 16 07:10:36 1998  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hprop.c: conditionalize ka-server reading support on
+       KASERVER_DB
+
+       * configure.in: new option `--enable-kaserver-db'
+
+Fri May 15 19:39:18 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/get_cred.c: Better error if local tgt couldn't be
+       found.
+
+Tue May 12 21:11:02 1998  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0p
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_extended): only set
+       encryption type in auth_context if it's compatible with the type
+       of the session key
+
+Mon May 11 21:11:14 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/hprop.c: add support for ka-server databases
+
+       * appl/ftp/ftpd: link with -lcrypt, if needed
+
+Fri May  1 07:29:52 1998  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: don't test for winsock.h
+
+Sat Apr 18 21:43:11 1998  Johan Danielsson  <joda@puffer.pdc.kth.se>
+
+       * Release 0.0o
+
+Sat Apr 18 00:31:11 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/sock_principal.c: Save hostname.
+
+Sun Apr  5 11:29:45 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/mk_req_ext.c: Use same enctype as in ticket.
+
+       * kdc/hprop.c (v4_prop): Check for null key.
+
+Fri Apr  3 03:54:54 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/str2key.c: Fix DES3 string-to-key.
+
+       * lib/krb5/keytab.c: Get default keytab name from context.
+
+       * lib/krb5/context.c: Get `default_keytab_name' value.
+
+       * kadmin/util.c (foreach_principal): Print error message if
+       `kadm5_get_principals' fails.
+
+       * kadmin/kadmind.c: Use `kadmind_loop'.
+
+       * lib/kadm5/server.c: Replace several other functions with
+       `kadmind_loop'.
+
+Sat Mar 28 09:49:18 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/keytab.c (fkt_add_entry): use an explicit seek instead
+       of O_APPEND
+
+       * configure.in: generate ftp Makefiles
+
+       * kuser/klist.c (print_cred_verbose): print IPv4-address in a
+       portable way.
+
+       * admin/srvconvert.c (srvconv): return 0 if successful
+
+Tue Mar 24 00:40:33 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/keytab.c: MIT compatible changes: add and use sizes to
+       keytab entries, and change default keytab to `/etc/krb5.keytab'.
+
+Mon Mar 23 23:43:59 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/gssapi/wrap.c: Use `gss_krb5_getsomekey'.
+
+       * lib/gssapi/unwrap.c: Implement and use `gss_krb5_getsomekey'.
+       Fix bug in checking of pad.
+
+       * lib/gssapi/{un,}wrap.c: Add support for just integrity
+       protecting data.
+       
+       * lib/gssapi/accept_sec_context.c: Use
+       `gssapi_krb5_verify_8003_checksum'.
+
+       * lib/gssapi/8003.c: Implement `gssapi_krb5_verify_8003_checksum'.
+
+       * lib/gssapi/init_sec_context.c: Zero cred, and store session key
+       properly in auth-context.
+
+Sun Mar 22 00:47:22 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/kadm5/delete_s.c: Check immutable bit.
+
+       * kadmin/kadmin.c: Pass client name to kadm5_init.
+
+       * lib/kadm5/init_c.c: Get creds for client name passed in.
+
+       * kdc/hprop.c (v4_prop): Check for `changepw.kerberos'.
+
+Sat Mar 21 22:57:13 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/mk_error.c: Verify that error_code is in the range
+       [0,127].
+
+       * kdc/kerberos5.c: Move checking of principal flags to new
+       function `check_flags'.
+
+Sat Mar 21 14:38:51 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/get_s.c (kadm5_s_get_principal): handle an empty salt
+
+       * configure.in: define SunOS if running solaris
+
+Sat Mar 21 00:26:34 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/kadm5/server.c: Unifdef test for same principal when
+       changing password.
+
+       * kadmin/util.c: If kadm5_get_principals failes, we might still be
+       able to perform the requested opreration (for instance someone if
+       trying to change his own password).
+
+       * lib/kadm5/init_c.c: Try to get ticket via initial request, if
+       not possible via tgt.
+
+       * lib/kadm5/server.c: Check for principals changing their own
+       passwords.
+
+       * kdc/kerberos5.c (tgs_rep2): check for interesting flags on
+       involved principals.
+
+       * kadmin/util.c: Fix order of flags.
+
+Thu Mar 19 16:54:10 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos4.c: Return sane error code if krb_rd_req fails.
+
+Wed Mar 18 17:11:47 1998  Assar Westerlund  <assar@sics.se>
+
+       * acconfig.h: rename HAVE_STRUCT_SOCKADDR_IN6 to HAVE_IPV6
+
+Wed Mar 18 09:58:18 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_in_tkt_with_keytab.c (krb5_keytab_key_proc): don't
+       free keyseed; use correct keytab
+
+Tue Mar 10 09:56:16 1998  Assar Westerlund  <assar@sics.se>
+
+       * acinclude.m4 (AC_KRB_IPV6): rewrote to avoid false positives
+
+Mon Mar 16 23:58:23 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Release 0.0n
+
+Fri Mar  6 00:41:30 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/gssapi/{accept_sec_context,release_cred}.c: Use
+       krb5_kt_close/krb5_kt_resolve.
+       
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): Use resolver
+       to lookup hosts, so CNAMEs can be ignored.
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc, send_and_recv_http):
+       Add support for using proxy.
+
+       * lib/krb5/context.c: Initialize `http_proxy' from
+       `libdefaults/http_proxy'.
+
+       * lib/krb5/krb5.h: Add `http_proxy' to context.
+
+       * lib/krb5/send_to_kdc.c: Recognize `http/' and `udp/' as protocol
+       specifications.
+
+Wed Mar  4 01:47:29 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * admin/ktutil.c: Implement `add' and `remove' functions. Make
+       `--keytab' a global option.
+
+       * lib/krb5/keytab.c: Implement remove with files. Add memory
+       operations.
+
+Tue Mar  3 20:09:59 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/keytab.c: Use function pointers.
+
+       * admin: Remove kdb_edit.
+
+Sun Mar  1 03:28:42 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/dump_log.c: print operation names
+
+Sun Mar  1 03:04:12 1998  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: add X-tests, and {bin,...}dir appl/{kx,kauth}
+       
+       * lib/krb5/build_auth.c,mk_priv.c,rd_safe.c,mk_safe.c,mk_rep.c:
+       remove arbitrary limit
+
+       * kdc/hprop-common.c: use krb5_{read,write}_message
+
+       * lib/kadm5/ipropd_master.c (send_diffs): more careful use
+       krb5_{write,read}_message
+
+       * lib/kadm5/ipropd_slave.c (get_creds): get credentials for
+       `iprop/master' directly.
+       (main): use `krb5_read_message'
+
+Sun Mar  1 02:05:11 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kadmin/kadmin.c: Cleanup commands list, and add help strings.
+
+       * kadmin/get.c: Add long, short, and terse (equivalent to `list')
+       output formats. Short is the default.
+
+       * kadmin/util.c: Add `include_time' flag to timeval2str.
+
+       * kadmin/init.c: Max-life and max-renew can, infact, be zero.
+
+       * kadmin/{cpw,del,ext,get}.c: Use `foreach_principal'.
+
+       * kadmin/util.c: Add function `foreach_principal', that loops over
+       all principals matching an expression.
+
+       * kadmin/kadmin.c: Add usage string to `privileges'.
+
+       * lib/kadm5/get_princs_s.c: Also try to match aganist the
+       expression appended with `@default-realm'.
+
+       * lib/krb5/principal.c: Add `krb5_unparse_name_fixed_short', that
+       excludes the realm if it's the same as the default realm.
+
+Fri Feb 27 05:02:21 1998  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: more WFLAGS and WFLAGS_NOUNUSED added missing
+       headers and functions error -> com_err
+
+       (krb5_get_init_creds_keytab): use krb5_keytab_key_proc
+
+       * lib/krb5/get_in_tkt_with_keytab.c: make `krb5_keytab_key_proc'
+       global
+
+       * lib/kadm5/marshall.c (ret_principal_ent): set `n_tl_data'
+
+       * lib/hdb/ndbm.c: use `struct ndbm_db' everywhere.
+
+Fri Feb 27 04:49:24 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_priv.c (krb5_mk_priv): bump static limit to 10240.
+       This should be fixed the correct way.
+
+       * lib/kadm5/ipropd_master.c (check_acl:) truncate buf correctly
+       (send_diffs): compare versions correctly
+       (main): reorder handling of events
+
+       * lib/kadm5/log.c (kadm5_log_previous): avoid bad type conversion
+
+Thu Feb 26 02:22:35 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/ipropd_{slave,master}.c: new files
+
+       * lib/kadm5/log.c (kadm5_log_get_version): take an `fd' as
+       argument
+
+       * lib/krb5/krb5.h (krb5_context_data): `et_list' should be `struct
+       et_list *'
+
+       * aux/make-proto.pl: Should work with perl4
+
+Mon Feb 16 17:20:22 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/krb5_locl.h: Remove <error.h> (it gets included via
+       {asn1,krb5}_err.h).
+
+Thu Feb 12 03:28:40 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_in_tkt.c (_krb5_extract_ticket): if time difference
+       is larger than max_skew, return KRB5KRB_AP_ERR_SKEW
+
+       * lib/kadm5/log.c (get_version): globalize
+
+       * lib/kadm5/kadm5_locl.h: include <sys/file.h>
+
+       * lib/asn1/Makefile.am: add PA_KEY_INFO and PA_KEY_INFO_ENTRY
+
+       * kdc/kerberos5.c (get_pa_etype_info): remove gcc-ism of
+       initializing local struct in declaration.
+
+Sat Jan 31 17:28:58 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/524.c: Use krb5_decode_EncTicketPart.
+
+       * kdc/kerberos5.c: Check at runtime whether to use enctypes
+       instead of keytypes. If so use the same value to encrypt ticket,
+       and kdc-rep as well as `keytype' for session key. Fix some obvious
+       bugs with the handling of additional tickets.
+
+       * lib/krb5/rd_req.c: Use krb5_decode_EncTicketPart, and
+       krb5_decode_Authenticator.
+
+       * lib/krb5/rd_rep.c: Use krb5_decode_EncAPRepPart.
+
+       * lib/krb5/rd_cred.c: Use krb5_decode_EncKrbCredPart.
+
+       * lib/krb5/mk_rep.c: Make sure enc_part.etype is an encryption
+       type, and not a key type.  Use krb5_encode_EncAPRepPart.
+
+       * lib/krb5/init_creds_pw.c: Use krb5_decode_PA_KEY_INFO.
+
+       * lib/krb5/get_in_tkt.c: Use krb5_decode_Enc{AS,TGS}RepPart.
+
+       * lib/krb5/get_for_creds.c: Use krb5_encode_EncKrbCredPart.
+
+       * lib/krb5/get_cred.c: Use krb5_decode_Enc{AS,TGS}RepPart.
+
+       * lib/krb5/build_auth.c: Use krb5_encode_Authenticator.
+
+       * lib/krb5/codec.c: Enctype conversion stuff.
+
+       * lib/krb5/context.c: Ignore KRB5_CONFIG if *not* running
+       setuid. Get configuration for libdefaults ktype_is_etype, and
+       default_etypes.
+
+       * lib/krb5/encrypt.c: Add krb5_string_to_etype, rename
+       krb5_convert_etype to krb5_decode_keytype, and add
+       krb5_decode_keyblock.
+
+Fri Jan 23 00:32:09 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/{get_in_tkt,rd_req}.c: Use krb5_convert_etype.
+
+       * lib/krb5/encrypt.c: Add krb5_convert_etype function - converts
+       from protocol keytypes (that really are enctypes) to internal
+       representation.
+
+Thu Jan 22 21:24:36 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/asn1/k5.asn1: Add PA-KEY-INFO structure to hold information
+       on keys in the database; and also a new `pa-key-info' padata-type.
+
+       * kdc/kerberos5.c: If pre-authentication fails, return a list of
+       keytypes, salttypes, and salts.
+
+       * lib/krb5/init_creds_pw.c: Add better support for
+       pre-authentication, by looking at hints from the KDC.
+
+       * lib/krb5/get_in_tkt.c: Add better support for specifying what
+       pre-authentication to use.
+
+       * lib/krb5/str2key.c: Merge entries for KEYTYPE_DES and
+       KEYTYPE_DES_AFS3.
+
+       * lib/krb5/krb5.h: Add pre-authentication structures.
+
+       * kdc/connect.c: Don't fail if realloc(X, 0) returns NULL.
+
+Wed Jan 21 06:20:40 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/init_s.c (kadm5_s_init_with_password_ctx): initialize
+       `log_context.socket_name' and `log_context.socket_fd'
+
+       * lib/kadm5/log.c (kadm5_log_flush): send a unix domain datagram
+       to inform the possible running ipropd of an update.
+
+Wed Jan 21 01:34:09 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_in_tkt.c: Return error-packet to caller.
+
+       * lib/krb5/free.c (krb5_free_kdc_rep): Free krb5_kdc_rep->error.
+
+       * kdc/kerberos5.c: Add some support for using enctypes instead of
+       keytypes.
+
+       * lib/krb5/get_cred.c: Fixes to send authorization-data to the
+       KDC.
+
+       * lib/krb5/build_auth.c: Only generate local subkey if there is
+       none.
+
+       * lib/krb5/krb5.h: Add krb5_authdata type.
+
+       * lib/krb5/auth_context.c: Add
+       krb5_auth_con_set{,localsub,remotesub}key.
+
+       * lib/krb5/init_creds_pw.c: Return some error if prompter
+       functions return failure.
+
+Wed Jan 21 01:16:13 1998  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswd.c: detect bad password.  use krb5_err.
+
+       * kadmin/util.c (edit_entry): remove unused variables
+
+Tue Jan 20 22:58:31 1998  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c: rename `-s' to `-S' to be MIT-compatible.
+
+       * lib/kadm5/kadm5_locl.h: add kadm5_log_context and
+       kadm5_log*-functions
+
+       * lib/kadm5/create_s.c (kadm5_s_create_principal): add change to
+       log
+
+       * lib/kadm5/rename_s.c (kadm5_s_rename_principal): add change to
+       log
+
+       * lib/kadm5/init_s.c (kadm5_s_init_with_password_ctx): initialize
+       log_context
+
+       * lib/kadm5/delete_s.c (kadm5_s_delete_principal): add change to
+       log
+
+       * lib/kadm5/modify_s.c (kadm5_s_modify_principal): add change to
+       log
+
+       * lib/kadm5/randkey_s.c (kadm5_s_randkey_principal): add change to
+       log
+
+       * lib/kadm5/chpass_s.c (kadm5_s_chpass_principal): add change to
+       log
+
+       * lib/kadm5/Makefile.am: add log.c, dump_log and replay_log
+
+       * lib/kadm5/replay_log.c: new file
+
+       * lib/kadm5/dump_log.c: new file
+
+       * lib/kadm5/log.c: new file
+
+       * lib/krb5/str2key.c (get_str): initialize pad space to zero
+
+       * lib/krb5/config_file.c (krb5_config_vget_next): handle c == NULL
+
+       * kpasswd/kpasswdd.c: rewritten to use the kadm5 API
+
+       * kpasswd/Makefile.am: link with kadm5srv
+
+       * kdc/kerberos5.c (tgs_rep): initialize `i'
+
+       * kadmin/kadmind.c (main): use kadm5_server_{send,recv}_sp
+
+       * include/Makefile.am: added admin.h
+
+Sun Jan 18 01:41:34 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/asn1/gen_copy.c: Don't return ENOMEM if allocating 0 bytes.
+
+       * lib/krb5/mcache.c (mcc_store_cred): restore linked list if
+       copy_creds fails.
+
+Tue Jan  6 04:17:56 1998  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/server.c: add kadm5_server_{send,recv}{,_sp}
+
+       * lib/kadm5/marshall.c: add kadm5_{store,ret}_principal_ent_mask.
+
+       * lib/kadm5/init_c.c (kadm5_c_init_with_password_ctx): use
+       krb5_getportbyname
+
+       * kadmin/kadmind.c (main): htons correctly.
+       moved kadm5_server_{recv,send}
+
+       * kadmin/kadmin.c (main): only set admin_server if explicitly
+       given
+
+Mon Jan  5 23:34:44 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/hdb/ndbm.c: Implement locking of database.
+
+       * kdc/kerberos5.c: Process AuthorizationData.
+
+Sat Jan  3 22:07:07 1998  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/string2key.c: Use AFS string-to-key from libkrb5.
+
+       * lib/krb5/get_in_tkt.c: Handle pa-afs3-salt case.
+
+       * lib/krb5/krb5.h: Add value for AFS salts.
+
+       * lib/krb5/str2key.c: Add support for AFS string-to-key.
+
+       * lib/kadm5/rename_s.c: Use correct salt.
+
+       * lib/kadm5/ent_setup.c: Always enable client. Only set max-life
+       and max-renew if != 0.
+
+       * lib/krb5/config_file.c: Add context to all krb5_config_*get_*.
+
+Thu Dec 25 17:03:25 1997  Assar Westerlund  <assar@sics.se>
+
+       * kadmin/ank.c (ank): don't zero password if --random-key was
+       given.
+
+Tue Dec 23 01:56:45 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0m
+
+       * lib/kadm5/ent_setup.c (attr_to_flags): try to set `client'
+
+       * kadmin/util.c (edit_time): only set mask if != 0
+       (edit_attributes): only set mask if != 0
+
+       * kadmin/init.c (init): create `default'
+
+Sun Dec 21 09:44:05 1997  Assar Westerlund  <assar@sics.se>
+
+       * kadmin/util.c (str2deltat, str2attr, get_deltat): return value
+       as pointer and have return value indicate success.
+       
+       (get_response): check NULL from fgets
+       
+       (edit_time, edit_attributes): new functions for reading values and
+       offering list of answers on '?'
+       
+       (edit_entry): use edit_time and edit_attributes
+
+       * kadmin/ank.c (add_new_key): test the return value of
+       `krb5_parse_name'
+
+       * kdc/kerberos5.c (tgs_check_authenticator): RFC1510 doesn't say
+       that the checksum has to be keyed, even though later drafts do.
+       Accept unkeyed checksums to be compatible with MIT.
+
+       * kadmin/kadmin_locl.h: add some prototypes.
+
+       * kadmin/util.c (edit_entry): return a value
+
+       * appl/afsutil/afslog.c (main): return a exit code.
+
+       * lib/krb5/get_cred.c (init_tgs_req): use krb5_keytype_to_enctypes
+
+       * lib/krb5/encrypt.c (krb5_keytype_to_enctypes): new function.
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): use
+       krb5_{free,copy}_keyblock instead of the _contents versions
+
+Fri Dec 12 14:20:58 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/{mk,rd}_priv.c: fix check for local/remote subkey
+
+Mon Dec  8 08:48:09 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/context.c: don't look at KRB5_CONFIG if running setuid
+
+Sat Dec  6 10:09:40 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/keyblock.c (krb5_free_keyblock): check for NULL
+       keyblock
+
+Sat Dec  6 08:26:10 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0l
+
+Thu Dec  4 03:38:12 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/send_to_kdc.c: Add TCP client support.
+
+       * lib/krb5/store.c: Add k_{put,get}_int.
+
+       * kadmin/ank.c: Set initial kvno to 1.
+
+       * kdc/connect.c: Send version 5 TCP-reply as length+data.
+
+Sat Nov 29 07:10:11 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_req.c (krb5_rd_req): fixed obvious bug
+
+       * kdc/kaserver.c (create_reply_ticket): use a random nonce in the
+       reply packet.
+
+       * kdc/connect.c (init_sockets): less reallocing.
+
+       * **/*.c: changed `struct fd_set' to `fd_set'
+
+Sat Nov 29 05:12:01 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_default_principal.c: More guessing.
+
+Thu Nov 20 02:55:09 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/rd_req.c: Use principal from ticket if no server is
+       given.
+
+Tue Nov 18 02:58:02 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kuser/klist.c: Use krb5_err*().
+
+Sun Nov 16 11:57:43 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kadmin/kadmin.c: Add local `init', `load', `dump', and `merge'
+       commands.
+
+Sun Nov 16 02:52:20 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_ext): figure out the correct
+       `enctype'
+
+       * lib/krb5/mk_req.c (krb5_mk_req): use `(*auth_context)->enctype'
+       if set.
+
+       * lib/krb5/get_cred.c: handle the case of a specific keytype
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): enctype as a
+       parameter instead of guessing it.
+
+       * lib/krb5/build_ap_req.c (krb5_build_ap_req): new parameter
+       `enctype'
+
+       * appl/test/common.c (common_setup): don't use `optarg'
+
+       * lib/krb5/keytab.c (krb5_kt_copy_entry_contents): new function
+       (krb5_kt_get_entry): retrieve the latest version if kvno == 0
+
+       * lib/krb5/krb5.h: define KRB5_TC_MATCH_KEYTYPE
+
+       * lib/krb5/creds.c (krb5_compare_creds): check for
+       KRB5_TC_MATCH_KEYTYPE
+
+       * lib/gssapi/8003.c (gssapi_krb5_create_8003_checksum): remove
+       unused variable
+
+       * lib/krb5/creds.c (krb5_copy_creds_contents): only free the
+       contents if we fail.
+
+Sun Nov 16 00:32:48 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kpasswd/kpasswdd.c: Get password expiration time from config
+       file.
+
+       * lib/asn1/{der_get,gen_decode}.c: Allow passing NULL size.
+
+Wed Nov 12 02:35:57 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds):
+       restructured and fixed.
+
+       * lib/krb5/addr_families.c (krb5_h_addr2addr): new function.
+
+Wed Nov 12 01:36:01 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_addrs.c: Fall back to hostname's addresses if other
+       methods fail.
+
+Tue Nov 11 22:22:12 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kadmin/kadmin.c: Add `-l' flag to use local database.
+
+       * lib/kadm5/acl.c: Use KADM5_PRIV_ALL.
+
+       * lib/kadm5: Use function pointer trampoline for easier dual use
+       (without radiation-hardening capability).
+
+Tue Nov 11 05:15:22 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/encrypt.c (krb5_etype_valid): new function
+
+       * lib/krb5/creds.c (krb5_copy_creds_contents): zero target
+
+       * lib/krb5/context.c (valid_etype): remove
+
+       * lib/krb5/checksum.c: remove dead code
+
+       * lib/krb5/changepw.c (send_request): free memory on error.
+
+       * lib/krb5/build_ap_req.c (krb5_build_ap_req): check return value
+       from malloc.
+
+       * lib/krb5/auth_context.c (krb5_auth_con_init): free memory on
+       failure correctly.
+       (krb5_auth_con_setaddrs_from_fd): return error correctly.
+
+       * lib/krb5/get_in_tkt_with_{keytab,skey}.c: new files
+
+Tue Nov 11 02:53:19 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/auth_context.c: Implement auth_con_setuserkey.
+
+       * lib/gssapi/init_sec_context.c: Use krb5_auth_con_getkey.
+
+       * lib/krb5/keyblock.c: Rename krb5_free_keyblock to
+       krb5_free_keyblock_contents, and reimplement krb5_free_keyblock.
+
+       * lib/krb5/rd_req.c: Use auth_context->keyblock if
+       ap_options.use_session_key.
+
+Tue Nov 11 02:35:17 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/net_{read,write}.c: change `int fd' to `void *p_fd'.
+       fix callers.
+
+       * lib/krb5/krb5_locl.h: include <asn1.h> and <der.h>
+
+       * include/Makefile.am: add xdbm.h
+
+Tue Nov 11 01:58:22 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_cred.c: Implement krb5_get_cred_from_kdc.
+
+Mon Nov 10 22:41:53 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/ticket.c: Implement copy_ticket.
+
+       * lib/krb5/get_in_tkt.c: Make `options' parameter MIT-compatible.
+
+       * lib/krb5/data.c: Implement free_data and copy_data.
+
+Sun Nov  9 02:17:27 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/kadm5: Implement kadm5_get_privs, and kadm5_get_principals.
+
+       * kadmin/kadmin.c: Add get_privileges function.
+
+       * lib/kadm5: Rename KADM5_ACL_* -> KADM5_PRIV_* to conform with
+       specification.
+
+       * kdc/connect.c: Exit if no sockets could be bound.
+
+       * kadmin/kadmind.c: Check return value from krb5_net_read().
+
+       * lib/kadm5,kadmin: Fix memory leaks.
+
+Fri Nov  7 02:45:26 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/kadm5/create_s.c: Get some default values from `default'
+       principal.
+
+       * lib/kadm5/ent_setup.c: Add optional default entry to get some
+       values from.
+
+Thu Nov  6 00:20:41 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/error/compile_et.awk: Remove generated destroy_*_error_table
+       prototype
+
+       * kadmin/kadmind.c: Crude admin server.
+
+       * kadmin/kadmin.c: Update to use remote protocol.
+
+       * kadmin/get.c: Fix principal formatting.
+
+       * lib/kadm5: Add client support.
+
+       * lib/kadm5/error.c: Error code mapping.
+
+       * lib/kadm5/server.c: Kadmind support function.
+
+       * lib/kadm5/marshall.c: Kadm5 marshalling.
+
+       * lib/kadm5/acl.c: Simple acl system.
+
+       * lib/kadm5/kadm5_locl.h: Add client stuff.
+
+       * lib/kadm5/init_s.c: Initialize acl.
+
+       * lib/kadm5/*:  Return values.
+
+       * lib/kadm5/create_s.c: Correct kvno.
+
+Wed Nov  5 22:06:50 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/log.c: Fix parsing of log destinations.
+
+Mon Nov  3 20:33:55 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/principal.c: Reduce number of reallocs in unparse_name.
+
+Sat Nov  1 01:40:53 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kadmin: Simple kadmin utility.
+
+       * admin/ktutil.c: Print keytype.
+
+       * lib/kadm5/get_s.c: Set correct n_key_data.
+
+       * lib/kadm5/init_s.c: Add kadm5_s_init_with_password_ctx. Use
+       master key.
+
+       * lib/kadm5/destroy_s.c: Check for allocated context.
+
+       * lib/kadm5/{create,chpass}_s.c: Use _kadm5_set_keys().
+
+Sat Nov  1 00:21:00 1997  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: test for readv, writev
+
+Wed Oct 29 23:41:26 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/warn.c (_warnerr): handle the case of an illegal error
+       code
+
+       * kdc/kerberos5.c (encode_reply): return success
+
+Wed Oct 29 18:01:59 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c (find_etype) Return correct index of selected
+       etype.
+
+Wed Oct 29 04:07:06 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0k
+
+       * lib/krb5/context.c (krb5_init_context): support `KRB5_CONFIG'
+       environment variable
+
+       * *: use the roken_get*-macros from roken.h for the benefit of
+       Crays.
+
+       * configure.in: add --{enable,disable}-otp.  check for compatible
+       prototypes for gethostbyname, gethostbyaddr, getservbyname, and
+       openlog (they have strange prototypes on Crays)
+
+       * acinclude.m4: new macro `AC_PROTO_COMPAT'
+
+Tue Oct 28 00:11:22 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/connect.c: Log bad requests.
+
+       * kdc/kerberos5.c: Move stuff that's in common between as_rep and
+       tgs_rep to separate functions.
+
+       * kdc/kerberos5.c: Fix user-to-user authentication.
+
+       * lib/krb5/get_cred.c: Some restructuring of krb5_get_credentials:
+         - add a kdc-options argument to krb5_get_credentials, and rename
+           it to krb5_get_credentials_with_flags
+         - honour the KRB5_GC_CACHED, and KRB5_GC_USER_USER options
+         - add some more user-to-user glue
+
+       * lib/krb5/rd_req.c: Move parts of krb5_verify_ap_req into a new
+       function, krb5_decrypt_ticket, so it is easier to decrypt and
+       check a ticket without having an ap-req.
+
+       * lib/krb5/krb5.h: Add KRB5_GC_CACHED, and KRB5_GC_USER_USER
+       flags.
+
+       * lib/krb5/crc.c (crc_init_table): Check if table is already
+       inited.
+
+Sun Oct 26 04:51:02 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/asn1/der_get.c (der_get_length, fix_dce): Special-case
+       indefinite encoding.
+
+       * lib/asn1/gen_glue.c (generate_units): Check for empty
+       member-list.
+
+Sat Oct 25 07:24:57 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/error/compile_et.awk: Allow specifying table-base.
+
+Tue Oct 21 20:21:40 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c: Check version number of krbtgt.
+
+Mon Oct 20 01:14:53 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/prompter_posix.c (krb5_prompter_posix): implement the
+       case of unhidden prompts.
+
+       * lib/krb5/str2key.c (string_to_key_internal): return error
+       instead of aborting.  always free memory
+
+       * admin/ktutil.c: add `help' command
+
+       * admin/kdb_edit.c: implement new commands: add_random_key(ark),
+       change_password(cpw), change_random_key(crk)
+
+Thu Oct 16 05:16:36 1997  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswdd.c: change all the keys in the database
+
+       * kdc: removed all unsealing, now done by the hdb layer
+
+       * lib/hdb/hdb.c: new functions `hdb_create', `hdb_set_master_key'
+       and `hdb_clear_master_key'
+
+       * admin/misc.c: removed
+
+Wed Oct 15 22:47:31 1997  Assar Westerlund  <assar@sics.se>
+
+       * kuser/klist.c: print year as YYYY iff verbose
+
+Wed Oct 15 20:02:13 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kuser/klist.c: print etype from ticket
+
+Mon Oct 13 17:18:57 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Release 0.0j
+
+       * lib/krb5/get_cred.c: Get the subkey from mk_req so it can be
+       used to decrypt the reply from DCE secds.
+
+       * lib/krb5/auth_context.c: Add {get,set}enctype.
+
+       * lib/krb5/get_cred.c: Fix for DCE secd.
+
+       * lib/krb5/store.c: Store keytype twice, as MIT does.
+
+       * lib/krb5/get_in_tkt.c: Use etype from reply.
+
+Fri Oct 10 00:39:48 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/connect.c: check for leading '/' in http request
+
+Tue Sep 30 21:50:18 1997  Assar Westerlund  <assar@assaris.pdc.kth.se>
+
+       * Release 0.0i
+
+Mon Sep 29 15:58:43 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_req.c (krb5_rd_req): redone because we don't know
+       the kvno or keytype before receiving the AP-REQ
+
+       * lib/krb5/mk_safe.c (krb5_mk_safe): figure out what cksumtype to
+       use from the keytype.
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_extended): figure out what
+       cksumtype to use from the keytype.
+
+       * lib/krb5/mk_priv.c (krb5_mk_priv): figure out what etype to use
+       from the keytype.
+
+       * lib/krb5/keytab.c (krb5_kt_get_entry): check the keytype
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): figure out
+       what etype to use from the keytype.
+
+       * lib/krb5/generate_seq_number.c (krb5_generate_seq_number):
+       handle other key types than DES
+
+       * lib/krb5/encrypt.c (key_type): add `best_cksumtype'
+       (krb5_keytype_to_cksumtype): new function
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): figure out
+       what etype to use from the keytype.
+
+       * lib/krb5/auth_context.c (krb5_auth_con_init): set `cksumtype'
+       and `enctype' to 0
+
+       * admin/extkeytab.c (ext_keytab): extract all keys
+
+       * appl/telnet/telnet/commands.c: INET6_ADDRSTRLEN kludge
+
+       * configure.in: check for <netinet6/in6.h>. check for -linet6
+       
+Tue Sep 23 03:00:53 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/encrypt.c: fix checksumtype for des3-cbc-sha1
+
+       * lib/krb5/rd_safe.c: fix check for keyed and collision-proof
+       checksum
+
+       * lib/krb5/context.c (valid_etype): remove hard-coded constants
+       (default_etypes): include DES3
+
+       * kdc/kerberos5.c: fix check for keyed and collision-proof
+       checksum
+
+       * admin/util.c (init_des_key, set_password): DES3 keys also
+
+       * lib/krb/send_to_kdc.c (krb5_sendto_kdc): no data returned means
+       no contact?
+
+       * lib/krb5/addr_families.c: fix typo in `ipv6_anyaddr'
+
+Mon Sep 22 11:44:27 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/kerberos5.c: Somewhat fix the etype usage. The list sent by
+       the client is used to select wich key to encrypt the kdc rep with
+       (in case of as-req), and with the server info to select the
+       session key type. The server key the ticket is encrypted is based
+       purely on the keys in the database.
+
+       * kdc/string2key.c: Add keytype support. Default to version 5
+       keys.
+
+       * lib/krb5/get_in_tkt.c: Fix a lot of etype/keytype misuse.
+
+       * lib/krb5/encrypt.c: Add des3-cbc-md5, and des3-cbc-sha1. Add
+       many *_to_* functions.
+
+       * lib/krb5/str2key.c: Add des3 string-to-key. Add ktype argument
+       to krb5_string_to_key().
+
+       * lib/krb5/checksum.c: Some cleanup, and added: 
+         - rsa-md5-des3 
+         - hmac-sha1-des3 
+         - keyed and collision proof flags to each checksum method
+         - checksum<->string functions.
+
+       * lib/krb5/generate_subkey.c: Use krb5_generate_random_keyblock.
+
+Sun Sep 21 15:19:23 1997  Assar Westerlund  <assar@sics.se>
+
+       * kdc/connect.c: use new addr_families functions
+
+       * kpasswd/kpasswdd.c: use new addr_families functions.  Now works
+       over IPv6
+
+       * kuser/klist.c: use correct symbols for address families
+
+       * lib/krb5/sock_principal.c: use new addr_families functions
+
+       * lib/krb5/send_to_kdc.c: use new addr_families functions
+
+       * lib/krb5/krb5.h: add KRB5_ADDRESS_INET6
+
+       * lib/krb5/get_addrs.c: use new addr_families functions
+
+       * lib/krb5/changepw.c: use new addr_families functions.  Now works
+       over IPv6
+
+       * lib/krb5/auth_context.c: use new addr_families functions
+
+       * lib/krb5/addr_families.c: new file
+
+       * acconfig.h: AC_SOCKADDR_IN6 -> AC_STRUCT_SOCKADDR_IN6.  Updated
+       uses.
+
+       * acinclude.m4: new macro `AC_KRB_IPV6'.  Use it.
+
+Sat Sep 13 23:04:23 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/hprop.c: Don't encrypt twice. Complain on non-convertable
+       principals.
+
+Sat Sep 13 00:59:36 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0h
+       
+       * appl/telnet/telnet/commands.c: AF_INET6 support
+
+       * admin/misc.c: new file
+
+       * lib/krb5/context.c: new configuration variable `max_retries'
+
+       * lib/krb5/get_addrs.c: fixes and better #ifdef's
+
+       * lib/krb5/config_file.c: implement krb5_config_get_int
+
+       * lib/krb5/auth_context.c, send_to_kdc.c, sock_principal.c:
+       AF_INET6 support
+
+       * kuser/klist.c: support for printing IPv6-addresses
+
+       * kdc/connect.c: support AF_INET6
+
+       * configure.in: test for gethostbyname2 and struct sockaddr_in6
+
+Thu Sep 11 07:25:28 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/k5.asn1: Use `METHOD-DATA' instead of `SEQUENCE OF
+       PA-DATA'
+
+Wed Sep 10 21:20:17 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c: Fixes for cross-realm, including (but not
+       limited to):
+         - allow client to be non-existant (should probably check for
+           "local realm")
+         - if server isn't found and it is a request for a krbtgt, try to
+           find a realm on the way to the requested realm
+         - update the transited encoding iff 
+           client-realm != server-realm != tgt-realm
+
+       * lib/krb5/get_cred.c: Several fixes for cross-realm.
+
+Tue Sep  9 15:59:20 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/string2key.c: Fix password handling.
+
+       * lib/krb5/encrypt.c: krb5_key_to_string
+
+Tue Sep  9 07:46:05 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_addrs.c: rewrote.  Now should be able to handle
+       aliases and IPv6 addresses
+
+       * kuser/klist.c: try printing IPv6 addresses
+
+       * kdc/kerberos5.c: increase the arbitrary limit from 1024 to 8192
+
+       * configure.in: check for <netinet/in6_var.h>
+
+Mon Sep  8 02:57:14 1997  Assar Westerlund  <assar@sics.se>
+
+       * doc: fixes
+
+       * admin/util.c (init_des_key): increase kvno
+       (set_password): return -1 if `des_read_pw_string' failed
+
+       * admin/mod.c (doit2): check the return value from `set_password'
+
+       * admin/ank.c (doit): don't add a new entry if `set_password'
+       failed
+
+Mon Sep  8 02:20:16 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/verify_init.c: fix ap_req_nofail semantics
+
+       * lib/krb5/transited.c: something that might resemble
+       domain-x500-compress
+
+Mon Sep  8 01:24:42 1997  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c (main): check number of arguments
+
+       * appl/popper/pop_init.c (pop_init): check number of arguments
+
+       * kpasswd/kpasswd.c (main): check number of arguments
+
+       * kdc/string2key.c (main): check number of arguments
+
+       * kuser/kdestroy.c (main): check number of arguments
+
+       * kuser/kinit.c (main): check number of arguments
+
+       * kpasswd/kpasswdd.c (main): use sigaction without SA_RESTART to
+       break out of select when a signal arrives
+
+       * kdc/main.c (main): use sigaction without SA_RESTART to break out
+       of select when a signal arrives
+
+       * kdc/kstash.c: default to HDB_DB_DIR "/m-key"
+
+       * kdc/config.c (configure): add `--version'.  Check the number of
+       arguments. Handle the case of there being no specification of port
+       numbers.
+
+       * admin/util.c: seal and unseal key at appropriate places
+
+       * admin/kdb_edit.c (main): parse arguments, config file and read
+       master key iff there's one.
+
+       * admin/extkeytab.c (ext_keytab): unseal key while extracting
+
+Sun Sep  7 20:41:01 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/roken/roken.h: include <fcntl.h>
+
+       * kdc/kerberos5.c (set_salt_padata): new function
+
+       * appl/telnet/telnetd/telnetd.c: Rename some variables that
+       conflict with cpp symbols on HP-UX 10.20
+
+       * change all calls of `gethostbyaddr' to cast argument 1 to `const
+       char *'
+
+       * acconfig.h: only use SGTTY on nextstep
+
+Sun Sep  7 14:33:50 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c: Check invalid flag.
+
+Fri Sep  5 14:19:38 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/verify_user.c: Use get_init_creds/verify_init_creds.
+
+       * lib/kafs: Move functions common to krb/krb5 modules to new file,
+       and make things more modular.
+
+       * lib/krb5/krb5.h: rename STRING -> krb5_config_string, and LIST
+       -> krb5_config_list
+
+Thu Sep  4 23:39:43 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/get_addrs.c: Fix loopback test.
+
+Thu Sep  4 04:45:49 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/roken/roken.h: fallback definition of `O_ACCMODE'
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): be more careful when
+       checking for a v4 reply
+
+Wed Sep  3 18:20:14 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/hprop.c: Add `--decrypt' and `--encrypt' flags.
+
+       * lib/hdb/hdb.c: new {seal,unseal}_keys functions
+
+       * kdc/{hprop,hpropd}.c: Add support to dump database to stdout.
+
+       * kdc/hprop.c: Don't use same master key as version 4.
+
+       * admin/util.c: Don't dump core if no `default' is found.
+
+Wed Sep  3 16:01:07 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/connect.c: Allow run time port specification.
+
+       * kdc/config.c: Add flags for http support, and port
+       specifications.
+
+Tue Sep  2 02:00:03 1997  Assar Westerlund  <assar@sics.se>
+
+       * include/bits.c: Don't generate ifndef's in bits.h.  Instead, use
+       them when building the program.  This makes it possible to include
+       bits.h without having defined all HAVE_INT17_T symbols.
+       
+       * configure.in: test for sigaction
+
+       * doc: updated documentation.
+       
+Tue Sep  2 00:20:31 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Release 0.0g
+
+Mon Sep  1 17:42:14 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/data.c: don't return ENOMEM if len == 0
+
+Sun Aug 31 17:15:49 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/hdb/hdb.asn1: Include salt type in salt.
+
+       * kdc/hprop.h: Change port to 754.
+
+       * kdc/hpropd.c: Verify who tries to transmit a database.
+
+       * appl/popper: Use getarg and krb5_log.
+
+       * lib/krb5/get_port.c: Add context parameter. Now takes port in
+       host byte order.
+
+Sat Aug 30 18:48:19 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/connect.c: Add timeout to select, and log about expired tcp
+       connections.
+
+       * kdc/config.c: Add `database' option.
+
+       * kdc/hpropd.c: Log about duplicate entries.
+
+       * lib/hdb/{db,ndbm}.c: Use common routines.
+
+       * lib/hdb/common.c: Implement more generic fetch/store/delete
+       functions.
+
+       * lib/hdb/hdb.h: Add `replace' parameter to store.
+       
+       * kdc/connect.c: Set filedecriptor to -1 on allocated decriptor
+       entries.
+
+Fri Aug 29 03:13:23 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_in_tkt.c: extract_ticket -> _krb5_extract_ticket
+
+       * aux/make-proto.pl: fix __P for stone age mode
+
+Fri Aug 29 02:45:46 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/45/mk_req.c: implementation of krb_mk_req that uses 524
+       protocol
+
+       * lib/krb5/init_creds_pw.c: make change_password and
+       get_init_creds_common static
+
+       * lib/krb5/krb5.h: Merge stuff from removed headerfiles.
+
+       * lib/krb5/fcache.c: fcc_ops -> krb5_fcc_ops
+
+       * lib/krb5/mcache.c: mcc_ops -> krb5_mcc_ops
+
+Fri Aug 29 01:45:25 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/krb5.h: Remove all prototypes.
+
+       * lib/krb5/convert_creds.c: Use `struct credentials' instead of
+       `CREDENTIALS'.
+
+Fri Aug 29 00:08:18 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/gen_glue.c: new file. generates 2int and int2 functions
+       and units for bit strings.
+
+       * admin/util.c: flags2int, int2flags, and flag_units are now
+       generated by asn1_compile
+
+       * lib/roken/parse_units.c: generalised `parse_units' and
+       `unparse_units' and added new functions `parse_flags' and
+       `unparse_flags' that use these
+
+       * lib/krb5/krb5_locl.h: moved krb5_data* functions to krb5.h
+
+       * admin/util.c: Use {un,}parse_flags for printing and parsing
+       hdbflags.
+
+Thu Aug 28 03:26:12 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_addrs.c: restructured
+
+       * lib/krb5/warn.c (_warnerr): leak less memory
+
+       * lib/hdb/hdb.c (hdb_free_entry): zero keys
+       (hdb_check_db_format): leak less memory
+
+       * lib/hdb/ndbm.c (NDBM_seq): check for valid hdb_entries implement
+       NDBM__get, NDBM__put
+
+       * lib/hdb/db.c (DB_seq): check for valid hdb_entries
+
+Thu Aug 28 02:06:58 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/send_to_kdc.c: Don't use sendto on connected sockets.
+
+Thu Aug 28 01:13:17 1997  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.1, klist.1, kdestroy.1: new man pages
+
+       * kpasswd/kpasswd.1, kpasswdd.8: new man pages
+
+       * kdc/kstash.8, hprop.8, hpropd.8: new man pages
+
+       * admin/ktutil.8, admin/kdb_edit.8: new man pages
+
+       * admin/mod.c: new file
+
+       * admin/life.c: renamed gettime and puttime to getlife and putlife
+       and moved them to life.c
+
+       * admin/util.c: add print_flags, parse_flags, init_entry,
+       set_created_by, set_modified_by, edit_entry, set_password.  Use
+       them.
+
+       * admin/get.c: use print_flags
+
+       * admin: removed unused stuff.  use krb5_{warn,err}*
+
+       * admin/ank.c: re-organized and abstracted.
+
+       * admin/gettime.c: removed
+
+Thu Aug 28 00:37:39 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/{get_cred,get_in_tkt}.c: Check for v4 reply.
+
+       * lib/roken/base64.c: Add base64 functions.
+
+       * kdc/connect.c lib/krb5/send_to_kdc.c: Add http support.
+
+Wed Aug 27 00:29:20 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * include/Makefile.am: Don't make links to built files.
+
+       * admin/kdb_edit.c: Add command to set the database path.
+
+       * lib/hdb: Include version number in database.
+
+Tue Aug 26 20:14:54 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * admin/ktutil: Merged v4 srvtab conversion.
+
+Mon Aug 25 23:02:18 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/roken/roken.h: add F_OK
+
+       * lib/gssapi/acquire_creds.c: fix typo
+
+       * configure.in: call AC_TYPE_MODE_T
+
+       * acinclude.m4: Add AC_TYPE_MODE_T
+
+Sun Aug 24 16:46:53 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0f
+
+Sun Aug 24 08:06:54 1997  Assar Westerlund  <assar@sics.se>
+
+       * appl/popper/pop_pass.c: log poppers
+
+       * kdc/kaserver.c: some more checks
+
+       * kpasswd/kpasswd.c: removed `-p'
+
+       * kuser/kinit.c: removed `-p'
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): If
+       KDC_ERR_PREUATH_REQUIRED, add preauthentication and try again.
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): don't print out
+       krb-error text
+
+       * lib/gssapi/import_name.c (input_name): more names types.
+
+       * admin/load.c (parse_keys): handle the case of an empty salt
+
+       * kdc/kaserver.c: fix up memory deallocation
+
+       * kdc/kaserver.c: quick hack at talking kaserver protocol
+
+       * kdc/kerberos4.c: Make `db-fetch4' global
+
+       * configure.in: add --enable-kaserver
+
+       * kdc/rx.h, kdc/kerberos4.h: new header files
+
+       * lib/krb5/principal.c: fix krb5_build_principal_ext & c:o
+
+Sun Aug 24 03:52:44 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/{get_in_tkt,mk_safe,mk_priv}.c: Fix some Cray specific
+       type conflicts.
+
+       * lib/krb5/{get_cred,get_in_tkt}.c: Mask nonce to 32 bits.
+
+       * lib/des/{md4,md5,sha}.c: Now works on Crays.
+
+Sat Aug 23 18:15:01 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * appl/afsutil/afslog.c: If no cells or files specified, get
+       tokens for all local cells. Better test for files.
+
+Thu Aug 21 23:33:38 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/gssapi/v1.c: new file with v1 compatibility functions.
+
+Thu Aug 21 20:36:13 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/kafs/afskrb5.c: Don't check ticket file for afs ticket.
+
+       * kdc/kerberos4.c: Check database when converting v4 principals.
+
+       * kdc/kerberos5.c: Include kvno in Ticket.
+
+       * lib/krb5/encrypt.c: Add kvno parameter to encrypt_EncryptedData.
+
+       * kuser/klist.c: Print version number of ticket, include more
+       flags.
+
+Wed Aug 20 21:26:58 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/kafs/afskrb5.c (get_cred): Check cached afs tickets for
+       expiration.
+
+Wed Aug 20 17:40:31 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/recvauth.c (krb5_recvauth): Send a KRB-ERROR iff
+       there's an error.
+
+       * lib/krb5/sendauth.c (krb5_sendauth): correct the protocol
+       documentation and process KRB-ERROR's
+
+Tue Aug 19 20:41:30 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos4.c: Fix memory leak in v4 protocol handler.
+
+Mon Aug 18 05:15:09 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/gssapi/accept_sec_context.c: Added
+       `gsskrb5_register_acceptor_identity'
+
+Sun Aug 17 01:40:20 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/gssapi/accept_sec_context.c (gss_accept_sec_context): don't
+       always pass server == NULL to krb5_rd_req.
+
+       * lib/gssapi: new files: canonicalize_name.c export_name.c
+       context_time.c compare_name.c release_cred.c acquire_cred.c
+       inquire_cred.c, from Luke Howard <lukeh@xedoc.com.au>
+
+       * lib/krb5/config_file.c: Add netinfo support from Luke Howard
+       <lukeh@xedoc.com.au>
+
+       * lib/editline/sysunix.c: sgtty-support from Luke Howard
+       <lukeh@xedoc.com.au>
+
+       * lib/krb5/principal.c: krb5_sname_to_principal fix from Luke
+       Howard <lukeh@xedoc.com.au>
+
+Sat Aug 16 00:44:47 1997  Assar Westerlund  <assar@koi.pdc.kth.se>
+
+       * Release 0.0e
+
+Sat Aug 16 00:23:46 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * appl/afsutil/afslog.c: Use new libkafs.
+
+       * lib/kafs/afskrb5.c: Get AFS tokens via 524 protocol.
+
+       * lib/krb5/warn.c: Fix format string for *x type.
+
+Fri Aug 15 22:15:01 1997  Assar Westerlund  <assar@sics.se>
+
+       * admin/get.c (get_entry): print more information about the entry
+
+       * lib/des/Makefile.am: build destest, mdtest, des, rpw, speed
+
+       * lib/krb5/config_file.c: new functions `krb5_config_get_time' and
+       `krb5_config_vget_time'.  Use them.
+
+Fri Aug 15 00:09:37 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * admin/ktutil.c: Keytab manipulation program.
+
+       * lib/krb5/keytab.c: Return sane values from resolve and
+       start_seq_get.
+
+       * kdc/kerberos5.c: Fix for old clients passing 0 for `no endtime'.
+
+       * lib/45/get_ad_tkt.c: Kerberos 4 get_ad_tkt using
+       krb524_convert_creds_kdc.
+
+       * lib/krb5/convert_creds.c: Implementation of
+       krb524_convert_creds_kdc.
+
+       * lib/asn1/k5.asn1: Make kdc-req-body.till OPTIONAL
+
+       * kdc/524.c: A somewhat working 524-protocol module.
+
+       * kdc/kerberos4.c: Add version 4 ticket encoding and encryption
+       functions.
+
+       * lib/krb5/context.c: Fix kdc_timeout.
+
+       * lib/hdb/{ndbm,db}.c: Free name in close.
+
+       * kdc/kerberos5.c (tgs_check_autenticator): Return error code
+
+Thu Aug 14 21:29:03 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c (tgs_make_reply): Fix endtime in reply.
+
+       * lib/krb5/store_emem.c: Fix reallocation bug.
+
+Tue Aug 12 01:29:46 1997  Assar Westerlund  <assar@sics.se>
+
+       * appl/telnet/libtelnet/kerberos5.c, appl/popper/pop_init.c: Use
+       `krb5_sock_to_principal'.  Send server parameter to
+       krb5_rd_req/krb5_recvauth.  Set addresses in auth_context.
+
+       * lib/krb5/recvauth.c: Set addresses in auth_context if there
+       aren't any
+
+       * lib/krb5/auth_context.c: New function
+       `krb5_auth_con_setaddrs_from_fd'
+
+       * lib/krb5/sock_principal.c: new function
+       `krb5_sock_to_principal'
+       
+       * lib/krb5/time.c: new file with `krb5_timeofday' and
+       `krb5_us_timeofday'.  Use these functions.
+
+       * kuser/klist.c: print KDC offset iff verbose
+
+       * lib/krb5/get_in_tkt.c: implement KDC time offset and use it if
+       [libdefaults]kdc_timesync is set.
+       
+       * lib/krb5/fcache.c: Implement version 4 of the ccache format.
+
+Mon Aug 11 05:34:43 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_rep.c (krb5_free_ap_rep_enc_part): free all memory
+
+       * lib/krb5/principal.c (krb5_unparse_name): allocate memory
+       properly
+
+       * kpasswd/kpasswd.c: Use `krb5_change_password'
+
+       * lib/krb5/init_creds_pw.c (init_cred): set realm of server
+       correctly.
+
+       * lib/krb5/init_creds_pw.c: support changing of password when it
+       has expired
+
+       * lib/krb5/changepw.c: new file
+
+       * kuser/klist.c: use getarg
+
+       * admin/init.c (init): add `kadmin/changepw'
+
+Mon Aug 11 04:30:47 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_cred.c: Make get_credentials handle cross-realm.
+
+Mon Aug 11 00:03:24 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/config_file.c: implement support for #-comments
+
+Sat Aug  9 02:21:46 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/hprop*.c: Add database propagation programs.
+
+       * kdc/connect.c: Max request size.
+
+Sat Aug  9 00:47:28 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/otp: resurrected from krb4
+
+       * appl/push: new program for fetching mail with POP.
+
+       * appl/popper/popper.h: new include files.  new fields in `POP'
+
+       * appl/popper/pop_pass.c: Implement both v4 and v5.
+
+       * appl/popper/pop_init.c: Implement both v4 and v5.
+
+       * appl/popper/pop_debug.c: use getarg.  Talk both v4 and v5
+
+       * appl/popper: Popper from krb4.
+
+       * configure.in: check for inline and <netinet/tcp.h> generate
+       files in appl/popper, appl/push, and lib/otp
+
+Fri Aug  8 05:51:02 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_cred.c: clean-up and try to free memory even when
+       there're errors
+
+       * lib/krb5/get_cred.c: adapt to new `extract_ticket'
+
+       * lib/krb5/get_in_tkt.c: reorganize.  check everything and try to
+       return memory even if there are errors.
+
+       * kuser/kverify.c: new file
+
+       * lib/krb5/free_host_realm.c: new file
+
+       * lib/krb5/principal.c (krb5_sname_to_principal): implement
+       different nametypes.  Also free memory.
+
+       * lib/krb5/verify_init.c: more functionality
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_extended): free the checksum
+
+       * lib/krb5/get_in_tkt.c (extract_ticket): don't copy over the
+       principals in creds.  Should also compare them with that received
+       from the KDC
+
+       * lib/krb5/cache.c (krb5_cc_gen_new): copy the newly allocated
+       krb5_ccache
+       (krb5_cc_destroy): call krb5_cc_close
+       (krb5_cc_retrieve_cred): delete the unused creds
+
+Fri Aug  8 02:30:40 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/log.c: Allow better control of destinations of logging
+       (like passing explicit destinations, and log-functions).
+
+Fri Aug  8 01:20:39 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_default_principal.c: new file
+
+       * kpasswd/kpasswdd.c: use krb5_log*
+
+Fri Aug  8 00:37:47 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/init_creds_pw.c: Implement krb5_get_init_creds_keytab.
+
+Fri Aug  8 00:37:17 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/init_creds_pw.c: Use `krb5_get_default_principal'.
+       Print password expire information.
+
+       * kdc/config.c: new variable `kdc_warn_pwexpire'
+
+       * kpasswd/kpasswd.c: converted to getarg and get_init_creds
+
+Thu Aug  7 22:17:09 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mcache.c: new file
+
+       * admin/gettime.c: new function puttime.  Use it.
+
+       * lib/krb5/keyblock.c: Added krb5_free_keyblock and
+       krb5_copy_keyblock
+
+       * lib/krb5/init_creds_pw.c: more functionality
+
+       * lib/krb5/creds.c: Added krb5_free_creds_contents and
+       krb5_copy_creds.  Changed callers.
+
+       * lib/krb5/config_file.c: new functions krb5_config_get and
+       krb5_config_vget
+
+       * lib/krb5/cache.c: cleanup added mcache
+       
+       * kdc/kerberos5.c: include last-req's of type 6 and 7, if
+       applicable
+
+Wed Aug  6 20:38:23 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/log.c: New parameter `log-level'. Default to `SYSLOG'.
+
+Tue Aug  5 22:53:54 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/verify_init.c, init_creds_pw.c, init_creds.c,
+       prompter_posix.c: the beginning of an implementation of the cygnus
+       initial-ticket API.
+
+       * lib/krb5/get_in_tkt_pw.c: make `krb5_password_key_proc' global
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): new function that is
+       almost krb5_get_in_tkt but doesn't write the creds to the ccache.
+       Small fixes in krb5_get_in_tkt
+
+       * lib/krb5/get_addrs.c (krb5_get_all_client_addrs): don't include
+       loopback.
+
+Mon Aug  4 20:20:48 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc: Make context global.
+
+Fri Aug  1 17:23:56 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0d
+
+       * lib/roken/flock.c: new file
+
+       * kuser/kinit.c: check for and print expiry information in the
+       `kdc_rep'
+
+       * lib/krb5/get_in_tkt.c: Set `ret_as_reply' if != NULL
+
+       * kdc/kerberos5.c: Check the valid times on client and server.
+       Check the password expiration.
+       Check the require_preauth flag.
+       Send an lr_type == 6 with pw_end.
+       Set key.expiration to min(valid_end, pw_end)
+       
+       * lib/hdb/hdb.asn1: new flags `require_preauth' and `change_pw'
+
+       * admin/util.c, admin/load.c: handle the new flags.
+
+Fri Aug  1 16:56:12 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/hdb: Add some simple locking.
+
+Sun Jul 27 04:44:31 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/log.c: Add some general logging functions.
+
+       * kdc/kerberos4.c: Add version 4 protocol handler. The requrement
+       for this to work is that all involved principals has a des key in
+       the database, and that the client has a version 4 (un-)salted
+       key. Furthermore krb5_425_conv_principal has to do it's job, as
+       present it's not very clever.
+
+       * lib/krb5/principal.c: Quick patch to make 425_conv work
+       somewhat.
+
+       * lib/hdb/hdb.c: Add keytype->key and next key functions.
+
+Fri Jul 25 17:32:12 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): don't free
+       `cksum'.  It's allocated and freed by the caller
+
+       * lib/krb5/get_cred.c (krb5_get_kdc_cred): Don't free `addresses'.
+
+       * kdc/kerberos5.c (tgs_rep2): make sure we also have an defined
+       `client' to return as part of the KRB-ERROR
+
+Thu Jul 24 08:13:59 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c: Unseal keys from database before use.
+
+       * kdc/misc.c: New functions set_master_key, unseal_key and
+       free_key.
+
+       * lib/roken/getarg.c: Handle `-f arg' correctly.
+
+Thu Jul 24 01:54:43 1997  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c: implement `-l' aka `--lifetime'
+
+       * lib/roken/parse_units.c, parse_time.c: new files
+
+       * admin/gettime.c (gettime): use `parse_time'
+
+       * kdc/kerberos5.c (as_rep): Use `METHOD-DATA' when sending
+       KRB5KDC_ERR_PREAUTH_REQUIRED, not PA-DATA.
+
+       * kpasswd/kpasswdd.c: fix freeing bug use sequence numbers set
+       addresses in auth_context bind one socket per interface.
+       
+       * kpasswd/kpasswd.c: use sequence numbers
+
+       * lib/krb5/rd_req.c (krb5_verify_ap_req): do abs when verifying
+       the timestamps
+
+       * lib/krb5/rd_priv.c (krb5_rd_priv): Fetch the correct session key
+       from auth_context
+
+       * lib/krb5/mk_priv.c (krb5_mk_priv): Fetch the correct session key
+       from auth_context
+
+       * lib/krb5/mk_error.c (krb5_mk_error): return an error number and
+       not a comerr'd number.
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_tkt): interpret the error
+       number in KRB-ERROR correctly.
+
+       * lib/krb5/get_cred.c (krb5_get_kdc_cred): interpret the error
+       number in KRB-ERROR correctly.
+
+       * lib/asn1/k5.asn1: Add `METHOD-DATA'
+
+       * removed some memory leaks.
+
+Wed Jul 23 07:53:18 1997  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.0c
+
+       * lib/krb5/rd_cred.c, get_for_creds.c: new files
+
+       * lib/krb5/get_host_realm.c: try default realm as last chance
+
+       * kpasswd/kpasswdd.c: updated to hdb changes
+
+       * appl/telnet/libtelnet/kerberos5.c: Implement forwarding
+
+       * appl/telnet/libtelnet: removed totally unused files
+
+       * admin/ank.c: fix prompts and generation of random keys
+
+Wed Jul 23 04:02:32 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * admin/dump.c: Include salt in dump.
+
+       * admin: Mostly updated for new db-format.
+
+       * kdc/kerberos5.c: Update to use new db format. Better checking of
+       flags and such. More logging.
+
+       * lib/hdb/hdb.c: Use generated encode and decode functions.
+
+       * lib/hdb/hdb.h: Get hdb_entry from ASN.1 generated code.
+
+       * lib/krb5/get_cred.c: Get addresses from krbtgt if there are none
+       in the reply.
+
+Sun Jul 20 16:22:30 1997  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c: break if des_read_pw_string() != 0
+
+       * kpasswd/kpasswdd.c: send a reply
+
+       * kpasswd/kpasswd.c: restructured code.  better report on
+       krb-error break if des_read_pw_string() != 0
+
+       * kdc/kerberos5.c: Check `require_enc_timestamp' malloc space for
+       starttime and renew_till
+
+       * appl/telnet/libtelnet/kerberos5.c (kerberos5_is): Send a
+       keyblock to krb5_verify_chekcsum
+
+Sun Jul 20 06:35:46 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Release 0.0b
+
+       * kpasswd/kpasswd.c: Avoid using non-standard struct names.
+
+Sat Jul 19 19:26:23 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/keytab.c (krb5_kt_get_entry): check return from
+       `krb5_kt_start_seq_get'.  From <map@stacken.kth.se>
+
+Sat Jul 19 04:07:39 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/asn1/k5.asn1: Update with more pa-data types from
+       draft-ietf-cat-kerberos-revisions-00.txt
+
+       * admin/load.c: Update to match current db-format.
+
+       * kdc/kerberos5.c (as_rep): Try all valid pa-datas before giving
+       up. Send back an empty pa-data if the client has the v4 flag set.
+
+       * lib/krb5/get_in_tkt.c: Pass both version5 and version4 salted
+       pa-data. DTRT if there is any pa-data in the reply.
+
+       * lib/krb5/str2key.c: XOR with some sane value.
+
+       * lib/hdb/hdb.h: Add `version 4 salted key' flag.
+
+       * kuser/kinit.c: Ask for password before calling get_in_tkt. This
+       makes it possible to call key_proc more than once.
+
+       * kdc/string2key.c: Add flags to output version 5 (DES only),
+       version 4, and AFS string-to-key of a password.
+
+       * lib/asn1/gen_copy.c: copy_* functions now returns an int (0 or
+       ENOMEM).
+
+Fri Jul 18 02:54:58 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm): do the
+       name2name thing
+
+       * kdc/misc.c: check result of hdb_open
+
+       * admin/kdb_edit: updated to new sl
+
+       * lib/sl: sl_func now returns an int. != 0 means to exit.
+
+       * kpasswd/kpasswdd: A crude (but somewhat working) implementation
+       of `draft-ietf-cat-kerb-chg-password-00.txt'
+
+Fri Jul 18 00:55:39 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kuser/krenew.c: Crude ticket renewing program.
+
+       * kdc/kerberos5.c: Rewritten flags parsing, it now might work to
+       get forwarded and renewed tickets.
+
+       * kuser/kinit.c: Add `-r' flag.
+
+       * lib/krb5/get_cred.c: Move most of contents of get_creds to new
+       function get_kdc_cred, that always contacts the kdc and doesn't
+       save in the cache. This is a hack.
+
+       * lib/krb5/get_in_tkt.c: Pass starttime and renew_till in request
+       (a bit kludgy).
+
+       * lib/krb5/mk_req_ext.c: Make an auth_context if none passed in.
+
+       * lib/krb5/send_to_kdc.c: Get timeout from context.
+
+       * lib/krb5/context.c: Add kdc_timeout to context struct.
+
+Thu Jul 17 20:35:45 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kuser/klist.c: Print start time of ticket if available.
+
+       * lib/krb5/get_host_realm.c: Return error if no realm was found.
+
+Thu Jul 17 20:28:21 1997  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd: non-working kpasswd added
+
+Thu Jul 17 00:21:22 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * Release 0.0a
+
+       * kdc/main.c: Add -p flag to disable pa-enc-timestamp requirement.
+
+Wed Jul 16 03:37:41 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/kerberos5.c (tgs_rep2): Free ticket and ap_req.
+
+       * lib/krb5/auth_context.c (krb5_auth_con_free): Free remote
+       subkey.
+
+       * lib/krb5/principal.c (krb5_free_principal): Check for NULL.
+
+       * lib/krb5/send_to_kdc.c: Check for NULL return from
+       gethostbyname.
+
+       * lib/krb5/set_default_realm.c: Try to get realm of local host if
+       no default realm is available.
+
+       * Remove non ASN.1 principal code.
+
+Wed Jul 16 03:17:30 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/kerberos5.c: Split tgs_rep in smaller functions. Add better
+       error handing. Do some logging.
+
+       * kdc/log.c: Some simple logging facilities.
+
+       * kdc/misc.c (db_fetch): Take a krb5_principal.
+
+       * kdc/connect.c: Pass address of request to as_rep and
+       tgs_rep. Send KRB-ERROR.
+
+       * lib/krb5/mk_error.c: Add more fields.
+
+       * lib/krb5/get_cred.c: Print normal error code if no e_text is
+       available.
+
+Wed Jul 16 03:07:50 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_in_tkt.c: implement `krb5_init_etype'.
+       Change encryption type of pa_enc_timestamp to DES-CBC-MD5
+
+       * lib/krb5/context.c: recognize all encryption types actually
+       implemented
+
+       * lib/krb5/auth_context.c (krb5_auth_con_init): Change default
+       encryption type to `DES_CBC_MD5'
+
+       *  lib/krb5/read_message.c, write_message.c: new files
+
+Tue Jul 15 17:14:21 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1: replaced asn1_locl.h by `der_locl.h' and `gen_locl.h'.
+
+       * lib/error/compile_et.awk: generate a prototype for the
+       `destroy_foo_error_table' function.
+
+Mon Jul 14 12:24:40 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krbhst.c (krb5_get_krbhst): Get all kdc's and try also
+       with `kerberos.REALM'
+
+       * kdc/kerberos5.c, lib/krb5/rd_priv.c, lib/krb5/rd_safe.c: use
+       `max_skew'
+
+       * lib/krb5/rd_req.c (krb5_verify_ap_req): record authenticator
+       subkey
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): always
+       generate a subkey.
+
+       * lib/krb5/address.c: implement `krb5_address_order'
+
+       * lib/gssapi/import_name.c: Implement `gss_import_name'
+
+       * lib/gssapi/external.c: Use new OID
+
+       * lib/gssapi/encapsulate.c: New functions
+       `gssapi_krb5_encap_length' and `gssapi_krb5_make_header'.  Changed
+       callers.
+
+       * lib/gssapi/decapsulate.c: New function
+       `gssaspi_krb5_verify_header'.  Changed callers.
+
+       * lib/asn1/gen*.c: Give tags to generated structs.
+       Use `err' and `asprintf'
+
+       * appl/test/gss_common.c: new file
+
+       * appl/test/gssapi_server.c: removed all krb5 calls
+
+       * appl/telnet/libtelnet/kerberos5.c: Add support for genering and
+       verifying checksums.  Also start using session subkeys.
+
+Mon Jul 14 12:08:25 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/rd_req.c (krb5_rd_req_with_keyblock): Split up.
+
+Sun Jul 13 03:07:44 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_safe.c, mk_safe.c: made bug-compatible with MIT
+
+       * lib/krb5/encrypt.c: new functions `DES_encrypt_null_ivec' and
+       `DES_encrypt_key_ivec'
+
+       * lib/krb5/checksum.c: implement rsa-md4-des and rsa-md5-des
+
+       * kdc/kerberos5.c (tgs_rep): support keyed checksums
+
+       * lib/krb5/creds.c: new file
+
+       * lib/krb5/get_in_tkt.c: better freeing
+
+       * lib/krb5/context.c (krb5_free_context): more freeing
+
+       * lib/krb5/config_file.c: New function `krb5_config_file_free'
+
+       * lib/error/compile_et.awk: Generate a `destroy_' function.
+
+       * kuser/kinit.c, klist.c: Don't leak memory.
+
+Sun Jul 13 02:46:27 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kdc/connect.c: Check filedescriptor in select.
+
+       * kdc/kerberos5.c: Remove most of the most common memory leaks.
+
+       * lib/krb5/rd_req.c: Free allocated data.
+
+       * lib/krb5/auth_context.c (krb5_auth_con_free): Free a lot of
+       fields.
+
+Sun Jul 13 00:32:16 1997  Assar Westerlund  <assar@sics.se>
+
+       * appl/telnet: Conditionalize the krb4-support.
+
+       * configure.in: Test for krb4
+
+Sat Jul 12 17:14:12 1997  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c: check if the pre-auth was decrypted properly.
+       set the `pre_authent' flag
+
+       * lib/krb5/get_cred.c, lib/krb5/get_in_tkt.c: generate a random nonce.
+
+       * lib/krb5/encrypt.c: Made `generate_random_block' global.
+
+       * appl/test: Added gssapi_client and gssapi_server.
+
+       * lib/krb5/data.c: Add `krb5_data_zero'
+
+       * appl/test/tcp_client.c: try `mk_safe' and `mk_priv'
+
+       * appl/test/tcp_server.c: try `rd_safe' and `rd_priv'
+
+Sat Jul 12 16:45:58 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_addrs.c: Fix for systems that has sa_len, but
+       returns zero length from SIOCGIFCONF.
+
+Sat Jul 12 16:38:34 1997  Assar Westerlund  <assar@sics.se>
+
+       * appl/test: new programs
+       
+       * lib/krb5/rd_req.c: add address compare
+
+       * lib/krb5/mk_req_ext.c: allow no checksum
+
+       * lib/krb5/keytab.c (krb5_kt_ret_string): 0-terminate string
+
+       * lib/krb5/address.c: fix `krb5_address_compare'
+
+Sat Jul 12 15:03:16 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/get_addrs.c: Fix ip4 address extraction.
+
+       * kuser/klist.c: Add verbose flag, and split main into smaller
+       pieces.
+
+       * lib/krb5/fcache.c: Save ticket flags.
+
+       * lib/krb5/get_in_tkt.c (extract_ticket): Extract addresses and
+       flags.
+
+       * lib/krb5/krb5.h: Add ticket_flags to krb5_creds.
+
+Sat Jul 12 13:12:48 1997  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: Call `AC_KRB_PROG_LN_S'
+
+       * acinclude.m4: Add `AC_KRB_PROG_LN_S' from krb4
+
+Sat Jul 12 00:57:01 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/get_in_tkt.c: Use union of krb5_flags and KDCOptions to
+       pass options.
+
+Fri Jul 11 15:04:22 1997  Assar Westerlund  <assar@sics.se>
+
+       * appl/telnet: telnet & telnetd seems to be working.
+       
+       * lib/krb5/config_file.c: Added krb5_config_v?get_list Fixed
+       krb5_config_vget_next
+
+       * appl/telnet/libtelnet/kerberos5.c: update to current API
+
+Thu Jul 10 14:54:39 1997  Assar Westerlund  <assar@sics.se>
+
+       * appl/telnet/libtelnet/kerberos5.c (kerberos5_status): call
+       `krb5_kuserok'
+
+       * appl/telnet: Added.
+
+Thu Jul 10 05:09:25 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/error/compile_et.awk: Remove usage of sub, gsub, and
+       functions for compatibility with awk.
+
+       * include/bits.c: Must use signed char.
+
+       * lib/krb5/context.c: Move krb5_get_err_text, and krb5_init_ets
+       here.
+
+       * lib/error/error.c: Replace krb5_get_err_text with new function
+       com_right.
+
+       * lib/error/compile_et.awk: Avoid using static variables.
+
+       * lib/error/error.c: Don't use krb5_locl.h
+
+       * lib/error/error.h: Move definitions of error_table and
+       error_list from krb5.h.
+
+       * lib/error: Moved from lib/krb5.
+
+Wed Jul  9 07:42:04 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/encrypt.c: Temporary hack to avoid des_rand_data.
+
+Wed Jul  9 06:58:00 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/{rd,mk}_{*}.c: more checking for addresses and stuff
+       according to pseudocode from 1510
+
+Wed Jul  9 06:06:06 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/hdb/hdb.c: Add hdb_etype2key.
+
+       * kdc/kerberos5.c: Check authenticator. Use more general etype
+       functions.
+       
+Wed Jul  9 03:51:12 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/k5.asn1: Made all `s_address' OPTIONAL according to
+       draft-ietf-cat-kerberos-r-00.txt
+
+       * lib/krb5/principal.c (krb5_parse_name): default to local realm
+       if none given
+       
+       * kuser/kinit.c: New option `-p' and prompt
+
+Wed Jul  9 02:30:06 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/keyblock.c: Keyblock generation functions.
+
+       * lib/krb5/encrypt.c: Use functions from checksum.c.
+
+       * lib/krb5/checksum.c: Move checksum functions here. Add
+       krb5_cksumsize function.
+
+Wed Jul  9 01:15:38 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_host_realm.c: implemented
+
+       * lib/krb5/config_file.c: Redid part.  New functions:
+       krb5_config_v?get_next
+
+       * kuser/kdestroy.c: new program
+
+       * kuser/kinit.c: new flag `-f'
+
+       * lib/asn1/k5.asn1: Made HostAddresses = SEQUENCE OF HostAddress
+
+       * acinclude.m4: Added AC_KRB_STRUCT_SOCKADDR_SA_LEN
+
+       * lib/krb5/krb5.h: krb5_addresses == HostAddresses.  Changed all
+       users.
+
+       * lib/krb5/get_addrs.c: figure out all local addresses, possibly
+       even IPv6!
+
+       * lib/krb5/checksum.c: table-driven checksum
+
+Mon Jul  7 21:13:28 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/encrypt.c: Make krb5_decrypt use the same struct as
+       krb5_encrypt.
+
+Mon Jul  7 11:15:51 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/roken/vsyslog.c: new file
+
+       * lib/krb5/encrypt.c: add des-cbc-md4.
+       adjust krb5_encrypt and krb5_decrypt to reality
+
+Mon Jul  7 02:46:31 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/encrypt.c: Implement as a vector of function pointers.
+
+       * lib/krb5/{decrypt,encrypt}.c: Implement des-cbc-crc, and
+       des-cbc-md5 in separate functions.
+
+       * lib/krb5/krb5.h: Add more checksum and encryption types.
+
+       * lib/krb5/krb5_locl.h: Add etype to krb5_decrypt.
+
+Sun Jul  6 23:02:59 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/[gs]et_default_realm.c, kuserok.c: new files
+
+       * lib/krb5/config_file.[ch]: new c-based configuration reading
+       stuff
+
+Wed Jul  2 23:12:56 1997  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: Set WFLAGS if using gcc
+
+Wed Jul  2 17:47:03 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/asn1/der_put.c (der_put_int): Return size correctly.
+
+       * admin/ank.c: Be compatible with the asn1 principal format.
+
+Wed Jul  1 23:52:20 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/asn1: Now all decode_* and encode_* functions now take a
+       final size_t* argument, that they return the size in. Return
+       values are zero for success, and anything else (such as some
+       ASN1_* constant) for error.
+
+Mon Jun 30 06:08:14 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/keytab.c (krb5_kt_add_entry): change open mode to
+       O_WRONLY | O_APPEND
+
+       * lib/krb5/get_cred.c: removed stale prototype for
+       `extract_ticket' and corrected call.
+
+       * lib/asn1/gen_length.c (length_type): Make the length functions
+       for SequenceOf non-destructive
+
+       * admin/ank.c (doit): Fix reading of `y/n'.
+
+Mon Jun 16 05:41:43 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/gssapi/wrap.c, unwrap.c: do encrypt and add sequence number
+
+       * lib/gssapi/get_mic.c, verify_mic.c: Add sequence number.
+
+       * lib/gssapi/accept_sec_context.c (gss_accept_sec_context): Set
+       KRB5_AUTH_CONTEXT_DO_SEQUENCE.  Verify 8003 checksum.
+
+       * lib/gssapi/8003.c: New file.
+
+       * lib/krb/krb5.h: Define a `krb_authenticator' as an ASN.1
+       Authenticator.
+
+       * lib/krb5/auth_context.c: New functions
+       `krb5_auth_setlocalseqnumber' and `krb5_auth_setremoteseqnumber'
+
+Tue Jun 10 00:35:54 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5: Preapre for use of some asn1-types.
+
+       * lib/asn1/*.c (copy_*): Constness.
+
+       * lib/krb5/krb5.h: Include asn1.h; krb5_data is now an
+       octet_string.
+
+       * lib/asn1/der*,gen.c: krb5_data -> octet_string, char * ->
+       general_string
+
+       * lib/asn1/libasn1.h: Moved stuff from asn1_locl.h that doesn't
+       have anything to do with asn1_compile.
+
+       * lib/asn1/asn1_locl.h: Remove der.h. Add some prototypes.
+
+Sun Jun  8 03:51:55 1997  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c: Fix PA-ENC-TS-ENC
+
+       * kdc/connect.c(process_request): Set `new'
+       
+       * lib/krb5/get_in_tkt.c: Do PA-ENC-TS-ENC the correct way.
+
+       * lib: Added editline,sl,roken.
+
+Mon Jun  2 00:37:48 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/fcache.c: Move file cache from cache.c.
+
+       * lib/krb5/cache.c: Allow more than one cache type.
+
+Sun Jun  1 23:45:33 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * admin/extkeytab.c: Merged with kdb_edit.
+
+Sun Jun  1 23:23:08 1997  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kdc.c: more support for ENC-TS-ENC
+
+       * lib/krb5/get_in_tkt.c: redone to enable pre-authentication
+
+Sun Jun  1 22:45:11 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/hdb/db.c: Merge fetch and store.
+
+       * admin: Merge to one program.
+
+       * lib/krb5/str2key.c: Fill in keytype and length.
+
+Sun Jun  1 16:31:23 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_safe.c, lib/krb5/rd_priv.c, lib/krb5/mk_rep.c,
+       lib/krb5/mk_priv.c, lib/krb5/build_auth.c: Some support for
+       KRB5_AUTH_CONTEXT_DO_SEQUENCE
+
+       * lib/krb5/get_in_tkt.c (get_in_tkt): be prepared to parse an
+       KRB_ERROR.  Some support for PA_ENC_TS_ENC.
+
+       * lib/krb5/auth_context.c: implemented seq_number functions
+
+       * lib/krb5/generate_subkey.c, generate_seq_number.c: new files
+
+       * lib/gssapi/gssapi.h: avoid including <krb5.h>
+
+       * lib/asn1/Makefile.am: SUFFIXES as a variable to make automake
+       happy
+
+       * kdc/kdc.c: preliminary PREAUTH_ENC_TIMESTAMP
+
+       * configure.in: adapted to automake 1.1p
+
+Mon May 26 22:26:21 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/principal.c: Add contexts to many functions.
+
+Thu May 15 20:25:37 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/verify_user.c: First stab at a verify user.
+
+       * lib/auth/sia/sia5.c: SIA module for Kerberos 5.
+
+Mon Apr 14 00:09:03 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/gssapi: Enough of a gssapi-over-krb5 implementation to be
+       able to (mostly) run gss-client and gss-server.
+       
+       * lib/krb5/keytab.c: implemented krb5_kt_add_entry,
+       krb5_kt_store_principal, krb5_kt_store_keyblock
+
+       * lib/des/md5.[ch], sha.[ch]: new files
+
+       * lib/asn1/der_get.c (generalizedtime2time): use `timegm'
+
+       * lib/asn1/timegm.c: new file
+
+       * admin/extkeytab.c: new program
+
+       * admin/admin_locl.h: new file
+
+       * admin/Makefile.am: Added extkeytab
+
+       * configure.in: moved config to include
+       removed timezone garbage
+       added lib/gssapi and admin
+
+       * Makefile.am: Added admin
+
+Mon Mar 17 11:34:05 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/kdc.c: Use new copying functions, and free some data.
+
+       * lib/asn1/Makefile.am: Try to not always rebuild generated files.
+
+       * lib/asn1/der_put.c: Add fix_dce().
+
+       * lib/asn1/der_{get,length,put}.c: Fix include files.
+
+       * lib/asn1/der_free.c: Remove unused functions.
+       
+       * lib/asn1/gen.c: Split into gen_encode, gen_decode, gen_free,
+       gen_length, and gen_copy.
+
+Sun Mar 16 18:13:52 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/sendauth.c: implemented functionality
+
+       * lib/krb5/rd_rep.c: Use `krb5_decrypt'
+
+       * lib/krb5/cache.c (krb5_cc_get_name): return default if `id' ==
+       NULL
+
+       * lib/krb5/principal.c (krb5_free_principal): added `context'
+       argument.  Changed all callers.
+       
+       (krb5_sname_to_principal): new function
+
+       * lib/krb5/auth_context.c (krb5_free_authenticator): add `context'
+       argument.  Changed all callers
+
+       * lib/krb5/{net_write.c,net_read.c,recvauth.c}: new files
+
+       * lib/asn1/gen.c: Fix encoding and decoding of BitStrings
+
+Fri Mar 14 11:29:00 1997  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: look for *dbm?
+
+       * lib/asn1/gen.c: Fix filename in generated files. Check fopens.
+       Put trailing newline in asn1_files.
+
+Fri Mar 14 05:06:44 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/get_in_tkt.c: Fix some memory leaks.
+
+       * lib/krb5/krbhst.c: Properly free hostlist.
+
+       * lib/krb5/decrypt.c: CRCs are 32 bits.
+
+Fri Mar 14 04:39:15 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/asn1/gen.c: Generate one file for each type.
+
+Fri Mar 14 04:13:47 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/gen.c: Generate `length_FOO' functions
+
+       * lib/asn1/der_length.c: new file
+
+       * kuser/klist.c: renamed stime -> printable_time to avoid conflict
+       on HP/UX
+
+Fri Mar 14 03:37:23 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/hdb/ndbm.c: Return NOENTRY if fetch fails. Don't free
+       datums. Don't add .db to filename.
+
+Fri Mar 14 02:49:51 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/dump.c: Database dump program.
+
+       * kdc/ank.c: Trivial database editing program.
+
+       * kdc/{kdc.c, load.c}: Use libhdb.
+
+       * lib/hdb: New database routine library.
+
+       * lib/krb5/error/Makefile.am: Add hdb_err.
+
+Wed Mar 12 17:41:14 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * kdc/kdc.c: Rewritten AS, and somewhat more working TGS support.
+
+       * lib/asn1/gen.c: Generate free functions.
+
+       * Some specific free functions.
+
+Wed Mar 12 12:30:13 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5_mk_req_ext.c: new file
+
+       * lib/asn1/gen.c: optimize the case with a simple type
+
+       * lib/krb5/get_cred.c (krb5_get_credentials): Use
+       `mk_req_extended' and remove old code.
+
+       * lib/krb5/get_in_tkt.c (decrypt_tkt): First try with an
+       EncASRepPart, then with an EncTGSRepPart.
+
+Wed Mar 12 08:26:04 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/store_emem.c: New resizable memory storage.
+
+       * lib/krb5/{store.c, store_fd.c, store_mem.c}: Split of store.c
+
+       * lib/krb5/krb5.h: Add free entry to krb5_storage.
+
+       * lib/krb5/decrypt.c: Make keyblock const.
+
+Tue Mar 11 20:22:17 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/krb5.h: Add EncTicketPart to krb5_ticket.
+
+       * lib/krb5/rd_req.c: Return whole asn.1 ticket in
+       krb5_ticket->tkt.
+
+       * lib/krb5/get_in_tkt.c: TGS -> AS
+
+       * kuser/kfoo.c: Print error string rather than number.
+
+       * kdc/kdc.c: Some kind of non-working TGS support.
+
+Mon Mar 10 01:43:22 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/gen.c: reduced generated code by 1/5
+
+       * lib/asn1/der_put.c: (der_put_length_and_tag): new function
+
+       * lib/asn1/der_get.c (der_match_tag_and_length): new function
+
+       * lib/asn1/der.h: added prototypes
+
+Mon Mar 10 01:15:43 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/krb5.h: Include <asn1_err.h>. Add prototype for
+       krb5_rd_req_with_keyblock.
+
+       * lib/krb5/rd_req.c: Add function krb5_rd_req_with_keyblock that
+       takes a precomputed keyblock.
+
+       * lib/krb5/get_cred.c: Use krb5_mk_req rather than inlined code.
+
+       * lib/krb5/mk_req.c: Calculate checksum of in_data.
+
+Sun Mar  9 21:17:58 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/error/compile_et.awk: Add a declaration of struct
+       error_list, and multiple inclusion block to header files.
+
+Sun Mar  9 21:01:12 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_req.c: do some checks on times
+
+       * lib/krb/{mk_priv.c, rd_priv.c, sendauth.c, decrypt.c,
+       address.c}: new files
+
+       * lib/krb5/auth_context.c: more code
+
+       * configure.in: try to figure out timezone
+
+Sat Mar  8 11:41:07 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/error/error.c: Try strerror if error code wasn't found.
+
+       * lib/krb5/get_in_tkt.c: Remove realm parameter from
+       krb5_get_salt.
+
+       * lib/krb5/context.c: Initialize error table.
+
+       * kdc: The beginnings of a kdc.
+
+Sat Mar  8 08:16:28 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_safe.c: new file
+
+       * lib/krb5/checksum.c (krb5_verify_checksum): New function
+
+       * lib/krb5/get_cred.c: use krb5_create_checksum
+
+       * lib/krb5/checksum.c: new file
+
+       * lib/krb5/store.c: no more arithmetic with void*
+
+       * lib/krb5/cache.c: now seems to work again
+
+Sat Mar  8 06:58:09 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/Makefile.am: Add asn1_glue.c and error/*.c to libkrb5.
+
+       * lib/krb5/get_in_tkt.c: Moved some functions to asn1_glue.c.
+
+       * lib/krb5/asn1_glue.c: Moved some asn1-stuff here.
+       
+       * lib/krb5/{cache,keytab}.c: Use new storage functions.
+
+       * lib/krb5/krb5.h: Protypes for new storage functions.
+
+       * lib/krb5/krb5.h: Make krb5_{ret,store}_* functions able to write
+       data to more than file descriptors.
+
+Sat Mar  8 01:01:17 1997  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/encrypt.c: New file.
+
+       * lib/krb5/Makefile.am: More -I
+
+       * configure.in: Test for big endian, random, rand, setitimer
+
+       * lib/asn1/gen.c: perhaps even decodes bitstrings
+
+Thu Mar  6 19:05:29 1997  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/config_file.y: Better return values on error.
+
+Sat Feb  8 15:59:56 1997  Assar Westerlund  <assar@pdc.kth.se>
+
+       * lib/asn1/parse.y: ifdef HAVE_STRDUP
+
+       * lib/asn1/lex.l: ifdef strdup
+       brange-dead version of list of special characters to make stupid
+       lex accept it.
+
+       * lib/asn1/gen.c: A DER integer should really be a `unsigned'
+
+       * lib/asn1/der_put.c: A DER integer should really be a `unsigned'
+
+       * lib/asn1/der_get.c: A DER integer should really be a `unsigned'
+
+       * lib/krb5/error/Makefile.am: It seems "$(SHELL) ./compile_et" is
+       needed.
+
+       * lib/krb/mk_rep.c, lib/krb/rd_req.c, lib/krb/store.c,
+       lib/krb/store.h: new files.
+
+       * lib/krb5/keytab.c: now even with some functionality.
+
+       * lib/asn1/gen.c: changed paramater from void * to Foo *
+
+       * lib/asn1/der_get.c (der_get_octet_string): Fixed bug with empty
+       string.
+
+Sun Jan 19 06:17:39 1997  Assar Westerlund  <assar@pdc.kth.se>
+
+       * lib/krb5/get_cred.c (krb5_get_credentials): Check for creds in
+       cc before getting new ones.
+
+       * lib/krb5/krb5.h (krb5_free_keyblock): Fix prototype.
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): It seems the
+       CRC should be stored LSW first. (?)
+
+       * lib/krb5/auth_context.c: Implement `krb5_auth_con_getkey' and
+       `krb5_free_keyblock'
+
+       * lib/**/Makefile.am: Rename foo libfoo.a
+
+       * include/Makefile.in: Use test instead of [
+       -e does not work with /bin/sh on psoriasis
+
+       * configure.in: Search for awk
+       create lib/krb/error/compile_et
+       
+Tue Jan 14 03:46:26 1997  Assar Westerlund  <assar@pdc.kth.se>
+
+       * lib/krb5/Makefile.am: replaced mit-crc.c by crc.c
+
+Wed Dec 18 00:53:55 1996  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * kuser/kinit.c: Guess principal.
+
+       * lib/krb5/error/compile_et.awk: Don't include krb5.h. Fix some
+       warnings.
+
+       * lib/krb5/error/asn1_err.et: Add ASN.1 error messages.
+
+       * lib/krb5/mk_req.c: Get client from cache.
+
+       * lib/krb5/cache.c: Add better error checking some useful return
+       values.
+
+       * lib/krb5/krb5.h: Fix krb5_auth_context.
+
+       * lib/asn1/der.h: Make krb5_data compatible with krb5.h
+
+Tue Dec 17 01:32:36 1996  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/error: Add primitive error library.
+
+Mon Dec 16 16:30:20 1996  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * lib/krb5/cache.c: Get correct address type from cache.
+
+       * lib/krb5/krb5.h: Change int16 to int to be compatible with asn1.
+
diff --git a/src/kerberosV/src/ChangeLog.1999 b/src/kerberosV/src/ChangeLog.1999
new file mode 100644 (file)
index 0000000..e022b96
--- /dev/null
@@ -0,0 +1,2194 @@
+1999-12-30  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (krb4): use `-ldes' in tests
+
+1999-12-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/print.c (event2string): handle events without principal.
+       From Luke Howard <lukeh@PADL.COM>
+
+1999-12-25  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2j
+
+Tue Dec 21 18:03:17 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/Makefile.am (asn1_files): add $(EXEEXT) for cygwin and
+       related systems
+
+       * lib/asn1/Makefile.am (asn1_files): add $(EXEEXT) for cygwin and
+       related systems
+
+       * include/Makefile.am (krb5-types.h): add $(EXEEXT) for cygwin and
+       related systems
+
+1999-12-20  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2i
+
+1999-12-20  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): bump version to 6:3:1
+
+       * lib/krb5/send_to_kdc.c (send_via_proxy): free data
+       * lib/krb5/send_to_kdc.c (send_via_proxy): new function use
+       getaddrinfo instead of gethostbyname{,2}
+       * lib/krb5/get_for_creds.c: use getaddrinfo instead of
+       getnodebyname{,2}
+
+1999-12-17  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2h
+
+1999-12-17  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2g
+
+1999-12-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: bump version to 6:2:1
+
+       * lib/krb5/principal.c (krb5_sname_to_principal): handle
+       ai_canonname not being set
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname): handle
+       ai_canonname not being set
+
+       * appl/test/uu_server.c: print messages to stderr
+       * appl/test/tcp_server.c: print messages to stderr
+       * appl/test/nt_gss_server.c: print messages to stderr
+       * appl/test/gssapi_server.c: print messages to stderr
+
+       * appl/test/tcp_client.c (proto): remove shadowing `context'
+       * appl/test/common.c (client_doit): add forgotten ntohs
+
+1999-12-13  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (VERISON): bump to 0.2g-pre
+
+1999-12-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): be more
+       robust and handle extra dot at the beginning of default_domain
+
+1999-12-12  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2f
+
+1999-12-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: bump version to 6:1:1
+       
+       * lib/krb5/changepw.c (get_kdc_address): use
+       `krb5_get_krb_changepw_hst'
+
+       * lib/krb5/krbhst.c (krb5_get_krb_changepw_hst): add
+
+       * lib/krb5/get_host_realm.c: add support for _kerberos.domain
+       (according to draft-ietf-cat-krb-dns-locate-01.txt)
+
+1999-12-06  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2e
+
+1999-12-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/changepw.c (krb5_change_password): use the correct
+       address
+
+       * lib/krb5/Makefile.am: bump version to 6:0:1
+
+       * lib/asn1/Makefile.am: bump version to 1:4:0
+
+1999-12-04  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: move AC_KRB_IPv6 to make sure it's performed
+       before AC_BROKEN
+       (el_init): use new feature of AC_FIND_FUNC_NO_LIBS
+
+       * appl/test/uu_client.c: use client_doit
+       * appl/test/test_locl.h (client_doit): add prototype
+       * appl/test/tcp_client.c: use client_doit
+       * appl/test/nt_gss_client.c: use client_doit
+       * appl/test/gssapi_client.c: use client_doit
+       * appl/test/common.c (client_doit): move identical code here and
+       start using getaddrinfo
+
+       * appl/kf/kf.c (doit): rewrite to use getaddrinfo
+       * kdc/hprop.c: re-write to use getaddrinfo
+       * lib/krb5/principal.c (krb5_sname_to_principal): use getaddrinfo
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname): use
+       getaddrinfo
+       * lib/krb5/changepw.c: re-write to use getaddrinfo
+       * lib/krb5/addr_families.c (krb5_parse_address): use getaddrinfo
+
+1999-12-03  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (BROKEN): check for freeaddrinfo, getaddrinfo,
+       getnameinfo, gai_strerror
+       (socklen_t): check for
+
+1999-12-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/crypto.c: ARCFOUR_set_key -> RC4_set_key
+
+1999-11-23  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (ARCFOUR_string_to_key): change order of bytes
+       within unicode characters.  this should probably be done in some
+       arbitrarly complex way to do it properly and you would have to
+       know what character encoding was used for the password and salt
+       string.
+
+       * lib/krb5/addr_families.c (ipv4_uninteresting): ignore 0.0.0.0
+       (INADDR_ANY)
+       (ipv6_uninteresting): remove unused macro
+
+1999-11-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: rc4->arcfour
+
+       * lib/krb5/crypto.c: rc4->arcfour
+
+1999-11-17  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5_locl.h: add <rc4.h>
+       * lib/krb5/krb5.h (krb5_keytype): add KEYTYPE_RC4
+       * lib/krb5/crypto.c: some code for doing RC4/MD5/HMAC which might
+       not be totally different from some small company up in the
+       north-west corner of the US
+
+       * lib/krb5/get_addrs.c (find_all_addresses): change code to
+       actually increment buf_size
+
+1999-11-14  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.h (krb5_context_data): add `scan_interfaces'
+       * lib/krb5/get_addrs.c (krb5_get_all_client_addrs): make interaces
+       scanning optional
+       * lib/krb5/context.c (init_context_from_config_file): set
+       `scan_interfaces'
+
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add add_et_list.c
+       * lib/krb5/add_et_list.c (krb5_add_et_list): new function
+
+1999-11-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_default_realm.c (krb5_get_default_realm,
+       krb5_get_default_realms): set realms if they were unset
+       * lib/krb5/context.c (init_context_from_config_file): don't
+       initialize default realms here.  it's done lazily instead.
+       
+       * lib/krb5/krb5.h (KRB5_TC_*): make constants unsigned
+       * lib/asn1/gen_glue.c (generate_2int, generate_units): make sure
+       bit constants are unsigned
+       * lib/asn1/gen.c (define_type): make length in sequences be
+       unsigned.
+
+       * configure.in: remove duplicate test for setsockopt test for
+       struct tm.tm_isdst
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): generate
+       preauthentication information if we get back ERR_PREAUTH_REQUIRED
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): remove
+       preauthentication generation code.  it's now in krb5_get_in_cred
+       
+       * configure.in (AC_BROKEN_SNPRINTF): add strptime check for struct
+       tm.tm_gmtoff and timezone
+       
+1999-11-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/main.c: make this work with multi-db
+
+       * kdc/kdc_locl.h: make this work with multi-db
+
+       * kdc/config.c: make this work with multi-db
+
+1999-11-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/misc.c: update for multi-database code
+
+       * kdc/main.c: update for multi-database code
+
+       * kdc/kdc_locl.h: update
+
+       * kdc/config.c: allow us to have more than one database
+
+1999-11-04  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2d
+
+       * lib/krb5/Makefile.am: bump version to 5:0:0 to be safe
+       (krb5_context_data has changed and some code do (might) access
+       fields directly)
+
+       * lib/krb5/krb5.h (krb5_context_data): add `etypes_des'
+
+       * lib/krb5/get_cred.c (init_tgs_req): use
+       krb5_keytype_to_enctypes_default
+
+       * lib/krb5/crypto.c (krb5_keytype_to_enctypes_default): new
+       function
+
+       * lib/krb5/context.c (set_etypes): new function
+       (init_context_from_config_file): set both `etypes' and `etypes_des'
+
+1999-11-02  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (VERSION): bump to 0.2d-pre
+
+1999-10-29  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (krb5_parse_name): check memory allocations
+
+1999-10-28  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2c
+
+       * lib/krb5/dump_config.c (print_tree): check for empty tree
+
+       * lib/krb5/string-to-key-test.c (tests): update the test cases
+       with empty principals so that they actually use an empty realm and
+       not the default.  use the correct etype for 3DES
+
+       * lib/krb5/Makefile.am: bump version to 4:1:0
+
+       * kdc/config.c (configure): more careful with the port string
+
+1999-10-26  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2b
+
+1999-10-20  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: bump version to 4:0:0
+       (krb524_convert_creds_kdc and potentially some other functions
+       have changed prototypes)
+
+       * lib/hdb/Makefile.am: bump version to 4:0:1
+
+       * lib/asn1/Makefile.am: bump version to 1:3:0
+
+       * configure.in (LIB_roken): add dbopen.  getcap in roken
+       references dbopen and with shared libraries we need to add this
+       dependency.
+
+       * lib/krb5/verify_krb5_conf.c (main): support speicifying the
+       configuration file to test on the command line
+
+       * lib/krb5/config_file.c (parse_binding): handle line with no
+       whitespace before =
+       (krb5_config_parse_file_debug): set lineno earlier so that we don't
+       use it unitialized
+
+       * configure.in (AM_INIT_AUTOMAKE): bump to 0.2b-pre opt*: need
+       more include files for these tests
+
+       * lib/krb5/set_default_realm.c (krb5_set_default_realm): use
+       krb5_config_get_strings, which means that your configuration file
+       should look like:
+       
+       [libdefaults]
+         default_realm = realm1 realm2 realm3
+
+       * lib/krb5/set_default_realm.c (config_binding_to_list): fix
+       copy-o.  From Michal Vocu <michal@karlin.mff.cuni.cz>
+
+       * kdc/config.c (configure): add a missing strdup.  From Michal
+       Vocu <michal@karlin.mff.cuni.cz>
+
+1999-10-17  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2a
+
+       * configure.in: only test for db.h with using berkeley_db. remember
+       to link with LIB_tgetent when checking for el_init. add xnlock
+
+       * appl/Makefile.am: add xnlock
+
+       * kdc/kerberos5.c (find_etype): support null keys
+
+       * kdc/kerberos4.c (get_des_key): support null keys
+
+       * lib/krb5/crypto.c (krb5_get_wrapped_length): more correct
+       calculation
+
+1999-10-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c (main): pass ccache to krb524_convert_creds_kdc
+
+1999-10-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/crypto.c (krb5_enctype_to_keytype): remove warning
+
+1999-10-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_req.c (krb5_mk_req): use krb5_free_host_realm
+
+       * lib/krb5/krb5.h (krb5_ccache_data): make `ops' const
+
+       * lib/krb5/crypto.c (krb5_string_to_salttype): new function
+
+       * **/*.[ch]: const-ize
+
+1999-10-06  Assar Westerlund  <assar@sics.se>
+       
+       * lib/krb5/creds.c (krb5_compare_creds): const-ify
+       
+       * lib/krb5/cache.c: clean-up and comment-up
+
+       * lib/krb5/copy_host_realm.c (krb5_copy_host_realm): copy all the
+       strings
+
+       * lib/krb5/verify_user.c (krb5_verify_user_lrealm): free the
+       correct realm part
+
+       * kdc/connect.c (handle_tcp): things work much better when ret is
+       initialized
+
+1999-10-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): look at the
+       type of the session key
+
+       * lib/krb5/crypto.c (krb5_enctypes_compatible_keys): spell
+       correctly
+
+       * lib/krb5/creds.c (krb5_compare_creds): fix spelling of
+       krb5_enctypes_compatible_keys
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): get new
+       credentials from the KDC if the existing one doesn't have a DES
+       session key.
+
+       * lib/45/get_ad_tkt.c (get_ad_tkt): update to new
+       krb524_convert_creds_kdc
+
+1999-10-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_keyfile.c: make krb5_akf_ops const
+
+       * lib/krb5/keytab_memory.c: make krb5_mkt_ops const
+
+       * lib/krb5/keytab_file.c: make krb5_fkt_ops const
+
+1999-10-01  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/config_file.c: rewritten to allow error messages
+
+       * lib/krb5/Makefile.am (bin_PROGRAMS): add verify_krb5_conf
+       (libkrb5_la_SOURCES): add config_file_netinfo.c
+
+       * lib/krb5/verify_krb5_conf.c: new program for verifying that
+       krb5.conf is corret
+
+       * lib/krb5/config_file_netinfo.c: moved netinfo code here from
+       config_file.c
+
+1999-09-28  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c (dump_krb4): kludge default_realm
+
+       * lib/asn1/check-der.c: add test cases for Generalized time and
+       make sure we return the correct value
+
+       * lib/asn1/der_put.c: simplify by using der_put_length_and_tag
+
+       * lib/krb5/verify_user.c (krb5_verify_user_lrealm): ariant of
+       krb5_verify_user that tries in all the local realms
+
+       * lib/krb5/set_default_realm.c: add support for having several
+       default realms
+
+       * lib/krb5/kuserok.c (krb5_kuserok): use `krb5_get_default_realms'
+
+       * lib/krb5/get_default_realm.c (krb5_get_default_realms): add
+
+       * lib/krb5/krb5.h (krb5_context_data): change `default_realm' to
+       `default_realms'
+
+       * lib/krb5/context.c: change from `default_realm' to
+       `default_realms'
+
+       * lib/krb5/aname_to_localname.c (krb5_aname_to_localname): use
+       krb5_get_default_realms
+
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add copy_host_realm.c
+
+       * lib/krb5/copy_host_realm.c: new file
+
+1999-09-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/asn1/der_put.c (encode_generalized_time): encode length
+
+       * lib/krb5/recvauth.c: new function `krb5_recvauth_match_version'
+       that allows more intelligent matching of the application version
+
+1999-09-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/asn1_print.c: add err.h
+
+       * kdc/config.c (configure): use parse_bytes
+
+       * appl/test/nt_gss_common.c: use the correct header file
+
+1999-09-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.c: add a `--cache' flag
+
+       * kuser/kinit.c (main): only get default value for `get_v4_tgt' if
+       it's explicitly set in krb5.conf
+
+1999-09-23  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/asn1_print.c (tag_names); add another univeral tag
+
+       * lib/asn1/der.h: update universal tags
+
+1999-09-22  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/asn1_print.c (loop): print length of octet string
+
+1999-09-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/ktutil.c (kt_get): add `--help'
+
+1999-09-21  Assar Westerlund  <assar@sics.se>
+
+       * kuser/Makefile.am: add kdecode_ticket
+
+       * kuser/kdecode_ticket.c: new debug program
+
+       * appl/test/nt_gss_server.c: new program to test against `Sample *
+       SSPI Code' in Windows 2000 RC1 SDK.
+
+       * appl/test/Makefile.am: add nt_gss_client and nt_gss_server
+
+       * lib/asn1/der_get.c (decode_general_string): remember to advance
+       ret over the length-len
+
+       * lib/asn1/Makefile.am: add asn1_print
+
+       * lib/asn1/asn1_print.c: new program for printing DER-structures
+
+       * lib/asn1/der_put.c: make functions more consistent
+
+       * lib/asn1/der_get.c: make functions more consistent
+
+1999-09-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c: be more informative in pa-data error messages
+
+1999-09-16  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: test for strlcpy, strlcat
+
+1999-09-14  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): return
+       KRB5_LIBOS_PWDINTR when interrupted
+
+       * lib/krb5/get_in_tkt_pw.c (krb5_password_key_proc): check return
+       value from des_read_pw_string
+
+       * kuser/kinit.c (main): don't print any error if reading the
+       password was interrupted
+
+       * kpasswd/kpasswd.c (main): don't print any error if reading the
+       password was interrupted
+
+       * kdc/string2key.c (main): check the return value from fgets
+
+       * kdc/kstash.c (main): check return value from des_read_pw_string
+
+       * admin/ktutil.c (kt_add): check the return-value from fgets and
+       overwrite the password for paranoid reasons
+
+       * lib/krb5/keytab_keyfile.c (get_cell_and_realm): only remove the
+       newline if it's there
+
+1999-09-13  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c (main): remove bogus error with `--print'.  remove
+       sysloging of number of principals transferred
+
+       * kdc/hprop.c (ka_convert): set flags correctly for krbtgt/CELL
+       principals
+       (main): get rid of bogus opening of hdb database when propagating
+       ka-server database
+
+1999-09-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5_locl.h (O_BINARY): add fallback definition
+
+       * lib/krb5/krb5.h (krb5_context_data): add keytab types
+
+       * configure.in: revert back awk test, not worked around in
+       roken.awk
+
+       * lib/krb5/keytab_krb4.c: remove O_BINARY
+
+       * lib/krb5/keytab_keyfile.c: some support for AFS KeyFile's.  From
+       Love <lha@e.kth.se>
+
+       * lib/krb5/keytab_file.c: remove O_BINARY
+
+       * lib/krb5/keytab.c: move the list of keytab types to the context
+
+       * lib/krb5/fcache.c: remove O_BINARY
+
+       * lib/krb5/context.c (init_context_from_config_file): register all
+       standard cache and keytab types
+       (krb5_free_context): free `kt_types'
+
+       * lib/krb5/cache.c (krb5_cc_resolve): move the registration of the
+       standard types of credential caches to context
+
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add keytab_keyfile.c
+
+1999-09-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/keytab.c: add comments and clean-up
+
+       * admin/ktutil.c: add `ktutil copy'
+
+       * lib/krb5/keytab_krb4.c: new file
+
+       * lib/krb5/krb5.h (krb5_kt_cursor): add a `data' field
+
+       * lib/krb5/Makefile.am: add keytab_krb4.c
+
+       * lib/krb5/keytab.c: add krb4 and correct some if's
+
+       * admin/srvconvert.c (srvconv): move common code
+
+       * lib/krb5/krb5.h (krb5_fkt_ops, krb5_mkt_ops): new variables
+
+       * lib/krb5/keytab.c: move out file and memory functions
+
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add keytab_file.c,
+       keytab_memory.c
+
+       * lib/krb5/keytab_memory.c: new file
+
+       * lib/krb5/keytab_file.c: new file
+
+       * kpasswd/kpasswdd.c: move out password quality functions
+
+1999-09-07  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/Makefile.am (libhdb_la_SOURCES): add keytab.c.  From
+       Love <lha@e.kth.se>
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): check
+       return value from `krb5_sendto_kdc'
+
+1999-09-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (send_and_recv): rename to recv_loop and
+       remove the sending of data.  add a parameter `limit'.  let callers
+       send the date themselves (and preferably with net_write on tcp
+       sockets)
+       (send_and_recv_tcp): read first the length field and then only that
+       many bytes
+
+1999-09-05  Assar Westerlund  <assar@sics.se>
+
+       * kdc/connect.c (handle_tcp): try to print warning `TCP data of
+       strange type' less often
+
+       * lib/krb5/send_to_kdc.c (send_and_recv): handle EINTR properly.
+       return on EOF.  always free data.  check return value from
+       realloc.
+       (send_and_recv_tcp, send_and_recv_http): check advertised length
+       against actual length
+
+1999-09-01  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: check for sgi capabilities
+
+1999-08-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/get_addrs.c: krb5_get_all_server_addrs shouldn't return
+       extra addresses
+
+       * kpasswd/kpasswdd.c: use HDB keytabs; change some error messages;
+       add --realm flag
+
+       * lib/krb5/address.c (krb5_append_addresses): remove duplicates
+
+1999-08-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/keytab.c: HDB keytab backend
+
+1999-08-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab.c
+       (krb5_kt_{start_seq_get,next_entry,end_seq_get}): check for NULL
+       pointer
+
+1999-08-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kpasswd/kpasswdd.c: add `--keytab' flag
+
+1999-08-23  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c (IN6_ADDR_V6_TO_V4): use `s6_addr'
+       instead of the non-standard `s6_addr32'.  From Yoshinobu Inoue
+       <shin@kame.net> by way of the KAME repository
+
+1999-08-18  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (--enable-new-des3-code): remove check for `struct
+       addrinfo'
+
+       * lib/krb5/crypto.c (etypes): remove NEW_DES3_CODE, enable
+       des3-cbc-sha1 and keep old-des3-cbc-sha1 for backwards
+       compatability
+
+       * lib/krb5/krb5.h (krb5_enctype): des3-cbc-sha1 (with key
+       derivation) just got assigned etype 16 by <bcn@isi.edu>.  keep the
+       old etype at 7.
+
+1999-08-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/sendauth.c (krb5_sendauth): only look at errno if
+       krb5_net_read actually returns -1
+
+       * lib/krb5/recvauth.c (krb5_recvauth): only look at errno if
+       krb5_net_read actually returns -1
+
+       * appl/kf/kf.c (proto): don't trust errno if krb5_net_read hasn't
+       returned -1
+
+       * appl/test/tcp_server.c (proto): only trust errno if
+       krb5_net_read actually returns -1
+
+       * appl/kf/kfd.c (proto): be more careful with the return value
+       from krb5_net_read
+
+1999-08-13  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_addrs.c (get_addrs_int): try the different ways
+       sequentially instead of just one.  this helps if your heimdal was
+       built with v6-support but your kernel doesn't have it, for
+       example.
+
+1999-08-12  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c: add inetd flag.  default means try to figure out
+       if stdin is a socket or not.
+
+       * Makefile.am (ACLOCAL): just use `cf', this variable is only used
+       when the current directory is $(top_srcdir) anyways and having
+       $(top_srcdir) there breaks if it's a relative path
+
+1999-08-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: check for setproctitle
+
+1999-08-05  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (krb5_sname_to_principal): remember to call
+       freehostent
+
+       * appl/test/tcp_client.c: call freehostent
+
+       * appl/kf/kf.c (doit): call freehostent
+
+       * appl/kf/kf.c: make v6 friendly and simplify
+
+       * appl/kf/kfd.c: make v6 friendly and simplify
+
+       * appl/test/tcp_server.c: simplify by using krb5_err instead of
+       errx
+       
+       * appl/test/tcp_client.c: simplify by using krb5_err instead of
+       errx
+
+       * appl/test/tcp_server.c: make v6 friendly and simplify
+
+       * appl/test/tcp_client.c: make v6 friendly and simplify
+
+1999-08-04  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1m
+
+1999-08-04  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c (main): some more KRB4-conditionalizing
+
+       * lib/krb5/get_in_tkt.c: type correctness
+
+       * lib/krb5/get_for_creds.c (krb5_fwd_tgs_creds): set forwarded in
+       flags.  From Miroslav Ruda <ruda@ics.muni.cz>
+
+       * kuser/kinit.c (main): add config file support for forwardable
+       and krb4 support.  From Miroslav Ruda <ruda@ics.muni.cz>
+
+       * kdc/kerberos5.c (as_rep): add an empty X500-compress string as
+       transited.
+       (fix_transited_encoding): check length.
+       From Miroslav Ruda <ruda@ics.muni.cz>
+
+       * kdc/hpropd.c (dump_krb4): check the realm so that we don't dump
+       principals in some other realm. From Miroslav Ruda
+       <ruda@ics.muni.cz>
+       (main): rename sa_len -> sin_len, sa_lan is a define on some
+       platforms.
+
+       * appl/kf/kfd.c: add regpag support. From Miroslav Ruda
+       <ruda@ics.muni.cz>
+
+       * appl/kf/kf.c: add `-G' and forwardable option in krb5.conf.
+       From Miroslav Ruda <ruda@ics.muni.cz>
+
+       * lib/krb5/config_file.c (parse_list): don't run past end of line
+
+       * appl/test/gss_common.h: new prototypes
+
+       * appl/test/gssapi_client.c: use gss_err instead of abort
+
+       * appl/test/gss_common.c (gss_verr, gss_err): add
+
+1999-08-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (n_fold_test_LDADD): need to set this
+       otherwise it doesn't build with shared libraries
+
+       * kdc/hpropd.c: v6-ify
+
+       * kdc/hprop.c: v6-ify
+
+1999-08-01  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_req.c (krb5_mk_req): use krb5_expand_hostname
+
+1999-07-31  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm_int): new
+       function that takes a FQDN
+
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add exapnd_hostname.c
+
+       * lib/krb5/expand_hostname.c: new file
+
+1999-07-28  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1l
+
+1999-07-28  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/Makefile.am: bump version to 1:2:0
+
+       * lib/krb5/Makefile.am: bump version to 3:1:0
+
+       * configure.in: more inet_pton to roken
+
+       * lib/krb5/principal.c (krb5_sname_to_principal): use
+       getipnodebyname
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1k
+
+1999-07-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/Makefile.am: bump version number (changed function
+       signatures)
+
+       * lib/hdb/Makefile.am: bump version number (changes to some
+       function signatures)
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: bump version to 3:0:2
+
+       * lib/hdb/Makefile.am: bump version to 2:1:0
+
+       * lib/asn1/Makefile.am: bump version to 1:1:0
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1j
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: rokenize inet_ntop
+
+       * lib/krb5/store_fd.c: lots of changes from size_t to ssize_t
+       
+       * lib/krb5/store_mem.c: lots of changes from size_t to ssize_t
+       
+       * lib/krb5/store_emem.c: lots of changes from size_t to ssize_t
+       
+       * lib/krb5/store.c: lots of changes from size_t to ssize_t
+       (krb5_ret_stringz): check return value from realloc
+
+       * lib/krb5/mk_safe.c: some type correctness
+       
+       * lib/krb5/mk_priv.c: some type correctness
+       
+       * lib/krb5/krb5.h (krb5_storage): change return values of
+       functions from size_t to ssize_t
+       
+1999-07-24  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1i
+
+       * configure.in (AC_PROG_AWK): disable. mawk seems to mishandle \#
+       in lib/roken/roken.awk
+
+       * lib/krb5/get_addrs.c (find_all_addresses): try to use SA_LEN to
+       step over addresses if there's no `sa_lan' field
+
+       * lib/krb5/sock_principal.c (krb5_sock_to_principal): simplify by
+       using `struct sockaddr_storage'
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc): simplify by using
+       `struct sockaddr_storage'
+
+       * lib/krb5/changepw.c (krb5_change_password): simplify by using
+       `struct sockaddr_storage'
+
+       * lib/krb5/auth_context.c (krb5_auth_con_setaddrs_from_fd):
+       simplify by using `struct sockaddr_storage'
+
+       * kpasswd/kpasswdd.c (*): simplify by using `struct
+       sockaddr_storage'
+
+       * kdc/connect.c (*): simplify by using `struct sockaddr_storage'
+
+       * configure.in (sa_family_t): just test for existence
+       (sockaddr_storage): also specify include file
+
+       * configure.in (AM_INIT_AUTOMAKE): bump version to 0.1i
+       (sa_family_t): test for
+       (struct sockaddr_storage): test for
+
+       * kdc/hprop.c (propagate_database): typo, NULL should be
+       auth_context
+
+       * lib/krb5/get_addrs.c: conditionalize on HAVE_IPV6 instead of
+       AF_INET6
+
+       * appl/kf/kf.c (main): use warnx
+
+       * appl/kf/kf.c (proto): remove shadowing context
+
+       * lib/krb5/get_addrs.c (find_all_addresses): try to handle the
+       case of getting back an `sockaddr_in6' address when sizeof(struct
+       sockaddr_in6) > sizeof(struct sockaddr) and we have no sa_len to
+       tell us how large the address is.  This obviously doesn't work
+       with unknown protocol types.
+
+1999-07-24  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1h
+
+1999-07-23  Assar Westerlund  <assar@sics.se>
+
+       * appl/kf/kfd.c: clean-up and more paranoia
+
+       * etc/services.append: add kf
+
+       * appl/kf/kf.c: rename tk_file to ccache for consistency.  clean-up
+
+1999-07-22  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/n-fold-test.c (main): print the correct data
+
+       * appl/Makefile.am (SUBDIRS): add kf
+
+       * appl/kf: new program.  From Miroslav Ruda <ruda@ics.muni.cz>
+
+       * kdc/hprop.c: declare some variables unconditionally to simplify
+       things
+
+       * kpasswd/kpasswdd.c: initialize kadm5 connection for every change
+       (otherwise the modifier in the database doesn't get set)
+
+       * kdc/hpropd.c: clean-up and re-organize
+
+       * kdc/hprop.c: clean-up and re-organize
+
+       * configure.in (SunOS): define to xy for SunOS x.y
+
+1999-07-19  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (AC_BROKEN): test for copyhostent, freehostent,
+       getipnodebyaddr, getipnodebyname
+
+1999-07-15  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/check-der.c: more test cases for integers
+
+       * lib/asn1/der_length.c (length_int): handle the case of the
+       largest negative integer by not calling abs
+
+1999-07-14  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/check-der.c (generic_test): check malloc return value
+       properly
+
+       * lib/krb5/Makefile.am: add string_to_key_test
+
+       * lib/krb5/prog_setup.c (krb5_program_setup): always initialize
+       the context
+
+       * lib/krb5/n-fold-test.c (main): return a relevant return value
+
+       * lib/krb5/krbhst.c: do SRV lookups for admin server as well.
+       some clean-up.
+
+1999-07-12  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: handle not building X programs
+
+1999-07-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c (ipv6_parse_addr): remove duplicate
+       variable
+       (ipv6_sockaddr2port): fix typo
+
+       * etc/services.append: beginning of a file with services
+
+       * lib/krb5/cache.c (krb5_cc_resolve): fall-back to files if
+       there's no prefix.  also clean-up a little bit.
+
+       * kdc/hprop.c (--kaspecials): new flag for handling special KA
+       server entries.  From "Brandon S. Allbery KF8NH"
+       <allbery@kf8nh.apk.net>
+
+1999-07-05  Assar Westerlund  <assar@sics.se>
+
+       * kdc/connect.c (handle_tcp): make sure we have data before
+       starting to look for HTTP
+
+       * kdc/connect.c (handle_tcp): always do getpeername, we can't
+       trust recvfrom to return anything sensible
+
+1999-07-04  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_in_tkt.c (add_padat): encrypt pre-auth data with
+       all enctypes
+
+       * kpasswd/kpasswdd.c (change): fetch the salt-type from the entry
+
+       * admin/srvconvert.c (srvconv): better error messages
+
+1999-07-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (unparse_name): error check malloc properly
+
+       * lib/krb5/get_in_tkt.c (krb5_init_etype): error check malloc
+       properly
+
+       * lib/krb5/crypto.c (*): do some malloc return-value checks
+       properly
+
+       * lib/hdb/hdb.c (hdb_process_master_key): simplify by using
+       krb5_data_alloc
+
+       * lib/hdb/hdb.c (hdb_process_master_key): check return value from
+       malloc
+
+       * lib/asn1/gen_decode.c (decode_type): fix generation of decoding
+       information for TSequenceOf.
+
+       * kdc/kerberos5.c (get_pa_etype_info): check return value from
+       malloc
+
+1999-07-02  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/der_copy.c (copy_octet_string): don't fail if length ==
+       0 and malloc returns NULL
+
+1999-06-29  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c (ipv6_parse_addr): implement
+
+1999-06-24  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_cred.c (krb5_rd_cred): compare the sender's address
+       as an addrport one
+
+       * lib/krb5/krb5.h (KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_IPPORT):
+       add
+       (krb5_auth_context): add local and remote port
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): get the
+       local and remote address and add them to the krb-cred packet
+
+       * lib/krb5/auth_context.c: save the local and remove ports in the
+       auth_context
+
+       * lib/krb5/address.c (krb5_make_addrport): create an address of
+       type KRB5_ADDRESS_ADDRPORT from (addr, port)
+
+       * lib/krb5/addr_families.c (krb5_sockaddr2port): new function for
+       grabbing the port number out of the sockaddr
+
+1999-06-23  Assar Westerlund  <assar@sics.se>
+
+       * admin/srvcreate.c (srvcreate): always take the DES-CBC-MD5 key.
+       increase possible verbosity.
+
+       * lib/krb5/config_file.c (parse_list): handle blank lines at
+       another place
+       
+       * kdc/connect.c (add_port_string): don't return a value
+
+       * lib/kadm5/init_c.c (get_cred_cache): you cannot reuse the cred
+       cache if the principals are different.  close and NULL the old one
+       so that we create a new one.
+
+       * configure.in: move around cgywin et al
+       (LIB_kdb): set at the end of krb4-block
+       (krb4): test for krb_enable_debug and krb_disable_debug
+
+1999-06-16  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kdestroy.c (main): try to destroy v4 ticket even if the
+       destruction of the v5 one fails
+
+       * lib/krb5/crypto.c (DES3_postproc): new version that does the
+       right thing
+       (*): don't put and recover length in 3DES encoding
+       other small fixes
+
+1999-06-15  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_default_principal.c: rewrite to use
+       get_default_username
+
+       * lib/krb5/Makefile.am: add n-fold-test
+
+       * kdc/connect.c: add fallbacks for all lookups by service name
+       (handle_tcp): break-up and clean-up
+
+1999-06-09  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c (ipv6_uninteresting): don't consider
+       the loopback address as uninteresting
+
+       * lib/krb5/get_addrs.c: new magic flag to get loopback address if
+       there are no other addresses.
+       (krb5_get_all_client_addrs): use that flag
+
+1999-06-04  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (HMAC_SHA1_DES3_checksum): don't include the
+       length
+       (checksum_sha1, checksum_hmac_sha1_des3): blocksize should be 64
+       (encrypt_internal_derived): don't include the length and don't
+       decrease by the checksum size twice
+       (_get_derived_key): the constant should be 5 bytes
+
+1999-06-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: use KRB_CHECK_X
+       
+       * configure.in: check for netinet/ip.h
+       
+1999-05-31  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswdd.c (setup_passwd_quality_check): conditionalize
+       on RTLD_NOW
+
+1999-05-23  Assar Westerlund  <assar@sics.se>
+
+       * appl/test/uu_server.c: removed unused stuff
+
+       * appl/test/uu_client.c: removed unused stuff
+
+1999-05-21  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kgetcred.c (main): correct error message
+
+       * lib/krb5/crypto.c (verify_checksum): call (*ct->checksum)
+       directly, avoiding redundant lookups and memory leaks
+
+       * lib/krb5/auth_context.c (krb5_auth_con_setaddrs_from_fd): free
+       local and remote addresses
+
+       * lib/krb5/get_default_principal.c (get_logname): also try
+       $USERNAME
+       
+       * lib/asn1/Makefile.am (asn1_files): add $(EXEEXT)
+
+       * lib/krb5/principal.c (USE_RESOLVER): try to define only if we
+       have a libresolv (currently by checking for res_search)
+
+1999-05-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/connect.c (handle_tcp): remove %-escapes in request
+
+1999-05-14  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1g
+
+       * admin/ktutil.c (kt_remove): -t should be -e
+
+       * configure.in (CHECK_NETINET_IP_AND_TCP): use
+
+       * kdc/hpropd.c: support for dumping to krb4.  From Miroslav Ruda
+       <ruda@ics.muni.cz>
+
+       * admin/ktutil.c (kt_add): new option `--no-salt'.  From Miroslav
+       Ruda <ruda@ics.muni.cz>
+
+       * configure.in: add cygwin and DOS tests replace sendmsg, recvmsg,
+       and innetgr with roken versions
+
+       * kuser/kgetcred.c: new program
+
+Tue May 11 14:09:33 1999  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/mcache.c: fix paste-o
+       
+1999-05-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: don't use uname
+
+1999-05-10  Assar Westerlund  <assar@sics.se>
+
+       * acconfig.h (KRB_PUT_INT): if we don't have KRB4 use four
+       arguments :-)
+
+       * appl/test/uu_server.c (setsockopt): cast to get rid of a warning
+       
+       * appl/test/tcp_server.c (setsockopt): cast to get rid of a
+       warning
+
+       * appl/test/tcp_client.c (proto): call krb5_sendauth with ccache
+       == NULL
+
+       * appl/test/gssapi_server.c (setsockopt): cast to get rid of a
+       warning
+
+       * lib/krb5/sendauth.c (krb5_sendauth): handle ccache == NULL by
+       setting the default ccache.
+
+       * configure.in (getsockopt, setsockopt): test for
+       (AM_INIT_AUTOMAKE): bump version to 0.1g
+
+       * appl/Makefile.am (SUBDIRS): add kx
+       
+       * lib/hdb/convert_db.c (main): handle the case of no master key
+       
+1999-05-09  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1f
+
+       * kuser/kinit.c: add --noaddresses
+       
+       * lib/krb5/get_in_tkt.c (init_as_req): interpret `addrs' being an
+       empty sit of list as to not ask for any addresses.
+       
+1999-05-08  Assar Westerlund  <assar@sics.se>
+
+       * acconfig.h (_GNU_SOURCE): define this to enable (used)
+       extensions on glibc-based systems such as linux
+
+1999-05-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_cred.c (get_cred_from_kdc_flags): allocate and free
+       `*out_creds' properly
+
+       * lib/krb5/creds.c (krb5_compare_creds): just verify that the
+       keytypes/enctypes are compatible, not that they are the same
+
+       * kuser/kdestroy.c (cache): const-correctness
+
+1999-05-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/hdb.c (hdb_set_master_key): initialise master key
+       version
+
+       * lib/hdb/convert_db.c: add support for upgrading database
+       versions
+
+       * kdc/misc.c: add flags to fetch
+
+       * kdc/kstash.c: unlink keyfile on failure, chmod to 400
+
+       * kdc/hpropd.c: add --print option
+
+       * kdc/hprop.c: pass flags to hdb_foreach
+
+       * lib/hdb/convert_db.c: add some flags
+
+       * lib/hdb/Makefile.am: remove extra LDFLAGS, update version to 2;
+       build prototype headers
+       
+       * lib/hdb/hdb_locl.h: update prototypes
+
+       * lib/hdb/print.c: move printable version of entry from kadmin
+
+       * lib/hdb/hdb.c: change hdb_{seal,unseal}_* to check if the key is
+       sealed or not; add flags to hdb_foreach
+
+       * lib/hdb/ndbm.c: add flags to NDBM_seq, NDBM_firstkey, and
+       NDBM_nextkey
+
+       * lib/hdb/db.c: add flags to DB_seq, DB_firstkey, and DB_nextkey
+
+       * lib/hdb/common.c: add flags to _hdb_{fetch,store}
+
+       * lib/hdb/hdb.h: add master_key_version to struct hdb, update
+       prototypes
+
+       * lib/hdb/hdb.asn1: make mkvno optional, update version to 2
+
+       * configure.in: --enable-netinfo
+
+       * lib/krb5/config_file.c: HAVE_NETINFO_NI_H -> HAVE_NETINFO
+
+       * config.sub: fix for crays
+
+       * config.guess: new version from automake 1.4
+       
+       * config.sub: new version from automake 1.4
+
+Wed Apr 28 00:21:17 1999  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.1e
+
+       * lib/krb5/mcache.c (mcc_get_next): get the current cursor
+       correctly
+
+       * acconfig.h: correct definition of KRB_PUT_INT for old krb4 code.
+       From Ake Sandgren <ake@cs.umu.se>
+
+1999-04-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c: fix arguments to decrypt_ticket
+       
+1999-04-25  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_internal): try to handle old
+       DCE secd's that are not able to handle MD5 checksums by defaulting
+       to MD4 if the keytype was DES-CBC-CRC
+       
+       * lib/krb5/mk_req.c (krb5_mk_req): use auth_context->keytype
+       
+       * lib/krb5/krb5.h (krb5_auth_context_data): add `keytype' and
+       `cksumtype'
+
+       * lib/krb5/get_cred.c (make_pa_tgs_req): remove old kludge for
+       secd
+       (init_tgs_req): add all supported enctypes for the keytype in
+       `in_creds->session.keytype' if it's set
+
+       * lib/krb5/crypto.c (F_PSEUDO): new flag for non-protocol
+       encryption types
+       (do_checksum): new function
+       (verify_checksum): take the checksum to use from the checksum message
+       and not from the crypto struct
+       (etypes): add F_PSEUDO flags
+       (krb5_keytype_to_enctypes): new function
+
+       * lib/krb5/auth_context.c (krb5_auth_con_init): initalize keytype
+       and cksumtype
+       (krb5_auth_setcksumtype, krb5_auth_getcksumtype): implement
+       (krb5_auth_setkeytype, krb5_auth_getkeytype): implement
+       (krb5_auth_setenctype): comment out, it's rather bogus anyway
+
+Sun Apr 25 16:55:50 1999  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5_locl.h: fix for stupid aix warnings
+
+       * lib/krb5/fcache.c (erase_file): don't malloc
+       
+Sat Apr 24 18:35:21 1999  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/config.c: pass context to krb5_config_file_free
+
+       * kuser/kinit.c: add `--fcache-version' to set cache version to
+       create
+
+       * kuser/klist.c: print cache version if verbose
+
+       * lib/krb5/transited.c (krb5_domain_x500_decode): don't abort
+
+       * lib/krb5/principal.c: abort -> krb5_abortx
+
+       * lib/krb5/mk_rep.c: abort -> krb5_abortx
+
+       * lib/krb5/config_file.c: abort -> krb5_abortx
+
+       * lib/krb5/context.c (init_context_from_config_file): init
+       fcache_version; add krb5_{get,set}_fcache_version
+
+       * lib/krb5/keytab.c: add support for reading (and writing?) old
+       version keytabs
+
+       * lib/krb5/cache.c: add krb5_cc_get_version
+
+       * lib/krb5/fcache.c: add support for reading and writing old
+       version cache files
+
+       * lib/krb5/store_mem.c (krb5_storage_from_mem): zero flags
+
+       * lib/krb5/store_emem.c (krb5_storage_emem): zero flags
+
+       * lib/krb5/store_fd.c (krb5_storage_from_fd): zero flags
+
+       * lib/krb5/store.c: add flags to change how various fields are
+       stored, used for old cache version support
+       
+       * lib/krb5/krb5.h: add support for reading and writing old version
+       cache files, and keytabs
+       
+Wed Apr 21 00:09:26 1999  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: fix test for readline.h remember to link with
+       $LIB_tgetent when trying linking with readline
+
+       * lib/krb5/init_creds_pw.c (get_init_creds_common): if start_time
+       is given, request a postdated ticket.
+
+       * lib/krb5/data.c (krb5_data_free): free data as long as it's not
+       NULL
+
+Tue Apr 20 20:18:14 1999  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/Makefile.am (kpasswdd_LDADD): add LIB_dlopen
+
+       * lib/krb5/krb5.h (KRB5_VERIFY_AP_REQ_IGNORE_INVALID): add
+
+       * lib/krb5/rd_req.c (krb5_decrypt_ticket): add `flags` and
+       KRB5_VERIFY_AP_REQ_IGNORE_INVALID for ignoring that the ticket is
+       invalid
+
+Tue Apr 20 12:42:08 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * kpasswd/kpasswdd.c: don't try to load library by default; get
+       library and function name from krb5.conf
+
+       * kpasswd/sample_passwd_check.c: sample password checking
+       functions
+
+Mon Apr 19 22:22:19 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/store.c (krb5_storage_to_data, krb5_ret_data): use
+       krb5_data_alloc and be careful with checking allocation and sizes.
+
+       * kuser/klist.c (--tokens): conditionalize on KRB4
+
+       * kuser/kinit.c (renew_validate): set all flags
+       (main): fix cut-n-paste error when setting start-time
+
+       * kdc/kerberos5.c (check_tgs_flags): starttime of a validate
+       ticket should be > than current time
+       (*): send flags to krb5_verify_ap_req and krb5_decrypt_ticket
+
+       * kuser/kinit.c (renew_validate): use the client realm instead of
+       the local realm when renewing tickets.
+
+       * lib/krb5/get_for_creds.c (krb5_fwd_tgs_creds): compat function
+       (krb5_get_forwarded_creds): correct freeing of out_creds
+
+       * kuser/kinit.c (renew_validate): hopefully fix up freeing of
+       memory
+
+       * configure.in: do all the krb4 tests with "$krb4" != "no"
+
+       * lib/krb5/keyblock.c (krb5_free_keyblock_contents): don't zero
+       keyvalue if it's NULL.  noticed by Ake Sandgren <ake@cs.umu.se>
+
+       * lib/krb5/get_in_tkt.c (add_padata): loop over all enctypes
+       instead of just taking the first one.  fix all callers.  From
+       "Brandon S. Allbery KF8NH" <allbery@kf8nh.apk.net>
+
+       * kdc/kdc_locl.h (enable_kaserver): declaration
+       
+       * kdc/hprop.c (ka_convert): print the failing principal.  AFS 3.4a
+       creates krbtgt.REALMOFCELL as NOTGS+NOSEAL, work around.  From
+       "Brandon S. Allbery KF8NH" <allbery@kf8nh.apk.net>
+
+       * kdc/hpropd.c (open_socket): stupid cast to get rid of a warning
+
+       * kdc/connect.c (add_standard_ports, process_request): look at
+       enable_kaserver.  From "Brandon S. Allbery KF8NH"
+       <allbery@kf8nh.apk.net>
+
+       * kdc/config.c: new flag --kaserver and config file option
+       enable-kaserver.  From "Brandon S. Allbery KF8NH"
+       <allbery@kf8nh.apk.net>
+
+Mon Apr 19 12:32:04 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: check for dlopen, and dlfcn.h
+
+       * kpasswd/kpasswdd.c: add support for dlopen:ing password quality
+       check library
+
+       * configure.in: add appl/su
+
+Sun Apr 18 15:46:53 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/cache.c: add krb5_cc_get_type that returns type of a
+       cache
+
+Fri Apr 16 17:58:51 1999  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: LIB_kdb: -L should be before -lkdb
+       test for prototype of strsep
+       
+Thu Apr 15 11:34:38 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/Makefile.am: update version
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): use
+       ALLOC_SEQ
+
+       * lib/krb5/fcache.c: add some support for reading and writing old
+       cache formats;
+       (fcc_store_cred): use krb5_store_creds; (fcc_read_cred): use
+       krb5_ret_creds
+
+       * lib/krb5/store_mem.c (krb5_storage_from_mem): check malloc,
+       initialize host_byteorder
+
+       * lib/krb5/store_fd.c (krb5_storage_from_fd): initialize
+       host_byteorder
+
+       * lib/krb5/store_emem.c (krb5_storage_emem): initialize
+       host_byteorder
+
+       * lib/krb5/store.c (krb5_storage_set_host_byteorder): add;
+       (krb5_store_int32,krb5_ret_int32,krb5_store_int16,krb5_ret_int16):
+       check host_byteorder flag; (krb5_store_creds): add;
+       (krb5_ret_creds): add
+
+       * lib/krb5/krb5.h (krb5_storage): add `host_byteorder' flag for
+       storage of numbers
+
+       * lib/krb5/heim_err.et: add `host not found' error
+
+       * kdc/connect.c: don't use data after clearing decriptor
+
+       * lib/krb5/auth_context.c: abort -> krb5_abortx
+
+       * lib/krb5/warn.c: add __attribute__; add *abort functions
+
+       * configure.in: check for __attribute__
+
+       * kdc/connect.c: log bogus requests
+
+Tue Apr 13 18:38:05 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/kadm5/create_s.c (kadm5_s_create_principal): create v4 salts
+       for all DES keys
+
+1999-04-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_cred.c (init_tgs_req): re-structure a little bit
+
+       * lib/krb5/get_cred.c (init_tgs_req): some more error checking
+
+       * lib/krb5/generate_subkey.c (krb5_generate_subkey): check return
+       value from malloc
+
+Sun Apr 11 03:47:23 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/krb5.conf.5: update to reality
+
+       * lib/krb5/krb5_425_conv_principal.3: update to reality
+
+1999-04-11  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_host_realm.c: handle more than one realm for a host
+
+       * kpasswd/kpasswd.c (main): use krb5_program_setup and
+       print_version
+
+       * kdc/string2key.c (main): use krb5_program_setup and
+       print_version
+
+Sun Apr 11 02:35:58 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/principal.c (krb5_524_conv_principal): make it actually
+       work, and check built-in list of host-type first-components
+
+       * lib/krb5/krbhst.c: lookup SRV-records to find a kdc for a realm
+
+       * lib/krb5/context.c: add srv_* flags to context
+
+       * lib/krb5/principal.c: add default v4_name_convert entries
+
+       * lib/krb5/krb5.h: add srv_* flags to context
+
+Sat Apr 10 22:52:28 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * kadmin/kadmin.c: complain about un-recognised commands
+
+       * admin/ktutil.c: complain about un-recognised commands
+
+Sat Apr 10 15:41:49 1999  Assar Westerlund  <assar@sics.se>
+
+       * kadmin/load.c (doit): fix error message
+
+       * lib/krb5/crypto.c (encrypt_internal): free checksum if lengths
+       fail to match.
+       (krb5_get_wrapped_length): new function
+
+       * configure.in: security/pam_modules.h: check for
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): kludge
+       around `ret_as_reply' semantics by only freeing it when ret == 0
+
+Fri Apr  9 20:24:04 1999  Assar Westerlund  <assar@sics.se>
+
+       * kuser/klist.c (print_cred_verbose): handle the case of a bad
+       enctype
+
+       * configure.in: test for more header files
+       (LIB_roken): set
+
+Thu Apr  8 15:01:59 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: fixes for building w/o krb4
+
+       * ltmain.sh: update to libtool 1.2d
+
+       * ltconfig: update to libtool 1.2d
+
+Wed Apr  7 23:37:26 1999  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c: fix some error messages to be more understandable.
+
+       * kdc/hprop.c (ka_dump): remove unused variables
+
+       * appl/test/tcp_server.c: remove unused variables
+
+       * appl/test/gssapi_server.c: remove unused variables
+
+       * appl/test/gssapi_client.c: remove unused variables
+
+Wed Apr  7 14:05:15 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/context.c (krb5_get_err_text): long -> krb5_error_code
+
+       * kuser/klist.c: make it compile w/o krb4
+
+       * kuser/kdestroy.c: make it compile w/o krb4
+
+       * admin/ktutil.c: fix {srv,key}2{srv,key}tab confusion; add help
+       strings
+
+Mon Apr  5 16:13:46 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: test for MIPS ABI; new test_package
+
+Thu Apr  1 11:00:40 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * include/Makefile.am: clean krb5-private.h
+
+       * Release 0.1d
+
+       * kpasswd/kpasswdd.c (doit): pass context to
+       krb5_get_all_client_addrs
+
+       * kdc/connect.c (init_sockets): pass context to
+       krb5_get_all_server_addrs
+
+       * lib/krb5/get_in_tkt.c (init_as_req): pass context to
+       krb5_get_all_client_addrs
+
+       * lib/krb5/get_cred.c (get_cred_kdc_la): pass context to
+       krb5_get_all_client_addrs
+
+       * lib/krb5/get_addrs.c (get_addrs_int): add extra host addresses
+
+       * lib/krb5/krb5.h: add support for adding an extra set of
+       addresses
+
+       * lib/krb5/context.c: add support for adding an extra set of
+       addresses
+
+       * lib/krb5/addr_families.c: add krb5_parse_address
+
+       * lib/krb5/address.c: krb5_append_addresses
+
+       * lib/krb5/config_file.c (parse_binding): don't zap everything
+       after first whitespace
+
+       * kuser/kinit.c (renew_validate): don't allocate out
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): don't
+       allocate out_creds
+
+       * lib/krb5/get_cred.c (get_cred_kdc, get_cred_kdc_la): make
+       out_creds pointer;
+       (krb5_get_kdc_cred): allocate out_creds; (get_cred_from_kdc_flags):
+       free more memory
+
+       * lib/krb5/crypto.c (encrypt_internal): free checksum
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): free reply,
+       and ticket
+
+       * kuser/Makefile.am: remove kfoo
+
+       * lib/Makefile.am: add auth
+
+       * lib/kadm5/iprop.h: getarg.h
+
+       * lib/kadm5/replay_log.c: use getarg
+
+       * lib/kadm5/ipropd_slave.c: use getarg
+
+       * lib/kadm5/ipropd_master.c: use getarg
+
+       * lib/kadm5/dump_log.c: use getarg
+
+       * kpasswd/kpasswdd.c: use getarg
+
+       * Makefile.am.common: make a more working check-local target
+
+       * lib/asn1/main.c: use getargs
+
+Mon Mar 29 20:19:57 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * kuser/klist.c (print_cred_verbose): use krb5_print_address
+
+       * lib/kadm5/server.c: k_{put,get}_int -> _krb5_{put,get}_int
+
+       * lib/krb5/addr_families.c (krb5_print_address): handle unknown
+       address types; (ipv6_print_addr): print in 16-bit groups (as it
+       should)
+
+       * lib/krb5/crc.c: crc_{init_table,update} ->
+       _krb5_crc_{init_table,update}
+
+       * lib/krb5/crypto.c: k_{put,get}_int -> _krb5_{put,get}_int
+       crc_{init_table,update} -> _krb5_crc_{init_table,update}
+
+       * lib/krb5/send_to_kdc.c: k_{put,get}_int -> _krb5_{put,get}_int
+
+       * lib/krb5/store.c: k_{put,get}_int -> _krb5_{put,get}_int
+
+       * lib/krb5/krb5_locl.h: include krb5-private.h
+
+       * kdc/connect.c (addr_to_string): use krb5_print_address
+
+       * lib/krb5/addr_families.c (krb5_print_address): int -> size_t
+
+       * lib/krb5/addr_families.c: add support for printing ipv6
+       addresses, either with inet_ntop, or ugly for-loop
+
+       * kdc/524.c: check that the ticket came from a valid address; use
+       the address of the connection as the address to put in the v4
+       ticket (if this address is AF_INET)
+
+       * kdc/connect.c: pass addr to do_524
+
+       * kdc/kdc_locl.h: prototype for do_524
+
+Sat Mar 27 17:48:31 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: check for OSF C2; bind/bitypes.h, getudbnam,
+       setlim; check for auth modules; siad.h, getpwnam_r;
+       lib/auth/Makefile, lib/auth/sia/Makefile
+
+       * lib/krb5/crypto.c: n_fold -> _krb5_n_fold
+
+       * lib/krb5/n-fold.c: n_fold -> _krb5_n_fold
+
+Thu Mar 25 04:35:21 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/set_keys.c (_kadm5_set_keys): free salt when zapping
+       it
+
+       * lib/kadm5/free.c (kadm5_free_principal_ent): free `key_data'
+
+       * lib/hdb/ndbm.c (NDBM_destroy): clear master key
+
+       * lib/hdb/db.c (DB_destroy): clear master key
+       (DB_open): check malloc
+
+       * kdc/connect.c (init_sockets): free addresses
+
+       * kadmin/kadmin.c (main): make code more consistent.  always free
+       configuration information.
+
+       * kadmin/init.c (create_random_entry): free the entry
+
+Wed Mar 24 04:02:03 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password):
+       re-organize the code to always free `kdc_reply'
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): be more careful about
+       freeing memory
+
+       * lib/krb5/fcache.c (fcc_destroy): don't call fcc_close
+
+       * lib/krb5/crypto.c (krb5_crypto_destroy): free `crypto'
+
+       * lib/hdb/hdb_locl.h: try db_185.h first in case db.h is a DB 2.0
+       header
+
+       * configure.in (db_185.h): check for
+
+       * admin/srvcreate.c: new file. contributed by Daniel Kouril
+       <kouril@informatics.muni.cz>
+
+       * admin/ktutil.c: srvcreate: new command
+
+       * kuser/klist.c: add support for printing AFS tokens
+
+       * kuser/kdestroy.c: add support for destroying v4 tickets and AFS
+       tokens.  based on code by Love <lha@stacken.kth.se>
+
+       * kuser/Makefile.am (kdestroy_LDADD, klist_LDADD): more libraries
+
+       * configure.in: sys/ioccom.h: test for
+
+       * kuser/klist.c (main): don't print `no ticket file' with --test.
+       From: Love <lha@e.kth.se>
+
+       * kpasswd/kpasswdd.c (doit): more braces to make gcc happy
+
+       * kdc/connect.c (init_socket): get rid of a stupid warning
+
+       * include/bits.c (my_strupr): cast away some stupid warnings
+
+Tue Mar 23 14:34:44 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm): no infinite
+       loops, please
+
+Tue Mar 23 00:00:45 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/kadm5/Makefile.am (install_build_headers): recover from make
+       rewriting the names of the headers kludge to help solaris make
+
+       * lib/krb5/Makefile.am: kludge to help solaris make
+
+       * lib/hdb/Makefile.am: kludge to help solaris make
+
+       * configure.in (LIB_kdb): make sure there's a -L option in here by
+       adding $(LIB_krb4)
+
+       * lib/asn1/gen_glue.c (generate_2int, generate_int2): int ->
+       unsigned
+
+       * configure.in (SunOS): set to a number KRB4, KRB5 conditionals:
+       remove the `dnl' to work around an automake flaw
+
+Sun Mar 21 15:08:49 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/get_default_realm.c: char* -> krb5_realm
+
+Sun Mar 21 14:08:30 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * include/bits.c: <bind/bitypes.h>
+
+       * lib/krb5/Makefile.am: create krb5-private.h
+
+Sat Mar 20 00:08:59 1999  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (gethostname): remove duplicate
+
+Fri Mar 19 14:48:03 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/hdb/Makefile.am: add version-info
+
+       * lib/gssapi/Makefile.am: add version-info
+
+       * lib/asn1/Makefile.am: use $(x:y=z) make syntax; move check-der
+       to check_PROGRAMS
+
+       * lib/Makefile.am: add 45
+
+       * lib/kadm5/Makefile.am: split in client and server libraries
+       (breaks shared libraries otherwise)
+
+Thu Mar 18 11:33:30 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * include/kadm5/Makefile.am: clean a lot of header files (since
+       automake lacks a clean-hook)
+
+       * include/Makefile.am: clean a lot of header files (since automake
+       lacks a clean-hook)
+
+       * lib/kadm5/Makefile.am: fix build-installation of headers
+
+       * lib/krb5/Makefile.am: remove include_dir hack
+
+       * lib/hdb/Makefile.am: remove include_dir hack
+
+       * lib/asn1/Makefile.am: remove include_dir hack
+
+       * include/Makefile.am: remove include_dir hack
+
+       * doc/whatis.texi: define sub for html
+
+       * configure.in: LIB_kdb, have_err_h, have_fnmatch_h, have_glob_h
+
+       * lib/asn1/Makefile.am: der.h
+
+       * kpasswd/kpasswdd.c: admin.h -> kadm5/admin.h
+
+       * kdc/Makefile.am: remove junk
+
+       * kadmin/Makefile.am: sl.a -> sl.la
+
+       * appl/afsutil/Makefile.am: remove EXTRA_bin_PROGRAMS
+
+       * admin/Makefile.am: sl.a -> sl.la
+
+       * configure.in: condition KRB5; AC_CHECK_XAU
+
+       * Makefile.am: include Makefile.am.common
+
+       * include/kadm5/Makefile.am: include Makefile.am.common; don't
+       install headers from here
+
+       * include/Makefile.am: include Makefile.am.common; don't install
+       headers from here
+
+       * doc/Makefile.am: include Makefile.am.common
+
+       * lib/krb5/Makefile.am: include Makefile.am.common
+
+       * lib/kadm5/Makefile.am: include Makefile.am.common
+
+       * lib/hdb/Makefile.am: include Makefile.am.common
+
+       * lib/gssapi/Makefile.am: include Makefile.am.common
+
+       * lib/asn1/Makefile.am: include Makefile.am.common
+
+       * lib/Makefile.am: include Makefile.am.common
+
+       * lib/45/Makefile.am: include Makefile.am.common
+
+       * kuser/Makefile.am: include Makefile.am.common
+
+       * kpasswd/Makefile.am: include Makefile.am.common
+
+       * kdc/Makefile.am: include Makefile.am.common
+
+       * kadmin/Makefile.am: include Makefile.am.common
+
+       * appl/test/Makefile.am: include Makefile.am.common
+
+       * appl/afsutil/Makefile.am: include Makefile.am.common
+
+       * appl/Makefile.am: include Makefile.am.common
+
+       * admin/Makefile.am: include Makefile.am.common
+
+Wed Mar 17 03:04:38 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/store.c (krb5_store_stringz): braces fix
+
+       * lib/kadm5/get_s.c (kadm5_s_get_principal): braces fix
+
+       * lib/kadm5/ent_setup.c (_kadm5_setup_entry): braces fix
+
+       * kdc/connect.c (loop): braces fix
+
+       * lib/krb5/config_file.c: cast to unsigned char to make is* happy
+
+       * lib/krb5/log.c (krb5_addlog_dest): more braces to make gcc happy
+
+       * lib/krb5/crypto.c (krb5_verify_checksum): rename C -> cksum to
+       be consistent
+
+       * kadmin/util.c (timeval2str): more braces to make gcc happy
+
+       * kadmin/load.c: cast in is* to get rid of stupid warning
+
+       * kadmin/dump.c (append_hex): cast in isalnum to get rid of stupid
+       warning
+
+       * kdc/kaserver.c: malloc checks and fixes
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm): include leading
+       dot (if any) when looking up realms.
+
+Fri Mar 12 13:57:56 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/get_host_realm.c: add dns support
+
+       * lib/krb5/set_default_realm.c: use krb5_free_host_realm
+
+       * lib/krb5/free_host_realm.c: check for NULL realmlist
+
+       * lib/krb5/context.c: don't print warning if there is no krb5.conf
+
+Wed Mar 10 19:29:46 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: use AC_WFLAGS
+
+Mon Mar  8 11:49:43 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Release 0.1c
+
+       * kuser/klist.c: use print_version
+
+       * kuser/kdestroy.c: use print_version
+
+       * kdc/hpropd.c: use print_version
+
+       * kdc/hprop.c: use print_version
+
+       * kdc/config.c: use print_version
+
+       * kadmin/kadmind.c: use print_version
+
+       * kadmin/kadmin.c: use print_version
+
+       * appl/test/common.c: use print_version
+
+       * appl/afsutil/afslog.c: use print_version
+
+Mon Mar  1 10:49:14 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/krb5/get_addrs.c: SOCKADDR_HAS_SA_LEN ->
+       HAVE_STRUCT_SOCKADDR_SA_LEN
+
+       * configure.in, acconfig.h, cf/*: update to automake 1.4/autoconf 2.13
+
+Sun Feb 28 18:19:20 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/asn1/gen.c: make `BIT STRING's unsigned
+
+       * lib/asn1/{symbol.h,gen.c}: add TUInteger type
+
+       * lib/krb5/verify_user.c (krb5_verify_user): pass prompter to
+       krb5_get_init_creds_password
+
+       * lib/krb5/fcache.c (fcc_gen_new): implement
+
+Sat Feb 27 22:41:23 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * doc/install.texi: krb4 is now automatically detected
+
+       * doc/misc.texi: update procedure to set supported encryption
+       types
+
+       * doc/setup.texi: change some silly wordings
+
+Sat Feb 27 22:17:30 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/krb5/keytab.c (fkt_remove_entry): make this work
+
+       * admin/ktutil.c: add minimally working `get' command
+
+Sat Feb 27 19:44:49 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * lib/hdb/convert_db.c: more typos
+
+       * include/Makefile.am: remove EXTRA_DATA (as of autoconf
+       2.13/automake 1.4)
+
+       * appl/Makefile.am: OTP_dir
+
+Fri Feb 26 17:37:00 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * doc/setup.texi: add kadmin section
+
+       * lib/asn1/check-der.c: fix printf warnings
+
+Thu Feb 25 11:16:49 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: -O does not belong in WFLAGS
+
+Thu Feb 25 11:05:57 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/asn1/der_put.c: fix der_put_int
+
+Tue Feb 23 20:35:12 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * configure.in: use AC_BROKEN_GLOB
+
+Mon Feb 22 15:12:44 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * configure.in: check for glob
+
+Mon Feb 22 11:32:42 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Release 0.1b
+
+Sat Feb 20 15:48:06 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * lib/hdb/convert_db.c: convert DES3 keys to des3-cbc-sha1, and
+       des3-cbc-md5
+
+       * lib/krb5/crypto.c (DES3_string_to_key): make this actually do
+       what the draft said it should
+
+       * lib/hdb/convert_db.c: little program for database conversion
+
+       * lib/hdb/db.c (DB_open): try to open database w/o .db extension
+
+       * lib/hdb/ndbm.c (NDBM_open): add test for database format
+
+       * lib/hdb/db.c (DB_open): add test for database format
+
+       * lib/asn1/gen_glue.c (generate_2int): don't depend on flags being
+       unsigned
+
+       * lib/hdb/hdb.c: change `hdb_set_master_key' to take an
+       EncryptionKey, and add a new function `hdb_set_master_keyfile' to
+       do what `hdb_set_master_key' used to do
+
+       * kdc/kstash.c: add `--convert-file' option to change keytype of
+       existing master key file
+
+Fri Feb 19 07:04:14 1999  Assar Westerlund  <assar@squid.pdc.kth.se>
+
+       * Release 0.1a
+
+Sat Feb 13 17:12:53 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mk_safe.c (krb5_mk_safe): sizeof(buf) -> buf_size, buf
+       is now a `u_char *'
+
+       * lib/krb5/get_in_tkt.c (krb5_init_etype): etypes are now `int'
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm): constize
+       orig_host
+
+       (krb5_salttype_to_string): new function (RSA_MD5_DES_verify,
+       RSA_MD5_DES3_verify): initialize ret
+
+       * lib/gssapi/init_sec_context.c (init_auth): remove unnecessary
+       gssapi_krb5_init.  ask for KEYTYPE_DES credentials
+
+       * kadmin/get.c (print_entry_long): print the keytypes and salts
+       available for the principal
+
+       * configure.in (WFLAGS): add `-O' to catch unitialized variables
+       and such
+       (gethostname, mkstemp, getusershell, inet_aton): more tests
+
+       * lib/hdb/hdb.h: update prototypes
+
+       * configure.in: homogenize broken detection with krb4
+
+       * lib/kadm5/init_c.c (kadm5_c_init_with_context): remove unused
+       `error'
+
+       * lib/asn1/Makefile.am (check-der): add
+
+       * lib/asn1/gen.c (define_type): map ASN1 Integer to `int' instead
+       of `unsigned'
+
+       * lib/asn1/der_length.c (length_unsigned): new function
+       (length_int): handle signed integers
+
+       * lib/asn1/der_put.c (der_put_unsigned): new function
+       (der_put_int): handle signed integers
+
+       * lib/asn1/der_get.c (der_get_unsigned): new function
+       (der_get_int): handle signed integers
+
+       * lib/asn1/der.h: all integer functions take `int' instead of
+       `unsigned'
+
+       * lib/asn1/lex.l (filename): unused. remove.
+
+       * lib/asn1/check-der.c: new test program for der encoding and
+       decoding.
+
+Mon Feb  1 04:09:06 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc): only call
+       gethostbyname2 with AF_INET6 if we actually have IPv6.  From
+       "Brandon S. Allbery KF8NH" <allbery@kf8nh.apk.net>
+
+       * lib/krb5/changepw.c (get_kdc_address): dito
+
+Sun Jan 31 06:26:36 1999  Assar Westerlund  <assar@sics.se>
+
+       * kdc/connect.c (parse_prots): always bind to AF_INET, there are
+       v6-implementations without support for `mapped V4 addresses'.
+       From Jun-ichiro itojun Hagino <itojun@kame.net>
+
+Sat Jan 30 22:38:27 1999  Assar Westerlund  <assar@juguete.sics.se>
+
+       * Release 0.0u
+
+Sat Jan 30 13:43:02 1999  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: explicit rules for *.et files
+
+       * lib/kadm5/init_c.c (get_kadm_ticket): only remove creds if
+       krb5_get_credentials was succesful.
+       (get_new_cache): return better error codes and return earlier.
+       (get_cred_cache): only delete default_client if it's different
+       from client
+       (kadm5_c_init_with_context): return a more descriptive error.
+
+       * kdc/kerberos5.c (check_flags): handle NULL client or server
+
+       * lib/krb5/sendauth.c (krb5_sendauth): return the error in
+       `ret_error' iff != NULL
+
+       * lib/krb5/rd_error.c (krb5_free_error, krb5_free_error_contents):
+       new functions
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_extended): more
+       type-correctness
+
+       * lib/krb5/krb5.h (krb5_error): typedef to KRB_ERROR
+
+       * lib/krb5/init_creds_pw.c: KRB5_TGS_NAME: use
+
+       * lib/krb5/get_cred.c: KRB5_TGS_NAME: use
+
+       * lib/kafs/afskrb5.c (afslog_uid_int): update to changes
+
+       * lib/kadm5/rename_s.c (kadm5_s_rename_principal): call remove
+       instead of rename, but shouldn't this just call rename?
+
+       * lib/kadm5/get_s.c (kadm5_s_get_principal): always return an
+       error if the principal wasn't found.
+
+       * lib/hdb/ndbm.c (NDBM_seq): unseal key
+
+       * lib/hdb/db.c (DB_seq): unseal key
+
+       * lib/asn1/Makefile.am: added explicit rules for asn1_err.[ch]
+
+       * kdc/hprop.c (v4_prop): add krbtgt/THISREALM@OTHERREALM when
+       finding cross-realm tgts in the v4 database
+
+       * kadmin/mod.c (mod_entry): check the number of arguments.  check
+       that kadm5_get_principal worked.
+
+       * lib/krb5/keytab.c (fkt_remove_entry): remove KRB5_KT_NOTFOUND if
+       we weren't able to remove it.
+
+       * admin/ktutil.c: less drive-by-deleting.  From Love
+       <lha@e.kth.se>
+
+       * kdc/connect.c (parse_ports): copy the string before mishandling
+       it with strtok_r
+
+       * kdc/kerberos5.c (tgs_rep2): print the principal with mismatching
+       kvnos
+
+       * kadmin/kadmind.c (main): convert `debug_port' to network byte
+       order
+
+       * kadmin/kadmin.c: allow specification of port number.
+
+       * lib/kadm5/kadm5_locl.h (kadm5_client_context): add
+       `kadmind_port'.
+
+       * lib/kadm5/init_c.c (_kadm5_c_init_context): move up
+       initalize_kadm5_error_table_r.
+       allow specification of port number.
+       
+       From Love <lha@stacken.kth.se>
+
+       * kuser/klist.c: add option -t | --test
+
diff --git a/src/kerberosV/src/ChangeLog.2000 b/src/kerberosV/src/ChangeLog.2000
new file mode 100644 (file)
index 0000000..a1cb687
--- /dev/null
@@ -0,0 +1,1320 @@
+2000-12-31  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/test_get_addrs.c (main): handle krb5_init_context
+       failure consistently
+       * lib/krb5/string-to-key-test.c (main): handle krb5_init_context
+       failure consistently
+       * lib/krb5/prog_setup.c (krb5_program_setup): handle
+       krb5_init_context failure consistently
+       * lib/hdb/convert_db.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/kverify.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/klist.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/kinit.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/kgetcred.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/kdestroy.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/kdecode_ticket.c (main): handle krb5_init_context failure
+       consistently
+       * kuser/generate-requests.c (generate_requests): handle
+       krb5_init_context failure consistently
+       * kpasswd/kpasswd.c (main): handle krb5_init_context failure
+       consistently
+       * kpasswd/kpasswd-generator.c (generate_requests): handle
+       krb5_init_context failure consistently
+       * kdc/main.c (main): handle krb5_init_context failure consistently
+       * appl/test/uu_client.c (proto): handle krb5_init_context failure
+       consistently
+       * appl/kf/kf.c (main): handle krb5_init_context failure
+       consistently
+       * admin/ktutil.c (main): handle krb5_init_context failure
+       consistently
+
+       * admin/get.c (kt_get): more error checking
+
+2000-12-29  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/asn1_print.c (loop): check for length longer than data.
+       inspired by lha@stacken.kth.se
+
+2000-12-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/ktutil.8: reflect recent changes
+
+       * admin/copy.c: don't copy an entry that already exists in the
+       keytab, and warn if the keyblock differs
+
+2000-12-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/Makefile.am: merge srvconvert and srvcreate with copy
+
+       * admin/copy.c: merge srvconvert and srvcreate with copy
+
+       * lib/krb5/Makefile.am: always build keytab_krb4.c
+
+       * lib/krb5/context.c: always register the krb4 keytab functions
+
+       * lib/krb5/krb5.h: declare krb4_ftk_ops
+
+       * lib/krb5/keytab_krb4.c: We don't really need to include krb.h
+       here, since we only use the principal size macros, so define these
+       here. Theoretically someone could have a krb4 system where these
+       values are != 40, but this is unlikely, and
+       krb5_524_conv_principal also assume they are 40.
+
+2000-12-13  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: s/krb5_donot_reply/krb5_donot_replay/
+
+       * lib/krb5/replay.c: fix query-replace-o from MD5 API change, and
+       the struct is called krb5_donot_replay
+
+2000-12-12  Assar Westerlund  <assar@sics.se>
+
+       * admin/srvconvert.c (srvconvert): do not use data after free:ing
+       it
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.3d
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): set version to 14:0:0
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): update to 6:3:0
+       * lib/krb5/Makefile.am (libkrb5_la_LIBADD): add library
+       dependencies
+
+2000-12-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/auth_context.c: implement krb5_auth_con_{get,set}rcache
+
+2000-12-08  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.h (krb5_enctype): add ETYPE_DES3_CBC_NONE_IVEC as
+       a new pseudo-type
+
+       * lib/krb5/crypto.c (DES_AFS3_CMU_string_to_key): always treat
+       cell names as lower case
+       (krb5_encrypt_ivec, krb5_decrypt_ivec): new functions that allow an
+       explicit ivec to be specified.  fix all sub-functions.
+       (DES3_CBC_encrypt_ivec): new function that takes an explicit ivec
+
+2000-12-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/Makefile.am: actually build replay cache code
+
+       * lib/krb5/replay.c: implement krb5_get_server_rcache
+
+       * kpasswd/kpasswdd.c: de-pointerise auth_context parameter to
+       krb5_mk_rep
+
+       * lib/krb5/recvauth.c: de-pointerise auth_context parameter to
+       krb5_mk_rep
+
+       * lib/krb5/mk_rep.c: auth_context should not be a pointer
+
+       * lib/krb5/auth_context.c: implement krb5_auth_con_genaddrs, and
+       make setaddrs_from_fd use that
+
+       * lib/krb5/krb5.h: add some more KRB5_AUTH_CONTEXT_* flags
+
+2000-12-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/Makefile.am: add kerberos.8 manpage
+
+       * lib/krb5/cache.c: check for NULL remove_cred function
+
+       * lib/krb5/fcache.c: pretend that empty files are non-existant
+
+       * lib/krb5/get_addrs.c (find_all_addresses): use getifaddrs, from
+       Jason Thorpe <thorpej@netbsd.org>
+
+2000-12-01  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: remove configure-time generation of krb5-config
+       * tools/Makefile.am: add generation of krb5-config at make-time
+       instead of configure-time
+
+       * tools/krb5-config.in: add --prefix and --exec-prefix
+
+2000-11-30  Assar Westerlund  <assar@sics.se>
+
+       * tools/Makefile.am: add krb5-config.1
+       * tools/krb5-config.in: add kadm-client and kadm5-server as
+       libraries
+
+2000-11-29  Assar Westerlund  <assar@sics.se>
+
+       * tools/krb5-config.in: add --prefix, --exec-prefix and gssapi
+
+2000-11-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: add roken/Makefile here, since it can't live in
+       rk_ROKEN
+
+2000-11-16  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: use the libtool -rpath, do not rely on ld
+       understanding -rpath
+
+       * configure.in: fix the -Wl stuff for krb4 linking add some
+       gratuitous extra options when linking with an existing libdes
+
+2000-11-15  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/hdb.c (hdb_next_enctype2key): const-ize a little bit
+       * lib/Makefile.am (SUBDIRS): try to only build des when needed
+       * kuser/klist.c: print key versions numbers of v4 tickets in
+       verbose mode
+
+       * kdc/kerberos5.c (tgs_rep2): adapt to new krb5_verify_ap_req2
+       * appl/test/gss_common.c (read_token): remove unused variable
+
+       * configure.in (krb4): add -Wl
+       (MD4Init et al): look for these in more libraries
+       (getmsg): only run test if we have the function
+       (AC_OUTPUT): create tools/krb5-config
+
+       * tools/krb5-config.in: new script for storing flags to use
+       * Makefile.am (SUBDIRS): add tools
+
+       * lib/krb5/get_cred.c (make_pa_tgs_req): update to new
+       krb5_mk_req_internal
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_internal): allow different
+       usages for the encryption.  change callers
+       * lib/krb5/rd_req.c (decrypt_authenticator): add an encryption
+       `usage'.  also try the old
+       (and wrong) usage of KRB5_KU_AP_REQ_AUTH for backwards compatibility
+       (krb5_verify_ap_req2): new function for specifying the usage different
+       from the default (KRB5_KU_AP_REQ_AUTH)
+       * lib/krb5/build_auth.c (krb5_build_authenticator): add a `usage'
+       parameter to permit the generation of authenticators with
+       different crypto usage
+
+       * lib/krb5/mk_req.c (krb5_mk_req_exact): new function that takes a
+       krb5_principal
+       (krb5_mk_req): use krb5_mk_req_exact
+
+       * lib/krb5/mcache.c (mcc_close): free data
+       (mcc_destroy): don't free data
+
+2000-11-13  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/ndbm.c: handle both ndbm.h and gdbm/ndbm.h
+       * lib/hdb/hdb.c: handle both ndbm.h and gdbm/ndbm.h
+
+2000-11-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/hpropd.8: remove extra .Xc
+
+2000-10-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: fix v4 fallback lifetime calculation
+
+2000-10-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/524.c: fix log messge
+
+2000-10-08  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/changepw.c (krb5_change_password): check for fd's being
+       too large to select on
+       * kpasswd/kpasswdd.c (add_new_tcp): check for the socket fd being
+       too large to select on
+       * kdc/connect.c (add_new_tcp): check for the socket fd being too
+       large to selct on
+       * kdc/connect.c (loop): check that the socket fd is not too large
+       to select on
+       * lib/krb5/send_to_kdc.c (recv_loop): check `fd' for being too
+       large to be able to select on
+
+       * kdc/kaserver.c (do_authenticate): check for time skew
+
+2000-10-01  Assar Westerlund  <assar@sics.se>
+
+       * kdc/524.c (set_address): allocate memory for storing addresses
+       in if the original request had an empty set of addresses
+       * kdc/524.c (set_address): fix bad return of pointer to automatic
+       data
+
+       * config.sub: update to version 2000-09-11 (aka 1.181) from
+       subversions.gnu.org
+
+       * config.guess: update to version 2000-09-05 (aka 1.156) from
+       subversions.gnu.org plus some minor tweaks
+
+2000-09-20  Assar Westerlund  <assar@juguete.sics.se>
+
+       * Release 0.3c
+
+2000-09-19  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): bump version to
+       13:1:0
+
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): bump version to 6:2:0
+
+2000-09-17  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_req.c (krb5_decrypt_ticket): plug some memory leak
+       (krb5_rd_req): try not to return an allocated auth_context on error
+
+       * lib/krb5/log.c (krb5_vlog_msg): fix const-ness
+
+2000-09-10  Assar Westerlund  <assar@sics.se>
+
+       * kdc/524.c: re-organize
+       * kdc/kerberos5.c (tgs_rep2): try to avoid leaking auth_context
+       * kdc/kerberos4.c (valid_princ): check return value of functions
+       (encode_v4_ticket): add some const
+       * kdc/misc.c (db_fetch): check malloc
+       (free_ent): new function
+
+       * lib/krb5/log.c (krb5_vlog_msg): log just the format string it we
+       fail to allocate the actual string to log, should at least provide
+       some hint as to where things went wrong
+
+2000-09-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/log.c: use DEFAULT_LOG_DEST
+
+       * kdc/config.c: use _PATH_KDC_CONF
+
+       * kdc/kdc_locl.h: add macro constants for kdc.conf, and kdc.log
+
+2000-09-09  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (_key_schedule): re-use an existing schedule
+
+2000-09-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: fix dpagaix test
+
+2000-09-05  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: with_dce -> enable_dce.  noticed by Ake Sandgren
+       <ake@cs.umu.se>
+
+2000-09-01  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kstash.8: update manual page
+
+       * kdc/kstash.c: fix typo, and remove unused option
+
+       * lib/krb5/kerberos.7: short kerberos intro page
+
+2000-08-27  Assar Westerlund  <assar@sics.se>
+
+       * include/bits.c: add __attribute__ for gcc's pleasure
+       * lib/hdb/keytab.c: re-write to delay the opening of the database
+       till it's known which principal is being sought, thereby allowing
+       the usage of multiple databases, however they need to be specified
+       in /etc/krb5.conf since all the programs using this keytab do not
+       read kdc.conf
+
+       * appl/test/test_locl.h (keytab): add
+       * appl/test/common.c: add --keytab
+       * lib/krb5/crypto.c: remove trailing commas
+       (KRB5_KU_USAGE_SEQ): renamed from KRB5_KU_USAGE_MIC
+
+2000-08-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (send_via_proxy): handle `http://' at the
+       beginning of the proxy specification.  use getaddrinfo correctly
+       (krb5_sendto): always return a return code
+
+       * lib/krb5/krb5.h (KRB5_KU_USAGE_MIC): rename to KRB5_KU_USAGE_SEQ
+       * lib/krb5/auth_context.c (krb5_auth_con_free): handle
+       auth_context == NULL
+
+2000-08-23  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c (find_type): make sure of always setting
+       `ret_etype' correctly.  clean-up structure some
+
+2000-08-23  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/mcache.c: implement resolve
+
+2000-08-18  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kdecode_ticket.c: check return value from krb5_crypto_init
+       * kdc/kerberos5.c, kdc/524.c: check return value from krb5_crypto_init
+       * lib/krb5/*.c: check return value from krb5_crypto_init
+
+2000-08-16  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.3b
+
+2000-08-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: bump version to 13:0:0
+
+       * lib/hdb/Makefile.am: set version to 6:1:0
+
+       * configure.in: do getmsg testing the same way as in krb4
+
+       * lib/krb5/config_file.c (krb5_config_parse_file_debug): make sure
+       of closing the file on error
+
+       * lib/krb5/crypto.c (encrypt_internal_derived): free the checksum
+       after use
+
+       * lib/krb5/warn.c (_warnerr): initialize args to make third,
+       purify et al happy
+
+2000-08-13  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c: re-write search for keys code.  loop over all
+       supported enctypes in order, looping over all keys of each type,
+       and picking the one with the v5 default salt preferably
+
+2000-08-10  Assar Westerlund  <assar@sics.se>
+
+       * appl/test/gss_common.c (enet_read): add and use
+       * lib/krb5/krb5.h (heimdal_version, heimdal_long_version): make
+       const
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_internal): add comment on
+       checksum type selection
+
+       * lib/krb5/context.c (krb5_init_context): do not leak memory on
+       failure
+       (default_etypes): prefer arcfour-hmac-md5 to des-cbc-md5
+
+       * lib/krb5/principal.c: add fnmatch.h
+
+2000-08-09  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: call AC_PROG_CC and AC_PROG_CPP to make sure later
+       checks that should require them don't fail
+       * acconfig.h: add HAVE_UINT17_T
+
+2000-08-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/mit_dump.c: handle all sorts of weird MIT salt types
+
+2000-08-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * doc/setup.texi: port 212 -> 2121
+
+       * lib/krb5/principal.c: krb5_principal_match
+
+2000-08-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/asn1/der_get.c: add comment on *why* DCE sometimes used BER
+       encoding
+
+       * kpasswd/Makefile.am: link with pidfile library
+
+       * kpasswd/kpasswdd.c: write a pid file
+
+       * kpasswd/kpasswd_locl.h: util.h
+
+       * kdc/Makefile.am: link with pidfile library
+
+       * kdc/main.c: write a pid file
+
+       * kdc/headers.h: util.h
+
+2000-08-04  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): always put
+       hostnames in lower case
+       (default_v4_name_convert): add imap
+
+2000-08-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crc.c (_krb5_crc_update): const-ize (finally)
+
+2000-07-31  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: check for uint*_t
+       * include/bits.c: define uint*_t
+       
+2000-07-29  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c (check_tgs_flags): set endtime correctly when
+       renewing, From Derrick J Brashear <shadow@dementia.org>
+
+2000-07-28  Assar Westerlund  <assar@juguete.sics.se>
+
+       * Release 0.3a
+
+2000-07-27  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hprop.c (dump_database): write an empty message to signal
+       end of dump
+
+2000-07-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/changepw.c (krb5_change_password): try to be more
+       careful when not to resend
+
+       * lib/hdb/db3.c: always create a cursor with db3.  From Derrick J
+       Brashear <shadow@dementia.org>
+
+2000-07-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/Makefile.am: bump version to 6:0:0
+
+       * lib/asn1/Makefile.am: bump version to 3:0:1
+
+       * lib/krb5/Makefile.am: bump version to 12:0:1
+
+       * lib/krb5/krb5_config.3: manpage
+
+       * lib/krb5/krb5_appdefault.3: manpage
+
+       * lib/krb5/appdefault.c: implementation of the krb5_appdefault set
+       of functions
+
+2000-07-23  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/init_creds_pw.c (change_password): reset forwardable
+       and proxiable.  copy preauthentication list correctly from
+       supplied options
+
+       * kdc/hpropd.c (main): check that the ticket was for `hprop/' for
+       paranoid reasons
+
+       * lib/krb5/sock_principal.c (krb5_sock_to_principal): look in
+       aliases for the real name
+
+2000-07-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * doc/setup.texi: say something about starting kadmind from the
+       command line
+
+2000-07-22  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswdd.c: use kadm5_s_chpass_principal_cond instead of
+       mis-doing it here
+
+       * lib/krb5/changepw.c (krb5_change_password): make timeout 1 +
+       2^{0,1,...}.  also keep track if we got an old packet back and
+       then just wait without sending a new packet
+       * lib/krb5/changepw.c: use a datagram socket and remove the
+       sequence numbers
+       * lib/krb5/changepw.c (krb5_change_password): clarify an
+       expression, avoiding a warning
+
+2000-07-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.c: make -a and -n aliases for -v
+
+       * lib/krb5/write_message.c: ws
+
+       * kdc/hprop-common.c: nuke extra definitions of
+       krb5_read_priv_message et.al
+
+       * lib/krb5/read_message.c (krb5_read_message): return error if EOF
+
+2000-07-20  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswd.c: print usage consistently
+       * kdc/hprop.h (HPROP_KEYTAB): use HDB for the keytab
+       * kdc/hpropd.c: add --keytab
+       * kdc/hpropd.c: don't care what principal we recvauth as
+
+       * lib/krb5/get_cred.c: be more careful of not returning creds at
+       all when an error is returned
+       * lib/krb5/fcache.c (fcc_gen_new): do mkstemp correctly
+
+2000-07-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * fix-export: use autoreconf
+
+       * configure.in: remove stuff that belong in roken, and remove some
+       obsolete constructs
+
+2000-07-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: fix some typos
+
+       * appl/Makefile.am: dceutil*s*
+
+       * missing: update to missing from automake 1.4a
+
+2000-07-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: try to get xlc flags from ibmcxx.cfg use
+       conditional for X use readline cf macro
+
+       * configure.in: subst AIX compiler flags
+
+2000-07-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: pass sixth parameter to test-package; use some
+       newer autoconf constructs
+
+       * ltmain.sh: update to libtool 1.3c
+
+       * ltconfig: update to libtool 1.3c
+
+       * configure.in: update this to newer auto*/libtool
+
+       * appl/Makefile.am: use conditional for dce
+       
+       * lib/Makefile.am: use conditional for dce
+       
+2000-07-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/write_message.c: krb5_write_{priv,save}_message
+       * lib/krb5/read_message.c: krb5_read_{priv,save}_message
+       * lib/krb5/convert_creds.c: try port kerberos/88 if no response on
+       krb524/4444
+
+       * lib/krb5/convert_creds.c: use krb5_sendto
+
+       * lib/krb5/send_to_kdc.c: add more generic krb5_sendto that send
+       to a port at arbitrary list of hosts
+
+2000-07-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * doc/misc.texi: language; say something about kadmin del_enctype
+
+2000-07-10  Assar Westerlund  <assar@sics.se>
+
+       * appl/kf/Makefile.am: actually install
+
+2000-07-08  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (AM_INIT_AUTOMAKE): bump to 0.3a-pre
+       (AC_ROKEN): roken is now at 10
+
+       * lib/krb5/string-to-key-test.c: add a arcfour-hmac-md5 test case
+       * kdc/Makefile.am (INCLUDES): add ../lib/krb5
+       * configure.in: update for standalone roken
+       * lib/Makefile.am (SUBDIRS): make roken conditional
+       * kdc/hprop.c: update to new hdb_seal_keys_mkey
+       * lib/hdb/mkey.c (_hdb_unseal_keys_int, _hdb_seal_keys_int):
+       rename and export them
+
+       * kdc/headers.h: add krb5_locl.h (since we just use some stuff
+       from there)
+
+2000-07-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.1: update for -f and add some more text for -v
+
+       * kuser/klist.c: use rtbl to format cred listing, add -f and -s
+
+       * lib/krb5/crypto.c: fix type in des3-cbc-none
+
+       * lib/hdb/mkey.c: add key usage
+
+       * kdc/kstash.c: remove writing of old keyfile, and treat
+       --convert-file as just reading and writing the keyfile without
+       asking for a new key
+       
+       * lib/hdb/mkey.c (read_master_encryptionkey): handle old keytype
+       based files, and convert the key to cfb64
+
+       * lib/hdb/mkey.c (hdb_read_master_key): set mkey to NULL before
+       doing anything else
+
+       * lib/krb5/send_to_kdc.c: use krb5_eai_to_heim_errno
+
+       * lib/krb5/get_for_creds.c: use krb5_eai_to_heim_errno
+
+       * lib/krb5/changepw.c: use krb5_eai_to_heim_errno
+
+       * lib/krb5/addr_families.c: use krb5_eai_to_heim_errno
+
+       * lib/krb5/eai_to_heim_errno.c: convert getaddrinfo error codes to
+       something that can be passed to get_err_text
+
+2000-07-07  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/hdb.c (hdb_next_enctype2key): make sure of skipping
+       `*key'
+
+       * kdc/kerberos4.c (get_des_key): rewrite some, be more careful
+
+2000-07-06  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c (as_rep): be careful as to now overflowing when
+       calculating the end of lifetime of a ticket.
+
+       * lib/krb5/context.c (default_etypes): add ETYPE_ARCFOUR_HMAC_MD5
+
+       * lib/hdb/db3.c: only use a cursor when needed, from Derrick J
+       Brashear <shadow@dementia.org>
+
+       * lib/krb5/crypto.c: introduce the `special' encryption methods
+       that are not like all other encryption methods and implement
+       arcfour-hmac-md5
+
+2000-07-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/mit_dump.c: set initial master key version number to 0
+       instead of 1; if we lated bump the mkvno we don't risk using the
+       wrong key to decrypt
+
+       * kdc/hprop.c: only get master key if we're actually going to use
+       it; enable reading of MIT krb5 dump files
+       
+       * kdc/mit_dump.c: read MIT krb5 dump files
+       
+       * lib/hdb/mkey.c (read_master_mit): fix this
+       
+       * kdc/kstash.c: make this work with the new mkey code
+       
+       * lib/hdb/Makefile.am: add mkey.c, and bump version number
+       
+       * lib/hdb/hdb.h: rewrite master key handling
+       
+       * lib/hdb/mkey.c: rewrite master key handling
+       
+       * lib/krb5/crypto.c: add some more pseudo crypto types
+       
+       * lib/krb5/krb5.h: change some funny etypes to use negative
+       numbers, and add some more
+
+2000-07-04  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krbhst.c (get_krbhst): only try SRV lookup if there are
+       none in the configuration file
+
+2000-07-02  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/keytab_keyfile.c (akf_add_entry): remove unused
+       variable
+
+       * kpasswd/kpasswd-generator.c: new test program
+       * kpasswd/Makefile.am: add kpasswd-generator
+
+       * include/Makefile.am (CLEANFILES): add rc4.h
+
+       * kuser/generate-requests.c: new test program
+       * kuser/Makefile.am (noinst_PROGRAMS): add generate-requests
+
+2000-07-01  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: add --enable-dce and related stuff
+       * appl/Makefile.am (SUBDIRS): add $(APPL_dce)
+
+2000-06-29  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos4.c (get_des_key): fix thinkos/typos
+
+2000-06-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/purge.c: use parse_time to parse age
+
+       * lib/krb5/log.c (krb5_vlog_msg): use krb5_format_time
+
+       * admin/list.c: add printing of timestamp and key data; some
+       cleanup
+
+       * lib/krb5/time.c (krb5_format_time): new function to format time
+
+       * lib/krb5/context.c (init_context_from_config_file): init
+       date_fmt, also do some cleanup
+
+       * lib/krb5/krb5.h: add date_fmt to context
+
+2000-06-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/{kerberos4,kaserver,524}.c (get_des_key): change to return
+       v4 or afs keys if possible
+
+2000-06-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/hprop.c (ka_convert): allow using null salt, and treat 0
+       pw_expire as never (from Derrick Brashear)
+
+2000-06-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/connect.c (add_standard_ports): only listen to port 750 if
+       serving v4 requests
+
+2000-06-22  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/lex.l: fix includes, and lex stuff
+       * lib/asn1/lex.h (error_message): update prototype
+       (yylex): add
+       * lib/asn1/gen_length.c (length_type): fail on malloc error
+       * lib/asn1/gen_decode.c (decode_type): fail on malloc error
+
+2000-06-21  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_for_creds.c: be more compatible with MIT code.
+       From Daniel Kouril <kouril@ics.muni.cz>
+       * lib/krb5/rd_cred.c: be more compatible with MIT code.  From
+       Daniel Kouril <kouril@ics.muni.cz>
+       * kdc/kerberos5.c (get_pa_etype_info): do not set salttype if it's
+       vanilla pw-salt, that keeps win2k happy.  also do the malloc check
+       correctly.  From Daniel Kouril <kouril@ics.muni.cz>
+
+2000-06-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/hprop.c: add hdb keytabs
+
+2000-06-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/principal.c: back out rev. 1.64
+
+2000-06-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c: pa_* -> KRB5_PADATA_*
+
+       * kdc/hpropd.c: add realm override flag
+       
+       * kdc/v4_dump.c: code for reading krb4 dump files
+       
+       * kdc/hprop.c: generalize source database handing, add support for
+       non-standard local realms (from by Daniel Kouril
+       <kouril@ics.muni.cz> and Miroslav Ruda <ruda@ics.muni.cz>), and
+       support for using different ports (requested by the Czechs, but
+       implemented differently)
+
+       * lib/krb5/get_cred.c: pa_* -> KRB5_PADATA_*
+       
+       * lib/krb5/get_in_tkt.c: pa_* -> KRB5_PADATA_*
+       
+       * lib/krb5/krb5.h: use some definitions from asn1.h
+
+       * lib/hdb/hdb.asn1: use new import syntax
+       
+       * lib/asn1/k5.asn1: use distinguished value integers
+       
+       * lib/asn1/gen_length.c: support for distinguished value integers
+       
+       * lib/asn1/gen_encode.c: support for distinguished value integers
+       
+       * lib/asn1/gen_decode.c: support for distinguished value integers
+       
+       * lib/asn1/gen.c: support for distinguished value integers
+
+       * lib/asn1/lex.l: add support for more standards like import
+       statements
+
+       * lib/asn1/parse.y: add support for more standards like import
+       statements, and distinguished value integers
+       
+2000-06-11  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_for_creds.c (add_addrs): ignore addresses of
+       unknown type
+       * lib/krb5/get_for_creds.c (add_addrs): zero memory before
+       starting to copy memory
+
+2000-06-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/test_get_addrs.c: test program for get_addrs
+       * lib/krb5/get_addrs.c (find_all_addresses): remember to add in
+       the size of ifr->ifr_name when using SA_LEN.  noticed by Ken
+       Raeburn <raeburn@MIT.EDU>
+
+2000-06-07  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: add db3 detection stuff do not use streamsptys on
+       HP-UX 11
+       * lib/hdb/hdb.h (HDB): add dbc for db3
+       * kdc/connect.c (add_standard_ports): also listen on krb524 aka
+       4444
+       * etc/services.append (krb524): add
+       * lib/hdb/db3.c: add berkeley db3 interface.  contributed by
+       Derrick J Brashear <shadow@dementia.org>
+       * lib/hdb/hdb.h (struct HDB): add
+
+2000-06-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/524.c: if 524 is not enabled, just generate error reply and
+       exit
+
+       * kdc/kerberos4.c: if v4 is not enabled, just generate error reply
+       and exit
+
+       * kdc/connect.c: only listen to port 4444 if 524 is enabled
+       
+       * kdc/config.c: add options to enable/disable v4 and 524 requests
+       
+2000-06-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/524.c: handle non-existant server principals (from Daniel
+       Kouril)
+
+2000-06-03  Assar Westerlund  <assar@sics.se>
+
+       * admin/ktutil.c: print name when failing to open keytab
+
+       * kuser/kinit.c: try also to fallback to v4 when no KDC is found
+
+2000-05-28  Assar Westerlund  <assar@sics.se>
+
+       * kuser/klist.c: continue even we have no v5 ccache.  make showing
+       your krb4 tickets the default (if build with krb4 support)
+       * kuser/kinit.c: add a fallback that tries to get a v4 ticket if
+       built with krb4 support and we got back a version error from the
+       KDC
+
+2000-05-23  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_keyfile.c: make this actually work
+
+2000-05-19  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/store_emem.c (emem_store): make it write-compatible
+       * lib/krb5/store_fd.c (fd_store): make it write-compatible
+       * lib/krb5/store_mem.c (mem_store): make it write-compatible
+       * lib/krb5/krb5.h (krb5_storage): make store write-compatible
+
+2000-05-18  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: add stdio.h in dbopen test
+
+2000-05-16  Assar Westerlund  <assar@assaris.sics.se>
+
+       * Release 0.2t
+
+2000-05-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): set version to 11:1:0
+       * lib/krb5/fcache.c: fix second lseek
+       * lib/krb5/principal.c (krb5_524_conv_principal): fix typo
+
+2000-05-15  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2s
+
+2000-05-15  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): set version to 11:0:0
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): set version to 4:2:1
+       * lib/asn1/Makefile.am (libasn1_la_LDFLAGS): bump to 2:0:0
+       * lib/krb5/principal.c (krb5_524_conv_principal): comment-ize, and
+       simplify string copying
+
+2000-05-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/fcache.c (scrub_file): new function
+       (erase_file): re-write, use scrub_file
+       * lib/krb5/krb5.h (KRB5_DEFAULT_CCFILE_ROOT): add
+
+       * configure.in (dbopen): add header files
+
+       * lib/krb5/krb5.h (krb5_key_usage): add some more
+       * lib/krb5/fcache.c (erase_file): try to detect symlink games.
+       also call revoke.
+       * lib/krb5/changepw.c (krb5_change_password): remember to close
+       the socket on error
+
+       * kdc/main.c (main): also call sigterm on SIGTERM
+
+2000-05-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/config_file.c (krb5_config_vget_string_default,
+       krb5_config_get_string_default): add
+
+2000-04-25  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/fcache.c (fcc_initialize): just forget about
+       over-writing the old cred cache.  it's too much of a hazzle trying
+       to do this safely.
+
+2000-04-11  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (krb5_get_wrapped_length): rewrite into
+       different parts for the derived and non-derived cases
+       * lib/krb5/crypto.c (krb5_get_wrapped_length): the padding should
+       be done after having added confounder and checksum
+
+2000-04-09  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_addrs.c (find_all_addresses): apperently solaris
+       can return EINVAL when the buffer is too small.  cope.
+       * lib/asn1/Makefile.am (gen_files): add asn1_UNSIGNED.x
+       * lib/asn1/gen_locl.h (filename): add prototype
+       (init_generate): const-ize
+       * lib/asn1/gen.c (filename): new function clean-up a little bit.
+       * lib/asn1/parse.y: be more tolerant in ranges
+       * lib/asn1/lex.l: count lines correctly.
+       (error_message): print filename in messages
+
+2000-04-08  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_safe.c (krb5_rd_safe): increment sequence number
+       after comparing
+       * lib/krb5/rd_priv.c (krb5_rd_priv): increment sequence number
+       after comparing
+       * lib/krb5/mk_safe.c (krb5_mk_safe): make `tmp_seq' unsigned
+       * lib/krb5/mk_priv.c (krb5_mk_priv): make `tmp_seq' unsigned
+       * lib/krb5/generate_seq_number.c (krb5_generate_seq_number): make
+       `seqno' be unsigned
+       * lib/krb5/mk_safe.c (krb5_mk_safe): increment local sequence
+       number after the fact and only increment it if we were successful
+       * lib/krb5/mk_priv.c (krb5_mk_priv): increment local sequence
+       number after the fact and only increment it if we were successful
+       * lib/krb5/krb5.h (krb5_auth_context_data): make sequence number
+       unsigned
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password):
+       `in_tkt_service' can be NULL
+
+2000-04-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/parse.y: regonize INTEGER (0..UNIT_MAX).
+       (DOTDOT): add
+       * lib/asn1/lex.l (DOTDOT): add
+       * lib/asn1/k5.asn1 (UNSIGNED): add.  use UNSIGNED for all sequence
+       numbers.
+       * lib/asn1/gen_length.c (length_type): add TUInteger
+       * lib/asn1/gen_free.c (free_type): add TUInteger
+       * lib/asn1/gen_encode.c (encode_type, generate_type_encode): add
+       TUInteger
+       * lib/asn1/gen_decode.c (decode_type, generate_type_decode): add
+       TUInteger
+       * lib/asn1/gen_copy.c (copy_type): add TUInteger
+       * lib/asn1/gen.c (define_asn1): add TUInteger
+       * lib/asn1/der_put.c (encode_unsigned): add
+       * lib/asn1/der_length.c (length_unsigned): add
+       * lib/asn1/der_get.c (decode_unsigned): add
+       * lib/asn1/der.h (decode_unsigned, encode_unsigned,
+       length_unsigned): add prototypes
+
+       * lib/asn1/k5.asn1: update pre-authentication types
+       * lib/krb5/krb5_err.et: add some error codes from pkinit
+
+2000-04-05  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/hdb.c: add support for hdb methods (aka back-ends).
+       include ldap.
+       * lib/hdb/hdb-ldap.c: tweak the ifdef to OPENLDAP
+       * lib/hdb/Makefile.am: add hdb-ldap.c and openldap
+       * kdc/Makefile.am, kpasswd/Makefile.am, kadmin/Makefile.am: add
+       * configure.in: bump version to 0.2s-pre add options and testing
+       for (open)ldap
+
+2000-04-04  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (krb4): fix the krb_mk_req test
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (krb4): add test for const arguments to krb_mk_req
+       * lib/45/mk_req.c (krb_mk_req): conditionalize const-ness of
+       arguments
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2r
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: set version to 10:0:0
+       * lib/45/mk_req.c (krb_mk_req): const-ize the arguments
+       
+2000-03-30  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): add some
+       comments.  add fall-back on adding the realm name in lower case.
+
+2000-03-29  Assar Westerlund  <assar@sics.se>
+
+       * kdc/connect.c: remember to repoint all descr->sa to _ss after
+       realloc as this might have moved the memory around.  problem
+       discovered and diagnosed by Brandon S. Allbery
+
+2000-03-27  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: recognize solaris 2.8
+       * config.guess, config.sub: update to current version from
+       :pserver:anoncvs@subversions.gnu.org:/home/cvs
+
+       * lib/krb5/init_creds_pw.c (print_expire): do not assume anything
+       about the size of time_t, i.e. make it 64-bit happy
+
+2000-03-13  Assar Westerlund  <assar@sics.se>
+
+       * kuser/klist.c: add support for display v4 tickets
+
+2000-03-11  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kaserver.c (do_authenticate, do_getticket): call check_flags
+       * kdc/kerberos4.c (do_version4): call check_flags.
+       * kdc/kerberos5.c (check_flags): make global
+
+2000-03-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): evil
+       hack to avoid recursion
+
+2000-03-04  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c: add `krb4_get_tickets' per realm. add --anonymous
+       * lib/krb5/krb5.h (krb5_get_init_creds_opt): add `anonymous' and
+       KRB5_GET_INIT_CREDS_OPT_ANONYMOUS
+       * lib/krb5/init_creds_pw.c (get_init_creds_common): set
+       request_anonymous flag appropriatly
+       * lib/krb5/init_creds.c (krb5_get_init_creds_opt_set_anonymous):
+       add
+
+       * lib/krb5/get_in_tkt.c (_krb5_extract_ticket): new parameter to
+       determine whetever to ignore client name of not.  always copy
+       client name from kdc.  fix callers.
+
+       * kdc: add support for anonymous tickets
+
+       * kdc/string2key.8: add man-page for string2key
+
+2000-03-03  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c (dump_krb4): get expiration date from `valid_end'
+       and not `pw_end'
+
+       * kdc/kadb.h (ka_entry): fix name pw_end -> valid_end.  add some
+       more fields
+
+       * kdc/hprop.c (v4_prop): set the `valid_end' from the v4
+       expiration date instead of the `pw_expire'
+       (ka_convert): set `valid_end' from ka expiration data and `pw_expire'
+       from pw_change + pw_expire
+       (main): add a default database for ka dumping
+
+2000-02-28  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/context.c (init_context_from_config_file): change
+       rfc2052 default to no.  2782 says that underscore should be used.
+
+2000-02-24  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/fcache.c (fcc_initialize, fcc_store_cred): verify that
+       stores and close succeed
+       * lib/krb5/store.c (krb5_store_creds): check to see that the
+       stores are succesful.
+
+2000-02-23  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2q
+
+2000-02-22  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: set version to 9:2:0
+       
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname_realms): copy
+       the correct hostname
+
+       * kdc/connect.c (add_new_tcp): use the correct entries in the
+       descriptor table
+       * kdc/connect.c: initialize `descr' uniformly and correctly
+
+2000-02-20  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2p
+
+2000-02-19  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: set version to 9:1:0
+       
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname): make sure
+       that realms is filled in even when getaddrinfo fails or does not
+       return any canonical name
+
+       * kdc/connect.c (descr): add sockaddr and string representation
+       (*): re-write to use the above mentioned
+
+2000-02-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c (krb5_parse_address): use
+       krb5_sockaddr2address to copy the result from getaddrinfo.
+
+2000-02-14  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2o
+
+2000-02-13  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: set version to 9:0:0
+
+       * kdc/kaserver.c (do_authenticate): return the kvno of the server
+       and not the client.  Thanks to Brandon S. Allbery KF8NH
+       <allbery@kf8nh.apk.net> and Chaskiel M Grundman
+       <cg2v@andrew.cmu.edu> for debugging.
+
+       * kdc/kerberos4.c (do_version4): if an tgs-req is received with an
+       old kvno, return an error reply and write a message in the log.
+       
+2000-02-12  Assar Westerlund  <assar@sics.se>
+
+       * appl/test/gssapi_server.c (proto): with `--fork', create a child
+       and send over/receive creds with export/import_sec_context
+       * appl/test/gssapi_client.c (proto): with `--fork', create a child
+       and send over/receive creds with export/import_sec_context
+       * appl/test/common.c: add `--fork' / `-f' (only used by gssapi)
+
+2000-02-11  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kdc_locl.h: remove keyfile add explicit_addresses
+       * kdc/connect.c (init_sockets): pay attention to
+       explicit_addresses some more comments.  better error messages.
+       * kdc/config.c: add some comments.
+       remove --key-file.
+       add --addresses.
+
+       * lib/krb5/context.c (krb5_set_extra_addresses): const-ize and use
+       proper abstraction
+
+2000-02-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/changepw.c: use roken_getaddrinfo_hostspec
+
+2000-02-07  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2n
+
+2000-02-07  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: set version to 8:0:0
+       * lib/krb5/keytab.c (krb5_kt_default_name): use strlcpy
+       (krb5_kt_add_entry): set timestamp
+
+2000-02-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.h: add macros for accessing krb5_realm
+       * lib/krb5/time.c (krb5_timeofday): use `krb5_timestamp' instead
+       of `int32_t'
+
+       * lib/krb5/replay.c (checksum_authenticator): update to new API
+       for md5
+
+       * lib/krb5/krb5.h: remove des.h, it's not needed and applications
+       should not have to make sure to find it.
+
+2000-02-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_req.c (get_key_from_keytab): rename parameter to
+       `out_key' to avoid conflicting with label.  reported by Sean Doran
+       <smd@ebone.net>
+
+2000-02-02  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/expand_hostname.c: remember to lower-case host names.
+       bug reported by <amu@mit.edu>
+
+       * kdc/kerberos4.c (do_version4): look at check_ticket_addresses
+       and emulate that by setting krb_ignore_ip_address (not a great
+       interface but it doesn't seem like the time to go around fixing
+       libkrb stuff now)
+
+2000-02-01  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: change --noaddresses into --no-addresses
+
+2000-01-28  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswd.c (main): make sure the ticket is not
+       forwardable and not proxiable
+
+2000-01-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c: update to pseudo-standard APIs for
+       md4,md5,sha.  some changes to libdes calls to make them more
+       portable.
+
+2000-01-21  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/verify_init.c (krb5_verify_init_creds): make sure to
+       clean up the correct creds.
+
+2000-01-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (append_component): change parameter to
+       `const char *'.  check malloc
+       * lib/krb5/principal.c (append_component, va_ext_princ, va_princ):
+       const-ize
+       * lib/krb5/mk_req.c (krb5_mk_req): make `service' and `hostname'
+       const
+       * lib/krb5/principal.c (replace_chars): also add space here
+       * lib/krb5/principal.c: (quotable_chars): add space
+
+2000-01-12  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos4.c (do_version4): check if preauth was required and
+       bail-out if so since there's no way that could be done in v4.
+       Return NULL_KEY as an error to the client (which is non-obvious,
+       but what can you do?)
+
+2000-01-09  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/principal.c (krb5_sname_to_principal): use
+       krb5_expand_hostname_realms
+       * lib/krb5/mk_req.c (krb5_km_req): use krb5_expand_hostname_realms
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname_realms): new
+       variant of krb5_expand_hostname that tries until it expands into
+       something that's digestable by krb5_get_host_realm, returning also
+       the result from that function.
+
+2000-01-08  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2m
+
+2000-01-08  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: replace AC_C_BIGENDIAN with KRB_C_BIGENDIAN
+
+       * lib/krb5/Makefile.am: bump version to 7:1:0
+
+       * lib/krb5/principal.c (krb5_sname_to_principal): use
+       krb5_expand_hostname
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname): handle
+       ai_canonname being set in any of the addresses returnedby
+       getaddrinfo.  glibc apparently returns the reverse lookup of every
+       address in ai_canonname.
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2l
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: set version to 7:0:0
+       * lib/krb5/principal.c (krb5_sname_to_principal): remove `hp'
+
+       * lib/hdb/Makefile.am: set version to 4:1:1
+
+       * kdc/hpropd.c (dump_krb4): use `krb5_get_default_realms'
+       * lib/krb5/get_in_tkt.c (add_padata): change types to make
+       everything work out
+       (krb5_get_in_cred): remove const to make types match
+       * lib/krb5/crypto.c (ARCFOUR_string_to_key): correct signature
+       * lib/krb5/principal.c (krb5_sname_to_principal): handle not
+       getting back a canonname
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.2k
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc): advance colon so that
+       we actually parse the port number.  based on a patch from Leif
+       Johansson <leifj@it.su.se>
+
+2000-01-02  Assar Westerlund  <assar@sics.se>
+
+       * admin/purge.c: remove all non-current and old entries from a
+       keytab
+
+       * admin: break up ktutil.c into files
+
+       * admin/ktutil.c (list): support --verbose (also listning time
+       stamps)
+       (kt_add, kt_get): set timestamp in newly created entries
+       (kt_change): add `change' command
+
+       * admin/srvconvert.c (srvconv): set timestamp in newly created
+       entries
+       * lib/krb5/keytab_keyfile.c (akf_next_entry): set timetsamp,
+       always go the a predicatble position on error
+       * lib/krb5/keytab.c (krb5_kt_copy_entry_contents): copy timestamp
+       * lib/krb5/keytab_file.c (fkt_add_entry): store timestamp
+       (fkt_next_entry_int): return timestamp
+       * lib/krb5/krb5.h (krb5_keytab_entry): add timestamp
diff --git a/src/kerberosV/src/ChangeLog.2001 b/src/kerberosV/src/ChangeLog.2001
new file mode 100644 (file)
index 0000000..b048488
--- /dev/null
@@ -0,0 +1,1122 @@
+2001-12-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/crypto.c: use our own des string-to-key function, since
+       the one from openssl sometimes generates wrong output
+
+2001-12-05  Jacques Vidrine <n@nectar.cc>
+
+        * lib/hdb/mkey.c: fix a bug in which kstash would crash if
+        there were no /etc/krb5.conf
+
+2001-11-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5_verify_user.3: sort references (from Thomas
+       Klausner)
+
+       * lib/krb5/krb5_principal_get_realm.3: add section to reference
+       (from Thomas Klausner)
+
+       * lib/krb5/krb5_krbhst_init.3: sort references (from Thomas
+       Klausner)
+
+       * lib/krb5/krb5_keytab.3: white space fixes (from Thomas Klausner)
+
+       * lib/krb5/krb5_get_krbhst.3: remove extra white space (from
+       Thomas Klausner)
+
+       * lib/krb5/krb5_get_all_client_addrs.3: add section to reference
+       (from Thomas Klausner)
+
+2001-10-29  Jacques Vidrine <n@nectar.com>
+
+       * admin/get.c: fix a bug in which a reference to a data
+       structure on the stack was being kept after the containing
+       function's lifetime, resulting in a segfault during `ktutil
+       get'.
+
+2001-10-22  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c: make all high-level encrypting and decrypting
+       functions check the return value of the underlying function and
+       handle errors more consistently.  noted by Sam Hartman
+       <hartmans@mit.edu>
+
+2001-10-21  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (enctype_arcfour_hmac_md5): actually use a
+       non-keyed checksum when it should be non-keyed
+
+2001-09-29  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.1: add the kauth alias
+       * kuser/kinit.c: allow specification of afslog in krb5.conf, noted
+       by jhutz@cs.cmu.edu
+
+2001-09-27  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/gen.c: remove the need for libasn1.h, also make
+       generated files include all files from IMPORTed modules
+
+       * lib/krb5/krb5.h (KRB5_KPASSWD_*): set correct values
+       * kpasswd/kpasswd.c: improve error message printing
+       * lib/krb5/changepw.c (krb5_passwd_result_to_string): add change
+       to use sequence numbers connect the udp socket so that we can
+       figure out the local address
+
+2001-09-25  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1: implement OBJECT IDENTIFIER and ENUMERATED
+
+2001-09-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): try using
+       lower case realm as domain, but only when given a verification
+       function
+
+2001-09-20  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/der_put.c (der_put_length): do not even try writing
+       anything when len == 0
+
+2001-09-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/hpropd.c: add realm override option
+
+       * lib/krb5/set_default_realm.c (krb5_set_default_realm): make
+       realm parameter const
+
+       * kdc/hprop.c: more free's
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_keytab): free key
+       proc data
+
+       * lib/krb5/expand_hostname.c (krb5_expand_hostname_realms): free
+       addrinfo
+
+       * lib/hdb/mkey.c (hdb_set_master_keyfile): clear error string when
+       not returning error
+
+2001-09-16  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/appdefault.c (krb5_appdefault_{boolean,string,time):
+       make realm const
+
+       * lib/krb5/crypto.c: use des functions to avoid generating
+       warnings with openssl's prototypes
+
+2001-09-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: check for termcap.h
+
+       * lib/asn1/lex.l: add another undef ECHO to keep AIX lex happy
+
+2001-09-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/addr_families.c (krb5_print_address): handle snprintf
+       returning < 0.  noticed by hin@stacken.kth.se
+
+2001-09-03  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.4e
+
+2001-09-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/Makefile.am: install kauth as a symlink to kinit
+
+       * kuser/kinit.c: get v4_tickets by default
+
+       * lib/asn1/Makefile.am: fix for broken automake
+
+2001-08-31  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/hdb-ldap.c: some pretty much untested changes from Luke
+       Howard
+
+       * kuser/kinit.1: remove references to kauth
+
+       * kuser/Makefile.am: kauth is no more
+
+       * kuser/kinit.c: use appdefaults for everything. defaults are now
+       as in kauth.
+
+       * lib/krb5/appdefault.c: also check libdefaults, and realms/realm
+
+       * lib/krb5/context.c (krb5_free_context): free more stuff
+
+2001-08-30  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/verify_krb5_conf.c: do some checks of the values in the
+       file
+
+       * lib/krb5/krb5.conf.5: remove srv_try_txt, fix spelling
+
+       * lib/krb5/context.c: don't init srv_try_txt, since it isn't used
+       anymore
+
+2001-08-29  Jacques Vidrine  <n@nectar.com>
+
+       * configure.in: Check for already-installed com_err.
+
+2001-08-28  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): set versoin to 18:2:1
+
+2001-08-24  Assar Westerlund  <assar@sics.se>
+
+       * kuser/Makefile.am: remove CHECK_LOCAL - non bin programs require
+       no special treatment now
+
+       * kuser/generate-requests.c: parse arguments in a useful way
+       * kuser/kverify.c: add --help/--verify
+
+2001-08-22  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: bump prereq to 2.52 remove unused test_LIB_KRB4
+
+       * configure.in: re-write the handling of crypto libraries.  try to
+       use the one of openssl's libcrypto or krb4's libdes that has all
+       the required functionality (md4, md5, sha1, des, rc4).  if there
+       is no such library, the included lib/des is built.
+
+       * kdc/headers.h: include libutil.h if it exists
+       * kpasswd/kpasswd_locl.h: include libutil.h if it exists
+       * kdc/kerberos4.c (get_des_key): check for null keys even if
+       is_server
+
+2001-08-21  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/asn1_print.c: print some size_t correctly
+       * configure.in: remove extra space after -L check for libutil.h
+
+2001-08-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kdc_locl.h: fix prototype for get_des_key
+
+       * kdc/kaserver.c: fix call to get_des_key
+
+       * kdc/524.c: fix call to get_des_key
+
+       * kdc/kerberos4.c (get_des_key): if getting a key for a server,
+       return any des-key not just keys that can be string-to-keyed by
+       the client
+
+2001-08-10  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.4d
+
+2001-08-10  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: check for openpty
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): update to 7:4:0
+
+2001-08-08  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: just add -L (if required) from krb4 when testing
+       for libdes/libcrypto
+
+2001-08-04  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (man_MANS): add some missing man pages
+       * fix-export: fix the sed expression for finding the man pages
+
+2001-07-31  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswd-generator.c (main): implement --version and
+       --help
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): update version to
+       18:1:1
+
+2001-07-27  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/context.c (init_context_from_config_file): check
+       parsing of addresses
+
+2001-07-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/sock_principal.c (krb5_sock_to_principal): rename
+       sa_len -> salen to avoid the macro that's defined on irix.  noted
+       by "Jacques A. Vidrine" <n@nectar.com>
+
+2001-07-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/addr_families.c: add support for type
+       KRB5_ADDRESS_ADDRPORT
+
+       * lib/krb5/addr_families.c (krb5_address_order): complain about
+       unsuppored address types
+
+2001-07-23  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/get.c: don't open connection to server until we loop over
+       the principals, at that time we know the realm of the (first)
+       principal and we can default to that admin server
+
+       * admin: add a rename command
+
+2001-07-19  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hprop.c (usage): clarify a tiny bit
+
+2001-07-19  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.4c
+
+2001-07-19  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): bump version to
+       18:0:1
+
+       * lib/krb5/get_for_creds.c (krb5_fwd_tgt_creds): make it behave
+       the same way as the MIT function
+
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): update to 7:3:0
+       * lib/krb5/sock_principal.c (krb5_sock_to_principal): use
+       getnameinfo
+
+       * lib/krb5/krbhst.c (srv_find_realm): handle port numbers
+       consistenly in local byte order
+
+       * lib/krb5/get_default_realm.c (krb5_get_default_realm): set an
+       error string
+
+       * kuser/kinit.c (renew_validate): invert condition correctly.  get
+       v4 tickets if we succeed renewing
+       * lib/krb5/principal.c (krb5_principal_get_type): add
+       (default_v4_name_convert): add "smtp"
+
+2001-07-13  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: remove make-print-version from LIBOBJS, it's no
+       longer in lib/roken but always built in lib/vers
+
+2001-07-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/mkey.c: more set_error_string
+
+2001-07-12  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/Makefile.am (libhdb_la_LIBADD): add required library
+       dependencies
+
+       * lib/asn1/Makefile.am (libasn1_la_LIBADD): add required library
+       dependencies
+
+2001-07-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/hprop.c: remove v4 master key handling; remove old v4-db and
+       ka-db flags; add defaults for v4_realm and afs_cell
+
+2001-07-09  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/sock_principal.c (krb5_sock_to_principal): copy hname
+       before calling krb5_sname_to_principal.  from "Jacques A. Vidrine"
+       <n@nectar.com>
+
+2001-07-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/context.c: use krb5_copy_addresses instead of
+       copy_HostAddresses
+
+2001-07-06  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (LIB_des_a, LIB_des_so): add these so that they can
+       be used by lib/auth/sia
+
+       * kuser/kinit.c: re-do some of the v4 fallbacks: look at
+       get-tokens flag do not print extra errors do not try to do 524 if
+       we got tickets from a v4 server
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/replay.c (krb5_get_server_rcache): cast argument to
+       printf
+
+       * lib/krb5/get_addrs.c (find_all_addresses): call free_addresses
+       on ignore_addresses correctly
+       * lib/krb5/init_creds.c
+       (krb5_get_init_creds_opt_set_default_flags): change to take a
+       const realm
+
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): if the
+       instance is the first component of the local hostname, the
+       converted host should be the long hostname.  from
+       <shadow@dementia.org>
+
+2001-07-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/Makefile.am: address.c is no more; add a couple of
+       manpages
+
+       * lib/krb5/krb5_timeofday.3: new manpage
+
+       * lib/krb5/krb5_get_all_client_addrs.3: new manpage
+
+       * lib/krb5/get_in_tkt.c (init_as_req): treat no addresses as
+       wildcard
+
+       * lib/krb5/get_cred.c (get_cred_kdc_la): treat no addresses as
+       wildcard
+
+       * lib/krb5/get_addrs.c: don't include client addresses that match
+       ignore_addresses
+
+       * lib/krb5/context.c: initialise ignore_addresses
+
+       * lib/krb5/addr_families.c: add new `arange' fake address type,
+       that matches more than one address; this required some internal
+       changes to many functions, so all of address.c got moved here
+       (wasn't much left there)
+
+       * lib/krb5/krb5.h: add list of ignored addresses to context
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.4b
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): set version to 17:0:0
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): set version to 7:2:0
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.4a
+
+2001-07-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: make this compile without krb4 support
+
+       * lib/krb5/write_message.c: remove priv parameter from
+       write_safe_message; don't know why it was there in the first place
+
+       * doc/install.texi: remove kaserver switches, it's always compiled
+       in now
+
+       * kdc/hprop.c: always include kadb support
+
+       * kdc/kaserver.c: always include kaserver support
+
+2001-07-02  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswdd.c (doit): make failing to bind a socket a
+       non-fatal error, and abort if no sockets were bound
+
+2001-07-01  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krbhst.c: remember the real port number when falling
+       back from kpasswd -> kadmin, and krb524 -> kdc
+
+2001-06-29  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): if
+       no_addresses is set, do not add any local addresses to KRB_CRED
+
+       * kuser/kinit.c: remove extra clearing of password and some
+       redundant code
+
+2001-06-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: move ticket conversion code to separate function,
+       and call that from a couple of places, like when renewing a
+       ticket; also add a flag for just converting a ticket
+
+       * lib/krb5/init_creds_pw.c: set renew-life to some sane value
+
+       * kdc/524.c: don't send more data than required
+
+2001-06-24  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/store_fd.c (krb5_storage_from_fd): check malloc returns
+
+       * lib/krb5/keytab_any.c (any_resolve); improving parsing of ANY:
+       (any_start_seq_get): remove a double free
+       (any_next_entry): iterate over all (sub) keytabs and avoid leave data
+       around to be freed again
+
+       * kdc/kdc_locl.h: add a define for des_new_random_key when using
+       openssl's libcrypto
+
+       * configure.in: move v6 tests down
+
+       * lib/krb5/krb5.h (krb5_context_data): remove srv_try_rfc2052
+
+       * update to libtool 1.4 and autoconf 2.50
+
+2001-06-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/hdb.c: use krb5_add_et_list
+
+2001-06-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/Makefile.am: add generation number
+       * lib/hdb/common.c: add generation number code
+       * lib/hdb/hdb.asn1: add generation number
+       * lib/hdb/print.c: use krb5_storage to make it more dynamic
+
+2001-06-21  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.conf.5: update to changed names used by
+       krb5_get_init_creds_opt_set_default_flags
+       * lib/krb5/init_creds.c
+       (krb5_get_init_creds_opt_set_default_flags): make the appdefault
+       keywords have the same names
+
+       * configure.in: only add -L and -R to the krb4 libdir if we are
+       actually using it
+
+       * lib/krb5/krbhst.c (fallback_get_hosts): do not copy trailing
+       dot of hostname add some comments
+       * lib/krb5/krbhst.c: use getaddrinfo instead of dns_lookup when
+       testing for kerberos.REALM.  this allows reusing that information
+       when actually contacting the server and thus avoids one DNS lookup
+
+2001-06-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: include k524_err.h
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): don't test
+       for keytype, the server will do this for us if it has anything to
+       complain about
+
+       * lib/krb5/context.c: add protocol compatible krb524 error codes
+
+       * lib/krb5/Makefile.am: add protocol compatible krb524 error codes
+
+       * lib/krb5/k524_err.et: add protocol compatible krb524 error codes
+
+       * lib/krb5/krb5_principal_get_realm.3: manpage
+
+       * lib/krb5/principal.c: add functions `krb5_principal_get_realm'
+       and `krb5_principal_get_comp_string' that returns parts of a
+       principal; this is a replacement for the internal
+       `krb5_princ_realm' and `krb5_princ_component' macros that everyone
+       seem to use
+
+2001-06-19  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c (main): dereference result from krb5_princ_realm.
+       from Thomas Nystrom <thn@saeab.se>
+
+2001-06-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/mk_req.c (krb5_mk_req_exact): free creds when done
+       * lib/krb5/crypto.c (krb5_string_to_key_derived): fix memory leak
+       * lib/krb5/krbhst.c (config_get_hosts): free hostlist
+       * kuser/kinit.c: free principal
+
+2001-06-18  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto): remove an extra
+       freeaddrinfo
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc_ccache):
+       remove some unused variables
+
+       * lib/krb5/krbhst.c (admin_get_next): spell kerberos correctly
+       * kdc/kerberos5.c: update to new krb5_auth_con* names
+       * kdc/hpropd.c: update to new krb5_auth_con* names
+       * lib/krb5/rd_req.c (krb5_rd_req): use krb5_auth_con* functions
+       and remove some comments
+       * lib/krb5/rd_safe.c (krb5_rd_safe): pick the keys in the right
+       order: remote - local - session
+       * lib/krb5/rd_rep.c (krb5_rd_rep): save the remote sub key in the
+       auth_context
+       * lib/krb5/rd_priv.c (krb5_rd_priv): pick keys in the correct
+       order: remote - local - session
+       * lib/krb5/mk_safe.c (krb5_mk_safe): pick keys in the right order,
+       local - remote - session
+
+2001-06-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/convert_creds.c: use starttime instead of authtime,
+       from Chris Chiappa
+
+       * lib/krb5/convert_creds.c: make krb524_convert_creds_kdc match
+       the MIT function by the same name; add
+       krb524_convert_creds_kdc_ccache that does what the old version did
+
+       * admin/list.c (do_list): make sure list of keys is NULL
+       terminated; similar to patch sent by Chris Chiappa
+
+2001-06-18  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/mcache.c (mcc_remove_cred): use
+       krb5_free_creds_contents
+
+       * lib/krb5/auth_context.c: name function krb5_auth_con more
+       consistenly
+       * lib/krb5/rd_req.c (krb5_verify_authenticator_checksum): use
+       renamed krb5_auth_con_getauthenticator
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): update to
+       use krb5_krbhst API
+       * lib/krb5/changepw.c (krb5_change_password): update to use
+       krb5_krbhst API
+       * lib/krb5/send_to_kdc.c: update to use krb5_krbhst API
+       * lib/krb5/krbhst.c (krb5_krbhst_get_addrinfo): add set def_port
+       in krb5_krbhst_info
+       (krb5_krbhst_free): free everything
+
+       * lib/krb5/krb5.h (KRB5_VERIFY_NO_ADDRESSES): add
+       (krb5_krbhst_info): add def_port (default port for this service)
+
+       * lib/krb5/krbhst-test.c: make it more verbose and useful
+       * lib/krb5/krbhst.c: remove some more memory leaks do not try any
+       dns operations if there is local configuration admin: fallback to
+       kerberos.REALM 524: fallback to kdcs kpasswd: fallback to admin
+       add some comments
+
+       * configure.in: remove initstate and setstate, they should be in
+       cf/roken-frag.m4
+
+       * lib/krb5/Makefile.am (noinst_PROGRAMS): add krbhst-test
+       * lib/krb5/krbhst-test.c: new program for testing krbhst
+       * lib/krb5/krbhst.c (common_init): remove memory leak
+       (main): move test program into krbhst-test
+
+2001-06-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5_krbhst_init.3: manpage
+
+       * lib/krb5/krb5_get_krbhst.3: manpage
+
+2001-06-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: add opaque krb5_krbhst_handle type
+
+       * lib/krb5/krbhst.c: change void* to krb5_krbhst_handle
+
+       * lib/krb5/krb5.h: types for new krbhst api
+
+       * lib/krb5/krbhst.c: implement a new api that looks up one host at
+       a time, instead of making a list of hosts
+
+2001-06-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: test for initstate and setstate
+
+       * lib/krb5/krbhst.c: remove rfc2052 support
+
+2001-06-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * fix some manpages for broken mdoc.old grog test
+
+2001-05-28  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.conf.5: add [appdefaults]
+       * lib/krb5/init_creds_pw.c: remove configuration reading that is
+       now done in krb5_get_init_creds_opt_set_default_flags
+       * lib/krb5/init_creds.c
+       (krb5_get_init_creds_opt_set_default_flags): add reading of
+       libdefaults versions of these and add no_addresses
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): clear error string
+       when preauth was required and we retry
+
+2001-05-25  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/convert_creds.c (krb524_convert_creds_kdc): call
+       krb5_get_krb524hst
+       * lib/krb5/krbhst.c (krb5_get_krb524hst): add and restructure the
+       support functions
+
+2001-05-22  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c (tgs_rep2): alloc and free csec and cusec
+       properly
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * Release 0.3f
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am: bump version to 16:0:0
+       * lib/hdb/Makefile.am: bump version to 7:1:0
+       * lib/asn1/Makefile.am: bump version to 5:0:0
+       * lib/krb5/keytab_krb4.c: add SRVTAB as an alias for krb4
+       * lib/krb5/codec.c: remove dead code
+
+2001-05-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/config.c: actually check the ticket addresses
+
+2001-05-15  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_error.c (krb5_error_from_rd_error): use correct
+       parenthesis
+
+       * lib/krb5/eai_to_heim_errno.c (krb5_eai_to_heim_errno): add
+       `errno' (called system_error) to allow callers to make sure they
+       pass the current and relevant value.  update callers
+
+2001-05-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/verify_user.c: krb5_verify_user_opt
+
+       * lib/krb5/krb5.h: verify_opt
+
+       * kdc/kerberos5.c: pass context to krb5_domain_x500_decode
+
+2001-05-14  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswdd.c: adapt to new address functions
+       * kdc/kerberos5.c: adapt to changing address functions use LR_TYPE
+       * kdc/connect.c: adapt to changing address functions
+       * kdc/config.c: new krb5_config_parse_file
+       * kdc/524.c: new krb5_sockaddr2address
+       * lib/krb5/*: add some krb5_{set,clear}_error_string
+
+       * lib/asn1/k5.asn1 (LR_TYPE): add
+       * lib/asn1/Makefile.am (gen_files): add asn1_LR_TYPE.x
+
+2001-05-11  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c (tsg_rep): fix typo in variable name
+
+       * kpasswd/kpasswd-generator.c (nop_prompter): update prototype
+       * lib/krb5/init_creds_pw.c: update to new prompter, use prompter
+       types and send two prompts at once when changning password
+       * lib/krb5/prompter_posix.c (krb5_prompter_posix): add name
+       * lib/krb5/krb5.h (krb5_prompt): add type
+       (krb5_prompter_fct): add anem
+
+       * lib/krb5/cache.c (krb5_cc_next_cred): transpose last two
+       paramaters to krb5_cc_next_cred (as MIT does, and not as they
+       document).  From "Jacques A. Vidrine" <n@nectar.com>
+
+2001-05-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/Makefile.am: store-test
+
+       * lib/krb5/store-test.c: simple bit storage test
+
+       * lib/krb5/store.c: add more byteorder storage flags
+       
+       * lib/krb5/krb5.h: add more byteorder storage flags
+       
+       * kdc/kerberos5.c: don't use NULL where we mean 0
+
+       * kdc/kerberos5.c: put referral test code in separate function,
+       and test for KRB5_NT_SRV_INST
+
+2001-05-10  Assar Westerlund  <assar@sics.se>
+
+       * admin/list.c (do_list): do not close the keytab if opening it
+       failed
+       * admin/list.c (do_list): always print complete names.  print
+       everything to stdout.
+       * admin/list.c: print both v5 and v4 list by default
+       * admin/remove.c (kt_remove): reorganize some.  open the keytab
+       (defaulting to the modify one).
+       * admin/purge.c (kt_purge): reorganize some.  open the keytab
+       (defaulting to the modify one). correct usage strings
+       * admin/list.c (kt_list): reorganize some.  open the keytab
+       * admin/get.c (kt_get): reorganize some.  open the keytab
+       (defaulting to the modify one)
+       * admin/copy.c (kt_copy): default to modify key name.  re-organise
+       * admin/change.c (kt_change): reorganize some.  open the keytab
+       (defaulting to the modify one)
+       * admin/add.c (kt_add): reorganize some.  open the keytab
+       (defaulting to the modify one)
+       * admin/ktutil.c (main): do not open the keytab, let every
+       sub-function handle it
+
+       * kdc/config.c (configure): call free_getarg_strings
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): set error strings for
+       a few more errors
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm_int): make
+       `use_dns' parameter boolean
+
+       * lib/krb5/krb5.h (krb5_context_data): add default_keytab_modify
+       * lib/krb5/context.c (init_context_from_config_file): set
+       default_keytab_modify
+       * lib/krb5/krb5_locl.h (KEYTAB_DEFAULT): change to
+       ANY:FILE:/etc/krb5.keytab,krb4:/etc/srvtab
+       (KEYTAB_DEFAULT_MODIFY): add
+       * lib/krb5/keytab.c (krb5_kt_default_modify_name): add
+       (krb5_kt_resolve): set error string for failed keytab type
+
+2001-05-08  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (encryption_type): make field names more
+       consistent
+       (create_checksum): separate usage and type
+       (krb5_create_checksum): add a separate type parameter
+       (encrypt_internal): only free once on mismatched checksum length
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc2): try to tell what
+       realm we didn't manage to reach any KDC for in the error string
+
+       * lib/krb5/generate_seq_number.c (krb5_generate_seq_number): free
+       the entire subkey.  from <tmartin@mirapoint.com>
+
+2001-05-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_keyfile.c (akf_start_seq_get): return
+       KT_NOTFOUND if the file is empty
+
+2001-05-07  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/fcache.c: call krb5_set_error_string when open fails
+       fatally
+       * lib/krb5/keytab_file.c: call krb5_set_error_string when open
+       fails fatally
+
+       * lib/krb5/warn.c (_warnerr): print error_string in context in
+       preference to error string derived from error code
+       * kuser/kinit.c (main): try to print the error string
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): set some sensible
+       error strings for errors
+
+       * lib/krb5/krb5.h (krb5_context_data): add error_string and
+       error_buf
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add error_string.c
+       * lib/krb5/error_string.c: new file
+
+2001-05-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/time.c: krb5_string_to_deltat
+
+       * lib/krb5/sock_principal.c: one less data copy
+
+       * lib/krb5/eai_to_heim_errno.c: conversion function for h_errno's
+
+       * lib/krb5/get_default_principal.c: change this slightly
+
+       * lib/krb5/crypto.c: make checksum_types into an array of pointers
+
+       * lib/krb5/convert_creds.c: make sure we always use a des-cbc-crc
+       ticket
+
+2001-04-29  Assar Westerlund  <assar@sics.se>
+
+       * kdc/kerberos5.c (tgs_rep2): return a reference to a krbtgt for
+       the right realm if we fail to find a non-krbtgt service in the
+       database and the second component does a succesful non-dns lookup
+       to get the real realm (which has to be different from the
+       originally-supplied realm).  this should help windows 2000 clients
+       that always start their lookups in `their' realm and do not have
+       any idea of how to map hostnames into realms
+       * kdc/kerberos5.c (is_krbtgt): rename to get_krbtgt_realm
+
+2001-04-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/get_host_realm.c (krb5_get_host_realm_int): add extra
+       parameter to request use of dns or not
+
+2001-04-25  Assar Westerlund  <assar@sics.se>
+
+       * admin/get.c (kt_get): allow specification of encryption types
+       * lib/krb5/verify_init.c (krb5_verify_init_creds): do not try to
+       close an unopened ccache, noted by <marc@mit.edu>
+
+       * lib/krb5/krb5.h (krb5_any_ops): add declaration
+       * lib/krb5/context.c (init_context_from_config_file): register
+       krb5_any_ops
+
+       * lib/krb5/keytab_any.c: new file, implementing union of keytabs
+       * lib/krb5/Makefile.am (libkrb5_la_SOURCES): add keytab_any.c
+       
+       * lib/krb5/init_creds_pw.c (get_init_creds_common): handle options
+       == NULL.  noted by <marc@mit.edu>
+
+2001-04-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/rd_cred.c: set ret_creds to NULL before doing anything
+       else, from Jacques Vidrine
+
+2001-04-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/hdb/libasn1.h: asn1.h -> krb5_asn1.h
+
+       * lib/asn1/Makefile.am: add asn1_ENCTYPE.x
+
+       * lib/krb5/krb5.h: adapt to asn1 changes
+
+       * lib/asn1/k5.asn1: move enctypes here
+
+       * lib/asn1/libasn1.h: rename asn1.h to krb5_asn1.h to avoid
+       conflicts
+
+       * lib/asn1/Makefile.am: rename asn1.h to krb5_asn1.h to avoid
+       conflicts
+
+       * lib/asn1/lex.l: use strtol to parse constants
+
+2001-04-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: add simple support for running commands
+
+2001-03-26  Assar Westerlund  <assar@sics.se>
+
+       * lib/hdb/hdb-ldap.c: change order of includes to allow it to work
+       with more versions of openldap
+
+       * kdc/kerberos5.c (tgs_rep2): try to set sec and usec in error
+       replies
+       (*): update callers of krb5_km_error
+       (check_tgs_flags): handle renews requesting non-renewable tickets
+
+       * lib/krb5/mk_error.c (krb5_mk_error): allow specifying both ctime
+       and cusec
+
+       * lib/krb5/krb5.h (krb5_checksum, krb5_keyusage): add
+       compatibility names
+
+       * lib/krb5/crypto.c (create_checksum): change so that `type == 0'
+       means pick from the `crypto' (context) and otherwise use that
+       type.  this is not a large change in practice and allows callers
+       to specify the exact checksum algorithm to use
+
+2001-03-13  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/get_cred.c (get_cred_kdc): add support for falling back
+       to KRB5_KU_AP_REQ_AUTH when KRB5_KU_TGS_REQ_AUTH gives `bad
+       integrity'.  this helps for talking to old (pre 0.3d) KDCs
+
+2001-03-12  Assar Westerlund  <assar@pdc.kth.se>
+
+       * lib/krb5/crypto.c (krb5_derive_key): new function, used by
+       derived-key-test.c
+       * lib/krb5/string-to-key-test.c: add new test vectors posted by
+       Ken Raeburn <raeburn@mit.edu> in <tx1bsra8919.fsf@raeburn.org> to
+       ietf-krb-wg@anl.gov
+       * lib/krb5/n-fold-test.c: more test vectors from same source
+       * lib/krb5/derived-key-test.c: more tests from same source
+
+2001-03-06  Assar Westerlund  <assar@sics.se>
+
+       * acconfig.h: include roken_rename.h when appropriate
+
+2001-03-06  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.h (krb5_enctype): remove trailing comma
+
+2001-03-04  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.h (krb5_enctype): add ENCTYPE_* aliases for
+       compatibility with MIT krb5
+
+2001-03-02  Assar Westerlund  <assar@sics.se>
+
+       * kuser/kinit.c (main): only request a renewable ticket when
+       explicitly requested.  it still gets a renewable one if the renew
+       life is specified
+       * kuser/kinit.c (renew_validate): treat -1 as flags not being set
+
+2001-02-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/context.c (krb5_init_ets): use krb5_add_et_list
+
+2001-02-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/get_cred.c: implement krb5_get_cred_from_kdc_opt
+
+2001-02-25  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: do not use -R when testing for des functions
+
+2001-02-14  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: test for lber.h when trying to link against
+       openldap to handle openldap v1, from Sumit Bose
+       <sumit.bose@suse.de>
+
+2001-02-19  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/libasn1.h: add string.h (for memset)
+
+2001-02-15  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/warn.c (_warnerr): add printf attributes
+       * lib/krb5/send_to_kdc.c (krb5_sendto): loop over all address
+       returned by getaddrinfo before trying the next kdc.  from
+       thorpej@netbsd.org
+
+       * lib/krb5/krb5.conf.5: fix default_realm in example
+
+       * kdc/connect.c: fix a few kdc_log format types
+
+       * configure.in: try to handle libdes/libcrypto ont requiring -L
+
+2001-02-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/asn1/gen_decode.c (generate_type_decode): zero the data at
+       the beginning of the generated function, and add a label `fail'
+       that the code jumps to in case of errors that frees all allocated
+       data
+
+2001-02-07  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: aix dce: fix misquotes, from Ake Sandgren
+       <ake@cs.umu.se>
+
+       * configure.in (dpagaix_LDFLAGS): try to add export file
+
+2001-02-05  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5_keytab.3: new man page, contributed by
+       <lha@stacken.kth.se>
+
+       * kdc/kaserver.c: update to new db_fetch4
+
+2001-02-05  Assar Westerlund  <assar@assaris.sics.se>
+
+       * Release 0.3e
+
+2001-01-30  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hprop.c (v4_get_masterkey): check kdb_verify_master_key
+       properly
+       (kdb_prop): decrypt key properly
+       * kdc/hprop.c: handle building with KRB4 always try to decrypt v4
+       data with the master key leave it up to the v5 how to encrypt with
+       that master key
+
+       * kdc/kstash.c: include file name in error messages
+       * kdc/hprop.c: fix a typo and check some more return values
+       * lib/hdb/hdb-ldap.c (LDAP__lookup_princ): call ldap_search_s
+       correctly.  From Jacques Vidrine <n@nectar.com>
+       * kdc/misc.c (db_fetch): HDB_ERR_NOENTRY makes more sense than
+       ENOENT
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): bump version to
+       15:0:0
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): bump version to 7:0:0
+       * lib/asn1/Makefile.am (libasn1_la_LDFLAGS): bump version to 4:0:2
+       * kdc/misc.c (db_fetch): return an error code.  change callers to
+       look at this and try to print it in log messages
+
+       * lib/krb5/crypto.c (decrypt_internal_derived): check that there's
+       enough data
+
+2001-01-29  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hprop.c (realm_buf): move it so it becomes properly
+       conditional on KRB4
+
+       * lib/hdb/mkey.c (hdb_unseal_keys_mkey, hdb_seal_keys_mkey,
+       hdb_unseal_keys, hdb_seal_keys): check that we have the correct
+       master key and that we manage to decrypt the key properly,
+       returning an error code.  fix all callers to check return value.
+
+       * tools/krb5-config.in: use @LIB_des_appl@
+       * tools/Makefile.am (krb5-config): add LIB_des_appl
+       * configure.in (LIB_des): set correctly
+       (LIB_des_appl): add for the use by krb5-config.in
+
+       * lib/krb5/store_fd.c (fd_fetch, fd_store): use net_{read,write}
+       to make sure of not dropping data when doing it over a socket.
+       (this might break when used with ordinary files on win32)
+
+       * lib/hdb/hdb_err.et (NO_MKEY): add
+
+       * kdc/kerberos5.c (as_rep): be paranoid and check
+       krb5_enctype_to_string for failure, noted by <lha@stacken.kth.se>
+
+       * lib/krb5/krb5_init_context.3, lib/krb5/krb5_context.3,
+       lib/krb5/krb5_auth_context.3: add new man pages, contributed by
+       <lha@stacken.kth.se>
+
+       * use the openssl api for md4/md5/sha and handle openssl/*.h
+
+       * kdc/kaserver.c (do_getticket): check length of ticket.  noted by
+       <lha@stacken.kth.se>
+
+2001-01-28  Assar Westerlund  <assar@sics.se>
+
+       * configure.in: send -R instead of -rpath to libtool to set
+       runtime library paths
+
+       * lib/krb5/Makefile.am: remove all dependencies on libkrb
+
+2001-01-27  Assar Westerlund  <assar@sics.se>
+
+       * appl/rcp: add port of bsd rcp changed to use existing rsh,
+       contributed by Richard Nyberg <rnyberg@it.su.se>
+
+2001-01-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/get_port.c: don't warn if the port name can't be found,
+       nobody cares anyway
+
+2001-01-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/hprop.c: make it possible to convert a v4 dump file without
+       having any v4 libraries; the kdb backend still require them
+
+       * kdc/v4_dump.c: include shadow definition of kdb Principal, so we
+       don't have to depend on any v4 libraries
+
+       * kdc/hprop.h: include shadow definition of kdb Principal, so we
+       don't have to depend on any v4 libraries
+
+       * lib/hdb/print.c: reduce number of memory allocations
+
+       * lib/hdb/mkey.c: add support for reading krb4 /.k files
+
+2001-01-19  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/krb5.conf.5: document admin_server and kpasswd_server
+       for realms document capath better
+
+       * lib/krb5/krbhst.c (krb5_get_krb_changepw_hst): preferably look
+       at kpasswd_server before admin_server
+
+       * lib/krb5/get_cred.c (get_cred_from_kdc_flags): look in
+       [libdefaults]capath for better hint of realm to send request to.
+       this allows the client to specify `realm routing information' in
+       case it cannot be done at the server (which is preferred)
+
+       * lib/krb5/rd_priv.c (krb5_rd_priv): handle no sequence number as
+       zero when we were expecting a sequence number.  MIT krb5 cannot
+       generate a sequence number of zero, instead generating no sequence
+       number
+       * lib/krb5/rd_safe.c (krb5_rd_safe): dito
+
+2001-01-11  Assar Westerlund  <assar@sics.se>
+
+       * kpasswd/kpasswdd.c: add --port option
+
+2001-01-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/appdefault.c (krb5_appdefault_string): fix condition
+       just before returning
+
+2001-01-09  Assar Westerlund  <assar@sics.se>
+
+       * appl/kf/kfd.c (proto): use krb5_rd_cred2 instead of krb5_rd_cred
+
+2001-01-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: call a time `time', and not `seconds'
+
+       * lib/krb5/init_creds.c: not much point in setting the anonymous
+       flag here
+
+       * lib/krb5/krb5_appdefault.3: document appdefault_time
+
+2001-01-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/verify_user.c: use
+       krb5_get_init_creds_opt_set_default_flags
+
+       * kuser/kinit.c: use krb5_get_init_creds_opt_set_default_flags
+
+       * lib/krb5/init_creds.c: new function
+       krb5_get_init_creds_opt_set_default_flags to set options from
+       krb5.conf
+
+       * lib/krb5/rd_cred.c: make this match the MIT function
+       
+       * lib/krb5/appdefault.c (krb5_appdefault_string): handle NULL
+       def_val
+       (krb5_appdefault_time): new function
+
+2001-01-03  Assar Westerlund  <assar@sics.se>
+
+       * kdc/hpropd.c (main): handle EOF when reading from stdin
diff --git a/src/kerberosV/src/ChangeLog.2002 b/src/kerberosV/src/ChangeLog.2002
new file mode 100644 (file)
index 0000000..37fda2e
--- /dev/null
@@ -0,0 +1,726 @@
+2002-12-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/mk_rep.c: free allocated storage; reported by Howard
+       Chu
+
+2002-12-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kdc_locl.h: remove old encrypt_v4_ticket prototype
+
+2002-12-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kpasswd/kpasswdd.c (doit): initialise sa_size to size of
+       sockaddr_storage
+
+       * kdc/connect.c (init_socket): initialise sa_size to size of
+       sockaddr_storage
+
+2002-11-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: remove trailing comma in enum
+
+2002-11-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/524.c: implement crude b2 style (non-)conversion for use
+       with afs
+
+       * kdc/kerberos4.c: move encrypt_v4_ticket to 524.c, since that's
+       where it's used
+
+2002-10-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_keyfile.c: more strcspn
+
+       * lib/krb5/store_emem.c (emem_store): limit how much we allocate
+       (from Olaf Kirch)
+
+       * lib/krb5/principal.c: don't allow trailing backslashes in
+       components
+
+       * kdc/connect.c: check that %-quotes are followed by two hex
+       digits
+
+       * lib/krb5/keytab_any.c: properly close the open keytabs (from
+       Larry Greenfield)
+
+       * kdc/kaserver.c: make sure life is positive (from John Godehn)
+
+2002-10-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.c (display_tokens): allow tokens up to size of
+       buffer (from Magnus Holmberg)
+
+2002-09-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/changepw.c (process_reply): fix reply length check
+       calculation (reported by various people)
+
+2002-09-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_file.c (fkt_remove_entry): check return value
+       from start_seq_get (from Wynn Wilkes)
+
+2002-09-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/context.c (krb5_set_config_files): return ENXIO instead
+       of ENOENT when "unconfigured"
+
+2002-09-16  Jacques Vidrine  <nectar@kth.se>
+
+       * lib/krb5/kuserok.c, lib/krb5/prompter_posix.c: use strcspn
+       to convert the newline to NUL in fgets results.
+
+2002-09-13  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.1: remove unneeded Ns
+
+       * lib/krb5/krb5_appdefault.3: remove extra "application"
+
+       * fix-export: remove autom4ate.cache
+
+2002-09-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * include/make_crypto.c: don't use function macros if possible
+
+       * lib/krb5/krb5_locl.h: get limits.h for UINT_MAX
+
+       * include/Makefile.am: use make_crypto to create crypto-headers.h
+
+       * include/make_crypto.c: crypto header generation tool
+
+       * configure.in: move crypto test to just after testing for krb4,
+       and move roken tests to after both, this speeds up various failure
+       cases with krb4
+
+       * lib/krb5/config_file.c: don't use NULL when we mean 0
+
+       * configure.in: we don't set package_libdir anymore, so no point
+       in testing for it
+
+       * tools/Makefile.am: subst INCLUDE_des
+
+       * tools/krb5-config.in: add INCLUDE_des to cflags
+
+       * configure.in: use AC_CONFIG_SRCDIR
+
+       * fix-export: remove some unneeded stuff
+
+       * kuser/kinit.c (do_524init): free principals
+
+2002-09-09  Jacques Vidrine  <nectar@kth.se>
+
+       * kdc/kerberos5.c (get_pa_etype_info, fix_transited_encoding),
+       kdc/kaserver.c (krb5_ret_xdr_data),
+       lib/krb5/transited.c (krb5_domain_x500_decode): Validate some
+       counts: Check that they are non-negative, and that they are small
+       enough to avoid integer overflow when used in memory allocation
+       calculations.  Potential problem areas pointed out by 
+       Sebastian Krahmer <krahmer@suse.de>.
+
+       * lib/krb5/keytab_keyfile.c (akf_add_entry): Use O_EXCL when
+       creating a new keyfile.
+
+2002-09-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: don't try to build pam module
+
+2002-09-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * appl/kf/kf.c: fix warning string
+
+       * lib/krb5/log.c (krb5_vlog_msg): delay message formating till we
+       know we need it
+
+2002-09-04  Assar Westerlund  <assar@kth.se>
+
+       * kdc/kerberos5.c (encode_reply): correct error logging
+
+2002-09-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/sendauth.c: close ccache if we opened it
+
+       * appl/kf/kf.c: handle new protocol
+
+       * appl/kf/kfd.c: use krb5_err instead of sysloging directly,
+       handle the new protocol, and bail out if an old client tries to
+       connect
+
+       * appl/kf/kf_locl.h: we need a protocol version string
+
+       * lib/hdb/hdb-ldap.c: use ASN1_MALLOC_ENCODE
+
+       * kdc/kerberos5.c: use ASN1_MALLOC_ENCODE
+
+       * kdc/hprop.c: set AP_OPTS_USE_SUBKEY
+
+       * lib/hdb/common.c: use ASN1_MALLOC_ENCODE
+
+       * lib/asn1/gen.c: add convenience macro that allocates a buffer
+       and encoded into that
+
+       * lib/krb5/get_cred.c (init_tgs_req): use
+       in_creds->session.keytype literally instead of trying to convert
+       to a list of enctypes (it should already be an enctype)
+       
+       * lib/krb5/get_cred.c (init_tgs_req): init ret
+
+2002-09-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/asn1/k5.asn1: remove ETYPE_DES3_CBC_NONE_IVEC
+
+       * lib/krb5/krb5.h: remove ENCTYPE_DES3_CBC_NONE_IVEC
+
+       * lib/krb5/crypto.c: get rid of DES3_CBC_encrypt_ivec, just use
+       zero ivec in DES3_CBC_encrypt if passed ivec is NULL
+
+       * lib/krb5/Makefile.am: back out 1.144, since it will re-create
+       krb5-protos.h at build-time, which requires perl, which is bad
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): don't
+       blindly use the local subkey
+
+       * lib/krb5/crypto.c: add function krb5_crypto_getblocksize that
+       extracts the required blocksize from a crypto context
+
+       * lib/krb5/build_auth.c: just get the length of the encoded
+       authenticator instead of trying to grow a buffer
+
+2002-09-03  Assar Westerlund  <assar@kth.se>
+
+       * configure.in: add --disable-mmap option, and tests for
+       sys/mman.h and mmap
+
+2002-09-03  Jacques Vidrine  <nectar@kth.se>
+
+       * lib/krb5/changepw.c: verify lengths in response
+
+       * lib/asn1/der_get.c (decode_integer, decode_unsigned): check for
+       truncated integers
+
+2002-09-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/mk_req_ext.c: generate a local subkey if
+       AP_OPTS_USE_SUBKEY is set
+
+       * lib/krb5/build_auth.c: we don't have enough information about
+       whether to generate a local subkey here, so don't try to
+
+       * lib/krb5/auth_context.c: new function
+       krb5_auth_con_generatelocalsubkey
+
+       * lib/krb5/get_in_tkt.c: only set kdc_sec_offset if looking at an
+       initial ticket
+
+       * lib/krb5/context.c (init_context_from_config_file): simplify
+       initialisation of srv_lookup
+
+       * lib/krb5/changepw.c (send_request): set AP_OPTS_USE_SUBKEY
+
+       * lib/krb5/krb5.h: add AP_OPTS_USE_SUBKEY
+
+2002-08-30  Assar Westerlund  <assar@kth.se>
+
+       * lib/krb5/name-45-test.c: also test krb5_524_conv_principal
+       * lib/krb5/Makefile.am (TESTS): add name-45-test
+       * lib/krb5/name-45-test.c: add testcases for
+       krb5_425_conv_principal
+
+2002-08-29  Assar Westerlund  <assar@kth.se>
+
+       * lib/krb5/parse-name-test.c: also test unparse_short functions
+       * lib/asn1/asn1_print.c: use com_err/error_message API
+       * lib/krb5/Makefile.am: add parse-name-test
+       * lib/krb5/parse-name-test.c: add a program for testing parsing
+       and unparsing principal names
+
+2002-08-28  Assar Westerlund  <assar@kth.se>
+
+       * kdc/config.c: add missing ifdef DAEMON
+
+2002-08-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: use rk_SUNOS
+
+       * kdc/config.c: add detach options
+
+       * kdc/main.c: maybe detach from console?
+
+       * kdc/kdc.8: markup changes
+
+       * configure.in: AC_TEST_PACKAGE_NEW -> rk_TEST_PACKAGE
+
+       * configure.in: use rk_TELNET, rename some other macros, and don't
+       add -ldes to krb4 link command
+
+       * kuser/kinit.1: whitespace fix (from NetBSD)
+
+       * include/bits.c: we may need unistd.h for ssize_t
+
+2002-08-26  Assar Westerlund  <assar@kth.se>
+
+       * lib/krb5/principal.c (krb5_425_conv_principal_ext): lookup AAAA
+       rrs before A ones when using the resolver to verify a mapping,
+       also use getaddrinfo when resolver is not available
+
+       * lib/hdb/keytab.c (find_db): const-correctness in parameters to
+       krb5_config_get_next
+
+       * lib/asn1/gen.c: include <string.h> in the generated files (for
+       memset)
+
+2002-08-22  Assar Westerlund  <assar@kth.se>
+
+       * lib/krb5/test_get_addrs.c, lib/krb5/krbhst-test.c: make it use
+       getarg so that it can handle --help and --version (and thus make
+       check can pass)
+
+       * lib/asn1/check-der.c: make this build again
+
+2002-08-22  Assar Westerlund <assar@kth.se>
+
+       * lib/asn1/der_get.c (der_get_int): handle len == 0.  based on a
+       patch from Love <lha@stacken.kth.se>
+
+2002-08-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: we seem to call KRB5KDC_ERR_KEY_EXP
+       KRB5KDC_ERR_KEY_EXPIRED, so define the former to the latter
+       
+       * kdc/kdc.8: add blurb about adding and removing addresses; update
+       kdc.conf section to match reality
+
+       * configure.in: KRB_SENDAUTH_VLEN seems to always have existed, so
+       don't define it
+       
+2002-08-21  Assar Westerlund  <assar@kth.se>
+       
+       * lib/asn1/asn1_print.c: print OIDs too, based on a patch from
+       Love <lha@stacken.kth.se>
+
+2002-08-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c (do_v4_fallback): don't use krb_get_pw_in_tkt2
+       since it might not exist, and we don't actually care about the key
+       
+2002-08-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.conf.5: correct documentation for
+       verify_ap_req_nofail
+
+       * lib/krb5/log.c: rename syslog_data to avoid name conflicts (from
+       Mattias Amnefelt)
+
+       * kuser/klist.c (display_tokens): increase token buffer size, and
+       add more checks of the kernel data (from Love)
+
+2002-08-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * fix-export: use make to parse Makefile.am instead of perl
+
+       * configure.in: use argument-less AM_INIT_AUTOMAKE, now that it
+       groks AC_INIT with package name etc.
+
+       * kpasswd/kpasswdd.c: include <kadm5/private.h>
+
+       * lib/asn1/asn1_print.c: include com_right.h
+
+       * lib/krb5/addr_families.c: socklen_t -> krb5_socklen_t
+
+       * include/bits.c: define krb5_socklen_t type; this should really
+       go someplace else, but this was easy
+
+       * lib/krb5/verify_krb5_conf.c: don't bail out if parsing of a file
+       fails, just warn about it
+
+       * kdc/log.c (kdc_openlog): no need for a config_file parameter
+
+       * kdc/config.c: just treat kdc.conf like any other config file
+
+       * lib/krb5/context.c (krb5_get_default_config_files): ignore
+       duplicate files
+
+2002-08-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.h: turn strings into pointers, so we can assign to
+       them
+
+       * lib/krb5/constants.c: turn strings into pointers, so we can
+       assign to them
+
+       * lib/krb5/get_addrs.c (get_addrs_int): initialise res if
+       SCAN_INTERFACES is not set
+
+       * lib/krb5/context.c: fix various borked stuff in previous commits
+
+2002-08-16  Jacques Vidrine <n@nectar.com>
+
+       * lib/krb5/krbhst.c (kpasswd_get_next): if we fall back to using
+       the `admin_server' entry for kpasswd, override the `proto' result
+       to be UDP.
+
+2002-08-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/auth_context.c: check return value of
+       krb5_sockaddr2address
+
+       * lib/krb5/addr_families.c: check return value of
+       krb5_sockaddr2address
+
+       * lib/krb5/context.c: get the default keytab from KRB5_KTNAME
+
+2002-08-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/verify_krb5_conf.c: allow parsing of more than one file
+
+       * lib/krb5/context.c: allow changing config files with the
+       function krb5_set_config_files, there are also related functions
+       krb5_get_default_config_files and krb5_free_config_files; these
+       should work similar to their MIT counterparts
+
+       * lib/krb5/config_file.c: allow the use of more than one config
+       file by using the new function krb5_config_parse_file_multi
+
+2002-08-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * use sysconfdir instead of /etc
+
+       * configure.in: require autoconf 2.53; rename dpagaix_LDFLAGS etc
+       to appease automake; force sysconfdir and localstatedir to /etc
+       and /var/heimdal for now
+
+       * kdc/connect.c (addr_to_string): check return value of
+       sockaddr2address
+
+2002-08-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/rd_cred.c: if the remote address isn't an addrport,
+       don't try comparing to one; this should make old clients work with
+       new servers
+
+       * lib/asn1/gen_decode.c: remove unused variable
+
+2002-07-31  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/{kerberos5,524}.c: ENOENT -> HDB_ERR_NOENTRY (from Derrick
+       Brashear)
+
+       * lib/krb5/principal.c: actually lower case the lower case
+       instance name (spotted by Derrick Brashear)
+
+2002-07-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * fix-export: if DATEDVERSION is set, change the version to
+       current date
+
+       * configure.in: don't use AC_PROG_RANLIB, and use magic foo to set
+       LTLIBOBJS
+
+2002-07-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/connect.c: add some cache-control-foo to the http responses
+       (from Gombas Gabor)
+
+       * lib/krb5/addr_families.c (krb5_print_address): don't copy size
+       if ret_len == NULL
+
+2002-06-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.c (display_tokens): don't bail out before we get
+       EDOM (signaling the end of the tokens), the kernel can also return
+       ENOTCONN, meaning that the index does not exist anymore (for
+       example if the token has expired)
+
+2002-06-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/changepw.c: make sure we return an error if there are
+       no changepw hosts found; from Wynn Wilkes
+
+2002-05-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/cache.c (krb5_cc_register): break out of loop when the
+       same type is found; spotted by Wynn Wilkes
+
+2002-05-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_file.c: check size of entry before trying to
+       read 32-bit kvno; also fix typo in previous
+
+2002-05-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * include/Makefile.am: only add to INCLUDES
+
+       * lib/45/mk_req.c: fix for storage change
+
+       * lib/hdb/print.c: fix for storage change
+
+2002-05-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c: don't free encrypted padata until we're really
+       done with it
+
+2002-05-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c: when decrypting pa-data, try all keys matching
+       enctype
+
+       * kuser/kinit.1: document -a
+
+       * kuser/kinit.c: add command line switch for extra addresses
+
+2002-04-30  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * configure.in: remove some duplicate tests
+
+       * configure.in: use AC_HELP_STRING
+
+2002-04-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/crypto.c (usage2arcfour): don't abort if the usage is
+       unknown
+
+2002-04-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: use rk_DESTDIRS
+
+2002-04-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5_verify_user.3: make it clear that _lrealm modifies
+       the principal
+
+2002-04-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/verify_init.c: fix typo in error string
+
+2002-04-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * acconfig.h: remove some stuff that is defined elsewhere
+
+       * lib/krb5/krb5_locl.h: include <sys/file.h>
+
+       * lib/krb5/acl.c: rename acl_string parameter
+
+       * lib/krb5/Makefile.am: remove __P from protos, and put parameter
+       names in comments
+
+       * kuser/klist.c: better align some headers
+
+       * kdc/kerberos4.c: storage tweaks
+
+       * kdc/kaserver.c: storage tweaks
+
+       * kdc/524.c: storage tweaks
+
+       * lib/krb5/keytab_krb4.c: storage tweaks
+
+       * lib/krb5/keytab_keyfile.c: storage tweaks
+
+       * lib/krb5/keytab_file.c: storage tweaks; also try to handle zero
+       sized keytab files
+
+       * lib/krb5/keytab_any.c: use KRB5_KT_END instead of KRB5_CC_END
+
+       * lib/krb5/fcache.c: storage tweaks
+
+       * lib/krb5/store_mem.c: make the krb5_storage opaque, and add
+       function wrappers for store/fetch/seek, and also make the eof-code
+       configurable
+
+       * lib/krb5/store_fd.c: make the krb5_storage opaque, and add
+       function wrappers for store/fetch/seek, and also make the eof-code
+       configurable
+
+       * lib/krb5/store_emem.c: make the krb5_storage opaque, and add
+       function wrappers for store/fetch/seek, and also make the eof-code
+       configurable
+
+       * lib/krb5/store.c: make the krb5_storage opaque, and add function
+       wrappers for store/fetch/seek, and also make the eof-code
+       configurable
+
+       * lib/krb5/store-int.h: make the krb5_storage opaque, and add
+       function wrappers for store/fetch/seek, and also make the eof-code
+       configurable
+
+       * lib/krb5/krb5.h: make the krb5_storage opaque, and add function
+       wrappers for store/fetch/seek, and also make the eof-code
+       configurable
+
+       * include/bits.c: include <sys/socket.h> to get socklen_t
+
+       * kdc/kerberos5.c (get_pa_etype_info): sort ETYPE-INFOs by
+       requested KDC-REQ etypes
+
+       * kdc/hpropd.c: constify
+
+       * kdc/hprop.c: constify
+
+       * kdc/string2key.c: constify
+
+       * kdc/kdc_locl.h: make port_str const
+
+       * kdc/config.c: constify
+
+       * lib/krb5/config_file.c: constify
+
+       * kdc/kstash.c: constify
+
+       * lib/krb5/verify_user.c: remove unnecessary cast
+
+       * lib/krb5/recvauth.c: constify
+
+       * lib/krb5/principal.c (krb5_parse_name): const qualify
+
+       * lib/krb5/mcache.c (mcc_get_name): constify return type
+
+       * lib/krb5/context.c (krb5_free_context): don't try to free the
+       ccache prefix
+
+       * lib/krb5/cache.c (krb5_cc_register): don't make a copy of the
+       prefix
+
+       * lib/krb5/krb5.h: constify some struct members
+
+       * lib/krb5/log.c: constify
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): const
+       qualify
+
+       * lib/krb5/get_in_tkt.c (krb5_init_etype): constify
+
+       * lib/krb5/crypto.c: constify some
+
+       * lib/krb5/config_file.c: constify
+
+       * lib/krb5/aname_to_localname.c (krb5_aname_to_localname):
+       constify local variable
+
+       * lib/krb5/addr_families.c (ipv4_sockaddr2port): constify
+
+2002-04-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/verify_krb5_conf.c: add some log checking
+       
+       * lib/krb5/log.c (krb5_addlog_dest): reorganise syslog parsing
+
+2002-04-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/crypto.c (krb5_crypto_init): check that the key size
+       matches the expected length
+
+2002-03-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/send_to_kdc.c: rename send parameter to send_data
+
+       * lib/krb5/mk_error.c: rename ctime parameter to client_time
+
+2002-03-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c (find_etype): unsigned -> krb5_enctype (from
+       Reinoud Zandijk)
+
+2002-03-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/asn1/k5.asn1: add the GSS-API checksum type here
+
+2002-03-11  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): bump version to
+       18:3:1
+       * lib/hdb/Makefile.am (libhdb_la_LDFLAGS): bump version to 7:5:0
+       * lib/asn1/Makefile.am (libasn1_la_LDFLAGS): bump version to 6:0:0
+       
+2002-03-10  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/rd_cred.c: handle addresses with port numbers
+
+       * lib/krb5/keytab_file.c, lib/krb5/keytab.c:
+       store the kvno % 256 as the byte and the complete 32 bit kvno after
+       the end of the current keytab entry
+
+       * lib/krb5/init_creds_pw.c:
+       handle LR_PW_EXPTIME and LR_ACCT_EXPTIME in the same way
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds):
+       handle ports giving for the remote address
+
+       * lib/krb5/get_cred.c:
+       get a ticket with no addresses if no-addresses is set
+
+       * lib/krb5/crypto.c:
+       rename functions DES_* to krb5_* to avoid colliding with modern
+       openssl
+
+       * lib/krb5/addr_families.c:
+       make all functions taking 'struct sockaddr' actually take a socklen_t
+       instead of int and that acts as an in-out parameter (indicating the
+       maximum length of the sockaddr to be written)
+
+       * kdc/kerberos4.c:
+       make the kvno's in the krb4 universe by the real one % 256, since they
+       cannot only be 8 bit, and the v5 ones are actually 32 bits
+
+2002-02-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab_keyfile.c (akf_add_entry): don't create the file
+       before we need to write to it
+       (from Ã…ke Sandgren)
+
+2002-02-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: rk_RETSIGTYPE and rk_BROKEN_REALLOC are called via
+       rk_ROKEN (from Gombas Gabor); find inttypes by CHECK_TYPES
+       directly
+
+       * lib/krb5/rd_safe.c: actually use the correct key (from Daniel
+       Kouril)
+
+2002-02-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/context.c (krb5_get_err_text): protect against NULL
+       context
+
+2002-02-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/ktutil.c: no need to use the "modify" keytab anymore
+
+       * lib/krb5/keytab_any.c: implement add and remove
+
+       * lib/krb5/keytab_krb4.c: implement add and remove
+
+       * lib/krb5/store_emem.c (emem_free): clear memory before freeing
+       (this should perhaps be selectable with a flag)
+
+2002-02-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/config.c (get_dbinfo): if there are database specifications
+       in the config file, don't automatically try to use the default
+       values (from Gombas Gabor)
+
+       * lib/krb5/log.c (krb5_closelog): don't pass pointer to pointer
+       (from Gombas Gabor)
+
+2002-01-30  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin/list.c: get the default keytab from krb5.conf, and list
+       all parts of an ANY type keytab
+
+       * lib/krb5/context.c: default default_keytab_modify to NULL
+
+       * lib/krb5/keytab.c (krb5_kt_default_modify_name): if no modify
+       name is specified take it from the first component of the default
+       keytab name
+
+2002-01-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/keytab.c: compare keytab types case insensitively
+
+2002-01-07  Assar Westerlund  <assar@sics.se>
+
+       * lib/krb5/crypto.c (create_checksum): make usage `unsigned' (it's
+       not really a krb5_key_usage).  From Ben Harris <bjh21@netbsd.org>
+       * lib/krb5/get_in_tkt.c: use krb5_enctype consistently.  From Ben
+       Harris <bjh21@netbsd.org>
+       * lib/krb5/crypto.c: use krb5_enctype consistently.  From Ben
+       Harris <bjh21@netbsd.org>
+       * kdc/kerberos5.c: use krb5_enctype consistently.  From Ben Harris
+       <bjh21@netbsd.org>
diff --git a/src/kerberosV/src/ChangeLog.2003 b/src/kerberosV/src/ChangeLog.2003
new file mode 100644 (file)
index 0000000..8223351
--- /dev/null
@@ -0,0 +1,1795 @@
+2003-12-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/error_string.c: protect error_string with mutex
+       
+       * lib/krb5/context.c: allocate and destroy mutex in krb5_context
+       
+       * lib/krb5/krb5.h (krb5_context_data): add mutex for error_string
+       
+2003-12-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: make -9 work again
+       
+2003-12-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: try handle ts preauth better, still
+       not good, but at least it work with older heimdal releases that
+       doesn't send back KRB5KDC_ERR_PREAUTH_REQUIRED when preauth was
+       sent
+
+2003-12-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb.asn1: remove enforce-transited-policy, its no longer
+       used
+
+2003-12-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/pkinit.c (_krb5_pk_create_sign): fill in NULL as
+       parameters, required by CMS
+
+2003-12-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/get_in_tkt_with_keytab.c (krb5_get_in_tkt_with_keytab):
+       avoid memory leak that snuck in when krb5_keytab_key_proc was
+       exported, pointed out by Panases Inc
+       
+       * lib/krb5/keytab_file.c: do locking, found to be a problem for
+       Panasas Inc
+
+       * lib/krb5/fcache.c: internally export x{,un}lock and thus prefix
+       them with _krb5_
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): use
+       KRB5_AUTH_CONTEXT_DO_TIME if we want timestamp in forwarded
+       krb-cred
+
+       * lib/krb5/krb5_auth_context.3: some text about
+       krb5_auth_con_{add,remove}flags
+
+       * lib/krb5/auth_context.c: add krb5_auth_con_addflags and
+       krb5_auth_con_removeflags
+
+2003-12-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/crypto.c (decrypt_internal_derived): move up padsize to
+       avoid memory leak
+
+2003-12-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/crypto.c: require cipher-text to be padded to padsize
+       
+       * lib/krb5/eai_to_heim_errno.c: EAI_ADDRFAMILY and EAI_NODATA is
+       deprecated in RFC3493
+
+       * lib/krb5/verify_krb5_conf.c (check_host): don't check for
+       EAI_NODATA, because its depricated in RFC3493 Pointed out by
+       Hajimu UMEMOTO <ume@mahoroba.org> on heimdal-discuss
+
+2003-12-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: move test_crypto to noinst_PROGRAMS
+       
+       * lib/krb5/test_crypto.c: add --version,--help
+       
+       * kuser/kinit.c (main): return the return value from simple_execvp
+       
+2003-11-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: don't use PKINIT DH per default since its too
+       slow
+
+       * lib/krb5/pkinit.c: tweek to make pkinit work with the fact the
+       asn1_compile can't generate code for context tagless optionals
+       
+       * kdc/pkinit.c: add support for KDC side of DH PKINIT
+       
+       * lib/krb5/pkinit.c: clean up error handling, make enc-type work
+       again
+
+2003-11-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: add flag to make it work with pkinit dh
+       
+       * lib/krb5/pkinit.c: make PKINIT DH support work
+       
+2003-11-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/Makefile.am (LDADD): link with LIB_dlopen
+       
+       * kdc/pkinit.c: clean up
+       
+       * lib/krb5/krb5.h: make pkinit_win2k_compatible into a flag field
+       
+       * lib/krb5/pkinit.c: remove most compile depencies clean up
+       
+       * kdc/pkinit.c: print an error and turn of pkinit if openssl
+       failed to load
+
+       * kdc/config.c: read pkinit (pki-mumble) configuration options
+       
+       * kdc/kerberos5.c: add pkinit support
+       
+       * kdc/kdc_locl.h: add prototypes for pkinit
+       
+       * kdc/pkinit.c: PKINIT patch from Daniel Kouril and Petr Holub, I
+       removed the dependency on valicert asn1 parser, remove smartcard
+       and globus support (for now). Work to be done on this: DH support,
+       Globus support, Smartcard support, windows support (MS implements
+       -09 of the draft), make it conform to the new draft
+       
+       * lib/krb5/pkinit.c: fix bugs, improve error reporting
+
+2003-11-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: add some "struct foo;" glue for pkinit
+       structures that isn't used
+
+       * lib/krb5/pkinit.c: clean up, make remove depenency on openssl's
+       api
+
+       * lib/krb5/krb5_locl.h: add some glue for pkinit add reference
+       counter to _krb5_get_init_creds_opt_private
+       
+       * lib/krb5/init_creds.c: reference count krb5_get_init_creds_opt
+       private component to avoid copy all the data in it
+       
+       * lib/krb5/crypto.c (AES_string_to_key): fix memory leak
+
+       * lib/krb5/init_creds_pw.c (init_cred_loop): fix memory leak
+       
+       * lib/krb5/heim_threads.h: include pthread.h in the pthread case
+       
+2003-11-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswdd.c (main): parse kdc.conf
+       From: Jeffrey Hutzelman <jhutz@cmu.edu>
+       
+2003-11-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am (TESTS): add test_crypto
+       
+       * lib/krb5/test_crypto.c: time crypto operations
+       
+2003-11-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/init-creds: spelling, Bruno Rohee <bruno@rohee.com>
+       
+2003-11-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/rd_req.c (krb5_verify_ap_req2): krb5_free_ticket free
+       the ticket now, rewrite error handling to handle that
+       
+       * kpasswd/kpasswdd.c (process): don't free ticket,
+       krb5_free_ticket does that now
+
+       * kdc/kerberos5.c (tgs_rep2): don't free ticket, krb5_free_ticket
+       does that now
+
+       * lib/krb5/ticket.c (krb5_free_ticket): free the ticket itself to
+       match mit behavior, pointed out by Derrick Brashear
+       
+       * lib/krb5/krb5_ticket.3: krb5_free_ticket free the whole ticket
+       
+2003-11-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/padata.c: add krb5_padata_add
+       
+       * lib/krb5/krb5.h: krb5_context_data.pkinit_win2k_compatible
+       
+       * lib/krb5/Makefile.am: add pkinit.c
+       
+       * kuser/kinit.c: add pkinit support
+       
+       * lib/krb5/init_creds_pw.c: add support for pkinit
+       
+       * lib/krb5/krb5_locl.h: add the opaque krb5_pk_init_ctx to
+       _krb5_get_init_creds_opt_private
+
+       * lib/krb5/pkinit.c: rename krb5_pk_init_openssl_ctx to
+       krb5_pk_init_ctx fix win2k error handling
+       
+       * lib/krb5/pkinit.c: PKINIT patch from Daniel Kouril and Petr
+       Holub, I removed the dependency on valicert asn1 parser, remove
+       smartcard and globus support (for now). Work to be done on this:
+       DH support, Globus support, Smartcard support, windows support (MS
+       implements -09 of the draft), verify that it conforms the new
+       draft
+
+2003-11-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/der_copy.c (copy_oid): copy all components
+       
+2003-10-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.conf.5: document capaths section
+
+2003-10-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c: make sure that the server realm and the krbtgt
+       second component are identical; get rpath from the capaths section
+
+       * kdc/kerberos5.c: change logic for when to check transited policy
+       to a tri-state model involving per principal flags (to be
+       implemented)
+
+       * kdc/kdc_locl.h: change enforce_transited_policy to a tri-state
+       variable
+
+       * kdc/config.c: change enforce_transited_policy to a tri-state
+       variable
+
+2003-10-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/transited.c (krb5_domain_x500_encode): always zero out
+       encoding to make sure it have a defined value on failure
+
+       * lib/krb5/transited.c (krb5_domain_x500_encode): 
+       if num_realms ==0, set encoding and return (avoids malloc(0)),
+       check return value for malloc
+
+2003-10-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c (fix_transited_encoding): always print
+       cross-realm information
+       
+2003-10-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: spelling, From: Tracy Di Marco White
+       
+       * kdc/kerberos5.c (fix_transited_encoding): set transited type
+       
+2003-10-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kdc.8: document enforce-transited-policy
+
+       * kdc/kerberos5.c: always check transited policy if flag set
+       either globally or on principal
+
+       * kdc/config.c: add flag to always check transited policy
+
+       * lib/hdb/hdb.asn1: add flag to enforce transited policy
+
+2003-10-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/transited.c (krb5_domain_x500_decode): set *num_realms
+       to zero not num_realms
+
+       * kuser/kgetcred.1: add --no-transit-check
+       
+       * kuser/kgetcred.c: add --no-transit-check
+
+       * doc/setup.texi: describe Transit policy
+       
+2003-10-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kdc/kerberos5.c (fix_transited_encoding): also verify with
+       policy, unless asked not to
+
+       * lib/krb5/rd_req.c (krb5_decrypt_ticket): try to verify transited
+       realms, unless the transited-policy-checked flag is set
+
+       * lib/krb5/transited.c (krb5_domain_x500_decode): handle zero
+       length tr data;
+       (krb5_check_transited): new function that does more useful stuff
+
+       * lib/krb5/get_cred.c: get capath info from [capaths] section
+
+2003-10-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/fcache.c: Sleep forever waiting for lock. Previous
+       method doesn't work well with a large number of clients accessing
+       the cache at the same time, and there is no simple way to add a
+       timeout to the lock.
+
+2003-10-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c: print the error value
+       krb5_init_context failed with
+
+       * lib/krb5/config_file.c (krb5_config_parse_file_debug): punt if
+       there is binding before a section declaration. Bug found by
+       Arkadiusz Miskiewicz <arekm@pld-linux.org>
+
+2003-10-13  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/fcache.c (erase_file): revert a change in previous; if
+       the ccache is a symlink, kdestroy should remove it
+
+       * lib/krb5/fcache.c: implement locking
+
+2003-10-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.c (print_tickets): bail out if krb5_cc_next_cred
+       returns error other than KRB5_CC_END
+
+2003-10-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: add some help function that is common
+       between ENC_TS and SAM2, free the etype{,2}-infos on failure, move
+       the pa counter into krb5_get_init_creds_ctx
+       
+2003-10-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kaserver.c (do_getticket): if times data is shorter then 8
+       byte, request is malformed.
+
+       * kdc/kaserver.c (do_authenticate): if request length is less then
+       8 byte, its a bad request and fail. Pointed out by Marco Foglia
+       <marco@foglia.org>
+
+       * lib/krb5/verify_krb5_conf.c: add flag --warn-mit-syntax that
+       warns for mit syntax is used and just ignore the mit syntax when
+       its used
+
+       * lib/krb5/verify_krb5_conf.c: parse [kdc]use_2b and [gssapi]
+       
+2003-10-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/lex.l: add BOOLEAN
+       
+       * lib/asn1/parse.y: add BOOLEAN
+       
+2003-10-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: When running kinit in "fork mode" do pagsh
+       independent of krb4, also always do krb4 setup of cc. Always try
+       to destroy the v4 cc.
+       - add boolean --{,no-}request-pac that will request pac or not
+
+       * kuser/klist.c (check_for_tgt): set client as part of the
+       pattern/match cred
+
+       * lib/krb5/convert_creds.c (_krb5_krb_dest_tkt): unlink v4 token
+       (get_krb4_cc_name): move out from _krb5_krb_tf_setup
+       (_krb5_krb_tf_setup): adapt to allocated filename instead of
+       static filename
+
+       * lib/krb5/krb5-v4compat.h: add _krb5_krb_dest_tkt and TKT_ROOT
+       
+       * lib/krb5/init_creds_pw.c (*) send PA_PAC_REQUEST when the user
+       have requested either use PAC or not use PAC, if the option not
+       set from the user, leave it up to the kdc to decide.
+       (init_creds_loop): clear error string on success
+
+       * lib/krb5/init_creds.c: add
+       krb5_get_init_creds_opt_set_paq_request break out common part of
+       extended opt functions to require_ext_opt
+
+       * lib/krb5/krb5_locl.h: add enum krb5_get_init_creds_req_pac and
+       use it in struct _krb5_get_init_creds_opt_private
+       
+       * tools/kdc-log-analyze.pl: handle some more failure lines
+       
+       * doc/programming.texi: some diffrences between Heimdal and MIT
+       Kerberos in the API
+
+       * doc/setup.texi: add Setting up DNS
+       
+       * lib/krb5/rd_req.c (krb5_rd_req): always free keyblock since its
+       alway used
+
+       * lib/asn1/Makefile.am: add SAM types and PAC_REQUEST
+       
+       * lib/asn1/k5.asn1: add more preauth types, add PA-PAC-REQUEST
+       
+       * lib/asn1: add boolean support
+
+2003-10-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/changepw.c (setpw_send_request): free ap_req_data on
+       failure
+
+2003-09-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/test/http_client.c (do_connect): use ai_protocol 0
+       
+       * lib/krb5/init_creds_pw.c (init_cred_loop): handle
+       KRB5KRB_ERR_RESPONSE_TOO_BIG and loop again, this time requesting
+       LARGE_MSG from send to kdc, and if this is the second time bail
+       out; try to free memory
+
+       * lib/krb5/send_to_kdc.c (krb5_sendto_kdc_flags): new function,
+       and then implement the order krb5_sendto_kdc* function with this
+       function.
+
+       * lib/krb5/krbhst.c (krb5_krbhst_init_flags): new function, use it
+       and adapt callers
+       (krbhst_get_default_proto): new function, returns udp, or in case
+       large_msg was requested for the krb5_krbhst_data, use tcp.
+       (*): if the flag KD_LARGE_MSG was set on the krb5_krbhst_data, avoid
+       using udp, use krbhst_get_default_proto
+       
+       * lib/krb5/krb5.h: flags for krb5_krbhst_init_flags (and
+       krb5_send_to_kdc_flags)
+
+2003-09-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/rd_req.c (krb5_rd_req): if we have a keyblock in auth
+       context, use that
+
+       * appl/test/uu_client.c: print authorization data if there are any
+       
+       * lib/asn1/asn1_print.c: decode IA5Stringa and UTF8String
+       
+2003-09-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: use _krb5_get_init_creds_opt_copy
+       * lib/krb5/init_creds.c: don't export krb5_get_init_creds_opt_copy
+       
+       * lib/hdb/Makefile.am: libhdb might depend on LIB_dlopen
+       
+       * kuser/kinit.c: don't get v4 tickets by default
+       
+2003-09-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswdd.c (process): remove a abort()
+       
+       * doc/win2k.texi: add some text about netdom.exe and trusts
+       
+       * TODO-1.0: gssapi rc4 done
+       
+       * kpasswd/kpasswdd.c: add support for Set password protocol as
+       defined by RFC3244 -- Microsoft Windows 2000 Kerberos Change
+       Password and Set Password Protocols
+
+2003-09-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/db3.c: improve readability of ->open ifdef, check if
+       version >= 4.1
+
+       * lib/krb5/init_creds.c (krb5_get_init_creds_opt_copy): add
+       
+       * lib/krb5/rd_req.c (krb5_rd_req): allow caller to pass in a key
+       in the auth_context, they way processes that doesn't use the
+       keytab can still pass in the key of the service (matches behavior
+       of MIT Kerberos).
+       
+2003-09-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: collect all init_creds context into a
+       structure so it can easier be passed around, also, while here,
+       change nonce for every request
+
+       * lib/krb5/get_in_tkt.c (init_as_req): don't realloc data before
+       the loop, add_padata() will handle that itself
+
+       * lib/krb5/get_for_creds.c (add_addrs): don't increase addr->len
+       until in contains interesting data, use right iteration counter
+       when clearing the addresses
+
+       * lib/krb5/log.c (log_realloc): increase len after realloc returns
+       sucessfully
+
+2003-09-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/config_file.c: fix prototypes
+       From: Fredrik Ljungberg <flag@pobox.se>
+       
+2003-09-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/test/http_client.c: close socket when we are done, don't
+       allow the server to restart gssapi negotiation
+       
+       * lib/hdb/hdb_locl.h: include <limits.h> for ULONG_MAX noted by
+       Wissler Magnus <M.Wissler@abalon.se> on heimdal-discuss
+       
+       * appl/test/gssapi_client.c (proto): use select_mech
+       
+       * appl/test/http_client.c: use getarg
+       
+       * appl/test/gss_common.h: prototype for select_mech
+       
+       * appl/test/gss_common.c (select_mech): return the gss_OID from a
+       mech name
+
+       * appl/test/http_client.c: print both source and target
+       
+       * appl/test/Makefile.am: build http_client
+       
+2003-09-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/asn1_print.c: add support for printing Enumerated
+       
+       * appl/test/gssapi_client.c: allow user to select mech; krb5,
+       spnego, and no-oid
+
+       * appl/test/test_locl.h: add mech
+       
+       * appl/test/common.c: add --mech,-m argument
+       
+       * appl/test/gssapi_server.c: print the mech that was used
+       
+       * kdc/kerberos5.c (only_older_enctype_p): check request if the
+       client only supports old enctypes, before it used the database
+       
+2003-09-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * **/*.c: add context argument to krb5_get_init_creds_opt_alloc
+
+       * lib/krb5/init_creds.c (krb5_get_init_creds_opt_alloc): add
+       context argument
+
+       * lib/krb5/krb5_get_init_creds.3: spelling
+       
+2003-09-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/context.c (add_file): make len argument an pointer to
+       an integer
+
+       * lib/asn1/k5.asn1: add SAM types
+
+       * lib/krb5/init_creds_pw.c: break out the encrypt timestamp
+       preauth to its function break out the pa_data_to_key_plain to its
+       own function make more variables const
+       
+2003-09-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.conf.5: document appdefaults/{forward,encrypt}
+
+2003-09-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.h: Add key usage for encryption of the
+       SAM-NONCE-OR-SAD field.
+
+       * include/make_crypto.c: include <openssl/ui.h> in the openssl
+       case
+
+       * kdc/hprop.h: use new DES_ api
+       
+       * lib/krb5/krb5-v4compat.h: assume session key is a char array of
+       length 8
+
+       * lib/krb5/prompter_posix.c:
+       s/des_read_pw_string/UI_UTIL_read_pw_string/
+
+       * kuser/kinit.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+       
+       * kdc/string2key.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+       
+       * kdc/kstash.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+       
+       * admin/add.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+       
+       * lib/krb5/crypto.c: switch from the des_ to the DES_ api
+       
+       * kdc/hprop.c: use DES_KEY_SZ instead of sizeof(des_block)
+       
+       * kuser/kverify.c: use
+       krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free
+
+       * kpasswd/kpasswd-generator.c: use
+       krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free
+
+       * kdc/hprop.c: use
+       krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free compare
+       a uint32_t with 0xffffffff instead of -1
+
+       * lib/krb5/krb5_425_conv_principal.3: fix [Gt]
+       
+       * kuser/kinit.c: use
+       krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): handle
+       password passed in though context
+
+       * lib/krb5/Makefile.am (TESTS): += test_config
+
+       * lib/krb5/aes-test.c: move variable thats used within a #ifdef to
+       be defined within that #ifdef
+
+       * lib/krb5/data.c (krb5_data_free): reset whole krb5_data when
+       freeing it
+
+       * lib/krb5/keyblock.c (krb5_keyblock_zero): new function, zeros
+       out a keyblock
+
+       * lib/krb5/init_creds_pw.c: rewrite/implement
+       krb5_get_init_creds_password with new preauth handing, still it
+       can only work with krb5-pa-enc-timestamp for preauth, but now it
+       can handle etype-info2
+
+       * lib/krb5/init_creds.c (krb5_get_init_creds_opt_alloc): allocate
+       a opt structure
+       (krb5_get_init_creds_opt_free): free a opt structure
+       (krb5_get_init_creds_opt_set_pa_password): set preauth info for
+       enc-timestamp
+
+       * lib/krb5/krb5_locl.h: add struct
+       _krb5_get_init_creds_opt_private
+
+2003-09-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.h: add SAM keyusage numbers, add s2k proc typedef,
+       add a pointer to a private part of krb5_get_init_creds_opt
+       
+       * kdc/string2key.c (main): avoid const warning by using a extra
+       variable
+
+2003-08-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/ticket.c (krb5_ticket_get_authorization_data_type):
+       reindent
+
+       * lib/krb5/ticket.c (krb5_copy_ticket): free all data when
+       failing, copy data to right memory, the later pointed out by Luke
+       Howard.
+
+2003-08-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.h: cfx-01 use diffrent usage numbers
+       
+2003-08-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/db3.c: try to include more db headers
+
+       * lib/hdb/db3.c: patch for working with DB4 on heimdal-discuss
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-08-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.h: add KEYTYPE_ARCFOUR_56
+       
+       * appl/test/gssapi_client.c: send both INT and CONF wrapped token
+       
+       * appl/test/gssapi_server.c: recv both INT and CONF wrapped token
+       
+       * lib/asn1/k5.asn1: add KRB5_NT_SMTP_NAME and KRB5_NT_ENTERPRISE
+       
+2003-08-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/test/uu_client.c (proto): fill in client in the match cred
+       
+2003-08-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.h: CFX uses slightly diffrent usage numbers
+       
+       * lib/krb5/crypto.c (usage2arcfour): simplify, only include
+       special cases From: Luke Howard <lukeh@PADL.COM>
+       
+2003-08-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: code rewrite from Luke Howard
+       <lukeh@PADL.COM>
+
+       * lib/krb5/crypto.c (arcfour_checksum_p): return true when is
+       arcfour, not when its not pointed out by Luke Howard
+       
+       * doc/ack.texi: update Luke Howard email address
+       
+2003-08-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_encrypt.3: document:
+       krb5_crypto_getconfoundersize, krb5_crypto_getblocksize
+       krb5_crypto_getenctype, krb5_crypto_getpadsize
+
+       * lib/krb5/crypto.c (krb5_crypto_getpadsize,
+       krb5_crypto_getconfoundersize): added From: Luke Howard
+       <lukeh@PADL.COM>
+
+2003-08-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/connect.c (handle_tcp): handle recvfrom returning 0
+       (connection closed)
+
+       * kdc/connect.c (grow_descr): increment the size after we succeed
+       to allocate the space
+
+       * lib/krb5/krb5_create_checksum.3: text about when
+       krb5_crypto_get_checksum_type is useful
+
+       * lib/krb5/crypto.c (krb5_crypto_get_checksum_type): fix format
+       string
+
+       * lib/krb5/krb5_create_checksum.3: document
+       krb5_crypto_get_checksum_type
+
+       * lib/krb5/crypto.c: add krb5_crypto_get_checksum_type
+       From: Luke Howard <lukeh@PADL.COM>
+       
+       * lib/asn1/gen.c: s/UTF8String/heim_utf8_string/ in generated code
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-08-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * include/make_crypto.c: include aes.h inc in the local libdes
+       case too
+
+2003-08-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/asn1/der_free.c: set free'd poiners to NULL
+       
+       * lib/asn1/gen_free.c: set free'd poiners to NULL
+       
+2003-08-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/heim_threads.h: XXX don't use "plain" pthread support
+       on netbsd
+
+       * lib/krb5/crypto.c: Do the arcfour checksum mapping for
+       krb5_create_checksum and krb5_verify_checksum, From: Luke Howard
+       <lukeh@PADL.COM>
+
+2003-08-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/test_config.c: check krb5_prepend_config_files_default
+       and krb5_prepend_config_files
+
+       * lib/krb5/context.c: add krb5_prepend_config_files and
+       krb5_prepend_config_files_default
+
+2003-08-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/mkey.c (read_master_mit): krb5_ret_int16 takes a int16_t
+       as argument
+
+       * lib/krb5/parse-name-test.c: please lint (and me)
+       
+       * kdc/config.c (configure): remove only set variable 'e'
+       
+       * kdc/connect.c (init_socket): sockaddr size argument to
+       krb5_addr2sockaddr is a krb5_addr2sockaddr *
+       
+       * kdc/kerberos5.c (as_rep): remove usused variable
+       (tgs_rep2): don't use a temporary ret-variable, ret is reset later
+
+       * lib/krb5/krb5_get_in_cred.3: these function will be deprecated
+       
+       * lib/krb5/Makefile.am: man_MANS += krb5_get_init_creds.3
+       
+       * lib/krb5/krb5_get_init_creds.3: begining of documentation of
+       krb5_get_init_creds
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_tkt): for compatibility with
+       with the mit implemtation, don't free `creds' argument when done,
+       its up the the caller to do that, also allow a NULL ccache.
+       
+2003-08-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: document tgs_require_subkey
+       
+       * lib/asn1/Makefile.am: remove trance of generate tests files, its
+       not really for consumption yet
+
+       * lib/hdb/Makefile.am: split generated source from non generated
+       source we make-proto.pl can generate prototypes for non
+       generate-source only (make-proto.pl dies on asn1compile's .c
+       files)
+
+       * lib/krb5/get_cred.c (init_tgs_req): make generation of subkey
+       optional on configuration parameter
+       [realms]realm={tgs_require_subkey=bool}
+       defaults to off. The RFC1510 weakly defines the correct behavior,
+       so old DCE secd apparently required the subkey to be there, and MS
+       will use it when its there. But the request isn't encrypted in the
+       subkey, so you get to choose if you want to talk to a MS mdc or a
+       old DCE secd.
+
+       * kdc/kerberos5.c (*): handle krb5_unparse_name returning non-zero
+       
+2003-08-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/principal.c (unparse_name): len can't be zero, so,
+       don't check for that
+
+2003-08-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/principal.c (unparse_name): make sure there are space
+       for a NUL, set *name to NULL when there is a failure (so caller
+       can't get hold of a freed pointer)
+
+2003-07-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/kerberos.8: remove duplicate manual, from
+       cjep@netbsd.org
+
+2003-07-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/cache.c: indent
+       
+       * lib/krb5/cache.c (krb5_cc_set_default_name): only read
+       KRB5CCNAME when not suid
+
+2003-07-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/keytab_krb4.c (read_v4_entry): the des key is 8 bytes,
+       use a char array instead of des_cblock
+
+2003-07-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c: add support for KRB5_PADATA_ETYPE_INFO2
+       
+       * lib/krb5/crypto.c (hmac): make it return an error when out of
+       memory, update callsites to either return error or use krb5_abortx
+       (krb5_hmac): expose hmac
+
+2003-07-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/keyblock.c (krb5_keyblock_get_enctype): return enctype
+       of keyblock
+
+       * lib/krb5/Makefile.am (man_MANS): += krb5_keyblock.3
+
+       * lib/krb5/krb5_keyblock.3: some information about krb5_keyblock
+       and related functions
+
+       * lib/krb5/heim_threads.h: make the non-debug version of the mutex
+       macros "use" the "mutex" integer so the compile wont complain
+       about defined unused variables
+
+       * lib/krb5/heim_threads.h: make thread local storage macros take a
+       "return" argument so no functions need to be created for the
+       no-pthread case
+
+       * lib/krb5/heim_threads.h: adding RWLOCKS and [sg]etspecific
+       
+       * configure.in: use KRB_PTHREADS
+       
+       * lib/asn1/Makefile.am (gen_files): add asn1_KerberosString and
+       sort
+
+       * lib/asn1/k5.asn1 (ETYPE-INFO2-ENTRY): salt is a KerberosString
+       
+       * lib/krb5/krb5.3: add ticket access functions
+       * lib/krb5/krb5_ticket.3: ditto
+       * lib/krb5/ticket.c: ditto
+       * lib/krb5/Makefile.am: ditto
+       
+       * lib/krb5/mit_glue.c: add some more krb5_c functions
+       
+       * lib/krb5/krb5_c_make_checksum.3: add some more krb5_c functions
+       
+       * lib/krb5/crypto.c (krb5_cksumtype_valid): check is checksum type
+       is a valid one
+
+       * lib/krb5/crypto.c (krb5_checksum_is_keyed): only set extented
+       error string when there is a context
+       (krb5_checksum_is_collision_proof): ditto
+
+2003-07-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/mit_glue.c (krb5_c_get_checksum): make type and data
+       argument optional
+       (krb5_c_{encrypt,decrypt}): return "better" error codes for
+       invalid ivec length
+
+       * lib/krb5/krb5_c_make_checksum.3: update krb5_c_get_checksum
+       usage
+
+       * lib/krb5/crypto.c (krb5_crypto_getenctype): new function
+       
+       * include/make_crypto.c: avoid redefining
+       OPENSSL_DES_LIBDES_COMPATIBILITY
+
+       * lib/krb5/krb5.h: add krb5_enc_data
+       
+2003-07-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.3: add krb5_c_ functions
+       
+       * lib/krb5/mit_glue.c: support passing in NULL as the
+       cipher_state/ivec
+
+       * lib/krb5/aes-test.c: add test for krb5_c_encrypt_length and
+       krb5_c_decrypt
+
+       * lib/krb5/krb5_c_make_checksum.3: krb5_c encryption glue
+       
+       * lib/krb5/crypto.c (wrapped_length/wrapped_length_derived): when
+       calculating the length of the encrypted data, use the keyed
+       checksum length if the enctype supports a keyed checksum. This
+       only matter for aes, for all other enctypes the key and unkeyed
+       checksum have the same length.
+
+2003-07-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/mit_glue.c: first version of krb5_c encryption glue
+
+       * doc/install.texi: update pointer to luke ldap documentation
+       
+       * lib/hdb/hdb.c (hdb_create): check for dynamic backend after
+       static to avoid warning from dynamic backend when using a known
+       static backend
+
+2003-07-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/cache.c: don't return value in void function
+       
+2003-07-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/creds.c (krb5_compare_creds): if client is specified in
+       the mcreds, check that too
+
+       * lib/krb5/{keytab_file.c,principal.c,mk_error.c,krb5.h,get_cred.c}:
+       prefix libasn1 types with heim_
+       
+       * lib/asn1: prefix typedefs and structs with heim_
+
+2003-07-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb.c: avoid unnecessary setting of variable
+       
+2003-07-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/klist.c (check_for_tgt): use krb5_cc_clear_mcred
+       
+       * appl/test/uu_client.c (proto): use krb5_cc_clear_mcred
+       
+       * lib/krb5/get_cred.c (init_tgs_req): in case of error, don't free
+       in the req_body addresses since they where pass in by caller
+       (find_cred): use krb5_cc_clear_mcred
+
+       * lib/krb5/krb5_ccache.3: document krb5_cc_clear_mcred
+       
+       * lib/krb5/cache.c (krb5_cc_clear_mcred): new function, clear a
+       krb5_creds to use with krb5_cc_retrieve_cred
+       
+2003-06-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb.c (find_dynamic_method): if there isn't a prefix,
+       don't load anything
+
+2003-06-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb.c: Dynamic backend loading, based on patch from Luke
+       Howard <lukeh@PADL.COM>
+
+       * lib/hdb/hdb.h: add struct hdb_so_method and
+       HDB_INTERFACE_VERSION
+
+2003-06-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/mk_req_ext.c (krb5_mk_req_internal): when using
+       arcfour-hmac-md5, use an unkeyed checksum (rsa-md5), since
+       Microsoft calculates the keyed checksum with the subkey of the
+       authenticator.
+
+       * kuser/kinit.c: write out v4 credential caches with
+       _krb5_krb_tf_setup
+
+       * lib/krb5/krb5-v4compat.h: add _krb5_krb_tf_setup
+
+       * lib/krb5/convert_creds.c (_krb5_krb_tf_setup): create/append v4
+       credential to a new krb4 ticket file
+       
+2003-06-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5_kuserok.3: put Nd argument in double quotes since
+       it contains more than 9 words; from wiz
+
+2003-06-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c: add missing " within #if 0, from
+       stefan sokoll <stefansokoll@yahoo.de>
+
+2003-06-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_timeofday.3: improve krb5_set_real_time text
+       
+       * lib/krb5/time.c: improve comment for krb5_set_real_time
+       
+2003-06-23  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.1: document -A
+
+       * kuser/kinit.c: add -A as an alias for --no-addresses
+
+2003-06-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): pass in a
+       krb5_timestamp to krb5_us_timeofday
+
+       * lib/krb5/mk_error.c (krb5_mk_error): pass in a krb5_timestamp to
+       krb5_us_timeofday
+
+       * lib/krb5/time.c (krb5_set_real_time): fix comment and make it
+       work
+
+       * lib/krb5/time.c, lib/krb5/krb5_timeofday.3, 
+       lib/krb5/Makefile.am lib/krb5/test_time.c:
+       
+       implement krb5_set_real_time, used by SAMBA, requested by Luke
+       Howard <lukeh@PADL.COM>
+
+       * lib/asn1/k5.asn1: make the aes and sha1 checksum types match
+       draft-ietf-krb-wg-crypto-05
+
+2003-06-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/aes-test.c: add a test for aes kcrypto encrypted data
+       
+       * lib/krb5/crypto.c: clean up AES code to use a structure instead
+       of a key array
+       (_krb5_AES_string_to_default_iterator): set to 4096 as described in
+       aes draft -04
+       (derive_key): always remove the key->schedule since its
+       will contain the wrong (parent key) info
+
+2003-06-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/aes-test.c: add aes256 test vectors from Ken Raeburn
+       * doc/setup.texi: add more kdc's to the example
+       
+2003-06-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: use int2HDBFlags/HDBFlags2int From: Alberto
+       Patino <jalbertop@aranea.com.mx>, Luke Howard <lukeh@PADL.COM>
+       Pointed out by Andrew Bartlett of Samba
+       
+       * lib/krb5/heim_threads.h: remove freebsd comment, don't use debug
+       pthread stubs by default
+
+       * lib/krb5/Makefile.am (man_MANS): drop krb5_free_addresses.3
+       
+       * lib/krb5/krb5_free_addresses.3: removed file, functions are
+       documented in krb5_address.3
+       
+       * lib/krb5/codec.c: add krb5_{de,en}code_ETYPE_INFO2
+       
+       * lib/krb5/crypto.c: add _krb5_AES_string_to_default_iterator add
+       krb5_string_to_key_salt_opaque() fix keylengh for keytype_aes256
+       
+2003-06-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: Point out that slave needs /var/heimdal
+       directory and masterkey From: Mans Nilsson <mansaxel@sunet.se>,
+       Fix spelling while here
+       
+2003-06-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am, krb5_get_in_cred.3, krb5.3:
+       add manpage for: krb5_get_in_cred, krb5_get_in_tkt,
+       krb5_get_in_tkt_with_keytab, krb5_get_in_tkt_with_password,
+       krb5_get_in_tkt_with_skey
+
+2003-05-28  Assar Westerlund  <assar@kth.se>
+
+       * lib/krb5/heim_threads.h: Fix unlock/destroy macros for the
+       non-threaded cases to work.  Fix typo.
+
+2003-05-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/asn1/{der_put.c,der_length.c,check-der.c}: Fix encoding of
+       "unsigned" integers. If MSB is set, we need to pad with a zero
+       byte.
+
+2003-05-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_c_make_checksum.3: some more mdoc fixes
+       
+       * lib/hdb/hdb-ldap.c (LDAP__connect): bind sasl "EXTERNAL" to ldap
+       connection
+       (LDAP_store): remove superfluous argument to asprintf
+       
+       From Alberto Patino <jalbertop@aranea.com.mx>
+
+2003-05-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/*.[0-9]: pacify mdoclink
+
+       * lib/krb5/krb5_ccache.3: document diffrences between mit and
+       heimdal krb5_cc_gen_new ccache -> credential cache s/[\t ]+$//
+       
+2003-05-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * appl/test/gssapi_server.c (proto): start to use
+       gss_krb5_copy_ccache
+
+       * appl/test/nt_gss_server.c (proto): comment out gss_ctx_id_t
+       groveling for now
+
+2003-05-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1:
+       - add parser/generate glue for UTF8String and NULL
+         (DER primitive encode/decode functions missing)
+       - handle parsing of DEFAULT and, ...
+
+2003-05-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/heim_threads.h: add missing argument to mutex_init
+       
+       * lib/krb5/crypto.c: protect the random initiator with a mutex
+       
+       * lib/krb5/mcache.c: protect the mcc_head with a mutex
+       
+       * lib/krb5/krb5_locl.h: include heim_threads.h
+       
+       * lib/krb5/heim_threads.h: wrapper macros for thread
+       synchronization primitives
+
+2003-05-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_principal.3
+       lib/krb5/Makefile.am:
+       Add all Kerberos principal function to one manpage, add a few more
+       principal function to it, remove old now dup manpages
+       
+       * lib/krb5/krb5_build_principal.3: remove file
+       * lib/krb5/krb5_free_principal.3: remove file
+       * lib/krb5/krb5_sname_to_principal.3: remove file
+       * lib/krb5/krb5_principal_get_realm.3: remove file
+
+2003-05-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.8: sort sections, from netbsd
+       
+       * lib/krb5/krb5_verify_user.3: .Sh EXAMPLE -> .Sh EXAMPLES, from
+       netbsd
+
+       * lib/krb5/krb5_openlog.3: .Sh EXAMPLE -> .Sh EXAMPLES, sort
+       sections, from netbsd
+
+       * lib/krb5/krb5_keytab.3: .Sh EXAMPLE -> .Sh EXAMPLES, mdoc fixes,
+       from netbsd
+
+       * lib/krb5/krb5_get_krbhst.3: .Sh EXAMPLE -> .Sh EXAMPLES, from
+       netbsd
+       
+       * lib/krb5/krb5_get_all_client_addrs.3: add .Os, from NetBSD
+
+       * lib/krb5/krb5_build_principal.3: sort sections, from NetBSD
+       
+       * lib/krb5/krb5.conf.5: .Sh EXAMPLE -> .Sh EXAMPLES, from netbsd
+       
+       * lib/krb5/get_default_realm.c: compatability -> compatibility,
+       from netbsd
+
+       * lib/krb5/krb5_warn.3: add copyright/license
+       
+       * lib/krb5/krb5_context.3: add SYNOPSIS and LIBRARY
+       
+       * lib/krb5/krb5.3: add RCSID
+       
+       * kdc/hprop.8: fix mdoc problem, from netbsd
+       
+       * lib/krb5/krb5_krbhst_init.3: uppercase url, from Thomas Klausner
+       <wiz@netbsd.org>
+
+       * kuser/kinit.1: setup -> set up, new sentence, new line from
+       Thomas Klausner <wiz@netbsd.org>
+       
+2003-05-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswd.1: handle setting passwords for multiple
+       principals at the same time
+
+       * kpasswd/kpasswd.c: handle setting passwords for multiple
+       principals at the same time
+
+       * lib/krb5/changepw.c: draft-ietf-cat-kerb-chg-password-02 and
+       rfc3244 share the response packet sure more constants now that
+       they exists
+
+2003-05-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.h: some define for rfc3244
+       
+       * lib/krb5/krb5.3: add krb5_change_password and krb5_set_password
+       
+       * kpasswd/kpasswd.1: document --admin-principal
+       
+       * kpasswd/kpasswd.c: use krb5_set_password
+       
+       * lib/krb5/krb5_set_password.3: document krb5_change_password and
+       krb5_set_password
+
+       * lib/krb5/changepw.c: implement rfc3244, partly from
+       shadow@dementia.org
+
+       * lib/asn1/Makefile.am (gen_files): asn1_ChangePasswdDataMS.x for
+       RFC3244
+
+       * lib/asn1/k5.asn1: add ChangePasswdDataMS, for
+       RFC3244
+
+2003-05-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * kuser/kdestroy.c: destroy tokens even if there isn't v4 support
+
+       * kuser/kinit.c: get token even if there isn't v4 support
+       
+       * kuser/klist.c: print tokens even if there isn't v4 support
+       
+2003-05-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/name-45-test.c: need to use empty krb5.conf for some
+       tests
+
+       * lib/asn1/check-gen.c: there is no \e escape sequence; replace
+       everything with hex-codes, and cast to unsigned char* to make some
+       compilers happy
+
+2003-05-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_in_tkt.c (make_pa_enc_timestamp): make sure first
+       argument to krb5_us_timeofday have correct type
+       
+2003-05-05  Assar Westerlund  <assar@kth.se>
+
+       * include/make_crypto.c (main): include aes.h if ENABLE_AES
+
+2003-05-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * make-release: when fixing a valid cvs tag from release name
+       replace all number. to number- for all non-overlapping matches
+       
+2003-05-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/Makefile.am: gen_files += asn1_ETYPE_INFO2.x and
+       asn1_ETYPE_INFO2_ENTRY.x
+       (libasn1_la_LDFLAGS): set version to 6:1:1
+
+       * doc/Makefile.am: add apps.texi
+       
+       * doc/setup.texi: add move forward link to applications
+       
+       * doc/heimdal.texi: add applications
+       
+       * doc/misc.texi: move afs stuff to applications add link to
+       applications
+       
+       * doc/apps.texi: text about applications using kerberos
+       move afs text here
+       
+2003-05-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: add cross realm text
+       
+2003-04-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_crypto_init.3: document krb5_enctype_to_string and
+       krb5_string_to_enctype
+
+2003-04-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/v4_dump.c (v4_prop_dump): limit strings length, from openbsd
+       
+2003-04-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/aes-test.c: use _krb5_PKCS5_PBKDF2
+       * lib/krb5/crypto.c: unexport krb5_PKCS5_PBKDF2
+       
+2003-04-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): if the local
+       sequence number is non-zero, don't generate a new one
+
+       * lib/krb5/mk_rep.c (krb5_mk_rep): if the local sequence number is
+       non-zero, don't generate a new one
+       
+       * lib/krb5/time.c (krb5_us_timeofday): make the sec parameter a
+       krb5_timestamp
+
+       * lib/krb5/mk_priv.c lib/krb5/mk_safe.c lib/krb5/rd_priv.c
+       lib/krb5/rd_safe.c lib/krb5/rd_cred.c: implement RET_SEQUENCE and
+       RET_TIME
+
+       * lib/krb5/krb5.h (krb5_replay_data): make usec signed (matching
+       asn1)
+
+2003-04-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/programming.texi: s/managment/management/, from jmc
+       <jmc@prioris.mini.pw.edu.pl>
+
+2003-04-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/context.c (default_etypes): also advertise that we
+       handle aes encryption types
+
+       * lib/krb5/Makefile.am: add krb5_c_ checksum related functions
+
+       * lib/krb5/krb5_c_make_checksum.3: document krb5_c_ checksum
+       related functions
+
+       * lib/krb5/mit_glue.c: add compat mit krb5_c checksum related
+       functions
+
+       * lib/asn1/k5.asn1: add ETYPE-INFO2 and ETYPE-INFO2-ENTRY
+       
+2003-04-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krbhst.c: copy NUL too, from janj@wenf.org via openbsd
+       
+2003-04-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/der_copy.c (copy_general_string): use strdup
+       * lib/asn1/der_put.c: remove sprintf
+       * lib/asn1/gen.c: remove strcpy/sprintf
+       
+       * lib/krb5/name-45-test.c: use a more unique name then ratatosk so
+       that other (me) have such hosts in the local domain and the tests
+       fails, to take hokkigai.pdc.kth.se instead
+       
+       * lib/krb5/test_alname.c: add --version and --help
+       
+2003-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_warn.3: add krb5_get_err_text
+       
+       * lib/krb5/transited.c: use strlcat/strlcpy, from openbsd
+       * lib/krb5/krbhst.c (srv_find_realm): use strlcpy, from openbsd
+       * lib/krb5/aname_to_localname.c (krb5_aname_to_localname): use
+       strlcpy, from openbsd
+       * kdc/hpropd.c: s/strcat/strlcat/, inspired from openbsd
+       * appl/kf/kfd.c: use strlcpy, from openbsd
+       
+2003-04-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: fix for large file support in AIX, _LARGE_FILES
+       needs to be defined on the command line, since lex likes to
+       include stdio.h before we get to config.h
+
+2003-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/*.3: Change .Fd #include <header.h> to .In header.h,
+       from Thomas Klausner <wiz@netbsd.org>
+       
+       * lib/krb5/krb5.conf.5: spelling, from Thomas Klausner
+       <wiz@netbsd.org>
+
+2003-04-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c: fix some more memory leaks
+       
+2003-04-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/kf/kf.1: spelling, from jmc <jmc@prioris.mini.pw.edu.pl>
+       
+2003-04-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * admin/ktutil.8: typos, from jmc <jmc@acn.waw.pl>
+       
+2003-04-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.3: s/kerberos/Kerberos/
+       * lib/krb5/krb5_data.3: s/kerberos/Kerberos/
+       * lib/krb5/krb5_address.3: s/kerberos/Kerberos/
+       * lib/krb5/krb5_ccache.3: s/kerberos/Kerberos/
+       * lib/krb5/krb5.conf.5: s/kerberos/Kerberos/
+       * kuser/kinit.1: s/kerberos/Kerberos/
+       * kdc/kdc.8: s/kerberos/Kerberos/
+       
+2003-04-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/test_alname.c: more krb5_aname_to_localname tests
+       
+       * lib/krb5/aname_to_localname.c (krb5_aname_to_localname): when
+       converting too root, make sure user is ok according to
+       krb5_kuserok before allowing it.
+
+       * lib/krb5/Makefile.am (noinst_PROGRAMS): += test_alname
+       
+       * lib/krb5/test_alname.c: add test for krb5_aname_to_localname
+       
+       * lib/krb5/crypto.c (krb5_DES_AFS3_CMU_string_to_key): used p1
+       instead of the "illegal" salt #~, same change as kth-krb did
+       1999. Problems occur with crypt() that behaves like AT&T crypt
+       (openssl does this). Pointed out by Marcus Watts.
+
+       * admin/change.c (kt_change): collect all principals we are going
+       to change, and pick the highest kvno and use that to guess what
+       kvno the resulting kvno is going to be. Now two ktutil change in a
+       row works. XXX fix the protocol to pass the kvno back.
+       
+2003-03-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/kf/kf.1: afs->AFS, from jmc <jmc@acn.waw.pl>
+       
+2003-03-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: add description on how to turn on v4, 524 and
+       kaserver support
+
+2003-03-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c (appdefaults_entries): add afslog
+       and afs-use-524
+
+2003-03-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c (as_rep): when the second enctype_to_string
+       failes, remember to free memory from the first enctype_to_string
+
+       * lib/krb5/crypto.c (usage2arcfour): map KRB5_KU_TICKET to 2,
+       from Harald Joerg <harald.joerg@fujitsu-siemens.com>
+       (enctype_arcfour_hmac_md5): disable checksum_hmac_md5_enc
+
+       * lib/hdb/mkey.c (hdb_unseal_keys_mkey): truncate key to the key
+       length when key is longer then expected length, its probably
+       longer since the encrypted data was padded, reported by Aidan
+       Cully <aidan@kublai.com>
+
+       * lib/krb5/crypto.c (krb5_enctype_keysize): return key size of
+       encyption type, inspired by Aidan Cully <aidan@kublai.com>
+       
+2003-03-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/keytab.c (krb5_kt_get_entry): avoid printing 0
+       (wildcard kvno) after principal when the keytab entry isn't found,
+       reported by Chris Chiappa <chris@chiappa.net>
+       
+2003-03-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/misc.texi: update 2b example to match reality (from
+       mattiasa@e.kth.se)
+
+       * doc/misc.texi: spelling and add `Configuring AFS clients'
+       subsection
+
+2003-03-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.3: add krb5_free_data_contents.3
+       
+       * lib/krb5/data.c: add krb5_free_data_contents for compat with MIT
+       API
+
+       * lib/krb5/krb5_data.3: add krb5_free_data_contents for compat
+       with MIT API
+       
+       * lib/krb5/krb5_verify_user.3: write more about how the ccache
+       argument should be inited when used
+       
+2003-03-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/addr_families.c (krb5_print_address): make sure
+       print_addr is defined for the given address type; make addrports
+       printable
+
+       * kdc/string2key.c: print the used enctype for kerberos 5 keys
+
+2003-03-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/aes-test.c: add another arcfour test
+       
+2003-03-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/aes-test.c: sneek in a test for arcfour-hmac-md5
+       
+2003-03-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/krb5_ccache.3: update .Dd
+
+       * lib/krb5/krb5.3: sort in krb5_data functions
+
+       * lib/krb5/Makefile.am (man_MANS): += krb5_data.3
+
+       * lib/krb5/krb5_data.3: document krb5_data
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds_password): if
+       prompter is NULL, don't try to ask for a password to
+       change. reported by Iain Moffat @ ufl.edu via Howard Chu
+       <hyc@highlandsun.com>
+
+2003-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_keytab.3: spelling, from
+       <jmc@prioris.mini.pw.edu.pl>
+
+       * lib/krb5/krb5.conf.5: . means new line
+       
+       * lib/krb5/krb5.conf.5: spelling, from
+       <jmc@prioris.mini.pw.edu.pl>
+
+       * lib/krb5/krb5_auth_context.3: spelling, from
+       <jmc@prioris.mini.pw.edu.pl>
+
+2003-03-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/Makefile.am: INCLUDES: -I$(srcdir)/../lib/krb5
+       
+       * lib/krb5/convert_creds.c: add _krb5_krb_life_to_time
+       
+       * lib/krb5/krb5-v4compat.h: add _krb5_krb_life_to_time
+
+       * kdc/kdc_locl.h: 524 is independent of kerberos 4, so move out
+       #ifdef KRB4 from enable_v4_cross_realm since 524 needs it
+       
+       * kdc/config.c: 524 is independent of kerberos 4, so move out
+       enable_v4_cross_realm from #ifdef KRB4 since 524 needs it
+       
+2003-03-17  Assar Westerlund  <assar@kth.se>
+
+       * kdc/kdc.8: document --kerberos4-cross-realm
+       * kdc/kerberos4.c: pay attention to enable_v4_cross_realm
+       * kdc/kdc_locl.h (enable_v4_cross_realm): add
+       * kdc/524.c (encode_524_response): check the enable_v4_cross_realm
+       flag before giving out v4 tickets for foreign v5 principals
+       * kdc/config.c: add --enable-kerberos4-cross-realm option (default
+       to off)
+
+2003-03-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am (man_MANS) += krb5_aname_to_localname.3
+       
+       * lib/krb5/krb5_aname_to_localname.3: manpage for
+       krb5_aname_to_localname
+
+       * lib/krb5/krb5_kuserok.3: s/KRB5_USEROK/KRB5_KUSEROK/
+       
+2003-03-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am (man_MANS): add krb5_set_default_realm.3
+
+       * lib/krb5/krb5.3: add manpages from krb5_set_default_realm.3
+
+       * lib/krb5/krb5_set_default_realm.3: Manpage for
+       krb5_free_host_realm, krb5_get_default_realm,
+       krb5_get_default_realms, krb5_get_host_realm, and
+       krb5_set_default_realm.
+
+       * admin/ktutil.8: s/entype/enctype/, from Igor Sobrado
+       <sobrado@acm.org> via NetBSD
+
+       * lib/krb5/krb5_keytab.3: add documention for krb5_kt_get_type
+       
+       * lib/krb5/keytab.c (krb5_kt_get_type): get prefix/type of keytab
+       
+       * lib/krb5/krb5.h (KRB5_KT_PREFIX_MAX_LEN): max length of prefix
+       
+       * lib/krb5/krb5_ccache.3: document krb5_cc_get_ops, add more
+       types, add krb5_fcc_ops and krb5_mcc_ops
+       
+       * lib/krb5/cache.c (krb5_cc_get_ops): new function, return ops for
+       a id
+
+2003-03-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/intro.texi: add reference to source code, binaries and the
+       manual
+
+       * lib/krb5/krb5.3: krb5.h isn't in krb5 directory in heimdal
+       
+2003-03-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kdc.8: better/difrent english
+
+       * kdc/kdc.8: . -> .\n, copyright/license
+       
+       * kdc/kdc.8: changed configuration file -> restart kdc
+
+       * kdc/kerberos4.c: add krb4 into the most error messages written
+       to the logfile
+
+       * lib/krb5/krb5_ccache.3: add missing name of argument
+       (krb5_context) to most functions
+
+2003-03-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/kuserok.c (krb5_kuserok): preserve old behviour of
+       function and return FALSE when there isn't a local account for
+       `luser'.
+
+       * lib/krb5/krb5_kuserok.3: fix prototype, spelling and more text
+       describing the function
+
+2003-03-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/cache.c (krb5_cc_default): if krb5_cc_default_name
+       returned memory, don't return ENOMEM
+
+2003-03-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.3: add krb5_address stuff and sort
+       
+       * lib/krb5/krb5_address.3: fix krb5_addr2sockaddr description
+       
+       * lib/krb5/Makefile.am (man_MANS): += krb5_address.3
+       
+       * lib/krb5/krb5_address.3: document types krb5_address and
+       krb5_addresses and their helper functions
+
+2003-03-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am (man_MANS): += krb5_kuserok.3
+
+       * lib/krb5/krb5_kuserok.3: spelling, from cizzi@it.su.se
+
+       * lib/krb5/Makefile.am (man_MANS): += krb5_ccache.3
+
+       * lib/krb5/krb5_ccache.3: spelling, from cizzi@it.su.se
+       
+       * lib/krb5/krb5.3: add more functions
+       
+       * lib/krb5/krb5_ccache.3: document krb5_ccache and krb5_cc
+       functions
+
+       * lib/krb5/krb5_kuserok.3: document krb5_kuserok
+       
+       * lib/krb5/krb5_verify_user.3: document
+       krb5_verify_opt_set_flags(opt, KRB5_VERIFY_LREALMS) behavior
+
+       * lib/krb5/krb5_verify_user.3: document krb5_verify_opt* and
+       krb5_verify_user_opt
+
+       * lib/krb5/*.[0-9]: add copyright/licenses on more manpages
+
+       * kuser/kdestroy.c (main): handle that krb5_cc_default_name can
+       return NULL
+
+       * lib/krb5/Makefile.am (libkrb5_la_LDFLAGS): bump minor
+       (TESTS): add test_cc
+
+       * lib/krb5/test_cc.c: test some
+       krb5_cc_default_name/krb5_cc_set_default_name combinations
+       
+       * lib/krb5/context.c (init_context_from_config_file): set
+       default_cc_name to NULL
+       (krb5_free_context): free default_cc_name if set
+
+       * lib/krb5/cache.c (krb5_cc_set_default_name): new function
+       (krb5_cc_default_name): use krb5_cc_set_default_name
+
+       * lib/krb5/krb5.h (krb5_context_data): add default_cc_name
+       
+2003-02-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/kf/kf.1: s/securly/securely/ from NetBSD
+       
+2003-02-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/connect.c: s/intialize/initialize, from
+       <jmc@prioris.mini.pw.edu.pl>
+
+2003-02-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * configure.in: add AM_MAINTAINER_MODE
+       
+2003-02-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * **/*.[0-9]: add copyright/licenses on all manpages
+
+2003-14-16  Jacques Vidrine  <nectar@kth.se>
+
+       * lib/krb5/get_in_tkt.c (init_as_req): Send only a single
+       PA-ENC-TIMESTAMP in the AS-REQ, using the first encryption
+       type specified by the KDC.
+
+2003-02-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * fix-export: some autoconf put their version number in
+       autom4te.cache, so remove autom4te*.cache
+       
+       * fix-export: make sure $1 is a directory
+       
+2003-02-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswdd.8: spelling, from jmc <jmc@prioris.mini.pw.edu.pl>
+
+       * kdc/kdc.8: spelling, from jmc <jmc@prioris.mini.pw.edu.pl>
+       
+2003-01-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/hpropd.8: s/databases/a database/ s/Not/not/
+
+       * kdc/hprop.8: add missing .
+       
+2003-01-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: documentation for of boolean, etypes,
+       address, write out encryption type in sentences, s/Host/host
+       
+2003-01-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/check-gen.c: add checks for Authenticator too
+       
+2003-01-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: in the hprop example, use hprop and the first
+       component, not host
+
+       * lib/krb5/get_addrs.c (find_all_addresses): address-less
+       point-to-point might not have an address, just ignore
+       those. Reported by Harald Barth.
+
+2003-01-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c (check_section): when key isn't
+       found, don't print out all known keys
+
+       * lib/krb5/verify_krb5_conf.c (syslogvals): mark up where severity
+       and facility start resp
+       (check_log): find_value() returns -1 when key isn't found
+
+       * lib/krb5/crypto.c (_krb5_aes_cts_encrypt): make key argument a
+       'const void *' to avoid AES_KEY being exposed in krb5-private.h
+       
+       * lib/krb5/krb5.conf.5: add [kdc]use_2b
+
+       * kdc/524.c (encode_524_response): its 2b not b2
+       
+       * doc/misc.texi: quote @ where missing
+       
+       * lib/asn1/Makefile.am: add check-gen
+       
+       * lib/asn1/check-gen.c: add Principal check
+       
+       * lib/asn1/check-common.h: move generic asn1/der functions from
+       check-der.c to here
+
+       * lib/asn1/check-common.c: move generic asn1/der functions from
+       check-der.c to here
+
+       * lib/asn1/check-der.c: move out the generic asn1/der functions to
+       a common file
+
+2003-01-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/misc.texi: more text about afs, how to get get your KeyFile,
+       and how to start use 2b tokens
+
+       * lib/krb5/krb5.conf.5: spelling, from Jason McIntyre
+       <jmc@cvs.openbsd.org>
+       
+2003-01-21  Jacques Vidrine  <nectar@kth.se>
+
+       * kuser/kuser_locl.h: include crypto-headers.h for
+       des_read_pw_string prototype
+
+2003-01-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * admin/ktutil.8: document -v, --verbose
+
+       * admin/get.c (kt_get): make getarg usage consistent with other
+       other parts of ktutil
+
+       * admin/copy.c (kt_copy): remove adding verbose_flag to args
+       struct, since it will overrun the args array (from Sumit Bose)
+       
+2003-01-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: write more about [realms] REALM = { kdc =
+       ... }
+
+       * lib/krb5/aes-test.c: test vectors in aes-draft
+       
+       * lib/krb5/Makefile.am: add aes-test.c
+
+       * lib/krb5/crypto.c: Add support for AES
+       (draft-raeburn-krb-rijndael-krb-02), not enabled by default.
+       (HMAC_SHA1_DES3_checksum): rename to SP_HMAC_SHA1_checksum and modify
+       to support checksumtype that are have a shorter wireformat then
+       their output block size.
+       
+       * lib/krb5/crypto.c (struct encryption_type): split the blocksize
+       into blocksize and padsize, padsize is the minimum padding
+       size. they are the same for now
+       (enctype_*): add padsize
+       (encrypt_internal): use padsize
+       (encrypt_internal_derived): use padsize
+       (wrapped_length): use padsize
+       (wrapped_length_dervied): use padsize
+
+       * lib/krb5/crypto.c: add extra `opaque' argument to string_to_key
+       function for each enctype in preparation enctypes that uses
+       `Encryption and Checksum Specifications for Kerberos 5' draft
+       
+       * lib/asn1/k5.asn1: add checksum and enctype for AES from
+       draft-raeburn-krb-rijndael-krb-02.txt
+
+       * lib/krb5/krb5.h (krb5_keytype): add KEYTYPE_AES128,
+       KEYTYPE_AES256
+
+2003-01-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/common.c (_hdb_fetch): handle error code from
+       hdb_value2entry
+
+       * kdc/Makefile.am: always include kerberos4.c and 524.c in
+       kdc_SOURCES to support 524
+
+       * kdc/524.c: always compile in support for 524
+       
+       * kdc/kdc_locl.h: move out krb/524 protos from under #ifdef KRB4
+       
+       * kdc/config.c: always compile in support for 524
+       
+       * kdc/connect.c: always compile in support for 524
+       
+       * kdc/kerberos4.c: export encode_v4_ticket() and get_des_key()
+       even when we build without kerberos 4, 524 needs them
+       
+       * lib/krb5/convert_creds.c, lib/krb5/krb5-v4compat.h: Split out
+       Kerberos 4 help functions/structures so other parts of the source
+       tree can use it (like the KDC)
+
diff --git a/src/kerberosV/src/ChangeLog.2004 b/src/kerberosV/src/ChangeLog.2004
new file mode 100644 (file)
index 0000000..5e39342
--- /dev/null
@@ -0,0 +1,1485 @@
+2004-12-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am (CHECK_SYMBOLS): add heim_ and pkcs7_ for
+       now (used in pkinit)
+
+2004-12-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/Makefile.am: add CHECK_SYMBOLS
+
+       * lib/hdb/keys.c: make all_etypes static
+
+       * lib/krb5/Makefile.am: add CHECK_SYMBOLS, approve of: -com_err
+       -version krb5_ _krb5_ __heimdal krb524_ krb4_fkt_ops
+
+       * kdc/kerberos5.c: use private version of principalname
+
+       * kdc/kerberos4.c: use private version of principalname
+
+       * kdc/hpropd.c: use private version of principalname
+
+       * kdc/524.c: use private version of principalname
+
+       * lib/krb5/rd_req.c: use private version of principalname
+
+       * lib/krb5/rd_cred.c: use private version of principalname
+
+       * lib/krb5/init_creds_pw.c: use private version of principalname
+
+       * lib/krb5/get_in_tkt.c: use private version of principalname
+
+       * lib/krb5/asn1_glue.c: make principalname functions private
+
+       * lib/krb5/krb5.h: add key usage for server referrals
+       
+2004-12-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/principal.c: make default_v4_name_convert static
+       
+       * lib/krb5/crypto.c: make lots of crypto related variables static
+       
+       * lib/krb5/acache.c: make default_acc_name static
+       
+2004-12-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: add some text about samba, use example.com
+       
+       * lib/hdb/hdb-ldap.c: Add account expiration for samba from James
+       F.  Hranicky <jfh@cise.ufl.edu>.
+       Add LDAP_addmod_integer and use it.
+
+2004-12-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/{Makefile.am,setup.texi,win2k.texi}: spelling and text
+       fixes, from Dave Love
+
+2004-12-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/heim_threads.h: NetBSD 2.99.11 (any maybe 2.1) just
+       needs pthread.h, threadlib is dead
+
+2004-12-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/config.c (configure): check for deprecated
+       enforce-transited-policy is set and fail if it is
+       
+       * lib/asn1/asn1_print.c: don't print garabage for octet strings
+       
+2004-12-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/main.c (main): catch sigpipe, we don't bother select()ing
+       for errors
+
+       * kdc/connect.c (handle_http_tcp): handle error from write(2)
+       
+       * doc/setup.texi: clarify credentials refreshing stuff
+       
+       * doc/setup.texi: add new node: Providing Kerberos credentials to
+       servers and programs
+
+       * doc/whatis.texi: fix spurious cross-reference makeinfo warning
+       
+       * lib/hdb/hdb-ldap.c (pos): uppercase in character
+
+2004-12-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c (LDAP__bytes2hex,LDAP__hex2bytes): encode
+       nibbels in the other order
+
+       * lib/hdb/hdb-ldap.c: s/objectclass/objectClass/ check if
+       attribute exists before we try to delete it LDAP__bytes2hex
+       encodes in strange byte order, is this really right ?
+       
+2004-12-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c (LDAP_firstkey): When iterating over all
+       entries, search for samba accounts too, From: "James F. Hranicky"
+       <jfh@cise.ufl.edu>
+
+       * lib/hdb/hdb-ldap.c (krb5kdcentry_attrs): ask for attribute uid
+       too
+
+       * lib/hdb/hdb-ldap.c (LDAP_message2entry): if the entry is missing
+       both krb5PrincipalName and uid, it must be broken, ignore it and
+       return it doesn't exists.
+
+2004-12-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/hpropd.8: spelling, from OpenBSD
+       
+       * kdc/kdc.8: use keeps for options, From OpenBSD k
+       
+2004-12-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: document --random-key and the need to do backup
+       of the master key
+
+       * kdc/kstash.8: add --random-key
+       
+       * kdc/kstash.c: add --random-key
+       
+2004-12-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.8: spelling, from openbsd
+       
+       * lib/krb5/krb5_init_context.3: spelling, from openbsd
+       
+       * lib/krb5/krb5.conf.5: spelling, from openbsd
+       
+       * kuser/kdestroy.1: use keeps around options, spelling, from
+       openbsd
+
+       * kpasswd/kpasswdd.8: use ., use keeps around options, from OpenBSD
+       
+       * kdc/hpropd.8: use keeps around options, from OpenBSD
+       
+       * kdc/hprop.8: use keeps around options, from OpenBSD
+       
+2004-11-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/context.c (krb5_free_context): clear error string
+       before destroying mutex
+       (krb5_init_context): don't call krb5_free_context before there is a
+       mutex initialized
+
+2004-11-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c (get_new_tickets): only complain about ticket
+       renewable lifetime when the user asked for a specific renewable
+       lifetime
+
+2004-11-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c (find_keys): log what principal is missing
+       enctypes
+
+2004-11-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): clear pointer after
+       freeing data
+
+       * lib/krb5/init_creds_pw.c (change_password): handle old_options
+       being NULL From Guenther Deschner on samba-technical.
+       
+2004-11-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_get_init_creds.3: add more text describing the
+       krb5_get_init_creds functions
+
+2004-11-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c: make krb5_get_init_creds_keytab work
+       again
+
+2004-11-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb.asn1: use constrained integers
+       
+2004-11-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_get_init_creds.3: add description for opt_init,
+       opt_alloc, opt_free
+
+       * lib/krb5/pkinit.c: unexport krb5_get_init_creds_opt_free_pkinit
+       
+       * lib/krb5/init_creds.c: unexport
+       krb5_get_init_creds_opt_free_pkinit
+
+       * lib/krb5/init_creds_pw.c: fold init_init_creds_ctx into
+       get_init_creds_common
+
+       * lib/krb5/init_creds.c (_krb5_get_init_creds_opt_copy): if the in
+       options NULL, just make a clean copy
+
+2004-11-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/sendauth.c (krb5_rd_rep): free ap_rep message earlier
+       so we don't leak it on error
+
+2004-10-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: unbreak 2b entry
+       
+       * lib/krb5/acache.c (make_cred_from_ccred): the address isn't a
+       sockaddr but rather a kerberos address, deal with that.  Based on
+       bug report from Jakob Schlyter <jakob@rfc.se>.
+
+2004-10-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/connect.c: Make sure argument passed to ctype isn't signed
+       char
+
+2004-10-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: match new error names
+       
+       * lib/krb5/krb5_err.et: make error messages sane again
+       
+2004-10-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/keytab.c: use KRB5_KT_BADNAME
+
+       * lib/krb5/krb5_err.et: sync with mit krb5_err.et (require major
+       version bump) add KRB5_DELTAT_BADFORMAT
+       
+       * lib/krb5/krb5.conf.5: time defaults to "s"
+       
+       * lib/krb5/time.c (krb5_string_to_deltat): default to "s" again,
+       MIT's behavior was actually that it failed to parse the number
+       (and thus used the default). Even better, ticket_lifetime (that
+       was a consumer supposed a of the interface) was documented but
+       never implemented, when it was implemented, people configuraiton
+       files started to fail.  Also, use KRB5_DELTAT_BADFORMAT as a
+       failure code.
+
+       * lib/asn1/k5.asn1: sync enctypes with pkinit branch
+       
+       * lib/asn1/parse.y (readd) support negative numbers
+       
+       * lib/asn1/lex.l: support hex numbers
+       
+2004-10-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: use ETYPE_DES3_CBC_NONE_CMS
+       
+       * lib/krb5/crypto.c: add enctype_des3_cbc_none_cms add cms padding
+       for rc2 don't to padding for blocksize 1
+       
+       * lib/hdb/{keys.c,Makefile.am},lib/kadm5/{keys,set_keys}.c:
+       Move keyset parsing and password based keyset generation into hdb.
+       Requested by Andrew Bartlett <abartlet@samba.org> for hdb-ldb
+       backend.
+
+2004-10-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: adapt to new signature of
+       krb5_get_init_creds_opt_set_pkinit
+       
+       * lib/krb5/pkinit.c: free openssl engine deal with
+       RecipientIdentifier -> CMSIdentifier and heim_any -> name change
+       improve error messages
+       
+       * kdc/pkinit.c: free openssl engine deal with RecipientIdentifier
+       -> CMSIdentifier and heim_any -> name change
+       
+2004-10-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/klist.c: use rtbl_set_separator
+       
+2004-10-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: filter out dup openssl engine keys, parse
+       user options first
+
+       * lib/krb5/pkinit.c: stop using AlgorithmIdentifierNonOpt, add
+       openssl engine support for private key
+
+       * lib/krb5/crypto.c: support padding as its done in CMS
+       
+       * kdc/pkinit.c: improve error logging
+       
+       * kdc/pkinit.c: stop using AlgorithmIdentifierNonOpt
+       
+2004-09-30  Love Hörnquist Ã…strand <lha@it.su.se>
+
+       * lib/krb5/krb5.conf.5: assume minutes for time
+
+       * lib/krb5/config_file.c (krb5_config_vget_time_default): use
+       krb5_string_to_deltat
+
+       * lib/krb5/appdefault.c (krb5_appdefault_time): use
+       krb5_string_to_deltat
+
+       * lib/krb5/time.c (krb5_string_to_deltat): set default unit to
+       minute for compatibility with MIT Kerberos.
+       
+
+2004-09-28  Love Hörnquist Ã…strand <lha@it.su.se>
+
+       * lib/krb5/get_cred.c (get_cred_kdc_usage): retry using "large
+       message safe" transport if we get back
+       KRB5KRB_ERR_RESPONSE_TOO_BIG error. Idea from Guenther Deschner
+       <gd@sernet.de>
+
+2004-09-23 Johan Danielsson <joda@pdc.kth.se>
+
+       * admin/list.c: use rtbl
+       
+       * admin/ktutil-commands.in: slc source file
+       
+       * lib/krb5/constants.c: check
+       /Library/Preferences/edu.mit.Kerberos on OSX
+
+2004-09-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/time.c (krb5_format_time): check return value from
+       localtime and strftime
+
+2004-09-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: make sure we don't always get renewable creds
+       
+2004-09-11   Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/acache.c: use krb5_ccapi.h
+       
+       * lib/krb5/krb5_ccapi.h: break out krb5 api definitions to
+       separate (not installed) file
+
+       * lib/krb5/Makefile.am: add AM_CPPFLAGS to libkrb5_la_CPPFLAGS
+       since AM_CPPFLAGS overridden by target specific _CPPFLAGS
+       
+2004-09-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: make variable shorter, make error messages
+       from pkinit, make freeing easier
+       
+2004-09-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: link libkrb5 with LIB_dlopen
+       
+       * lib/krb5/crypto.c (seed_something): avoid poking at memory that
+       is uninitialized, make valgrind unhappy. Pointd out by
+       abartlet@samba.org. While where, plug the fd leak.
+       
+2004-09-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/der_get.c (decode_*): name all tag-length variables the
+       same
+       (decode_enumerated): check that the tag-length is not longer the length
+
+       * lib/asn1/der_get.c (decode_boolean): fail if length of tag is
+       larger then len
+
+2004-08-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c (krb5_get_init_creds): kdc_reply can be
+       set in case of failure too, free unconditionally on exit to avoid
+       memory leak
+
+2004-08-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_cred.c (set_auth_data): set pointer to NULL after
+       free
+
+2004-08-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/context.c (krb5_get_err_text): if neither of com_right
+       nor strerror finds the error-code, return Unknown error.
+       
+2004-08-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5_kuserok.3: update to reality
+
+       * lib/krb5/kuserok.c: if a .k5login file exist, don't give
+       implicit rights to anyone; also check owner/mode of .k5login
+
+2004-08-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: man_MANS = krb5_getportbyname.3
+       
+       * lib/krb5/krb5_getportbyname.3: manpage for krb5_getportbyname
+       
+       * lib/krb5/krb5.3: add krb5_getportbyname
+       
+       * lib/krb5/krb5.3: krb5_free_salt and krb5_enctype_valid
+
+       * lib/krb5/krb5_encrypt.3: document krb5_enctype_valid
+       
+2004-08-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c (get_pa_etype_info{,2}): check for dup enctypes
+       from the client and filter them out.
+       
+       * lib/krb5/krb5_string_to_key.3: document krb5_free_salt
+       
+2004-08-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_ticket.3: data needs to be freed when using
+       krb5_ticket_get_authorization_data_type
+
+2004-08-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/test_cc.c: test variables in default_cc_name
+       
+       * lib/krb5/krb5.conf.5: explain support for varibles in
+       [libdefaults]default_cc_name
+       
+       * lib/krb5/cache.c: drop ${time}, its not very useful
+       
+       * lib/krb5/cache.c: Add _krb5_expand_default_cc_name that expand
+       variables in the default cc name. Supported variables now are:
+       ${time},${uid} and ${null}
+
+       * lib/krb5/krb5.conf.5: document default_cc_name
+       
+       * lib/krb5/cache.c (krb5_cc_set_default_name):
+       s/libdefault/libdefaults/
+
+2004-08-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/acache.c: replace magic 3 with ccapi_version_3
+       
+       * lib/krb5/Makefile.am: libkrb5_la_SOURCES += acache.c
+       
+       * lib/krb5/krb5.h: add krb5_acc_ops
+       
+       * lib/krb5/acache.c: CCAPI v3 implementation, the read only
+       support was from Magnus Ahltorp and then extended by me to support
+       all other operations.  Tested with MIT kerberos cc cache
+       implementation on MacOS 10.3.3
+
+       * lib/krb5/cache.c (krb5_cc_set_default_name): allow setting the
+       default cc name, this is not very useful for general purpose glue
+       since its not possible to glue in user information (like uid), but
+       for CCAPI it works just fine
+
+2004-08-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kgetcred.1: document --cache/-c
+       
+       * kuser/kgetcred.c: allow to specify what credential cache to use
+       
+2004-08-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: add krb5_eai_to_heim_errno.3
+       
+       * lib/krb5/krb5_eai_to_heim_errno.3: document
+       krb5_eai_to_heim_errno, krb5_h_errno_to_heim_errno
+       
+       * lib/krb5/krb5.3: add krb5_eai_to_heim_errno,
+       krb5_h_errno_to_heim_errno
+
+2004-07-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_expand_hostname.3: krb5_expand_hostname_realms
+       result should be free with krb5_free_host_realm drop
+       krb5_get_host_realm text
+
+       * lib/krb5/krb5_set_default_realm.3: krb5_get_host_realm result
+       should be free with krb5_free_host_realm
+       
+       * lib/krb5/krb5_get_in_cred.3: document krb5_free_kdc_rep
+       
+       * lib/krb5/krb5_get_init_creds.3: remove dup krb5_get_init_creds
+       
+       * lib/krb5/krb5_auth_context.3: sort, add krb5_free_authenticator
+       
+       * lib/krb5/Makefile.am: man_MANS += krb5_rd_error
+       
+       * lib/krb5/krb5_rd_error.3: krb5_rd_error and friends
+       
+       * lib/krb5/krb5_warn.3: clarify on what string
+       krb5_free_error_string should operate on
+
+       * lib/krb5/krb5_get_credentials.3: add krb5_get_kdc_cred
+       
+       * lib/krb5/Makefile.am: krb5_get_credentials,
+       krb5_get_forwarded_creds and friends
+
+       * lib/krb5/krb5_get_forwarded_creds.3: krb5_get_forwarded_creds
+       and friends
+
+       * lib/krb5/krb5_get_credentials.3: krb5_get_credentials and
+       friends
+
+2004-07-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/klist.c (print_cred_verbose): keytypes are no longer, use
+       enctype
+
+2004-07-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c (LDAP_entry2mods): allow for pre-c99
+       compilers, From metze at samba.org
+
+2004-07-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/test_cc.c: more cc tests
+       
+       * lib/krb5/krb5_check_transited.3: document krb5_check_transited
+       
+2004-07-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c (pk_principal_from_X509): reverse test, makes
+       principal in cert work From: Mayur Patel <patelm4@rpi.edu>
+       
+2004-07-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: add krb5_verify_init_creds.3
+
+       * lib/krb5/krb5_verify_init_creds.3: add krb5_verify_init_creds
+       
+2004-07-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_set_password.3: spelling from wiz@netbsd.org
+       description for krb5_passwd_result_to_string
+       
+2004-07-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_set_password.3: Remove superfluous comma; grammar
+       fixes; split sentence in two for better understanding.  From
+       wiz@NetBSD.org. Describe krb5_set_password_using_ccache while here.
+
+       * lib/krb5/krb5_set_password.3: nroff and spelling, from Jonathan
+       Stone <jonathan@dsg.stanford.edu>
+
+       * lib/krb5/changepw.c (process_reply): cast ssize_t to long and
+       print that From NetBSD via Havard Eidnes.
+       
+2004-07-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * configure.in: fix helpstring for hdb-openldap-module
+       
+       * lib/krb5/test_cc.c: don't use krb5_err on error code 0
+       
+2004-07-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c (LDAP_seq): try handling errors better
+       
+2004-07-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_in_tkt.c (set_ptypes): make ptypes const
+       
+2004-07-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c (LDAP__connect): call ldap_initialize with
+       right argument
+
+2004-06-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): if the
+       krbtgt is without addresses, default to not sending our own
+       addrport
+
+       * lib/asn1/lex.l: add support for /* */ and partial line --
+       comments
+
+       * kuser/Makefile.am: don't install copy_cred_cache manpage
+       
+2004-06-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/init_creds.c (_krb5_get_init_creds_opt_copy): if
+       copying a static opt, make sure to allocate the "private" field
+
+2004-06-24  Love  <lha@stacken.kth.se>
+
+       * kdc/config.c: add enable_pkinit_princ_in_cert
+       
+       * kdc/kdc_locl.h: enable_pkinit_princ_in_cert
+       
+       * kdc/pkinit.c: Check certificate for Kerberos Principal in
+       OtherName of subjectAltName Based on patch from Mayur Patel
+       <patelm4@rpi.edu>
+
+2004-06-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_cred.c (init_tgs_req): if subkey not avaible, use
+       session key for authorization-data
+
+2004-06-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/connect.c (handle_tcp): note who is what that closed the
+       connection on us
+
+2004-06-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * admin/get.c (kt_get): catch errors from krb5_parse_name
+       
+2004-06-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: if its the entry just contains the
+       structural object (no samba nor heimdal object), add an aux
+       heimdal object on to it.
+       
+2004-06-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswd.c: use krb5_set_password_using_ccache
+       
+       * lib/krb5/krb5_set_password.3: add krb5_set_password_using_ccache
+       
+       * lib/krb5/changepw.c: implement krb5_set_password_using_ccache
+       
+       * lib/hdb/hdb-ldap.c: Allow the objectClass to be
+       "sambaSamAccount" or structural_object when searching for uid
+       entries.
+
+       * lib/krb5/krb5.conf.5: document [kdc]hdb-ldap-create-base
+       
+       * lib/hdb/hdb-ldap.c: add creation base that defaults to the
+       search base
+
+       * lib/hdb/hdb-ldap.c: indent like the rest of the code
+       
+2004-06-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: check return values from ldap operations and
+       close it we get back LDAP_SERVER_DOWN. stupid ldap client lib, you
+       should retry by yourself.
+
+       * lib/hdb/hdb-ldap.c: require search base to be configured, create
+       local context structure
+       
+2004-05-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: more ldap text, partly from Tarjei Huse
+       <tarjei@nu.no>
+
+2004-05-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/hdb/hdb-ldap.c: clean, indent
+       
+       * lib/hdb/hdb-ldap.c (LDAP_entry2mods): make sure
+       krb5KeyVersionNumber is added on new entires
+
+2004-05-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: minor fixes, partly from Tarjei Huse
+       <tarjei@nu.no>
+
+       * lib/krb5/krb5.conf.5: some text about dbname and realm
+       
+       * lib/krb5/krb5.conf.5: default value for
+       hdb-ldap-structural-object is account
+
+2004-05-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * tools/Makefile.am: use ! instead of , as sed delimiter
+       
+2004-05-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/*.c: add KRB5_LIB_FUNCTION to all exported functions
+
+2004-05-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: make samba_forwardable a krb5_boolean
+       
+       * lib/hdb/hdb-ldap.c: make samba forwarding a runtime configure
+       option
+
+       * lib/hdb/hdb-ldap.c (LDAP_message2entry): fix [] test From:
+       Andrew Bartlett <abartlet@samba.org>
+       
+       * lib/hdb/hdb-ldap.c (LDAP_message2entry): remove bogus length
+       check From: Andrew Bartlett <abartlet@samba.org>
+       
+       * lib/hdb/hdb-ldap.c (LDAP_message2entry): in the sambaNTPassword
+       case, make sure ent->etypes are allocated, From: Andrew Bartlett
+       <abartlet@samba.org>
+
+2004-05-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c: move "setpag if (argc < 1)" to common path
+       
+2004-05-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c: pacify pre c99 compilers
+       
+       * fix-export: use right argument for -E
+
+2004-05-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/kinit.c: print some diagnostics if the exec fails
+       
+2004-04-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c (pk_rd_pa_reply_dh): use krb5_random_to_key
+       From: Luke Howard <lukeh@padl.com>
+       
+       * lib/krb5/rd_req.c (krb5_verify_ap_req2): clear the whole ticket,
+       not just a pointer size of it From: Luke Howard <lukeh@padl.com>
+       
+2004-04-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * fix-export: add -E flag where needed to make-proto
+       
+2004-04-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/crypto.c: add set_param for RC2
+       
+       * lib/krb5/pkinit.c: use krb5_oid_to_enctype and remove all oids
+       that are no longer needed
+
+       * kdc/pkinit.c: use krb5_enctype_to_oid
+       
+       * lib/krb5/crypto.c (krb5_oid_to_enctype): make sure oid exists
+       before we compare with it
+
+       * lib/krb5/crypto.c (krb5_crypto_get_params): check ivec length
+       before returning it add aes-oids
+       
+       * lib/krb5/crypto.c: add krb5_enctype_to_oid and
+       krb5_oid_to_enctype
+
+       * kdc/pkinit.c: use krb5_crypto_set_params
+       
+       * lib/krb5/crypto.c: add krb5_crypto_set_params, add aes-NNN-cbc-none
+
+       * lib/krb5/krb5.h: add KEYTYPE_AES192
+       
+       * lib/krb5/pkinit.c: use krb5_crypto_get_params to implement
+       kcrypto RC2 support
+
+       * lib/asn1/k5.asn1: add CMS symmetrical parameters here, enctype
+       rc2-cbc XXX RC2CBCParameter is wrong because the compiler is
+       broken
+
+       * lib/krb5/krb5.h: add KEYTYPE_RC2
+       
+       * lib/krb5/crypto.c: add partial CMS parameter handling, this is
+       needed for RC2
+       
+       * lib/asn1/der_cmp.c: add heim_oid_cmp and heim_octet_string_cmp
+       
+       * lib/asn1/Makefile.am (libasn1_la_SOURCES) += der_cmp.c
+       
+       * lib/asn1/der.h: add heim_oid_cmp and heim_octet_string_cmp
+       
+       * lib/asn1/k5.asn1: add ETYPE_AESNNN_CBC_NONE
+       
+       * lib/asn1/k5.asn1: add CMS symmetrical parameters here, enctype
+       rc2-cbc, XXX RC2CBCParameter is wrong because the compiler is broken
+
+2004-04-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/config_file.c: allow parsing directly from strings with
+       krb5_config_parse_string_multi
+       
+       * lib/krb5/verify_krb5_conf.c: try to resolve hostnames
+       
+2004-04-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/store_fd.c (krb5_storage_from_fd): dup the file
+       descriptor so we don't have to keep track of it in two places
+       
+       * kuser/copy_cred_cache.c: krb5_cc_copy_cache_match now lives in
+       libkrb5
+
+       * lib/krb5/krb5_{,compare_}creds.3: move krb5_compare_creds to its
+       own manpage
+       
+       * replace krb5_free_creds_contents by krb5_free_cred_contents
+       
+       * lib/krb5/cache.c: add krb5_cc_next_cred_match() and
+       krb5_cc_copy_cred_match()
+       
+       * lib/krb5/creds.c (krb5_compare_creds): add more matching options
+       
+       * lib/krb5/krb5.h: add more creds match flags
+       
+       * kuser/copy_cred_cache: add --valid-for option
+       
+       * lib/krb5/store.c (krb5_store_creds): set is_skey flag if length
+       of second ticket is > 0
+
+2004-04-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * lib/krb5/pkinit.c: use the right oid for pkauthdata
+       
+       * lib/krb5/pkinit.c: always send both win2k compat version and the
+       ietf draft one, this is possible since microsoft use
+       wrong/diffrent PA number.  Make the configuration flag boolean
+       configuring if NOT to send the win2k compat glue.
+       
+       * lib/krb5/krb5_encrypt.3: document krb5_{de,en}crypt_ivec
+
+       * kuser/copy_cred_cache.1: pacify mdoclint
+       
+       * kdc/pkinit.c: use IV for envelopeddata encryption, patch
+       originally from Luke Howard <lukeh@padl.com>, tweeked by me.
+       
+       * lib/krb5/krb5_storage.3: document
+       KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER
+
+       * lib/krb5/krb5_data.3: document that krb5_data_free cleans the
+       structure too
+
+       * lib/krb5/pkinit.c: use IV for envelopeddata encryption, patch
+       originally from Luke Howard <lukeh@padl.com>, tweeked by me.
+       
+2004-04-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kuser/copy_cred_cache.{c,1}: add cred cache copy tool
+       
+       * configure.in: use rk_SYS_LARGEFILE
+       
+       * lib/krb5/{krb5.h,store.c,fcache.c}: Fix the cache flags bitorder
+       issue with a storage flag instead of a separate function.
+       
+2004-04-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: move out the oid check from get_reply_key
+
+       * lib/krb5/pkinit.c: uniquify error messages
+       
+       * lib/krb5/init_creds_pw.c: make the pkinit nonce same os the
+       plain nonce for now
+
+       * lib/krb5/pkinit.c: more w2k compat from Luke Howard
+       <lukeh@padl.com> add RC2 support, clean up error messages
+       
+       * lib/krb5/pkinit.c: remove more dependency on
+       krb5_config->pkinit_flags
+
+       * lib/krb5/pkinit.c (_krb5_pk_convert_rep): convert microsoft
+       style answer to IETF, From Luke Howard <lukeh@padl.com>
+       (_krb5_pk_create_sign): ms handles NULL in param, so always send it
+       (_krb5_pk_mk_padata): look for [realms]REALM = { win2k_pkinit = bool }
+
+       * lib/krb5/pkinit.c (_krb5_pk_create_sign): always set the
+       digestAlgorithm to sha1 (both for SignerInfo and SignedData, add
+       new function _set_digest_alg to set it
+
+2004-04-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * include/make_crypto.c: include rc2.h, and when I'm here, make
+       aes mandatory
+
+       * lib/krb5/krb5.h: add ENCTYPE_ARCFOUR_HMAC as compat glue for MIT
+       kerberos
+
+       * lib/krb5/crypto.c (krb5_crypto_init): clear return pointer on
+       failure
+
+       * lib/krb5/crypto.c (DES3_random_to_key): make it produce the
+       right result
+       (DES3_postproc): use DES3_random_to_key
+       (krb5_random_to_key): check the required number of bits (not the size
+       of the key)
+
+       * lib/krb5/aes-test.c: test random to key function
+
+       * lib/krb5/string-to-key-test.c: comment out the "@"/"" test for
+       now
+
+2004-04-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_string_to_key.3: document that
+       krb5_string_to_key_derived is broken for non 3des enctypes and
+       thus deprecated
+
+       * kdc/pkinit.c (generate_dh_keyblock): use the new function
+       krb5_random_to_key
+
+       * lib/krb5/crypto.c: add des and DES3 random_to_key hooks, they
+       need special processing
+
+       * lib/krb5/crypto.c (krb5_random_to_key): new function
+       
+       * lib/krb5/krb5_keyblock.3: document krb5_random_to_key
+       
+2004-04-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: use the first proposed enable enctype
+       
+       * lib/krb5/context.c (krb5_set_default_in_tkt_etypes): use the
+       return from krb5_enctype_valid
+
+       * kdc/pkinit.c: at least try to handle diffrent enveloped enctypes
+       
+2004-04-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/der_get.c: 1.28.2.16: (der_get_oid): handle all oid
+       components being smaller then 127 and allocate one extra element
+       since first byte is split to to elements.
+       
+2004-04-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/k5.asn1: ETYPE_DIGEST_MD5_NONE, ETYPE_CRAM_MD5_NONE:
+       private use, lukeh@padl.com
+
+2004-04-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c (build_auth_pack): use heim_integer to encode
+       DH public key
+
+2004-04-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_init_context.3: add krb5_context to so its added
+       as manpage-link too
+
+2004-04-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/fcache.c (fcc_remove_cred): simplistic implementation,
+       XXX add locking
+
+       * kuser/kdestroy.c: add --credential argument that just remove one
+       credential entry out of the cache specified
+       
+       * kdc/pkinit.c: replace the krb5.conf configuration option that
+       describes the mapping between principals and subject names with a
+       file, default /var/heimdal/pki-mapping. XXX this should be pushed
+       into HDB. XXX should add issuer too
+       
+       * kdc/config.c: merge certificate/private_key to a user_id
+       
+2004-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kdc_locl.h: update prototype for pk_initialize
+       
+       * kuser/kinit.c: merge certificate/private_key to a user_id
+       
+       * kdc/pkinit.c: adapt to heim_integer changes
+       
+       * lib/krb5/pkinit.c: merge certificate/private_key to a user_id
+       
+       * kdc/pkinit.c: adapt to heim_integer changes,
+       merge certificate/private_key to a user_id
+       
+2004-04-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: use KRB5_PADATA_PK_AS_REQ_WIN free X509_STORE
+       
+2004-04-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/Makefile.am: define BUILD_KRB5_LIB when building
+       libkrb5.la, add KRB5_LIB_FUNCTION proto
+
+       * lib/krb5/add_et_list.c: add KRB5_LIB_FUNCTION
+       
+       * configure.in: export KRB5_LIB_FUNCTION when building with
+       BUILD_KRB5_LIB
+
+       * lib/krb5/ticket.c (krb5_ticket_get_authorization_data_type): add
+       error strings
+
+       * lib/krb5/prompter_posix.c (krb5_prompter_posix): if some thing
+       is printed on stderr, fflush it
+
+       * lib/krb5/krb5_keyblock.3: free functions also zeros out the key
+       
+       * lib/krb5/krb5_get_init_creds.3: some text about
+       krb5_prompter_posix
+
+       * lib/krb5/krb5.conf.5: document hdb-ldap-structural-object
+       
+       * lib/krb5/cache.c: add krb5_cc_get_prefix_ops
+       
+       * lib/krb5/krb5_ccache.3: add krb5_cc_get_prefix_ops
+       
+2004-04-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * appl/test/http_client.c: support GSS_C_DELEG_FLAG and
+       GSS_C_MUTUAL_FLAG
+
+       * appl/test/http_client.c: verbose logging
+       
+2004-04-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/connect.c: case size_t to unsigned long for LP64 platforms
+       
+2004-04-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c (hdb_ldap_create): allow configuration of
+       default structural object
+
+       * tools/Makefile.am: handle sed expression breaking
+       
+2004-03-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krbhst.c: also lookup _kpasswd._tcp SRV-rr
+       
+       * lib/krb5/changepw.c: add tcp support to the set protocol, should
+       be cleaned up to enable sharing code with krb5_sendto
+       
+       * kpasswd/kpasswd.c (change_password): remove extra free
+       
+       * lib/krb5/krb5_acl_match_file.3: try to pacify mdoc macros on
+       osf/1
+
+2004-03-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c (pa_data_add_pac_request): don't
+       increase md->len, krb5_padata_add already does that
+       
+       * lib/krb5/init_creds.c: its PAC not PAQ
+       
+       * kuser/kinit.c: its PAC not PAQ
+       
+       * kdc/kerberos4.c: stop the client from renewing tickets into the
+       future From: Jeffrey Hutzelman <jhutz@cmu.edu>
+
+2004-03-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * configure.in: try to handle sys/strtty.h needing sys/stream.h
+       
+2004-03-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/send_to_kdc.c: remove function krb5_sendto_kdc2, its no
+       longer used
+       
+       * kdc/kerberos5.c: s/krb5_get_host_realm_int/_&/
+       
+       * lib/krb5/get_host_realm.c: unexport krb5_get_host_realm_int to
+       external users by prefixing it with _
+
+       * lib/krb5/get_cred.c: s/krb5_mk_req_internal/_&/
+       
+       * lib/krb5/mk_req_ext.c: unexport krb5_mk_req_internal to external
+       users by prefixing it with _
+
+2004-03-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: add missing }
+       
+2004-03-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: adapt to change of signature of
+       _krb5_pk_load_openssl_id
+
+       * lib/krb5/pkinit.c: (krb5_get_init_creds_opt_set_pkinit): add
+       prompter argument and use it
+
+       * kuser/kinit.c: adapt to signature change of
+       krb5_get_init_creds_opt_set_pkinit
+       
+       * lib/krb5/krb5.3: add more stuff, 105 functions to go
+
+       * lib/krb5/krb5_rcache.3: add krb5_get_server_rcache
+       
+       * lib/krb5/krb5_rcache.3: framework for replay cache manpage
+       
+       * lib/krb5/krb5_string_to_key.3: document string to key functions
+       
+       * lib/krb5/Makefile.am: man_MANS += krb5_expand_hostname.3
+       krb5_find_padata.3 krb5_generate_random_block.3
+
+       * lib/krb5/krb5_encrypt.3: document krb5_get_wrapped_length
+       
+       * lib/krb5/krb5.3: add some more, 137 to go
+       
+       * lib/krb5/krb5_principal.3: document krb5_get_default_principal
+       
+       * lib/krb5/krb5_keyblock.3: document krb5_generate_subkey
+       
+       * lib/krb5/krb5_generate_random_block.3: document
+       krb5_generate_random_block
+       
+       * lib/krb5/krb5_find_padata.3: document padata functions
+       
+       * lib/krb5/krb5.3: add some more, 142 to go
+       
+       * lib/krb5/krb5_creds.3: drop .Pp before .Sh
+       
+       * lib/krb5/krb5_set_default_realm.3: document krb5_copy_host_realm
+       
+       * lib/krb5/krb5_expand_hostname.3: document krb5_expand_hostname
+       and krb5_expand_hostname_realms
+
+       * lib/krb5/krb5.3: add more functions, 147 to go
+       
+       * lib/krb5/krb5_creds.3: document krb5_creds
+       
+       * lib/krb5/krb5_get_init_creds.3: add more functions, some more
+       text
+
+       * lib/krb5/krb5_ticket.3: document
+       krb5_ticket_get_authorization_data_type
+
+2004-03-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/aes-test.c: remove #if 0'ed code
+       
+       * lib/krb5/krb5.3: add keyblock functions, 177 functions to go
+       
+       * lib/krb5/krb5_verify_user.3: add krb5_verify_opt_set_ccache
+       
+       * lib/krb5/krb5_encrypt.3: document krb5_decrypt_ticket
+       
+       * lib/krb5/krb5_config.3: document krb5_config_free_strings and
+       krb5_config_file_free
+
+       * lib/krb5/krb5_create_checksum.3: add krb5_hmac
+       
+       * lib/krb5/krb5.3: add keyblock functions, 190 functions to go
+
+       * lib/krb5/krb5_keyblock.3: update .Dd
+       
+       * lib/krb5/krb5_keyblock.3: document krb5_copy_keyblock and
+       krb5_generate_random_keyblock
+
+       * lib/krb5/krb5_init_context.3: add krb5_init_ets
+       
+       * lib/krb5/krb5_config.3: add more krb5_config_ functions and
+       prototypes
+
+       * lib/krb5/krb5_init_context.3: document context modifcation
+       functions: address list, config file, use admin kdc, fcc version
+       
+       * lib/krb5/krb5_storage.3: document krb5_storage and related
+       functions
+
+       * lib/krb5/Makefile.am: add acl and krb524_convert_creds_kdc
+       manpages and test_acl test program
+
+       * lib/krb5/krb5.3: add error string functions and sort
+       
+       * lib/krb5/krb5_warn.3: document krb5_abort and error string
+       functions
+
+       * lib/krb5/krb5.3: add missing functions, only 285 left to
+       document
+
+       * lib/krb5/krb5_crypto_init.3: remove various enctype related
+       function
+
+       * lib/krb5/krb5_encrypt.3: add various enctype related function
+       here
+
+       * lib/krb5/krb5_create_checksum.3: add krb5_cksumtype_valid
+       krb5_cksumtype_valid
+
+       * lib/krb5/crypto.c: real return values for
+       krb5_{enctype,cksumtype}_valid
+
+       * lib/krb5/krb5_create_checksum.3: add some functions and
+       descriptions
+
+       * lib/krb5/krb5_c_make_checksum.3: move out non krb5_c functions
+       
+       * lib/krb5/krb5_auth_context.3: document
+       krb5_auth_con_generatelocalsubkey
+
+       * lib/krb5/krb5_krbhst_init.3: document krb5_krbhst_init_flags
+       
+       * lib/krb5/krb5_keytab.3: document krb5_kt_default_modify_name
+       
+       * lib/krb5/krb5_init_context.3: document krb5_add_et_list
+       
+       * lib/krb5/krb524_convert_creds_kdc.3: document
+       krb524_convert_creds_kdc, krb524_convert_creds_kdc_ccache
+
+       * lib/krb5/krb5_acl_match_file.3: document krb5_acl_match_*
+       
+       * lib/krb5/test_acl.c: test for generic acl code
+
+       * lib/krb5/acl.c: plug memory leak on file matching, 
+       make it not fall over when no non matching acl,
+       make fnmatch matching useful by switching arguments
+       
+2004-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/config.c: add --builtin-hdb command
+       
+       * lib/hdb/hdb.c (hdb_list_builtin): return a list of builtin
+       backends
+
+       * doc/setup.texi: include Luke Howard of PADL.COM ldap hdb
+       documentation
+
+       * doc/win2k.texi: fix bugs in examples, add more restrictions, use
+       example.com as an example. From: Pavel Ferdan
+       <xferdan@informatics.muni.cz>
+
+2004-03-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * lib/krb5/krb5.conf.5: add a bunch of Li and document [kadmin]
+       password_lifetime; from Henry B. Hotz
+
+2004-03-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/mk_rep.c (krb5_mk_rep): if KRB5_AUTH_CONTEXT_USE_SUBKEY
+       is set send subkey
+       (generate if needed)
+
+       * lib/krb5/krb5.h: add KRB5_AUTH_CONTEXT_USE_SUBKEY
+       
+2004-03-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: clean up error handling, plug memory leaks,
+       and free memory in error path, assume realloc(NULL, ...) works,
+       factor out common code, indent
+
+2004-03-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/verify_krb5_conf.c: understand [password_quality]
+       spelling
+       
+       * kuser/kgetcred.1: document --canonicalize
+       
+       * kuser/kgetcred.c: add --canonicalize
+       
+2004-03-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/fcache.c (fcc_store_cred): NULL terminate
+       krb5_config_get_bool_default' arglist
+       
+2004-03-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/kerberos5.c: add missing req argument to pk_mk_pa_reply
+       
+       * kdc/pkinit.c (pk_mk_pa_reply): add hdb_entry
+       
+       * kdc/pkinit.c: pass client hdb_entry to pk_check_client
+       
+       * kdc/kdc_locl.h: pass client hdb_entry to pk_check_client
+       
+       * kuser/kinit.c: rename ca_dir to pkinit/x509_anchors since its
+       more like that language in RFC3280
+       
+       * lib/krb5/pkinit.c: rename ca_dir to pkinit/x509_anchors since
+       its more like that language in RFC3280
+       
+       * lib/krb5/krb5.conf.5: document
+       [libdefaults]fcc-mit-ticketflags=boolean
+
+       * lib/krb5/fcache.c (fcc_store_cred): use
+       [libdefaults]fcc-mit-ticketflags=boolean to decide what format to
+       write the fcc in. Default to mit version (aka heimdal 0.7)
+       
+       * lib/krb5/store.c: add _krb5_store_creds_heimdal_0_7 and
+       _krb5_store_creds_heimdal_pre_0_7 that store the creds in just
+       that format make krb5_store_creds default to mit format
+       
+       * lib/krb5/store.c (krb5_ret_creds): Runtime detect the what is
+       the higher bits of the bitfield
+       
+2004-03-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/store.c (krb5_store_creds): add disabled code that
+       store the ticket flags in reverse order
+       (bitswap32): new function
+
+       * lib/krb5/store.c (krb5_ret_creds): if the higher ticket flags
+       are set, its a mit cache, reverse the bits, bug pointed out by
+       Sergio Gelato <Sergio.Gelato@astro.su.se>
+
+2004-03-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/hdb-ldap.c: use macro for HDB * -> LDAP *
+       
+       * kuser/kinit.c: when running kinit with a subprocess, fetch new
+       tickets after half the tickets lifetime
+       
+       * lib/hdb/hdb.c: spelling
+       
+       * lib/hdb/hdb-ldap.c: Intergrate Heimdal's hdb-ldap and the Samba
+       password database.  From: Andrew Bartlett <abartlet@samba.org>
+
+       * kdc/config.c: add --disable-DES
+       
+       * kdc/kdc.8: document --detach and --disable-DES
+       
+       * kdc/kerberos5.c: check if enctype is disabled before using it
+       
+       * lib/krb5/crypto.c: add support for disabling checksum/encryption
+       types
+
+       * tools/kdc-log-analyze.pl: add more cases
+       
+       * kdc/connect.c: on strange tcp error; log local port number and
+       socket type
+       
+       * lib/asn1/der.h: fix prototype of encode_utf8string
+       
+       * lib/asn1/gen.c: catch CHOICE and generate dummy placeholder
+       
+       * lib/asn1/lex.l: added dummy parsing of CHOICE
+       
+       * lib/asn1/parse.y: added dummy parsing of CHOICE
+       
+       * lib/asn1/k5.asn1: drop SMTP_NAME
+       
+2004-03-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/hdb/Makefile.am: support building ldap backend as module
+       sort asn1 hdb files
+       
+       * lib/hdb/hdb.c: when building ldap as a shared module, don't
+       include it in the list
+
+       * configure.in: add --enable-hdb-openldap-module
+       
+       * lib/hdb/hdb-ldap.c: make ldap possible to build as a shared
+       module
+
+       * lib/hdb/mkey.c: add hdb_{,un}seal_key{,_mkey} from Andrew
+       Bartlett <abartlet@samba.org>
+
+       * lib/krb5/crypto.c (decrypt_internal_special): do not not modify
+       the original data test case from Ronnie Sahlberg
+       <ronnie_sahlberg@ozemail.com.au>
+
+2004-03-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/test_cc.c: more cc tests, mostly related to mcc
+       behavior
+
+       * lib/krb5/mcache.c (mcc_get_principal): also check for
+       primary_principal == NULL now that that isn't used as dead flag
+       
+       * lib/krb5/mcache.c: don't overload the primary_principal == NULL
+       as dead since that doesn't always work. Based on patch from
+       Jeffrey Hutzelman <jhutz@cmu.edu>, tweeked by me
+       
+2004-02-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: adapt to rename of oid_cmp to heim_oid_cmp
+       
+       * lib/krb5/pkinit.c: adapt to rename of oid_cmp to heim_oid_cmp
+       
+       * lib/hdb/db3.c: fix all db >= 4.1 cases
+       
+       * doc/setup.texi: add text about hostname to realm mapping using
+       DNS
+
+2004-02-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: update error codes
+       
+       * lib/krb5/krb5_err.et: prefix pkinit error codes with KRB5_
+
+       * lib/krb5/pkinit.c: update error codes
+       
+2004-02-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/pkinit.c: indent, use krb5_abortx() instead of abort()
+       
+       * lib/krb5/init_creds_pw.c (process_pa_data_to_key): spelling
+       
+       * lib/krb5/store.c: handle memory allocate errors
+
+       * lib/krb5/fcache.c (_krb5_xlock): handle that everything was ok,
+       and don't put an error in the error strings then
+       
+2004-02-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kdc/pkinit.c: s/heim_big_integer/heim_integer/
+       
+       * lib/krb5/pkinit.c: s/heim_big_integer/heim_integer/
+       
+       * kdc/pkinit.c: adapt to asn1 bignum code, use HEIM_PKINIT errors
+       
+       * lib/krb5/pkinit.c: adapt to asn1 bignum code, use HEIM_PKINIT
+       errors
+       
+       * lib/krb5/heim_err.et: add HEIM_PKINIT specific errors
+       
+2004-02-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * configure.in: rename AC_WFLAGS to rk_WFLAGS
+       
+       * acinclude.m4: use m4_define, over-quote string
+       
+2004-02-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/init_creds_pw.c (change_password): handle that
+       printf("%.*s", 0, (void*)NULL); doesn't work on solaris
+       
+2004-02-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kpasswd/kpasswd.c (change_password): handle that printf("%.*s",
+       0, (void*)NULL); doesn't work on solaris
+       
+       * lib/krb5/krb5.conf.5: don't use path's in first .Nm, it confuses
+       some locate.updatedb, use FILES section to describe where the file
+       is instead.
+
+2004-02-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/check-der.c: test for "der_length.c: Fix len_unsigned
+       for certain negative integers, it got the length wrong" , from
+       Panasas, Inc.
+
+       * lib/asn1/der_length.c: Fix len_unsigned for certain negative
+       integers, it got the length wrong, fix from Panasas, Inc.
+       
+       rename len_int and len_unsigned to _heim_\&
+       
+       * lib/asn1/der_locl.h: add _heim_len_unsigned, _heim_len_int
+       
+2004-02-06  Dave Love  <d.love@dl.ac.uk>
+
+       * configure.in: Check for sys/socket.h, net/if.h.  Modify term.h,
+       security/pam_appl.h tests.
+       
+2004-02-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/check-gen.c: test for: (length_type): TSequenceOf: add
+       up the size of all the elements, don't use just the size of the
+       last element.
+
+       * lib/krb5/aes-test.c: add "next iv" test for aes128, check
+       decryption case too
+
+       * lib/krb5/crypto.c (_krb5_aes_cts_encrypt): out iv is the iv of
+       the next to last block, fix decryption case too
+       
+       * lib/krb5/aes-test.c: add "next iv" test for aes128
+       
+       * lib/krb5/crypto.c (_krb5_aes_cts_encrypt): out iv is the iv of
+       the next to last block
+
+       * lib/krb5/mk_rep.c (krb5_mk_rep): abort on internal asn1 encode
+       error
+       
+       * lib/krb5/mk_rep.c (krb5_mk_rep): abort on internal asn1 encode
+       error
+
+       * lib/krb5/get_in_tkt.c (krb5_get_in_cred): abort on internal asn1
+       encode error
+
+       * lib/krb5/mk_priv.c (krb5_mk_priv): abort on internal asn1 encode
+       error
+
+       * lib/krb5/get_cred.c (make_pa_tgs_req): abort on internal asn1
+       encode error
+
+       * lib/krb5/build_auth.c (krb5_build_authenticator): abort on
+       internal asn1 encode error
+
+       * lib/krb5/build_ap_req.c (krb5_build_ap_req): abort on internal
+       asn1 encode error
+
+2004-01-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * doc/setup.texi: some text about order of [capaths] realms
+       
+2004-01-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/context.c: register WRFILE ops
+       
+       * lib/krb5/keytab_file.c: add krb5_wrfkt_ops/WRFILE (same as FILE)
+       
+       * lib/krb5/krb5.h: add krb5_wrfkt_ops
+       
+       * kpasswd/kpasswdd.c (change): use the right password when
+       changing the password
+
+2004-01-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/fcache.c (_krb5_xlock): catch EINVAL and assume that it
+       means that the filesystem doesn't support locking
+       
+       * lib/krb5/keytab.c: remove #if 0 out file locking code
+       
+2004-01-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/asn1/gen_length.c (length_type): TSequenceOf: add up the
+       size of all the elements, don't use just the size of the last
+       element.
+
+2004-01-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kuser/kinit.c (renew_validate): if renewable_flag and not time
+       specifed, use "1 month"
+
+2004-01-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/krb5_keyblock.3: add prototypes, describe
+       krb5_keyblock_zero
+
+2004-01-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * lib/krb5/get_for_creds.c (add_addrs): don't add same address
+       multiple times
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): try to
+       handle errors better for previous commit
+
+       * lib/krb5/get_for_creds.c (krb5_get_forwarded_creds): If tickets
+       are address-less, forward address-less tickets.
+       
+       * lib/krb5/get_cred.c: rename get_krbtgt to _krb5_get_krbtgt and
+       export it
+
diff --git a/src/kerberosV/src/Makefile.am b/src/kerberosV/src/Makefile.am
new file mode 100644 (file)
index 0000000..5123921
--- /dev/null
@@ -0,0 +1,14 @@
+# $KTH: Makefile.am,v 1.17 2005/02/03 08:18:22 lukeh Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+if KCM
+kcm_dir = kcm
+endif
+
+SUBDIRS        = include lib kuser kdc admin kadmin kpasswd $(kcm_dir) appl doc tools
+
+## ACLOCAL = @ACLOCAL@ -I cf
+ACLOCAL_AMFLAGS = -I cf
+
+EXTRA_DIST = Makefile.am.common krb5.conf
diff --git a/src/kerberosV/src/Makefile.am.common b/src/kerberosV/src/Makefile.am.common
new file mode 100644 (file)
index 0000000..eee211f
--- /dev/null
@@ -0,0 +1,4 @@
+# $KTH: Makefile.am.common,v 1.5 2002/05/19 18:35:37 joda Exp $
+
+include $(top_srcdir)/cf/Makefile.am.common
+
diff --git a/src/kerberosV/src/Makefile.in b/src/kerberosV/src/Makefile.in
new file mode 100644 (file)
index 0000000..e143423
--- /dev/null
@@ -0,0 +1,921 @@
+# Makefile.in generated by automake 1.8.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program 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.
+
+@SET_MAKE@
+
+# $KTH: Makefile.am,v 1.17 2005/02/03 08:18:22 lukeh Exp $
+
+# $KTH: Makefile.am.common,v 1.5 2002/05/19 18:35:37 joda Exp $
+
+# $KTH: Makefile.am.common,v 1.44 2005/05/29 14:43:42 lha Exp $
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = .
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(top_srcdir)/Makefile.am.common \
+       $(top_srcdir)/cf/Makefile.am.common $(top_srcdir)/configure \
+       ChangeLog NEWS TODO compile config.guess config.sub install-sh \
+       ltconfig ltmain.sh missing ylwrap
+subdir = .
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \
+       $(top_srcdir)/cf/auth-modules.m4 \
+       $(top_srcdir)/cf/broken-getaddrinfo.m4 \
+       $(top_srcdir)/cf/broken-getnameinfo.m4 \
+       $(top_srcdir)/cf/broken-glob.m4 \
+       $(top_srcdir)/cf/broken-realloc.m4 \
+       $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \
+       $(top_srcdir)/cf/broken2.m4 $(top_srcdir)/cf/c-attribute.m4 \
+       $(top_srcdir)/cf/capabilities.m4 \
+       $(top_srcdir)/cf/check-compile-et.m4 \
+       $(top_srcdir)/cf/check-getpwnam_r-posix.m4 \
+       $(top_srcdir)/cf/check-man.m4 \
+       $(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \
+       $(top_srcdir)/cf/check-type-extra.m4 \
+       $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/check-x.m4 \
+       $(top_srcdir)/cf/check-xau.m4 $(top_srcdir)/cf/crypto.m4 \
+       $(top_srcdir)/cf/db.m4 $(top_srcdir)/cf/destdirs.m4 \
+       $(top_srcdir)/cf/dlopen.m4 \
+       $(top_srcdir)/cf/find-func-no-libs.m4 \
+       $(top_srcdir)/cf/find-func-no-libs2.m4 \
+       $(top_srcdir)/cf/find-func.m4 \
+       $(top_srcdir)/cf/find-if-not-broken.m4 \
+       $(top_srcdir)/cf/have-struct-field.m4 \
+       $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/irix.m4 \
+       $(top_srcdir)/cf/krb-bigendian.m4 \
+       $(top_srcdir)/cf/krb-func-getlogin.m4 \
+       $(top_srcdir)/cf/krb-ipv6.m4 $(top_srcdir)/cf/krb-prog-ln-s.m4 \
+       $(top_srcdir)/cf/krb-readline.m4 \
+       $(top_srcdir)/cf/krb-struct-spwd.m4 \
+       $(top_srcdir)/cf/krb-struct-winsize.m4 \
+       $(top_srcdir)/cf/largefile.m4 $(top_srcdir)/cf/mips-abi.m4 \
+       $(top_srcdir)/cf/misc.m4 $(top_srcdir)/cf/need-proto.m4 \
+       $(top_srcdir)/cf/osfc2.m4 $(top_srcdir)/cf/otp.m4 \
+       $(top_srcdir)/cf/proto-compat.m4 $(top_srcdir)/cf/pthreads.m4 \
+       $(top_srcdir)/cf/retsigtype.m4 $(top_srcdir)/cf/roken-frag.m4 \
+       $(top_srcdir)/cf/sunos.m4 $(top_srcdir)/cf/telnet.m4 \
+       $(top_srcdir)/cf/test-package.m4 $(top_srcdir)/cf/wflags.m4 \
+       $(top_srcdir)/cf/win32.m4 $(top_srcdir)/cf/with-all.m4 \
+       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno configure.status.lineno
+mkinstalldirs = $(mkdir_p)
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_FILES =
+depcomp =
+am__depfiles_maybe =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-exec-recursive install-info-recursive \
+       install-recursive installcheck-recursive installdirs-recursive \
+       pdf-recursive ps-recursive uninstall-info-recursive \
+       uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = include lib kuser kdc admin kadmin kpasswd kcm appl doc \
+       tools
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d $(distdir) \
+    || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr $(distdir); }; }
+DIST_ARCHIVES = $(distdir).tar.gz
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AIX4_FALSE = @AIX4_FALSE@
+AIX4_TRUE = @AIX4_TRUE@
+AIX_DYNAMIC_AFS_FALSE = @AIX_DYNAMIC_AFS_FALSE@
+AIX_DYNAMIC_AFS_TRUE = @AIX_DYNAMIC_AFS_TRUE@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AIX_FALSE = @AIX_FALSE@
+AIX_TRUE = @AIX_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CATMAN_FALSE = @CATMAN_FALSE@
+CATMAN_TRUE = @CATMAN_TRUE@
+CC = @CC@
+CFLAGS = @CFLAGS@
+COMPILE_ET = @COMPILE_ET@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBLIB = @DBLIB@
+DCE_FALSE = @DCE_FALSE@
+DCE_TRUE = @DCE_TRUE@
+DEFS = @DEFS@
+DIR_com_err = @DIR_com_err@
+DIR_des = @DIR_des@
+DIR_roken = @DIR_roken@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_LIB45 = @EXTRA_LIB45@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GROFF = @GROFF@
+HAVE_DB1_FALSE = @HAVE_DB1_FALSE@
+HAVE_DB1_TRUE = @HAVE_DB1_TRUE@
+HAVE_DB3_FALSE = @HAVE_DB3_FALSE@
+HAVE_DB3_TRUE = @HAVE_DB3_TRUE@
+HAVE_DLOPEN_FALSE = @HAVE_DLOPEN_FALSE@
+HAVE_DLOPEN_TRUE = @HAVE_DLOPEN_TRUE@
+HAVE_NDBM_FALSE = @HAVE_NDBM_FALSE@
+HAVE_NDBM_TRUE = @HAVE_NDBM_TRUE@
+HAVE_OPENSSL_FALSE = @HAVE_OPENSSL_FALSE@
+HAVE_OPENSSL_TRUE = @HAVE_OPENSSL_TRUE@
+HAVE_X_FALSE = @HAVE_X_FALSE@
+HAVE_X_TRUE = @HAVE_X_TRUE@
+INCLUDES_roken = @INCLUDES_roken@
+INCLUDE_des = @INCLUDE_des@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+INCLUDE_krb4 = @INCLUDE_krb4@
+INCLUDE_openldap = @INCLUDE_openldap@
+INCLUDE_readline = @INCLUDE_readline@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IRIX_FALSE = @IRIX_FALSE@
+IRIX_TRUE = @IRIX_TRUE@
+KCM_FALSE = @KCM_FALSE@
+KCM_TRUE = @KCM_TRUE@
+KRB4_FALSE = @KRB4_FALSE@
+KRB4_TRUE = @KRB4_TRUE@
+KRB5_FALSE = @KRB5_FALSE@
+KRB5_TRUE = @KRB5_TRUE@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_NDBM = @LIB_NDBM@
+LIB_XauFileName = @LIB_XauFileName@
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_XauWriteAuth = @LIB_XauWriteAuth@
+LIB_bswap16 = @LIB_bswap16@
+LIB_bswap32 = @LIB_bswap32@
+LIB_com_err = @LIB_com_err@
+LIB_com_err_a = @LIB_com_err_a@
+LIB_com_err_so = @LIB_com_err_so@
+LIB_crypt = @LIB_crypt@
+LIB_db_create = @LIB_db_create@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_des = @LIB_des@
+LIB_des_a = @LIB_des_a@
+LIB_des_appl = @LIB_des_appl@
+LIB_des_so = @LIB_des_so@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_door_create = @LIB_door_create@
+LIB_el_init = @LIB_el_init@
+LIB_freeaddrinfo = @LIB_freeaddrinfo@
+LIB_gai_strerror = @LIB_gai_strerror@
+LIB_getaddrinfo = @LIB_getaddrinfo@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_gethostbyname2 = @LIB_gethostbyname2@
+LIB_getnameinfo = @LIB_getnameinfo@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_hesiod = @LIB_hesiod@
+LIB_hstrerror = @LIB_hstrerror@
+LIB_kdb = @LIB_kdb@
+LIB_krb4 = @LIB_krb4@
+LIB_krb_disable_debug = @LIB_krb_disable_debug@
+LIB_krb_enable_debug = @LIB_krb_enable_debug@
+LIB_krb_get_kdc_time_diff = @LIB_krb_get_kdc_time_diff@
+LIB_krb_get_our_ip_for_realm = @LIB_krb_get_our_ip_for_realm@
+LIB_krb_kdctimeofday = @LIB_krb_kdctimeofday@
+LIB_loadquery = @LIB_loadquery@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_openldap = @LIB_openldap@
+LIB_openpty = @LIB_openpty@
+LIB_otp = @LIB_otp@
+LIB_pidfile = @LIB_pidfile@
+LIB_readline = @LIB_readline@
+LIB_res_nsearch = @LIB_res_nsearch@
+LIB_res_search = @LIB_res_search@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@
+NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+OPENLDAP_MODULE_FALSE = @OPENLDAP_MODULE_FALSE@
+OPENLDAP_MODULE_TRUE = @OPENLDAP_MODULE_TRUE@
+OTP_FALSE = @OTP_FALSE@
+OTP_TRUE = @OTP_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+YACC = @YACC@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__leading_dot = @am__leading_dot@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+do_roken_rename_FALSE = @do_roken_rename_FALSE@
+do_roken_rename_TRUE = @do_roken_rename_TRUE@
+dpagaix_cflags = @dpagaix_cflags@
+dpagaix_ldadd = @dpagaix_ldadd@
+dpagaix_ldflags = @dpagaix_ldflags@
+el_compat_FALSE = @el_compat_FALSE@
+el_compat_TRUE = @el_compat_TRUE@
+exec_prefix = @exec_prefix@
+have_cgetent_FALSE = @have_cgetent_FALSE@
+have_cgetent_TRUE = @have_cgetent_TRUE@
+have_err_h_FALSE = @have_err_h_FALSE@
+have_err_h_TRUE = @have_err_h_TRUE@
+have_fnmatch_h_FALSE = @have_fnmatch_h_FALSE@
+have_fnmatch_h_TRUE = @have_fnmatch_h_TRUE@
+have_glob_h_FALSE = @have_glob_h_FALSE@
+have_glob_h_TRUE = @have_glob_h_TRUE@
+have_ifaddrs_h_FALSE = @have_ifaddrs_h_FALSE@
+have_ifaddrs_h_TRUE = @have_ifaddrs_h_TRUE@
+have_vis_h_FALSE = @have_vis_h_FALSE@
+have_vis_h_TRUE = @have_vis_h_TRUE@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+SUFFIXES = .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8
+AM_CPPFLAGS = -I$(top_builddir)/include $(INCLUDES_roken)
+@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME
+AM_CFLAGS = $(WFLAGS)
+CP = cp
+buildinclude = $(top_builddir)/include
+LIB_getattr = @LIB_getattr@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_setpcred = @LIB_setpcred@
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+NROFF_MAN = groff -mandoc -Tascii
+LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la \
+@KRB5_TRUE@    $(top_builddir)/lib/asn1/libasn1.la
+
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+@KRB5_TRUE@LIB_tsasl = $(top_builddir)/lib/tsasl/libtsasl.la
+@DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la
+@KCM_TRUE@kcm_dir = kcm
+SUBDIRS = include lib kuser kdc admin kadmin kpasswd $(kcm_dir) appl doc tools
+ACLOCAL_AMFLAGS = -I cf
+EXTRA_DIST = Makefile.am.common krb5.conf
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .c
+am--refresh:
+       @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --foreign  --ignore-deps'; \
+             cd $(srcdir) && $(AUTOMAKE) --foreign  --ignore-deps \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  --ignore-deps Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  --ignore-deps Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @set fnord $$MAKEFLAGS; amf=$$2; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+       @set fnord $$MAKEFLAGS; amf=$$2; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+          || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       if (etags --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+       else \
+         include_option=--include; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -f $$subdir/TAGS && \
+             tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$tags$$unique" \
+         || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+            $$tags $$unique
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       mkdir $(distdir)
+       $(mkdir_p) $(distdir)/cf
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || mkdir "$(distdir)/$$subdir" \
+           || exit 1; \
+           (cd $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="../$(top_distdir)" \
+               distdir="../$(distdir)/$$subdir" \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       $(MAKE) $(AM_MAKEFLAGS) \
+         top_distdir="$(top_distdir)" distdir="$(distdir)" \
+         dist-hook
+       -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r $(distdir)
+dist-gzip: distdir
+       $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+dist-bzip2: distdir
+       $(AMTAR) chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2
+       $(am__remove_distdir)
+
+dist-tarZ: distdir
+       $(AMTAR) chof - $(distdir) | compress -c >$(distdir).tar.Z
+       $(am__remove_distdir)
+
+dist-shar: distdir
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__remove_distdir)
+
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+dist dist-all: distdir
+       $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - ;;\
+       *.tar.bz2*) \
+         bunzip2 -c $(distdir).tar.bz2 | $(AMTAR) xf - ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(AMTAR) xf - ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/_build
+       mkdir $(distdir)/_inst
+       chmod a-w $(distdir)
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && cd $(distdir)/_build \
+         && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck
+       $(am__remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e '1{h;s/./=/g;p;x;}' -e '$${p;x;}'
+distuninstallcheck:
+       @cd $(distuninstallcheck_dir) \
+       && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-recursive
+all-am: Makefile all-local
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-libtool \
+       distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+
+install-exec-am:
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am all-local \
+       am--refresh check check-am check-local clean clean-generic \
+       clean-libtool clean-recursive ctags ctags-recursive dist \
+       dist-all dist-bzip2 dist-gzip dist-shar dist-tarZ dist-zip \
+       distcheck distclean distclean-generic distclean-libtool \
+       distclean-recursive distclean-tags distcleancheck distdir \
+       distuninstallcheck dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-exec \
+       install-exec-am install-info install-info-am install-man \
+       install-strip installcheck installcheck-am installdirs \
+       installdirs-am maintainer-clean maintainer-clean-generic \
+       maintainer-clean-recursive mostlyclean mostlyclean-generic \
+       mostlyclean-libtool mostlyclean-recursive pdf pdf-am ps ps-am \
+       tags tags-recursive uninstall uninstall-am uninstall-info-am
+
+
+install-suid-programs:
+       @foo='$(bin_SUIDS)'; \
+       for file in $$foo; do \
+       x=$(DESTDIR)$(bindir)/$$file; \
+       if chown 0:0 $$x && chmod u+s $$x; then :; else \
+       echo "*"; \
+       echo "* Failed to install $$x setuid root"; \
+       echo "*"; \
+       fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+       @foo='$(include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \
+       for f in $$foo; do \
+               f=`basename $$f`; \
+               if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+               else file="$$f"; fi; \
+               if cmp -s  $$file $(buildinclude)/$$f 2> /dev/null ; then \
+               : ; else \
+                       echo " $(CP) $$file $(buildinclude)/$$f"; \
+                       $(CP) $$file $(buildinclude)/$$f; \
+               fi ; \
+       done
+
+all-local: install-build-headers
+
+check-local::
+       @if test '$(CHECK_LOCAL)' = "no-check-local"; then \
+         foo=''; elif test '$(CHECK_LOCAL)'; then \
+         foo='$(CHECK_LOCAL)'; else \
+         foo='$(PROGRAMS)'; fi; \
+         if test "$$foo"; then \
+         failed=0; all=0; \
+         for i in $$foo; do \
+           all=`expr $$all + 1`; \
+           if ./$$i --version > /dev/null 2>&1; then \
+             echo "PASS: $$i"; \
+           else \
+             echo "FAIL: $$i"; \
+             failed=`expr $$failed + 1`; \
+           fi; \
+         done; \
+         if test "$$failed" -eq 0; then \
+           banner="All $$all tests passed"; \
+         else \
+           banner="$$failed of $$all tests failed"; \
+         fi; \
+         dashes=`echo "$$banner" | sed s/./=/g`; \
+         echo "$$dashes"; \
+         echo "$$banner"; \
+         echo "$$dashes"; \
+         test "$$failed" -eq 0; \
+       fi ; \
+       if test '$(CHECK_SYMBOLS)' != ""; then \
+         echo "$$dashes"; \
+         echo "Checking symbols"; \
+         sh $(top_srcdir)/cf/check-symbols.sh $(CHECK_SYMBOLS) || exit 1; \
+         echo "Passed"; \
+         echo "$$dashes"; \
+       fi
+
+.x.c:
+       @cmp -s $< $@ 2> /dev/null || cp $< $@
+#NROFF_MAN = nroff -man
+.1.cat1:
+       $(NROFF_MAN) $< > $@
+.3.cat3:
+       $(NROFF_MAN) $< > $@
+.5.cat5:
+       $(NROFF_MAN) $< > $@
+.8.cat8:
+       $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+       @foo='$(man1_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.1) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-cat3-mans:
+       @foo='$(man3_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.3) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-cat5-mans:
+       @foo='$(man5_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.5) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-cat8-mans:
+       @foo='$(man8_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.8) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat-mans:
+       $(SHELL) $(top_srcdir)/cf/install-catman.sh "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+
+install-data-hook: install-cat-mans
+
+.et.h:
+       $(COMPILE_ET) $<
+.et.c:
+       $(COMPILE_ET) $<
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/kerberosV/src/NEWS b/src/kerberosV/src/NEWS
new file mode 100644 (file)
index 0000000..3036a7d
--- /dev/null
@@ -0,0 +1,682 @@
+Changes in release 0.7.2
+
+* Fix security problem in rshd that enable an attacker to overwrite
+  and change ownership of any file that root could write.
+
+* Fix a DOS in telnetd. The attacker could force the server to crash
+  in a NULL de-reference before the user logged in, resulting in inetd
+  turning telnetd off because it forked too fast.
+
+* Make gss_acquire_cred(GSS_C_ACCEPT) check that the requested name
+  exists in the keytab before returning success. This allows servers
+  to check if its even possible to use GSSAPI.
+
+* Fix receiving end of token delegation for GSS-API. It still wrongly
+  uses subkey for sending for compatibility reasons, this will change
+  in 0.8.
+
+* telnetd, login and rshd are now more verbose in logging failed and
+  successful logins.
+
+* Bug fixes
+
+Changes in release 0.7.1
+
+* Bug fixes
+
+Changes in release 0.7
+
+ * Support for KCM, a process based credential cache
+
+ * Support CCAPI credential cache
+
+ * SPNEGO support
+
+ * AES (and the gssapi conterpart, CFX) support
+
+ * Adding new and improve old documentation
+
+ * Bug fixes
+
+Changes in release 0.6.5
+
+ * fix vulnerabilities in telnetd
+
+ * unbreak Kerberos 4 and kaserver
+
+Changes in release 0.6.4
+
+ * fix vulnerabilities in telnet
+
+ * rshd: encryption without a separate error socket should now work
+
+ * telnet now uses appdefaults for the encrypt and forward/forwardable
+   settings
+
+ * bug fixes
+
+Changes in release 0.6.3
+
+ * fix vulnerabilities in ftpd
+
+ * support for linux AFS /proc "syscalls"
+
+ * support for RFC3244 (Windows 2000 Kerberos Change/Set Password) in
+   kpasswdd
+
+ * fix possible KDC denial of service
+
+ * bug fixes
+
+Changes in release 0.6.2
+
+ * Fix possible buffer overrun in v4 kadmin (which now defaults to off)
+
+Changes in release 0.6.1
+
+ * Fixed ARCFOUR suppport
+
+ * Cross realm vulnerability
+
+ * kdc: fix denial of service attack
+
+ * kdc: stop clients from renewing tickets into the future
+
+ * bug fixes
+       
+Changes in release 0.6
+
+* The DES3 GSS-API mechanism has been changed to inter-operate with
+  other GSSAPI implementations. See man page for gssapi(3) how to turn
+  on generation of correct MIC messages. Next major release of heimdal 
+  will generate correct MIC by default.
+
+* More complete GSS-API support
+
+* Better AFS support: kdc (524) supports 2b; 524 in kdc and AFS
+  support in applications no longer requires Kerberos 4 libs
+
+* Kerberos 4 support in kdc defaults to turned off (includes ka and 524)
+
+* other bug fixes
+
+Changes in release 0.5.2
+
+ * kdc: add option for disabling v4 cross-realm (defaults to off)
+
+ * bug fixes
+
+Changes in release 0.5.1
+
+ * kadmind: fix remote exploit
+
+ * kadmind: add option to disable kerberos 4
+
+ * kdc: make sure kaserver token life is positive
+
+ * telnet: use the session key if there is no subkey
+
+ * fix EPSV parsing in ftp
+
+ * other bug fixes
+
+Changes in release 0.5
+
+ * add --detach option to kdc
+
+ * allow setting forward and forwardable option in telnet from
+   .telnetrc, with override from command line
+
+ * accept addresses with or without ports in krb5_rd_cred
+
+ * make it work with modern openssl
+
+ * use our own string2key function even with openssl (that handles weak
+   keys incorrectly)
+
+ * more system-specific requirements in login
+
+ * do not use getlogin() to determine root in su
+
+ * telnet: abort if telnetd does not support encryption
+
+ * update autoconf to 2.53
+
+ * update config.guess, config.sub
+
+ * other bug fixes
+
+Changes in release 0.4e
+
+ * improve libcrypto and database autoconf tests
+
+ * do not care about salting of server principals when serving v4 requests
+
+ * some improvements to gssapi library
+
+ * test for existing compile_et/libcom_err
+
+ * portability fixes
+
+ * bug fixes
+
+Changes in release 0.4d
+
+ * fix some problems when using libcrypto from openssl
+
+ * handle /dev/ptmx `unix98' ptys on Linux
+
+ * add some forgotten man pages
+
+ * rsh: clean-up and add man page
+
+ * fix -A and -a in builtin-ls in tpd
+
+ * fix building problem on Irix
+
+ * make `ktutil get' more efficient
+
+ * bug fixes
+
+Changes in release 0.4c
+
+ * fix buffer overrun in telnetd
+
+ * repair some of the v4 fallback code in kinit
+
+ * add more shared library dependencies
+
+ * simplify and fix hprop handling of v4 databases
+
+ * fix some building problems (osf's sia and osfc2 login)
+
+ * bug fixes
+
+Changes in release 0.4b
+
+ * update the shared library version numbers correctly
+
+Changes in release 0.4a
+
+ * corrected key used for checksum in mk_safe, unfortunately this
+   makes it backwards incompatible
+
+ * update to autoconf 2.50, libtool 1.4
+
+ * re-write dns/config lookups (krb5_krbhst API)
+
+ * make order of using subkeys consistent
+
+ * add man page links
+
+ * add more man pages
+
+ * remove rfc2052 support, now only rfc2782 is supported
+
+ * always build with kaserver protocol support in the KDC (assuming
+   KRB4 is enabled) and support for reading kaserver databases in
+   hprop
+
+Changes in release 0.3f
+
+ * change default keytab to ANY:FILE:/etc/krb5.keytab,krb4:/etc/srvtab,
+   the new keytab type that tries both of these in order (SRVTAB is
+   also an alias for krb4:)
+
+ * improve error reporting and error handling (error messages should
+   be more detailed and more useful)
+
+ * improve building with openssl
+
+ * add kadmin -K, rcp -F 
+
+ * fix two incorrect weak DES keys
+
+ * fix building of kaserver compat in KDC
+
+ * the API is closer to what MIT krb5 is using
+
+ * more compatible with windows 2000
+
+ * removed some memory leaks
+
+ * bug fixes
+
+Changes in release 0.3e
+
+ * rcp program included
+
+ * fix buffer overrun in ftpd
+
+ * handle omitted sequence numbers as zeroes to handle MIT krb5 that
+   cannot generate zero sequence numbers
+
+ * handle v4 /.k files better
+
+ * configure/portability fixes
+
+ * fixes in parsing of options to kadmin (sub-)commands
+
+ * handle errors in kadmin load better
+
+ * bug fixes
+
+Changes in release 0.3d
+
+ * add krb5-config
+
+ * fix a bug in 3des gss-api mechanism, making it compatible with the
+   specification and the MIT implementation
+
+ * make telnetd only allow a specific list of environment variables to
+   stop it from setting `sensitive' variables
+
+ * try to use an existing libdes
+
+ * lib/krb5, kdc: use correct usage type for ap-req messages.  This
+   should improve compatability with MIT krb5 when using 3DES
+   encryption types
+
+ * kdc: fix memory allocation problem
+
+ * update config.guess and config.sub
+
+ * lib/roken: more stuff implemented
+
+ * bug fixes and portability enhancements
+
+Changes in release 0.3c
+
+ * lib/krb5: memory caches now support the resolve operation
+
+ * appl/login: set PATH to some sane default
+
+ * kadmind: handle several realms
+
+ * bug fixes (including memory leaks)
+
+Changes in release 0.3b
+
+ * kdc: prefer default-salted keys on v5 requests
+
+ * kdc: lowercase hostnames in v4 mode
+
+ * hprop: handle more types of MIT salts
+
+ * lib/krb5: fix memory leak
+
+ * bug fixes
+
+Changes in release 0.3a:
+
+ * implement arcfour-hmac-md5 to interoperate with W2K
+
+ * modularise the handling of the master key, and allow for other
+   encryption types. This makes it easier to import a database from
+   some other source without having to re-encrypt all keys.
+
+ * allow for better control over which encryption types are created
+
+ * make kinit fallback to v4 if given a v4 KDC
+
+ * make klist work better with v4 and v5, and add some more MIT
+   compatibility options
+
+ * make the kdc listen on the krb524 (4444) port for compatibility
+   with MIT krb5 clients
+
+ * implement more DCE/DFS support, enabled with --enable-dce, see
+   lib/kdfs and appl/dceutils
+
+ * make the sequence numbers work correctly
+
+ * bug fixes
+
+Changes in release 0.2t:
+
+ * bug fixes
+
+Changes in release 0.2s:
+
+ * add OpenLDAP support in hdb
+
+ * login will get v4 tickets when it receives forwarded tickets
+
+ * xnlock supports both v5 and v4
+
+ * repair source routing for telnet
+
+ * fix building problems with krb4 (krb_mk_req)
+
+ * bug fixes
+
+Changes in release 0.2r:
+
+ * fix realloc memory corruption bug in kdc
+
+ * `add --key' and `cpw --key' in kadmin
+
+ * klist supports listing v4 tickets
+
+ * update config.guess and config.sub
+
+ * make v4 -> v5 principal name conversion more robust
+
+ * support for anonymous tickets
+
+ * new man-pages
+
+ * telnetd: do not negotiate KERBEROS5 authentication if there's no keytab.
+
+ * use and set expiration and not password expiration when dumping
+   to/from ka server databases / krb4 databases
+
+ * make the code happier with 64-bit time_t
+
+ * follow RFC2782 and by default do not look for non-underscore SRV names
+
+Changes in release 0.2q:
+
+ * bug fix in tcp-handling in kdc
+
+ * bug fix in expand_hostname
+
+Changes in release 0.2p:
+
+ * bug fix in `kadmin load/merge'
+
+ * bug fix in krb5_parse_address
+
+Changes in release 0.2o:
+
+ * gss_{import,export}_sec_context added to libgssapi
+
+ * new option --addresses to kdc (for listening on an explicit set of
+   addresses)
+
+ * bug fixes in the krb4 and kaserver emulation part of the kdc
+
+ * other bug fixes
+
+Changes in release 0.2n:
+
+ * more robust parsing of dump files in kadmin
+ * changed default timestamp format for log messages to extended ISO
+   8601 format (Y-M-DTH:M:S)
+ * changed md4/md5/sha1 APIes to be de-facto `standard'
+ * always make hostname into lower-case before creating principal
+ * small bits of more MIT-compatability
+ * bug fixes
+
+Changes in release 0.2m:
+
+ * handle glibc's getaddrinfo() that returns several ai_canonname
+
+ * new endian test
+
+ * man pages fixes
+
+Changes in release 0.2l:
+
+ * bug fixes
+
+Changes in release 0.2k:
+
+ * better IPv6 test
+
+ * make struct sockaddr_storage in roken work better on alphas
+
+ * some missing [hn]to[hn]s fixed.
+
+ * allow users to change their own passwords with kadmin (with initial
+   tickets)
+
+ * fix stupid bug in parsing KDC specification
+
+ * add `ktutil change' and `ktutil purge'
+
+Changes in release 0.2j:
+
+ * builds on Irix
+
+ * ftpd works in passive mode
+
+ * should build on cygwin
+
+ * work around broken IPv6-code on OpenBSD 2.6, also add configure
+   option --disable-ipv6
+
+Changes in release 0.2i:
+
+ * use getaddrinfo in the missing places.
+
+ * fix SRV lookup for admin server
+
+ * use get{addr,name}info everywhere.  and implement it in terms of
+   getipnodeby{name,addr} (which uses gethostbyname{,2} and
+   gethostbyaddr)
+
+Changes in release 0.2h:
+
+ * fix typo in kx (now compiles)
+
+Changes in release 0.2g:
+
+ * lots of bug fixes:
+   * push works
+   * repair appl/test programs
+   * sockaddr_storage works on solaris (alignment issues)
+   * works better with non-roken getaddrinfo
+   * rsh works
+   * some non standard C constructs removed
+
+Changes in release 0.2f:
+
+ * support SRV records for kpasswd
+ * look for both _kerberos and krb5-realm when doing host -> realm mapping
+
+Changes in release 0.2e:
+
+ * changed copyright notices to remove `advertising'-clause.
+ * get{addr,name}info added to roken and used in the other code
+   (this makes things work much better with hosts with both v4 and v6
+    addresses, among other things)
+ * do pre-auth for both password and key-based get_in_tkt
+ * support for having several databases
+ * new command `del_enctype' in kadmin
+ * strptime (and new strftime) add to roken
+ * more paranoia about finding libdb
+ * bug fixes
+
+Changes in release 0.2d:
+
+ * new configuration option [libdefaults]default_etypes_des
+ * internal ls in ftpd builds without KRB4
+ * kx/rsh/push/pop_debug tries v5 and v4 consistenly
+ * build bug fixes
+ * other bug fixes
+
+Changes in release 0.2c:
+
+ * bug fixes (see ChangeLog's for details)
+
+Changes in release 0.2b:
+
+ * bug fixes
+ * actually bump shared library versions
+
+Changes in release 0.2a:
+
+ * a new program verify_krb5_conf for checking your /etc/krb5.conf
+ * add 3DES keys when changing password
+ * support null keys in database
+ * support multiple local realms
+ * implement a keytab backend for AFS KeyFile's
+ * implement a keytab backend for v4 srvtabs
+ * implement `ktutil copy'
+ * support password quality control in v4 kadmind
+ * improvements in v4 compat kadmind
+ * handle the case of having the correct cred in the ccache but with
+   the wrong encryption type better
+ * v6-ify the remaining programs.
+ * internal ls in ftpd
+ * rename strcpy_truncate/strcat_truncate to strlcpy/strlcat
+ * add `ank --random-password' and `cpw --random-password' in kadmin
+ * some programs and documentation for trying to talk to a W2K KDC
+ * bug fixes
+
+Changes in release 0.1m:
+
+ * support for getting default from krb5.conf for kinit/kf/rsh/telnet.
+   From Miroslav Ruda <ruda@ics.muni.cz>
+ * v6-ify hprop and hpropd
+ * support numeric addresses in krb5_mk_req
+ * shadow support in login and su. From Miroslav Ruda <ruda@ics.muni.cz>
+ * make rsh/rshd IPv6-aware
+ * make the gssapi sample applications better at reporting errors
+ * lots of bug fixes
+ * handle systems with v6-aware libc and non-v6 kernels (like Linux
+   with glibc 2.1) better
+ * hide failure of ERPT in ftp
+ * lots of bug fixes
+
+Changes in release 0.1l:
+
+ * make ftp and ftpd IPv6-aware
+ * add inet_pton to roken
+ * more IPv6-awareness
+ * make mini_inetd v6 aware
+
+Changes in release 0.1k:
+
+ * bump shared libraries versions
+ * add roken version of inet_ntop
+ * merge more changes to rshd
+
+Changes in release 0.1j:
+
+ * restore back to the `old' 3DES code.  This was supposed to be done
+   in 0.1h and 0.1i but I did a CVS screw-up.
+ * make telnetd handle v6 connections
+
+Changes in release 0.1i:
+
+ * start using `struct sockaddr_storage' which simplifies the code
+   (with a fallback definition if it's not defined)
+ * bug fixes (including in hprop and kf)
+ * don't use mawk which seems to mishandle roken.awk
+ * get_addrs should be able to handle v6 addresses on Linux (with the
+   required patch to the Linux kernel -- ask within)
+ * rshd builds with shadow passwords
+
+Changes in release 0.1h:
+
+ * kf: new program for forwarding credentials
+ * portability fixes
+ * make forwarding credentials work with MIT code
+ * better conversion of ka database
+ * add etc/services.append
+ * correct `modified by' from kpasswdd
+ * lots of bug fixes
+
+Changes in release 0.1g:
+
+ * kgetcred: new program for explicitly obtaining tickets
+ * configure fixes
+ * krb5-aware kx
+ * bug fixes
+
+Changes in release 0.1f;
+
+ * experimental support for v4 kadmin protokoll in kadmind
+ * bug fixes
+
+Changes in release 0.1e:
+
+ * try to handle old DCE and MIT kdcs
+ * support for older versions of credential cache files and keytabs
+ * postdated tickets work
+ * support for password quality checks in kpasswdd
+ * new flag --enable-kaserver for kdc
+ * renew fixes
+ * prototype su program
+ * updated (some) manpages
+ * support for KDC resource records
+ * should build with --without-krb4
+ * bug fixes
+
+Changes in release 0.1d:
+
+ * Support building with DB2 (uses 1.85-compat API)
+ * Support krb5-realm.DOMAIN in DNS
+ * new `ktutil srvcreate'
+ * v4/kafs support in klist/kdestroy
+ * bug fixes
+
+Changes in release 0.1c:
+
+ * fix ASN.1 encoding of signed integers
+ * somewhat working `ktutil get'
+ * some documentation updates
+ * update to Autoconf 2.13 and Automake 1.4
+ * the usual bug fixes
+
+Changes in release 0.1b:
+
+ * some old -> new crypto conversion utils
+ * bug fixes
+
+Changes in release 0.1a:
+
+ * new crypto code
+ * more bug fixes
+ * make sure we ask for DES keys in gssapi
+ * support signed ints in ASN1
+ * IPv6-bug fixes
+
+Changes in release 0.0u:
+
+ * lots of bug fixes
+
+Changes in release 0.0t:
+
+ * more robust parsing of krb5.conf
+ * include net{read,write} in lib/roken
+ * bug fixes
+
+Changes in release 0.0s:
+
+ * kludges for parsing options to rsh
+ * more robust parsing of krb5.conf
+ * removed some arbitrary limits
+ * bug fixes
+
+Changes in release 0.0r:
+
+ * default options for some programs
+ * bug fixes
+
+Changes in release 0.0q:
+
+ * support for building shared libraries with libtool
+ * bug fixes
+
+Changes in release 0.0p:
+
+ * keytab moved to /etc/krb5.keytab
+ * avoid false detection of IPv6 on Linux
+ * Lots of more functionality in the gssapi-library
+ * hprop can now read ka-server databases
+ * bug fixes
+
+Changes in release 0.0o:
+
+ * FTP with GSSAPI support.
+ * Bug fixes.
+
+Changes in release 0.0n:
+
+ * Incremental database propagation.
+ * Somewhat improved kadmin ui; the stuff in admin is now removed.
+ * Some support for using enctypes instead of keytypes.
+ * Lots of other improvement and bug fixes, see ChangeLog for details.
diff --git a/src/kerberosV/src/README b/src/kerberosV/src/README
new file mode 100644 (file)
index 0000000..1b4e70c
--- /dev/null
@@ -0,0 +1,19 @@
+$KTH: README,v 1.1 2000/07/27 02:33:54 assar Exp $
+
+Heimdal is a Kerberos 5 implementation.
+
+Please see the manual in doc, by default installed in
+/usr/heimdal/info/heimdal.info for information on how to install.
+There are also briefer man pages for most of the commands.
+
+Bug reports and bugs are appreciated, see more under Bug reports in
+the manual on how we prefer them.
+
+For more information see the web-page at
+<http://www.pdc.kth.se/heimdal/> or the mailing lists:
+
+heimdal-announce@sics.se       low-volume announcement
+heimdal-discuss@sics.se                high-volume discussion
+
+send a mail to heimdal-announce-request@sics.se and
+heimdal-discuss-request@sics.se respectively to subscribe.
diff --git a/src/kerberosV/src/TODO b/src/kerberosV/src/TODO
new file mode 100644 (file)
index 0000000..174137d
--- /dev/null
@@ -0,0 +1,92 @@
+-*- indented-text -*-
+
+$KTH: TODO,v 1.70 2004/01/05 13:32:01 lha Exp $
+
+* configure
+
+handle readline hiding in readline/readline.h
+
+* appl
+
+** appl/popper
+
+Implement RFC1731 and 1734, pop over GSS-API
+
+* doc
+
+* kdc
+
+* kadmin
+
+make it happy with reading and parsing kdc.conf
+
+is in need of a major cleanup
+
+* kpasswdd
+
+figure out what's the deal with do_sequence and the MIT client
+
+* lib
+
+** lib/asn1
+
+prepend a prefix on all generated symbols
+
+implicit optional CONS types
+
+untag optional
+
+
+** lib/auth
+
+** lib/auth/sia
+
+PAM
+
+** lib/com_err
+
+write a man-page
+
+** lib/des
+
+make everything work with openssl and make prototypes compatible
+
+** lib/gssapi
+
+anonymous credentials not implemented
+
+gss_acquire_cred(GSS_C_BOTH) with a keytab only, gss_add_cred,
+gss_release_cred renders the output_cred_handle broken.
+
+cache delegation credentials to avoid hitting the kdc ?  require time
+stampless tickets, and was supported in the recv'ing end with 0.6.1.
+
+flag to look at ok-to-delegate even if GSS_C_DELEG_FLAG was set
+(limited to some target domains).
+
+** lib/hdb
+
+** lib/kadm5
+
+add policies?
+
+fix to use rpc?
+
+** lib/krb5
+
+iv for aes
+
+the replay cache is, in its current state, not very useful
+
+OTP?
+
+make checksum/encryption type configuration more realm-specific.
+
+crypto: allow scatter/gather creation of checksums
+
+verify_user: handle non-secure verification failing because of
+host->realm mapping
+
+config_file: do it in case-sensitive and/or insensitive
+
+** lib/roken
diff --git a/src/kerberosV/src/TODO-1.0 b/src/kerberosV/src/TODO-1.0
new file mode 100644 (file)
index 0000000..14c7cc4
--- /dev/null
@@ -0,0 +1,9 @@
+$KTH: TODO-1.0,v 1.4 2003/09/20 18:49:01 lha Exp $
+
+- sort out hprop:ing
+- figure out hostname case sensitive issues
+- verify_user: handle non-secure verification failing because of
+  host->realm mapping
+- PAM?
+- kadmin: make it happy with reading and parsing kdc.conf
+- handle readline hiding in readline/readline.h
diff --git a/src/kerberosV/src/TODO-shadow b/src/kerberosV/src/TODO-shadow
new file mode 100644 (file)
index 0000000..313438d
--- /dev/null
@@ -0,0 +1,6 @@
+-krb5_fwd_tgt_creds() is still broken
+-the 4 to 5 principal thing
+-gss_acquire_cred still doesn't allow an alternate keytab
+-and the db lib versus headers thing
+
+/afs/andrew.cmu.edu/usr/shadow/ka2heim.txt
diff --git a/src/kerberosV/src/acconfig.h b/src/kerberosV/src/acconfig.h
new file mode 100644 (file)
index 0000000..9dabe37
--- /dev/null
@@ -0,0 +1,96 @@
+@BOTTOM@
+
+#undef BINDIR 
+#undef LIBDIR
+#undef LIBEXECDIR
+#undef SBINDIR
+
+#undef HAVE_INT8_T
+#undef HAVE_INT16_T
+#undef HAVE_INT32_T
+#undef HAVE_INT64_T
+#undef HAVE_U_INT8_T
+#undef HAVE_U_INT16_T
+#undef HAVE_U_INT32_T
+#undef HAVE_U_INT64_T
+#undef HAVE_UINT8_T
+#undef HAVE_UINT16_T
+#undef HAVE_UINT32_T
+#undef HAVE_UINT64_T
+
+#if defined(HAVE_FOUR_VALUED_KRB_PUT_INT) || !defined(KRB4)
+#define KRB_PUT_INT(F, T, L, S) krb_put_int((F), (T), (L), (S))
+#else
+#define KRB_PUT_INT(F, T, L, S) krb_put_int((F), (T), (S))
+#endif
+
+#ifdef BROKEN_REALLOC
+#define realloc(X, Y) isoc_realloc((X), (Y))
+#define isoc_realloc(X, Y) ((X) ? realloc((X), (Y)) : malloc(Y))
+#endif
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (const char *)rcsid, "\100(#)" msg }
+
+#undef PROTOTYPES
+
+/* Maximum values on all known systems */
+#define MaxHostNameLen (64+4)
+#define MaxPathLen (1024+4)
+
+#if defined(HAVE_SGTTY_H) && defined(__NeXT__)
+#define SGTTY
+#endif
+
+/* telnet stuff ----------------------------------------------- */
+
+#if defined(ENCRYPTION) && !defined(AUTHENTICATION)
+#define AUTHENTICATION 1
+#endif
+
+/* Set this to the default system lead string for telnetd 
+ * can contain %-escapes: %s=sysname, %m=machine, %r=os-release
+ * %v=os-version, %t=tty, %h=hostname, %d=date and time
+ */
+#undef USE_IM
+
+/* Used with login -p */
+#undef LOGIN_ARGS
+
+/* set this to a sensible login */
+#ifndef LOGIN_PATH
+#define LOGIN_PATH BINDIR "/login"
+#endif
+
+/* random defines */
+
+/*
+ * Defining this enables lots of useful (and used) extensions on
+ * glibc-based systems such as Linux
+ */
+
+#define _GNU_SOURCE
+
+/*
+ * this assumes that KRB_C_BIGENDIAN is used.
+ * if we can find out endianess at compile-time, do so,
+ * otherwise WORDS_BIGENDIAN should already have been defined
+ */
+
+#if ENDIANESS_IN_SYS_PARAM_H
+#  include <sys/types.h>
+#  include <sys/param.h>
+#  if BYTE_ORDER == BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+#  endif
+#endif
+
+#ifdef ROKEN_RENAME
+#include "roken_rename.h"
+#endif
diff --git a/src/kerberosV/src/acinclude.m4 b/src/kerberosV/src/acinclude.m4
new file mode 100644 (file)
index 0000000..50067fc
--- /dev/null
@@ -0,0 +1,9 @@
+dnl $KTH: acinclude.m4,v 1.16 2004/02/12 14:19:16 lha Exp $
+dnl
+dnl Only put things that for some reason can't live in the `cf'
+dnl directory in this file.
+dnl
+
+dnl $xId: misc.m4,v 1.1 1997/12/14 15:59:04 joda Exp $
+dnl
+m4_define([upcase],`echo $1 | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ`)dnl
diff --git a/src/kerberosV/src/aclocal.m4 b/src/kerberosV/src/aclocal.m4
new file mode 100644 (file)
index 0000000..f82cf3b
--- /dev/null
@@ -0,0 +1,6628 @@
+# generated automatically by aclocal 1.8.3 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+# Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program 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.
+
+# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*-
+
+# serial 47 AC_PROG_LIBTOOL
+
+
+# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED)
+# -----------------------------------------------------------
+# If this macro is not defined by Autoconf, define it here.
+m4_ifdef([AC_PROVIDE_IFELSE],
+         [],
+         [m4_define([AC_PROVIDE_IFELSE],
+                [m4_ifdef([AC_PROVIDE_$1],
+                          [$2], [$3])])])
+
+
+# AC_PROG_LIBTOOL
+# ---------------
+AC_DEFUN([AC_PROG_LIBTOOL],
+[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl
+dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX
+dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX.
+  AC_PROVIDE_IFELSE([AC_PROG_CXX],
+    [AC_LIBTOOL_CXX],
+    [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX
+  ])])
+dnl And a similar setup for Fortran 77 support
+  AC_PROVIDE_IFELSE([AC_PROG_F77],
+    [AC_LIBTOOL_F77],
+    [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77
+])])
+
+dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly.
+dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run
+dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both.
+  AC_PROVIDE_IFELSE([AC_PROG_GCJ],
+    [AC_LIBTOOL_GCJ],
+    [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],
+      [AC_LIBTOOL_GCJ],
+      [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],
+       [AC_LIBTOOL_GCJ],
+      [ifdef([AC_PROG_GCJ],
+            [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([A][M_PROG_GCJ],
+            [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])])
+       ifdef([LT_AC_PROG_GCJ],
+            [define([LT_AC_PROG_GCJ],
+               defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])])
+])])# AC_PROG_LIBTOOL
+
+
+# _AC_PROG_LIBTOOL
+# ----------------
+AC_DEFUN([_AC_PROG_LIBTOOL],
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl
+AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Prevent multiple expansion
+define([AC_PROG_LIBTOOL], [])
+])# _AC_PROG_LIBTOOL
+
+
+# AC_LIBTOOL_SETUP
+# ----------------
+AC_DEFUN([AC_LIBTOOL_SETUP],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+
+AC_REQUIRE([AC_PROG_LN_S])dnl
+AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl
+# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers!
+AC_REQUIRE([AC_OBJEXT])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+dnl
+
+AC_LIBTOOL_SYS_MAX_CMD_LEN
+AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+AC_LIBTOOL_OBJDIR
+
+AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+_LT_AC_PROG_ECHO_BACKSLASH
+
+case $host_os in
+aix3*)
+  # AIX sometimes has problems with the GCC collect2 program.  For some
+  # reason, if we set the COLLECT_NAMES environment variable, the problems
+  # vanish in a puff of smoke.
+  if test "X${COLLECT_NAMES+set}" != Xset; then
+    COLLECT_NAMES=
+    export COLLECT_NAMES
+  fi
+  ;;
+esac
+
+# Sed substitution that helps us do robust quoting.  It backslashifies
+# metacharacters that are still active within double-quoted strings.
+Xsed='sed -e s/^X//'
+[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g']
+
+# Same as above, but do not quote variable references.
+[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g']
+
+# Sed substitution to delay expansion of an escaped shell variable in a
+# double_quote_subst'ed string.
+delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g'
+
+# Sed substitution to avoid accidental globbing in evaled expressions
+no_glob_subst='s/\*/\\\*/g'
+
+# Constants:
+rm="rm -f"
+
+# Global variables:
+default_ofile=libtool
+can_build_shared=yes
+
+# All known linkers require a `.a' archive for static linking (except M$VC,
+# which needs '.lib').
+libext=a
+ltmain="$ac_aux_dir/ltmain.sh"
+ofile="$default_ofile"
+with_gnu_ld="$lt_cv_prog_gnu_ld"
+
+AC_CHECK_TOOL(AR, ar, false)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(STRIP, strip, :)
+
+old_CC="$CC"
+old_CFLAGS="$CFLAGS"
+
+# Set sane defaults for various variables
+test -z "$AR" && AR=ar
+test -z "$AR_FLAGS" && AR_FLAGS=cru
+test -z "$AS" && AS=as
+test -z "$CC" && CC=cc
+test -z "$LTCC" && LTCC=$CC
+test -z "$DLLTOOL" && DLLTOOL=dlltool
+test -z "$LD" && LD=ld
+test -z "$LN_S" && LN_S="ln -s"
+test -z "$MAGIC_CMD" && MAGIC_CMD=file
+test -z "$NM" && NM=nm
+test -z "$SED" && SED=sed
+test -z "$OBJDUMP" && OBJDUMP=objdump
+test -z "$RANLIB" && RANLIB=:
+test -z "$STRIP" && STRIP=:
+test -z "$ac_objext" && ac_objext=o
+
+# Determine commands to create old-style static archives.
+old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs'
+old_postinstall_cmds='chmod 644 $oldlib'
+old_postuninstall_cmds=
+
+if test -n "$RANLIB"; then
+  case $host_os in
+  openbsd*)
+    old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds"
+    ;;
+  *)
+    old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds"
+    ;;
+  esac
+  old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib"
+fi
+
+# Only perform the check for file, if the check method requires it
+case $deplibs_check_method in
+file_magic*)
+  if test "$file_magic_cmd" = '$MAGIC_CMD'; then
+    AC_PATH_MAGIC
+  fi
+  ;;
+esac
+
+AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no)
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+enable_win32_dll=yes, enable_win32_dll=no)
+
+AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+       [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+AC_ARG_WITH([pic],
+    [AC_HELP_STRING([--with-pic],
+       [try to use only PIC/non-PIC objects @<:@default=use both@:>@])],
+    [pic_mode="$withval"],
+    [pic_mode=default])
+test -z "$pic_mode" && pic_mode=default
+
+# Use C for the default configuration in the libtool script
+tagname=
+AC_LIBTOOL_LANG_C_CONFIG
+_LT_AC_TAGCONFIG
+])# AC_LIBTOOL_SETUP
+
+
+# _LT_AC_SYS_COMPILER
+# -------------------
+AC_DEFUN([_LT_AC_SYS_COMPILER],
+[AC_REQUIRE([AC_PROG_CC])dnl
+
+# If no C compiler was specified, use CC.
+LTCC=${LTCC-"$CC"}
+
+# Allow CC to be a program name with arguments.
+compiler=$CC
+])# _LT_AC_SYS_COMPILER
+
+
+# _LT_AC_SYS_LIBPATH_AIX
+# ----------------------
+# Links a minimal program and checks the executable
+# for the system default hardcoded library path. In most cases,
+# this is /usr/lib:/lib, but when the MPI compilers are used
+# the location of the communication and MPI libs are included too.
+# If we don't find anything, use the default library path according
+# to the aix ld manual.
+AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX],
+[AC_LINK_IFELSE(AC_LANG_PROGRAM,[
+aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
+}'`
+# Check for a 64-bit object if we didn't find anything.
+if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0  *\(.*\)$/\1/; p; }
+}'`; fi],[])
+if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi
+])# _LT_AC_SYS_LIBPATH_AIX
+
+
+# _LT_AC_SHELL_INIT(ARG)
+# ----------------------
+AC_DEFUN([_LT_AC_SHELL_INIT],
+[ifdef([AC_DIVERSION_NOTICE],
+            [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)],
+        [AC_DIVERT_PUSH(NOTICE)])
+$1
+AC_DIVERT_POP
+])# _LT_AC_SHELL_INIT
+
+
+# _LT_AC_PROG_ECHO_BACKSLASH
+# --------------------------
+# Add some code to the start of the generated configure script which
+# will find an echo command which doesn't interpret backslashes.
+AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH],
+[_LT_AC_SHELL_INIT([
+# Check that we are running under the correct shell.
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+case X$ECHO in
+X*--fallback-echo)
+  # Remove one level of quotation (which was required for Make).
+  ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','`
+  ;;
+esac
+
+echo=${ECHO-echo}
+if test "X[$]1" = X--no-reexec; then
+  # Discard the --no-reexec flag, and continue.
+  shift
+elif test "X[$]1" = X--fallback-echo; then
+  # Avoid inline document here, it may be left over
+  :
+elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then
+  # Yippee, $echo works!
+  :
+else
+  # Restart under the correct shell.
+  exec $SHELL "[$]0" --no-reexec ${1+"[$]@"}
+fi
+
+if test "X[$]1" = X--fallback-echo; then
+  # used as fallback echo
+  shift
+  cat <<EOF
+[$]*
+EOF
+  exit 0
+fi
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+if test -z "$ECHO"; then
+if test "X${echo_test_string+set}" != Xset; then
+# find a string as large as possible, as long as the shell can cope with it
+  for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do
+    # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ...
+    if (echo_test_string="`eval $cmd`") 2>/dev/null &&
+       echo_test_string="`eval $cmd`" &&
+       (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null
+    then
+      break
+    fi
+  done
+fi
+
+if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+   echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+   test "X$echo_testing_string" = "X$echo_test_string"; then
+  :
+else
+  # The Solaris, AIX, and Digital Unix default echo programs unquote
+  # backslashes.  This makes it impossible to quote backslashes using
+  #   echo "$something" | sed 's/\\/\\\\/g'
+  #
+  # So, first we look for a working echo in the user's PATH.
+
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for dir in $PATH /usr/ucb; do
+    IFS="$lt_save_ifs"
+    if (test -f $dir/echo || test -f $dir/echo$ac_exeext) &&
+       test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      echo="$dir/echo"
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  if test "X$echo" = Xecho; then
+    # We didn't find a better echo, so look for alternatives.
+    if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' &&
+       echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` &&
+       test "X$echo_testing_string" = "X$echo_test_string"; then
+      # This shell has a builtin print -r that does the trick.
+      echo='print -r'
+    elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) &&
+        test "X$CONFIG_SHELL" != X/bin/ksh; then
+      # If we have ksh, try running configure again with it.
+      ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh}
+      export ORIGINAL_CONFIG_SHELL
+      CONFIG_SHELL=/bin/ksh
+      export CONFIG_SHELL
+      exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"}
+    else
+      # Try using printf.
+      echo='printf %s\n'
+      if test "X`($echo '\t') 2>/dev/null`" = 'X\t' &&
+        echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` &&
+        test "X$echo_testing_string" = "X$echo_test_string"; then
+       # Cool, printf works
+       :
+      elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL
+       export CONFIG_SHELL
+       SHELL="$CONFIG_SHELL"
+       export SHELL
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` &&
+          test "X$echo_testing_string" = 'X\t' &&
+          echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` &&
+          test "X$echo_testing_string" = "X$echo_test_string"; then
+       echo="$CONFIG_SHELL [$]0 --fallback-echo"
+      else
+       # maybe with a smaller string...
+       prev=:
+
+       for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do
+         if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null
+         then
+           break
+         fi
+         prev="$cmd"
+       done
+
+       if test "$prev" != 'sed 50q "[$]0"'; then
+         echo_test_string=`eval $prev`
+         export echo_test_string
+         exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"}
+       else
+         # Oops.  We lost completely, so just stick with echo.
+         echo=echo
+       fi
+      fi
+    fi
+  fi
+fi
+fi
+
+# Copy echo and quote the copy suitably for passing to libtool from
+# the Makefile, instead of quoting the original, which is used later.
+ECHO=$echo
+if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then
+   ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo"
+fi
+
+AC_SUBST(ECHO)
+])])# _LT_AC_PROG_ECHO_BACKSLASH
+
+
+# _LT_AC_LOCK
+# -----------
+AC_DEFUN([_LT_AC_LOCK],
+[AC_ARG_ENABLE([libtool-lock],
+    [AC_HELP_STRING([--disable-libtool-lock],
+       [avoid locking (might break parallel builds)])])
+test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case $host in
+ia64-*-hpux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *ELF-32*)
+      HPUX_IA64_MODE="32"
+      ;;
+    *ELF-64*)
+      HPUX_IA64_MODE="64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+   if test "$lt_cv_prog_gnu_ld" = yes; then
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -melf32bsmip"
+      ;;
+    *N32*)
+      LD="${LD-ld} -melf32bmipn32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -melf64bmip"
+      ;;
+    esac
+   else
+    case `/usr/bin/file conftest.$ac_objext` in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+   fi
+  fi
+  rm -rf conftest*
+  ;;
+
+x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*)
+  # Find out which ABI we are using.
+  echo 'int i;' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      case $host in
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_i386"
+          ;;
+        ppc64-*linux*|powerpc64-*linux*)
+          LD="${LD-ld} -m elf32ppclinux"
+          ;;
+        s390x-*linux*)
+          LD="${LD-ld} -m elf_s390"
+          ;;
+        sparc64-*linux*)
+          LD="${LD-ld} -m elf32_sparc"
+          ;;
+      esac
+      ;;
+    *64-bit*)
+      case $host in
+        x86_64-*linux*)
+          LD="${LD-ld} -m elf_x86_64"
+          ;;
+        ppc*-*linux*|powerpc*-*linux*)
+          LD="${LD-ld} -m elf64ppc"
+          ;;
+        s390*-*linux*)
+          LD="${LD-ld} -m elf64_s390"
+          ;;
+        sparc*-*linux*)
+          LD="${LD-ld} -m elf64_sparc"
+          ;;
+      esac
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_LANG_PUSH(C)
+     AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])
+     AC_LANG_POP])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw* | *-*-pw32*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+  ])
+esac
+
+need_locks="$enable_libtool_lock"
+
+])# _LT_AC_LOCK
+
+
+# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#              [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE])
+# ----------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION],
+[AC_REQUIRE([LT_AC_PROG_SED])
+AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+  ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4])
+   printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+   lt_compiler_flag="$3"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   # The option is referenced via a variable to avoid confusing sed.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>conftest.err)
+   ac_status=$?
+   cat conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s "$ac_outfile"; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test ! -s conftest.err; then
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$5], , :, [$5])
+else
+    ifelse([$6], , :, [$6])
+fi
+])# AC_LIBTOOL_COMPILER_OPTION
+
+
+# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS,
+#                          [ACTION-SUCCESS], [ACTION-FAILURE])
+# ------------------------------------------------------------
+# Check whether the given compiler option works
+AC_DEFUN([AC_LIBTOOL_LINKER_OPTION],
+[AC_CACHE_CHECK([$1], [$2],
+  [$2=no
+   save_LDFLAGS="$LDFLAGS"
+   LDFLAGS="$LDFLAGS $3"
+   printf "$lt_simple_link_test_code" > conftest.$ac_ext
+   if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test -s conftest.err; then
+       # Append any errors to the config.log.
+       cat conftest.err 1>&AS_MESSAGE_LOG_FD
+     else
+       $2=yes
+     fi
+   fi
+   $rm conftest*
+   LDFLAGS="$save_LDFLAGS"
+])
+
+if test x"[$]$2" = xyes; then
+    ifelse([$4], , :, [$4])
+else
+    ifelse([$5], , :, [$5])
+fi
+])# AC_LIBTOOL_LINKER_OPTION
+
+
+# AC_LIBTOOL_SYS_MAX_CMD_LEN
+# --------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN],
+[# find the maximum length of command line arguments
+AC_MSG_CHECKING([the maximum length of command line arguments])
+AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl
+  i=0
+  testring="ABCD"
+
+  case $build_os in
+  msdosdjgpp*)
+    # On DJGPP, this test can blow up pretty badly due to problems in libc
+    # (any single argument exceeding 2000 bytes causes a buffer overrun
+    # during glob expansion).  Even if it were fixed, the result of this
+    # check would be larger than it should be.
+    lt_cv_sys_max_cmd_len=12288;    # 12K is about right
+    ;;
+
+  gnu*)
+    # Under GNU Hurd, this test is not required because there is
+    # no limit to the length of command line arguments.
+    # Libtool will interpret -1 as no limit whatsoever
+    lt_cv_sys_max_cmd_len=-1;
+    ;;
+
+  cygwin* | mingw*)
+    # On Win9x/ME, this test blows up -- it succeeds, but takes
+    # about 5 minutes as the teststring grows exponentially.
+    # Worse, since 9x/ME are not pre-emptively multitasking,
+    # you end up with a "frozen" computer, even though with patience
+    # the test eventually succeeds (with a max line length of 256k).
+    # Instead, let's just punt: use the minimum linelength reported by
+    # all of the supported platforms: 8192 (on NT/2K/XP).
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+  amigaos*)
+    # On AmigaOS with pdksh, this test takes hours, literally.
+    # So we just punt and use a minimum line length of 8192.
+    lt_cv_sys_max_cmd_len=8192;
+    ;;
+
+ *)
+    # If test is not a shell built-in, we'll probably end up computing a
+    # maximum length that is only half of the actual maximum length, but
+    # we can't tell.
+    while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \
+              = "XX$testring") >/dev/null 2>&1 &&
+           new_result=`expr "X$testring" : ".*" 2>&1` &&
+           lt_cv_sys_max_cmd_len=$new_result &&
+           test $i != 17 # 1/2 MB should be enough
+    do
+      i=`expr $i + 1`
+      testring=$testring$testring
+    done
+    testring=
+    # Add a significant safety factor because C++ compilers can tack on massive
+    # amounts of additional arguments before passing them to the linker.
+    # It appears as though 1/2 is a usable value.
+    lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2`
+    ;;
+  esac
+])
+if test -n $lt_cv_sys_max_cmd_len ; then
+  AC_MSG_RESULT($lt_cv_sys_max_cmd_len)
+else
+  AC_MSG_RESULT(none)
+fi
+])# AC_LIBTOOL_SYS_MAX_CMD_LEN
+
+
+# _LT_AC_CHECK_DLFCN
+# --------------------
+AC_DEFUN([_LT_AC_CHECK_DLFCN],
+[AC_CHECK_HEADERS(dlfcn.h)dnl
+])# _LT_AC_CHECK_DLFCN
+
+
+# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE,
+#                           ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING)
+# ------------------------------------------------------------------
+AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "$cross_compiling" = yes; then :
+  [$4]
+else
+  lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
+  lt_status=$lt_dlunknown
+  cat > conftest.$ac_ext <<EOF
+[#line __oline__ "configure"
+#include "confdefs.h"
+
+#if HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef RTLD_GLOBAL
+#  define LT_DLGLOBAL          RTLD_GLOBAL
+#else
+#  ifdef DL_GLOBAL
+#    define LT_DLGLOBAL                DL_GLOBAL
+#  else
+#    define LT_DLGLOBAL                0
+#  endif
+#endif
+
+/* We may have to define LT_DLLAZY_OR_NOW in the command line if we
+   find out it does not work in some platform. */
+#ifndef LT_DLLAZY_OR_NOW
+#  ifdef RTLD_LAZY
+#    define LT_DLLAZY_OR_NOW           RTLD_LAZY
+#  else
+#    ifdef DL_LAZY
+#      define LT_DLLAZY_OR_NOW         DL_LAZY
+#    else
+#      ifdef RTLD_NOW
+#        define LT_DLLAZY_OR_NOW       RTLD_NOW
+#      else
+#        ifdef DL_NOW
+#          define LT_DLLAZY_OR_NOW     DL_NOW
+#        else
+#          define LT_DLLAZY_OR_NOW     0
+#        endif
+#      endif
+#    endif
+#  endif
+#endif
+
+#ifdef __cplusplus
+extern "C" void exit (int);
+#endif
+
+void fnord() { int i=42;}
+int main ()
+{
+  void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW);
+  int status = $lt_dlunknown;
+
+  if (self)
+    {
+      if (dlsym (self,"fnord"))       status = $lt_dlno_uscore;
+      else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore;
+      /* dlclose (self); */
+    }
+
+    exit (status);
+}]
+EOF
+  if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then
+    (./conftest; exit; ) 2>/dev/null
+    lt_status=$?
+    case x$lt_status in
+      x$lt_dlno_uscore) $1 ;;
+      x$lt_dlneed_uscore) $2 ;;
+      x$lt_unknown|x*) $3 ;;
+    esac
+  else :
+    # compilation failed
+    $3
+  fi
+fi
+rm -fr conftest*
+])# _LT_AC_TRY_DLOPEN_SELF
+
+
+# AC_LIBTOOL_DLOPEN_SELF
+# -------------------
+AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF],
+[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl
+if test "x$enable_dlopen" != xyes; then
+  enable_dlopen=unknown
+  enable_dlopen_self=unknown
+  enable_dlopen_self_static=unknown
+else
+  lt_cv_dlopen=no
+  lt_cv_dlopen_libs=
+
+  case $host_os in
+  beos*)
+    lt_cv_dlopen="load_add_on"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ;;
+
+  mingw* | pw32*)
+    lt_cv_dlopen="LoadLibrary"
+    lt_cv_dlopen_libs=
+   ;;
+
+  cygwin*)
+    lt_cv_dlopen="dlopen"
+    lt_cv_dlopen_libs=
+   ;;
+
+  darwin*)
+  # if libdl is installed we need to link against it
+    AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[
+    lt_cv_dlopen="dyld"
+    lt_cv_dlopen_libs=
+    lt_cv_dlopen_self=yes
+    ])
+   ;;
+
+  *)
+    AC_CHECK_FUNC([shl_load],
+         [lt_cv_dlopen="shl_load"],
+      [AC_CHECK_LIB([dld], [shl_load],
+           [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"],
+       [AC_CHECK_FUNC([dlopen],
+             [lt_cv_dlopen="dlopen"],
+         [AC_CHECK_LIB([dl], [dlopen],
+               [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],
+           [AC_CHECK_LIB([svld], [dlopen],
+                 [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"],
+             [AC_CHECK_LIB([dld], [dld_link],
+                   [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"])
+             ])
+           ])
+         ])
+       ])
+      ])
+    ;;
+  esac
+
+  if test "x$lt_cv_dlopen" != xno; then
+    enable_dlopen=yes
+  else
+    enable_dlopen=no
+  fi
+
+  case $lt_cv_dlopen in
+  dlopen)
+    save_CPPFLAGS="$CPPFLAGS"
+    test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H"
+
+    save_LDFLAGS="$LDFLAGS"
+    eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\"
+
+    save_LIBS="$LIBS"
+    LIBS="$lt_cv_dlopen_libs $LIBS"
+
+    AC_CACHE_CHECK([whether a program can dlopen itself],
+         lt_cv_dlopen_self, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes,
+           lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross)
+    ])
+
+    if test "x$lt_cv_dlopen_self" = xyes; then
+      LDFLAGS="$LDFLAGS $link_static_flag"
+      AC_CACHE_CHECK([whether a statically linked program can dlopen itself],
+         lt_cv_dlopen_self_static, [dnl
+         _LT_AC_TRY_DLOPEN_SELF(
+           lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes,
+           lt_cv_dlopen_self_static=no,  lt_cv_dlopen_self_static=cross)
+      ])
+    fi
+
+    CPPFLAGS="$save_CPPFLAGS"
+    LDFLAGS="$save_LDFLAGS"
+    LIBS="$save_LIBS"
+    ;;
+  esac
+
+  case $lt_cv_dlopen_self in
+  yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;;
+  *) enable_dlopen_self=unknown ;;
+  esac
+
+  case $lt_cv_dlopen_self_static in
+  yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;;
+  *) enable_dlopen_self_static=unknown ;;
+  esac
+fi
+])# AC_LIBTOOL_DLOPEN_SELF
+
+
+# AC_LIBTOOL_PROG_CC_C_O([TAGNAME])
+# ---------------------------------
+# Check to see if options -c and -o are simultaneously supported by compiler
+AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)],
+  [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no
+   $rm -r conftest 2>/dev/null
+   mkdir conftest
+   cd conftest
+   mkdir out
+   printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+   lt_compiler_flag="-o out/conftest2.$ac_objext"
+   # Insert the option either (1) after the last *FLAGS variable, or
+   # (2) before a word containing "conftest.", or (3) at the end.
+   # Note that $ac_compile itself does not contain backslashes and begins
+   # with a dollar sign (not a hyphen), so the echo should work correctly.
+   lt_compile=`echo "$ac_compile" | $SED \
+   -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
+   -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \
+   -e 's:$: $lt_compiler_flag:'`
+   (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD)
+   (eval "$lt_compile" 2>out/conftest.err)
+   ac_status=$?
+   cat out/conftest.err >&AS_MESSAGE_LOG_FD
+   echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
+   if (exit $ac_status) && test -s out/conftest2.$ac_objext
+   then
+     # The compiler can only warn and ignore the option if not recognized
+     # So say no if there are warnings
+     if test ! -s out/conftest.err; then
+       _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+     fi
+   fi
+   chmod u+w .
+   $rm conftest*
+   # SGI C++ compiler will create directory out/ii_files/ for
+   # template instantiation
+   test -d out/ii_files && $rm out/ii_files/* && rmdir out/ii_files
+   $rm out/* && rmdir out
+   cd ..
+   rmdir conftest
+   $rm conftest*
+])
+])# AC_LIBTOOL_PROG_CC_C_O
+
+
+# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME])
+# -----------------------------------------
+# Check to see if we can do hard links to lock some files if needed
+AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS],
+[AC_REQUIRE([_LT_AC_LOCK])dnl
+
+hard_links="nottested"
+if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then
+  # do not overwrite the value of need_locks provided by the user
+  AC_MSG_CHECKING([if we can lock with hard links])
+  hard_links=yes
+  $rm conftest*
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  touch conftest.a
+  ln conftest.a conftest.b 2>&5 || hard_links=no
+  ln conftest.a conftest.b 2>/dev/null && hard_links=no
+  AC_MSG_RESULT([$hard_links])
+  if test "$hard_links" = no; then
+    AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe])
+    need_locks=warn
+  fi
+else
+  need_locks=no
+fi
+])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS
+
+
+# AC_LIBTOOL_OBJDIR
+# -----------------
+AC_DEFUN([AC_LIBTOOL_OBJDIR],
+[AC_CACHE_CHECK([for objdir], [lt_cv_objdir],
+[rm -f .libs 2>/dev/null
+mkdir .libs 2>/dev/null
+if test -d .libs; then
+  lt_cv_objdir=.libs
+else
+  # MS-DOS does not allow filenames that begin with a dot.
+  lt_cv_objdir=_libs
+fi
+rmdir .libs 2>/dev/null])
+objdir=$lt_cv_objdir
+])# AC_LIBTOOL_OBJDIR
+
+
+# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME])
+# ----------------------------------------------
+# Check hardcoding attributes.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH],
+[AC_MSG_CHECKING([how to hardcode library paths into programs])
+_LT_AC_TAGVAR(hardcode_action, $1)=
+if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \
+   test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \
+   test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then
+
+  # We can hardcode non-existant directories.
+  if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no &&
+     # If the only mechanism to avoid hardcoding is shlibpath_var, we
+     # have to relink, otherwise we might link with an installed library
+     # when we should be linking with a yet-to-be-installed one
+     ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no &&
+     test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then
+    # Linking always hardcodes the temporary library directory.
+    _LT_AC_TAGVAR(hardcode_action, $1)=relink
+  else
+    # We can link without hardcoding, and we can hardcode nonexisting dirs.
+    _LT_AC_TAGVAR(hardcode_action, $1)=immediate
+  fi
+else
+  # We cannot hardcode anything, or else we can only hardcode existing
+  # directories.
+  _LT_AC_TAGVAR(hardcode_action, $1)=unsupported
+fi
+AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)])
+
+if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then
+  # Fast installation is not supported
+  enable_fast_install=no
+elif test "$shlibpath_overrides_runpath" = yes ||
+     test "$enable_shared" = no; then
+  # Fast installation is not necessary
+  enable_fast_install=needless
+fi
+])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH
+
+
+# AC_LIBTOOL_SYS_LIB_STRIP
+# ------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP],
+[striplib=
+old_striplib=
+AC_MSG_CHECKING([whether stripping libraries is possible])
+if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then
+  test -z "$old_striplib" && old_striplib="$STRIP --strip-debug"
+  test -z "$striplib" && striplib="$STRIP --strip-unneeded"
+  AC_MSG_RESULT([yes])
+else
+# FIXME - insert some real tests, host_os isn't really good enough
+  case $host_os in
+   darwin*)
+       if test -n "$STRIP" ; then
+         striplib="$STRIP -x"
+         AC_MSG_RESULT([yes])
+       else
+  AC_MSG_RESULT([no])
+fi
+       ;;
+   *)
+  AC_MSG_RESULT([no])
+    ;;
+  esac
+fi
+])# AC_LIBTOOL_SYS_LIB_STRIP
+
+
+# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+# -----------------------------
+# PORTME Fill in your ld.so characteristics
+AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER],
+[AC_MSG_CHECKING([dynamic linker characteristics])
+library_names_spec=
+libname_spec='lib$name'
+soname_spec=
+shrext=".so"
+postinstall_cmds=
+postuninstall_cmds=
+finish_cmds=
+finish_eval=
+shlibpath_var=
+shlibpath_overrides_runpath=unknown
+version_type=none
+dynamic_linker="$host_os ld.so"
+sys_lib_dlsearch_path_spec="/lib /usr/lib"
+if test "$GCC" = yes; then
+  sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+  if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then
+    # if the path contains ";" then we assume it to be the separator
+    # otherwise default to the standard path separator (i.e. ":") - it is
+    # assumed that no part of a normal pathname contains ";" but that should
+    # okay in the real world where ";" in dirpaths is itself problematic.
+    sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+  else
+    sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+  fi
+else
+  sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib"
+fi
+need_lib_prefix=unknown
+hardcode_into_libs=no
+
+# when you set need_version to no, make sure it does not cause -set_version
+# flags to be left without arguments
+need_version=unknown
+
+case $host_os in
+aix3*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a'
+  shlibpath_var=LIBPATH
+
+  # AIX 3 has no versioning support, so we append a major version to the name.
+  soname_spec='${libname}${release}${shared_ext}$major'
+  ;;
+
+aix4* | aix5*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  hardcode_into_libs=yes
+  if test "$host_cpu" = ia64; then
+    # AIX 5 supports IA64
+    library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}'
+    shlibpath_var=LD_LIBRARY_PATH
+  else
+    # With GCC up to 2.95.x, collect2 would create an import file
+    # for dependence libraries.  The import file would start with
+    # the line `#! .'.  This would cause the generated library to
+    # depend on `.', always an invalid library.  This was fixed in
+    # development snapshots of GCC prior to 3.0.
+    case $host_os in
+      aix4 | aix4.[[01]] | aix4.[[01]].*)
+      if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)'
+          echo ' yes '
+          echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then
+       :
+      else
+       can_build_shared=no
+      fi
+      ;;
+    esac
+    # AIX (on Power*) has no versioning support, so currently we can not hardcode correct
+    # soname into executable. Probably we can add versioning support to
+    # collect2, so additional links can be useful in future.
+    if test "$aix_use_runtimelinking" = yes; then
+      # If using run time linking (on AIX 4.2 or later) use lib<name>.so
+      # instead of lib<name>.a to let people know that these are not
+      # typical AIX shared libraries.
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    else
+      # We preserve .a as extension for shared libraries through AIX4.2
+      # and later when we are not doing run time linking.
+      library_names_spec='${libname}${release}.a $libname.a'
+      soname_spec='${libname}${release}${shared_ext}$major'
+    fi
+    shlibpath_var=LIBPATH
+  fi
+  ;;
+
+amigaos*)
+  library_names_spec='$libname.ixlibrary $libname.a'
+  # Create ${libname}_ixlibrary.a entries in /sys/libs.
+  finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done'
+  ;;
+
+beos*)
+  library_names_spec='${libname}${shared_ext}'
+  dynamic_linker="$host_os ld.so"
+  shlibpath_var=LIBRARY_PATH
+  ;;
+
+bsdi4*)
+  version_type=linux
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib"
+  sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib"
+  # the default ld.so.conf also contains /usr/contrib/lib and
+  # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow
+  # libtool to hard-code these into programs
+  ;;
+
+cygwin* | mingw* | pw32*)
+  version_type=windows
+  shrext=".dll"
+  need_version=no
+  need_lib_prefix=no
+
+  case $GCC,$host_os in
+  yes,cygwin* | yes,mingw* | yes,pw32*)
+    library_names_spec='$libname.dll.a'
+    # DLL is installed to $(libdir)/../bin by postinstall_cmds
+    postinstall_cmds='base_file=`basename \${file}`~
+      dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~
+      dldir=$destdir/`dirname \$dlpath`~
+      test -d \$dldir || mkdir -p \$dldir~
+      $install_prog $dir/$dlname \$dldir/$dlname'
+    postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~
+      dlpath=$dir/\$dldll~
+       $rm \$dlpath'
+    shlibpath_overrides_runpath=yes
+
+    case $host_os in
+    cygwin*)
+      # Cygwin DLLs use 'cyg' prefix rather than 'lib'
+      soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib"
+      ;;
+    mingw*)
+      # MinGW DLLs use traditional 'lib' prefix
+      soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}'
+      sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"`
+      if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then
+        # It is most probably a Windows format PATH printed by
+        # mingw gcc, but we are running on Cygwin. Gcc prints its search
+        # path with ; separators, and with drive letters. We can handle the
+        # drive letters (cygwin fileutils understands them), so leave them,
+        # especially as we might pass files found there to a mingw objdump,
+        # which wouldn't understand a cygwinified path. Ahh.
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'`
+      else
+        sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED  -e "s/$PATH_SEPARATOR/ /g"`
+      fi
+      ;;
+    pw32*)
+      # pw32 DLLs use 'pw' prefix rather than 'lib'
+      library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}'
+      ;;
+    esac
+    ;;
+
+  *)
+    library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib'
+    ;;
+  esac
+  dynamic_linker='Win32 ld.exe'
+  # FIXME: first we should search . and the directory the executable is in
+  shlibpath_var=PATH
+  ;;
+
+darwin* | rhapsody*)
+  dynamic_linker="$host_os dyld"
+  version_type=darwin
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext'
+  soname_spec='${libname}${release}${major}$shared_ext'
+  shlibpath_overrides_runpath=yes
+  shlibpath_var=DYLD_LIBRARY_PATH
+  shrext='$(test .$module = .yes && echo .so || echo .dylib)'
+  # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same.
+  if test "$GCC" = yes; then
+    sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"`
+  else
+    sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib'
+  fi
+  sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
+  ;;
+
+dgux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+freebsd1*)
+  dynamic_linker=no
+  ;;
+
+kfreebsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='GNU ld.so'
+  ;;
+
+freebsd*)
+  objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout`
+  version_type=freebsd-$objformat
+  case $version_type in
+    freebsd-elf*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}'
+      need_version=no
+      need_lib_prefix=no
+      ;;
+    freebsd-*)
+      library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix'
+      need_version=yes
+      ;;
+  esac
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_os in
+  freebsd2*)
+    shlibpath_overrides_runpath=yes
+    ;;
+  freebsd3.[01]* | freebsdelf3.[01]*)
+    shlibpath_overrides_runpath=yes
+    hardcode_into_libs=yes
+    ;;
+  *) # from 3.2 on
+    shlibpath_overrides_runpath=no
+    hardcode_into_libs=yes
+    ;;
+  esac
+  ;;
+
+gnu*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  hardcode_into_libs=yes
+  ;;
+
+hpux9* | hpux10* | hpux11*)
+  # Give a soname corresponding to the major version so that dld.sl refuses to
+  # link against other versions.
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  case "$host_cpu" in
+  ia64*)
+    shrext='.so'
+    hardcode_into_libs=yes
+    dynamic_linker="$host_os dld.so"
+    shlibpath_var=LD_LIBRARY_PATH
+    shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    if test "X$HPUX_IA64_MODE" = X32; then
+      sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib"
+    else
+      sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64"
+    fi
+    sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+    ;;
+   hppa*64*)
+     shrext='.sl'
+     hardcode_into_libs=yes
+     dynamic_linker="$host_os dld.sl"
+     shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH
+     shlibpath_overrides_runpath=yes # Unless +noenvvar is specified.
+     library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+     soname_spec='${libname}${release}${shared_ext}$major'
+     sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64"
+     sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec
+     ;;
+   *)
+    shrext='.sl'
+    dynamic_linker="$host_os dld.sl"
+    shlibpath_var=SHLIB_PATH
+    shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    ;;
+  esac
+  # HP-UX runs *really* slowly unless shared libraries are mode 555.
+  postinstall_cmds='chmod 555 $lib'
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $host_os in
+    nonstopux*) version_type=nonstopux ;;
+    *)
+       if test "$lt_cv_prog_gnu_ld" = yes; then
+               version_type=linux
+       else
+               version_type=irix
+       fi ;;
+  esac
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}'
+  case $host_os in
+  irix5* | nonstopux*)
+    libsuff= shlibsuff=
+    ;;
+  *)
+    case $LD in # libtool.m4 will add one of these switches to LD
+    *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ")
+      libsuff= shlibsuff= libmagic=32-bit;;
+    *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ")
+      libsuff=32 shlibsuff=N32 libmagic=N32;;
+    *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ")
+      libsuff=64 shlibsuff=64 libmagic=64-bit;;
+    *) libsuff= shlibsuff= libmagic=never-match;;
+    esac
+    ;;
+  esac
+  shlibpath_var=LD_LIBRARY${shlibsuff}_PATH
+  shlibpath_overrides_runpath=no
+  sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}"
+  sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}"
+  hardcode_into_libs=yes
+  ;;
+
+# No shared lib support for Linux oldld, aout, or coff.
+linux*oldld* | linux*aout* | linux*coff*)
+  dynamic_linker=no
+  ;;
+
+# This must be Linux ELF.
+linux*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  # This implies no fast_install, which is unacceptable.
+  # Some rework will be needed to allow for fast_install
+  # before this can be enabled.
+  hardcode_into_libs=yes
+
+  # Append ld.so.conf contents to the search path
+  if test -f /etc/ld.so.conf; then
+    ld_extra=`$SED -e 's/[:,\t]/ /g;s/=[^=]*$//;s/=[^= ]* / /g' /etc/ld.so.conf`
+    sys_lib_dlsearch_path_spec="/lib /usr/lib $ld_extra"
+  fi
+
+  # We used to test for /lib/ld.so.1 and disable shared libraries on
+  # powerpc, because MkLinux only supported shared libraries with the
+  # GNU dynamic linker.  Since this was broken with cross compilers,
+  # most powerpc-linux boxes support dynamic linking these days and
+  # people can always --disable-shared, the test was removed, and we
+  # assume the GNU/Linux dynamic linker is in use.
+  dynamic_linker='GNU/Linux ld.so'
+  ;;
+
+knetbsd*-gnu)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=no
+  hardcode_into_libs=yes
+  dynamic_linker='GNU ld.so'
+  ;;
+
+netbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=no
+  if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+    finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+    dynamic_linker='NetBSD (a.out) ld.so'
+  else
+    library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}'
+    soname_spec='${libname}${release}${shared_ext}$major'
+    dynamic_linker='NetBSD ld.elf_so'
+  fi
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  ;;
+
+newsos6)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+nto-qnx*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  ;;
+
+openbsd*)
+  version_type=sunos
+  need_lib_prefix=no
+  need_version=yes
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    case $host_os in
+      openbsd2.[[89]] | openbsd2.[[89]].*)
+       shlibpath_overrides_runpath=no
+       ;;
+      *)
+       shlibpath_overrides_runpath=yes
+       ;;
+      esac
+  else
+    shlibpath_overrides_runpath=yes
+  fi
+  ;;
+
+os2*)
+  libname_spec='$name'
+  shrext=".dll"
+  need_lib_prefix=no
+  library_names_spec='$libname${shared_ext} $libname.a'
+  dynamic_linker='OS/2 ld.exe'
+  shlibpath_var=LIBPATH
+  ;;
+
+osf3* | osf4* | osf5*)
+  version_type=osf
+  need_lib_prefix=no
+  need_version=no
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib"
+  sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec"
+  ;;
+
+sco3.2v5*)
+  version_type=osf
+  soname_spec='${libname}${release}${shared_ext}$major'
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+solaris*)
+  version_type=linux
+  need_lib_prefix=no
+  need_version=no
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  hardcode_into_libs=yes
+  # ldd complains unless libraries are executable
+  postinstall_cmds='chmod +x $lib'
+  ;;
+
+sunos4*)
+  version_type=sunos
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix'
+  finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir'
+  shlibpath_var=LD_LIBRARY_PATH
+  shlibpath_overrides_runpath=yes
+  if test "$with_gnu_ld" = yes; then
+    need_lib_prefix=no
+  fi
+  need_version=yes
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  case $host_vendor in
+    sni)
+      shlibpath_overrides_runpath=no
+      need_lib_prefix=no
+      export_dynamic_flag_spec='${wl}-Blargedynsym'
+      runpath_var=LD_RUN_PATH
+      ;;
+    siemens)
+      need_lib_prefix=no
+      ;;
+    motorola)
+      need_lib_prefix=no
+      need_version=no
+      shlibpath_overrides_runpath=no
+      sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib'
+      ;;
+  esac
+  ;;
+
+sysv4*MP*)
+  if test -d /usr/nec ;then
+    version_type=linux
+    library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}'
+    soname_spec='$libname${shared_ext}.$major'
+    shlibpath_var=LD_LIBRARY_PATH
+  fi
+  ;;
+
+uts4*)
+  version_type=linux
+  library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}'
+  soname_spec='${libname}${release}${shared_ext}$major'
+  shlibpath_var=LD_LIBRARY_PATH
+  ;;
+
+*)
+  dynamic_linker=no
+  ;;
+esac
+AC_MSG_RESULT([$dynamic_linker])
+test "$dynamic_linker" = no && can_build_shared=no
+])# AC_LIBTOOL_SYS_DYNAMIC_LINKER
+
+
+# _LT_AC_TAGCONFIG
+# ----------------
+AC_DEFUN([_LT_AC_TAGCONFIG],
+[AC_ARG_WITH([tags],
+    [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@],
+        [include additional configurations @<:@automatic@:>@])],
+    [tagnames="$withval"])
+
+if test -f "$ltmain" && test -n "$tagnames"; then
+  if test ! -f "${ofile}"; then
+    AC_MSG_WARN([output file `$ofile' does not exist])
+  fi
+
+  if test -z "$LTCC"; then
+    eval "`$SHELL ${ofile} --config | grep '^LTCC='`"
+    if test -z "$LTCC"; then
+      AC_MSG_WARN([output file `$ofile' does not look like a libtool script])
+    else
+      AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile'])
+    fi
+  fi
+
+  # Extract list of available tagged configurations in $ofile.
+  # Note that this assumes the entire list is on one line.
+  available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'`
+
+  lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+  for tagname in $tagnames; do
+    IFS="$lt_save_ifs"
+    # Check whether tagname contains only valid characters
+    case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in
+    "") ;;
+    *)  AC_MSG_ERROR([invalid tag name: $tagname])
+       ;;
+    esac
+
+    if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null
+    then
+      AC_MSG_ERROR([tag name \"$tagname\" already exists])
+    fi
+
+    # Update the list of available tags.
+    if test -n "$tagname"; then
+      echo appending configuration tag \"$tagname\" to $ofile
+
+      case $tagname in
+      CXX)
+       if test -n "$CXX" && test "X$CXX" != "Xno"; then
+         AC_LIBTOOL_LANG_CXX_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      F77)
+       if test -n "$F77" && test "X$F77" != "Xno"; then
+         AC_LIBTOOL_LANG_F77_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      GCJ)
+       if test -n "$GCJ" && test "X$GCJ" != "Xno"; then
+         AC_LIBTOOL_LANG_GCJ_CONFIG
+       else
+         tagname=""
+       fi
+       ;;
+
+      RC)
+       AC_LIBTOOL_LANG_RC_CONFIG
+       ;;
+
+      *)
+       AC_MSG_ERROR([Unsupported tag name: $tagname])
+       ;;
+      esac
+
+      # Append the new tag name to the list of available tags.
+      if test -n "$tagname" ; then
+      available_tags="$available_tags $tagname"
+    fi
+    fi
+  done
+  IFS="$lt_save_ifs"
+
+  # Now substitute the updated list of available tags.
+  if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then
+    mv "${ofile}T" "$ofile"
+    chmod +x "$ofile"
+  else
+    rm -f "${ofile}T"
+    AC_MSG_ERROR([unable to update list of available tagged configurations.])
+  fi
+fi
+])# _LT_AC_TAGCONFIG
+
+
+# AC_LIBTOOL_DLOPEN
+# -----------------
+# enable checks for dlopen support
+AC_DEFUN([AC_LIBTOOL_DLOPEN],
+ [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_DLOPEN
+
+
+# AC_LIBTOOL_WIN32_DLL
+# --------------------
+# declare package support for building win32 dll's
+AC_DEFUN([AC_LIBTOOL_WIN32_DLL],
+[AC_BEFORE([$0], [AC_LIBTOOL_SETUP])
+])# AC_LIBTOOL_WIN32_DLL
+
+
+# AC_ENABLE_SHARED([DEFAULT])
+# ---------------------------
+# implement the --enable-shared flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_SHARED],
+[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([shared],
+    [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@],
+       [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_shared=yes ;;
+    no) enable_shared=no ;;
+    *)
+      enable_shared=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_shared=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_shared=]AC_ENABLE_SHARED_DEFAULT)
+])# AC_ENABLE_SHARED
+
+
+# AC_DISABLE_SHARED
+# -----------------
+#- set the default shared flag to --disable-shared
+AC_DEFUN([AC_DISABLE_SHARED],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)
+])# AC_DISABLE_SHARED
+
+
+# AC_ENABLE_STATIC([DEFAULT])
+# ---------------------------
+# implement the --enable-static flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_STATIC],
+[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([static],
+    [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@],
+       [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_static=yes ;;
+    no) enable_static=no ;;
+    *)
+     enable_static=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_static=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_static=]AC_ENABLE_STATIC_DEFAULT)
+])# AC_ENABLE_STATIC
+
+
+# AC_DISABLE_STATIC
+# -----------------
+# set the default static flag to --disable-static
+AC_DEFUN([AC_DISABLE_STATIC],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)
+])# AC_DISABLE_STATIC
+
+
+# AC_ENABLE_FAST_INSTALL([DEFAULT])
+# ---------------------------------
+# implement the --enable-fast-install flag
+# DEFAULT is either `yes' or `no'.  If omitted, it defaults to `yes'.
+AC_DEFUN([AC_ENABLE_FAST_INSTALL],
+[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE([fast-install],
+    [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@],
+    [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])],
+    [p=${PACKAGE-default}
+    case $enableval in
+    yes) enable_fast_install=yes ;;
+    no) enable_fast_install=no ;;
+    *)
+      enable_fast_install=no
+      # Look at the argument we got.  We use all the common list separators.
+      lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR,"
+      for pkg in $enableval; do
+       IFS="$lt_save_ifs"
+       if test "X$pkg" = "X$p"; then
+         enable_fast_install=yes
+       fi
+      done
+      IFS="$lt_save_ifs"
+      ;;
+    esac],
+    [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT)
+])# AC_ENABLE_FAST_INSTALL
+
+
+# AC_DISABLE_FAST_INSTALL
+# -----------------------
+# set the default to --disable-fast-install
+AC_DEFUN([AC_DISABLE_FAST_INSTALL],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)
+])# AC_DISABLE_FAST_INSTALL
+
+
+# AC_LIBTOOL_PICMODE([MODE])
+# --------------------------
+# implement the --with-pic flag
+# MODE is either `yes' or `no'.  If omitted, it defaults to `both'.
+AC_DEFUN([AC_LIBTOOL_PICMODE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+pic_mode=ifelse($#,1,$1,default)
+])# AC_LIBTOOL_PICMODE
+
+
+# AC_PROG_EGREP
+# -------------
+# This is predefined starting with Autoconf 2.54, so this conditional
+# definition can be removed once we require Autoconf 2.54 or later.
+m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP],
+[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep],
+   [if echo a | (grep -E '(a|b)') >/dev/null 2>&1
+    then ac_cv_prog_egrep='grep -E'
+    else ac_cv_prog_egrep='egrep'
+    fi])
+ EGREP=$ac_cv_prog_egrep
+ AC_SUBST([EGREP])
+])])
+
+
+# AC_PATH_TOOL_PREFIX
+# -------------------
+# find a file program which can recognise shared library
+AC_DEFUN([AC_PATH_TOOL_PREFIX],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(lt_cv_path_MAGIC_CMD,
+[case $MAGIC_CMD in
+[[\\/*] |  ?:[\\/]*])
+  lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path.
+  ;;
+*)
+  lt_save_MAGIC_CMD="$MAGIC_CMD"
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+dnl $ac_dummy forces splitting on constant user-supplied paths.
+dnl POSIX.2 word splitting is done only on the output of word expansions,
+dnl not every word.  This closes a longstanding sh security hole.
+  ac_dummy="ifelse([$2], , $PATH, [$2])"
+  for ac_dir in $ac_dummy; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/$1; then
+      lt_cv_path_MAGIC_CMD="$ac_dir/$1"
+      if test -n "$file_magic_test_file"; then
+       case $deplibs_check_method in
+       "file_magic "*)
+         file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`"
+         MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+         if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null |
+           $EGREP "$file_magic_regex" > /dev/null; then
+           :
+         else
+           cat <<EOF 1>&2
+
+*** Warning: the command libtool uses to detect shared libraries,
+*** $file_magic_cmd, produces output that libtool cannot recognize.
+*** The result is that libtool may fail to recognize shared libraries
+*** as such.  This will affect the creation of libtool libraries that
+*** depend on shared libraries, but programs linked with such libtool
+*** libraries will work regardless of this problem.  Nevertheless, you
+*** may want to report the problem to your system manager and/or to
+*** bug-libtool@gnu.org
+
+EOF
+         fi ;;
+       esac
+      fi
+      break
+    fi
+  done
+  IFS="$lt_save_ifs"
+  MAGIC_CMD="$lt_save_MAGIC_CMD"
+  ;;
+esac])
+MAGIC_CMD="$lt_cv_path_MAGIC_CMD"
+if test -n "$MAGIC_CMD"; then
+  AC_MSG_RESULT($MAGIC_CMD)
+else
+  AC_MSG_RESULT(no)
+fi
+])# AC_PATH_TOOL_PREFIX
+
+
+# AC_PATH_MAGIC
+# -------------
+# find a file program which can recognise a shared library
+AC_DEFUN([AC_PATH_MAGIC],
+[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH)
+if test -z "$lt_cv_path_MAGIC_CMD"; then
+  if test -n "$ac_tool_prefix"; then
+    AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH)
+  else
+    MAGIC_CMD=:
+  fi
+fi
+])# AC_PATH_MAGIC
+
+
+# AC_PROG_LD
+# ----------
+# find the pathname to the GNU or non-GNU linker
+AC_DEFUN([AC_PROG_LD],
+[AC_ARG_WITH([gnu-ld],
+    [AC_HELP_STRING([--with-gnu-ld],
+       [assume the C compiler uses GNU ld @<:@default=no@:>@])],
+    [test "$withval" = no || with_gnu_ld=yes],
+    [with_gnu_ld=no])
+AC_REQUIRE([LT_AC_PROG_SED])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$GCC" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by $CC])
+  case $host in
+  *-*-mingw*)
+    # gcc leaves a trailing carriage return which upsets mingw
+    ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+  *)
+    ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+  esac
+  case $ac_prog in
+    # Accept absolute paths.
+    [[\\/]]* | ?:[[\\/]]*)
+      re_direlt='/[[^/]][[^/]]*/\.\./'
+      # Canonicalize the pathname of ld
+      ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+       ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(lt_cv_path_LD,
+[if test -z "$LD"; then
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      lt_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in
+      *GNU* | *'with BFD'*)
+       test "$with_gnu_ld" != no && break
+       ;;
+      *)
+       test "$with_gnu_ld" != yes && break
+       ;;
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+else
+  lt_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$lt_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_PROG_LD_GNU
+])# AC_PROG_LD
+
+
+# AC_PROG_LD_GNU
+# --------------
+AC_DEFUN([AC_PROG_LD_GNU],
+[AC_REQUIRE([AC_PROG_EGREP])dnl
+AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+  lt_cv_prog_gnu_ld=yes
+  ;;
+*)
+  lt_cv_prog_gnu_ld=no
+  ;;
+esac])
+with_gnu_ld=$lt_cv_prog_gnu_ld
+])# AC_PROG_LD_GNU
+
+
+# AC_PROG_LD_RELOAD_FLAG
+# ----------------------
+# find reload flag for linker
+#   -- PORTME Some linkers may need a different reload flag.
+AC_DEFUN([AC_PROG_LD_RELOAD_FLAG],
+[AC_CACHE_CHECK([for $LD option to reload object files],
+  lt_cv_ld_reload_flag,
+  [lt_cv_ld_reload_flag='-r'])
+reload_flag=$lt_cv_ld_reload_flag
+case $reload_flag in
+"" | " "*) ;;
+*) reload_flag=" $reload_flag" ;;
+esac
+reload_cmds='$LD$reload_flag -o $output$reload_objs'
+])# AC_PROG_LD_RELOAD_FLAG
+
+
+# AC_DEPLIBS_CHECK_METHOD
+# -----------------------
+# how to check for library dependencies
+#  -- PORTME fill in with the dynamic library characteristics
+AC_DEFUN([AC_DEPLIBS_CHECK_METHOD],
+[AC_CACHE_CHECK([how to recognise dependent libraries],
+lt_cv_deplibs_check_method,
+[lt_cv_file_magic_cmd='$MAGIC_CMD'
+lt_cv_file_magic_test_file=
+lt_cv_deplibs_check_method='unknown'
+# Need to set the preceding variable on all platforms that support
+# interlibrary dependencies.
+# 'none' -- dependencies not supported.
+# `unknown' -- same as none, but documents that we really don't know.
+# 'pass_all' -- all dependencies passed with no checks.
+# 'test_compile' -- check by making test program.
+# 'file_magic [[regex]]' -- check by looking for files in library path
+# which responds to the $file_magic_cmd with a given extended regex.
+# If you have `file' or equivalent on your system and you're not sure
+# whether `pass_all' will *always* work, you probably want this one.
+
+case $host_os in
+aix4* | aix5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+beos*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+bsdi4*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)'
+  lt_cv_file_magic_cmd='/usr/bin/file -L'
+  lt_cv_file_magic_test_file=/shlib/libc.so
+  ;;
+
+cygwin*)
+  # win32_libid is a shell function defined in ltmain.sh
+  lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL'
+  lt_cv_file_magic_cmd='win32_libid'
+  ;;
+
+mingw* | pw32*)
+  # Base MSYS/MinGW do not provide the 'file' command needed by
+  # win32_libid shell function, so use a weaker test based on 'objdump'.
+  lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?'
+  lt_cv_file_magic_cmd='$OBJDUMP -f'
+  ;;
+
+darwin* | rhapsody*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+freebsd* | kfreebsd*-gnu)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    case $host_cpu in
+    i*86 )
+      # Not sure whether the presence of OpenBSD here was a mistake.
+      # Let's accept both of them until this is cleared up.
+      lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library'
+      lt_cv_file_magic_cmd=/usr/bin/file
+      lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+      ;;
+    esac
+  else
+    lt_cv_deplibs_check_method=pass_all
+  fi
+  ;;
+
+gnu*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+hpux10.20* | hpux11*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  case "$host_cpu" in
+  ia64*)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64'
+    lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so
+    ;;
+  hppa*64*)
+    [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]']
+    lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl
+    ;;
+  *)
+    lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library'
+    lt_cv_file_magic_test_file=/usr/lib/libc.sl
+    ;;
+  esac
+  ;;
+
+irix5* | irix6* | nonstopux*)
+  case $LD in
+  *-32|*"-32 ") libmagic=32-bit;;
+  *-n32|*"-n32 ") libmagic=N32;;
+  *-64|*"-64 ") libmagic=64-bit;;
+  *) libmagic=never-match;;
+  esac
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+# This must be Linux ELF.
+linux*)
+  case $host_cpu in
+  alpha*|hppa*|i*86|ia64*|m68*|mips*|powerpc*|sparc*|s390*|sh*)
+    lt_cv_deplibs_check_method=pass_all ;;
+  *)
+    # glibc up to 2.1.1 does not perform some relocations on ARM
+    # this will be overridden with pass_all, but let us keep it just in case
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;;
+  esac
+  lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so`
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+netbsd*)
+  if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$'
+  else
+    lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$'
+  fi
+  ;;
+
+newos6*)
+  lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)'
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=/usr/lib/libnls.so
+  ;;
+
+nto-qnx*)
+  lt_cv_deplibs_check_method=unknown
+  ;;
+
+openbsd*)
+  lt_cv_file_magic_cmd=/usr/bin/file
+  lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*`
+  if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object'
+  else
+    lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library'
+  fi
+  ;;
+
+osf3* | osf4* | osf5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sco3.2v5*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+solaris*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+
+sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+  case $host_vendor in
+  motorola)
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]'
+    lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*`
+    ;;
+  ncr)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  sequent)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )'
+    ;;
+  sni)
+    lt_cv_file_magic_cmd='/bin/file'
+    lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib"
+    lt_cv_file_magic_test_file=/lib/libc.so
+    ;;
+  siemens)
+    lt_cv_deplibs_check_method=pass_all
+    ;;
+  esac
+  ;;
+
+sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*)
+  lt_cv_deplibs_check_method=pass_all
+  ;;
+esac
+])
+file_magic_cmd=$lt_cv_file_magic_cmd
+deplibs_check_method=$lt_cv_deplibs_check_method
+test -z "$deplibs_check_method" && deplibs_check_method=unknown
+])# AC_DEPLIBS_CHECK_METHOD
+
+
+# AC_PROG_NM
+# ----------
+# find the pathname to a BSD-compatible name lister
+AC_DEFUN([AC_PROG_NM],
+[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  lt_cv_path_NM="$NM"
+else
+  lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    IFS="$lt_save_ifs"
+    test -z "$ac_dir" && ac_dir=.
+    tmp_nm="$ac_dir/${ac_tool_prefix}nm"
+    if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      # Tru64's nm complains that /dev/null is an invalid object file
+      case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in
+      */dev/null* | *'Invalid file or object type'*)
+       lt_cv_path_NM="$tmp_nm -B"
+       break
+        ;;
+      *)
+       case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in
+       */dev/null*)
+         lt_cv_path_NM="$tmp_nm -p"
+         break
+         ;;
+       *)
+         lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but
+         continue # so that we can try to find one that supports BSD flags
+         ;;
+       esac
+      esac
+    fi
+  done
+  IFS="$lt_save_ifs"
+  test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm
+fi])
+NM="$lt_cv_path_NM"
+])# AC_PROG_NM
+
+
+# AC_CHECK_LIBM
+# -------------
+# check for math library
+AC_DEFUN([AC_CHECK_LIBM],
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case $host in
+*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*)
+  # These system don't have libm, or don't need it
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, cos, LIBM="-lm")
+  ;;
+esac
+])# AC_CHECK_LIBM
+
+
+# AC_LIBLTDL_CONVENIENCE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl convenience library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-convenience to the configure arguments.  Note that LIBLTDL
+# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
+# DIRECTORY is not provided, it is assumed to be `libltdl'.  LIBLTDL will
+# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with
+# '${top_srcdir}/' (note the single quotes!).  If your package is not
+# flat and you're not using automake, define top_builddir and
+# top_srcdir appropriately in the Makefiles.
+AC_DEFUN([AC_LIBLTDL_CONVENIENCE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case $enable_ltdl_convenience in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la
+  LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_CONVENIENCE
+
+
+# AC_LIBLTDL_INSTALLABLE([DIRECTORY])
+# -----------------------------------
+# sets LIBLTDL to the link flags for the libltdl installable library and
+# LTDLINCL to the include flags for the libltdl header and adds
+# --enable-ltdl-install to the configure arguments.  Note that LIBLTDL
+# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called.  If
+# DIRECTORY is not provided and an installed libltdl is not found, it is
+# assumed to be `libltdl'.  LIBLTDL will be prefixed with '${top_builddir}/'
+# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single
+# quotes!).  If your package is not flat and you're not using automake,
+# define top_builddir and top_srcdir appropriately in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN([AC_LIBLTDL_INSTALLABLE],
+[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, lt_dlinit,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la
+    LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    LTDLINCL=
+  fi
+  # For backwards non-gettext consistent compatibility...
+  INCLTDL="$LTDLINCL"
+])# AC_LIBLTDL_INSTALLABLE
+
+
+# AC_LIBTOOL_CXX
+# --------------
+# enable support for C++ libraries
+AC_DEFUN([AC_LIBTOOL_CXX],
+[AC_REQUIRE([_LT_AC_LANG_CXX])
+])# AC_LIBTOOL_CXX
+
+
+# _LT_AC_LANG_CXX
+# ---------------
+AC_DEFUN([_LT_AC_LANG_CXX],
+[AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([AC_PROG_CXXCPP])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}CXX])
+])# _LT_AC_LANG_CXX
+
+
+# AC_LIBTOOL_F77
+# --------------
+# enable support for Fortran 77 libraries
+AC_DEFUN([AC_LIBTOOL_F77],
+[AC_REQUIRE([_LT_AC_LANG_F77])
+])# AC_LIBTOOL_F77
+
+
+# _LT_AC_LANG_F77
+# ---------------
+AC_DEFUN([_LT_AC_LANG_F77],
+[AC_REQUIRE([AC_PROG_F77])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}F77])
+])# _LT_AC_LANG_F77
+
+
+# AC_LIBTOOL_GCJ
+# --------------
+# enable support for GCJ libraries
+AC_DEFUN([AC_LIBTOOL_GCJ],
+[AC_REQUIRE([_LT_AC_LANG_GCJ])
+])# AC_LIBTOOL_GCJ
+
+
+# _LT_AC_LANG_GCJ
+# ---------------
+AC_DEFUN([_LT_AC_LANG_GCJ],
+[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[],
+  [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[],
+    [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[],
+      [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])],
+        [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])],
+          [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}GCJ])
+])# _LT_AC_LANG_GCJ
+
+
+# AC_LIBTOOL_RC
+# --------------
+# enable support for Windows resource files
+AC_DEFUN([AC_LIBTOOL_RC],
+[AC_REQUIRE([LT_AC_PROG_RC])
+_LT_AC_SHELL_INIT([tagnames=${tagnames+${tagnames},}RC])
+])# AC_LIBTOOL_RC
+
+
+# AC_LIBTOOL_LANG_C_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG])
+AC_DEFUN([_LT_AC_LANG_C_CONFIG],
+[lt_save_CC="$CC"
+AC_LANG_PUSH(C)
+
+# Source file extension for C test sources.
+ac_ext=c
+
+# Object file extension for compiled C test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(){return(0);}\n'
+
+_LT_AC_SYS_COMPILER
+
+#
+# Check for any special shared library compilation flags.
+#
+_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)=
+if test "$GCC" = no; then
+  case $host_os in
+  sco3.2v5*)
+    _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf'
+    ;;
+  esac
+fi
+if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then
+  AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries])
+  if echo "$old_CC $old_CFLAGS " | grep "[[    ]]$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[        ]]" >/dev/null; then :
+  else
+    AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure])
+    _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no
+  fi
+fi
+
+
+#
+# Check to make sure the static flag actually works.
+#
+AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works],
+  _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1),
+  $_LT_AC_TAGVAR(lt_prog_compiler_static, $1),
+  [],
+  [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=])
+
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+# Report which librarie types wil actually be built
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+
+aix4*)
+  if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then
+    test "$enable_shared" = yes && enable_static=no
+  fi
+  ;;
+  darwin* | rhapsody*)
+  if test "$GCC" = yes; then
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    case "$host_os" in
+    rhapsody* | darwin1.[[012]])
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress'
+      ;;
+    *) # Darwin 1.3 on
+      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+      else
+        case ${MACOSX_DEPLOYMENT_TARGET} in
+          10.[[012]])
+            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+            ;;
+          10.*)
+            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup'
+            ;;
+        esac
+      fi
+      ;;
+    esac
+    output_verbose_link_cmd='echo'
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring'
+    _LT_AC_TAGVAR(module_cmds, $1)='$CC $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+    # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag  -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    _LT_AC_TAGVAR(hardcode_direct, $1)=no
+    _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+    _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+  else
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+  fi
+    ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_C_CONFIG
+
+
+# AC_LIBTOOL_LANG_CXX_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)])
+AC_DEFUN([_LT_AC_LANG_CXX_CONFIG],
+[AC_LANG_PUSH(C++)
+AC_REQUIRE([AC_PROG_CXX])
+AC_REQUIRE([AC_PROG_CXXCPP])
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Dependencies to place before and after the object being linked:
+_LT_AC_TAGVAR(predep_objects, $1)=
+_LT_AC_TAGVAR(postdep_objects, $1)=
+_LT_AC_TAGVAR(predeps, $1)=
+_LT_AC_TAGVAR(postdeps, $1)=
+_LT_AC_TAGVAR(compiler_lib_search_path, $1)=
+
+# Source file extension for C++ test sources.
+ac_ext=cc
+
+# Object file extension for compiled C++ test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="int some_variable = 0;\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC=$CC
+lt_save_LD=$LD
+lt_save_GCC=$GCC
+GCC=$GXX
+lt_save_with_gnu_ld=$with_gnu_ld
+lt_save_path_LD=$lt_cv_path_LD
+if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then
+  lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx
+else
+  unset lt_cv_prog_gnu_ld
+fi
+if test -n "${lt_cv_path_LDCXX+set}"; then
+  lt_cv_path_LD=$lt_cv_path_LDCXX
+else
+  unset lt_cv_path_LD
+fi
+test -z "${LDCXX+set}" || LD=$LDCXX
+CC=${CXX-"c++"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+# We don't want -fno-exception wen compiling C++ code, so set the
+# no_builtin_flag separately
+if test "$GXX" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+else
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+fi
+
+if test "$GXX" = yes; then
+  # Set up default GNU C++ configuration
+
+  AC_PROG_LD
+
+  # Check if GNU C++ uses GNU ld as the underlying linker, since the
+  # archiving commands below assume that GNU ld is being used.
+  if test "$with_gnu_ld" = yes; then
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to
+    #     investigate it a little bit more. (MM)
+    wlarc='${wl}'
+
+    # ancient GNU ld didn't support --whole-archive et. al.
+    if eval "`$CC -print-prog-name=ld` --help 2>&1" | \
+       grep 'no-whole-archive' > /dev/null; then
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+    else
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+    fi
+  else
+    with_gnu_ld=no
+    wlarc=
+
+    # A generic and very simple default shared library creation
+    # command for GNU C++ for the case where it uses the native
+    # linker, instead of GNU ld.  If possible, this setting should
+    # overridden to take advantage of the native linker features on
+    # the platform it is being used on.
+    _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib'
+  fi
+
+  # Commands to make compiler produce verbose output that lists
+  # what "hidden" libraries, object files and flags are used when
+  # linking a shared library.
+  output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+else
+  GXX=no
+  with_gnu_ld=no
+  wlarc=
+fi
+
+# PORTME: fill in a description of your system's C++ link characteristics
+AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+_LT_AC_TAGVAR(ld_shlibs, $1)=yes
+case $host_os in
+  aix3*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  aix4* | aix5*)
+    if test "$host_cpu" = ia64; then
+      # On IA64, the linker does run time linking by default, so we don't
+      # have to do anything special.
+      aix_use_runtimelinking=no
+      exp_sym_flag='-Bexport'
+      no_entry_flag=""
+    else
+      aix_use_runtimelinking=no
+
+      # Test if we are trying to use run time linking or normal
+      # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+      # need to do runtime linking.
+      case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+       for ld_flag in $LDFLAGS; do
+         case $ld_flag in
+         *-brtl*)
+           aix_use_runtimelinking=yes
+           break
+           ;;
+         esac
+       done
+      esac
+
+      exp_sym_flag='-bexport'
+      no_entry_flag='-bnoentry'
+    fi
+
+    # When large executables or shared objects are built, AIX ld can
+    # have problems creating the table of contents.  If linking a library
+    # or program results in "error TOC overflow" add -mminimal-toc to
+    # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+    # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+    _LT_AC_TAGVAR(archive_cmds, $1)=''
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+    if test "$GXX" = yes; then
+      case $host_os in aix4.[012]|aix4.[012].*)
+      # We only want to do this on AIX 4.2 and lower, the check
+      # below for broken collect2 doesn't work under 4.3+
+       collect2name=`${CC} -print-prog-name=collect2`
+       if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+       then
+         # We have reworked collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+       else
+         # We have old collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+       fi
+      esac
+      shared_flag='-shared'
+    else
+      # not using gcc
+      if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+       shared_flag='-G'
+      else
+       if test "$aix_use_runtimelinking" = yes; then
+         shared_flag='${wl}-G'
+       else
+         shared_flag='${wl}-bM:SRE'
+       fi
+      fi
+    fi
+
+    # It seems that -bexpall does not export symbols beginning with
+    # underscore (_), so it is better to generate a list of symbols to export.
+    _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+    if test "$aix_use_runtimelinking" = yes; then
+      # Warning - without using the other runtime loading flags (-brtl),
+      # -berok will link without error, but may produce a broken library.
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+      # Determine the default libpath from the value encoded in an empty executable.
+      _LT_AC_SYS_LIBPATH_AIX
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+     else
+      if test "$host_cpu" = ia64; then
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+      else
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+       # Warning - without using the other run time loading flags,
+       # -berok will link without error, but may produce a broken library.
+       _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+       # -bexpall does not export symbols beginning with underscore (_)
+       _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+       # Exported symbols can be pulled into shared objects from archives
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
+       _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+       # This is similar to how AIX traditionally builds it's shared libraries.
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+      fi
+    fi
+    ;;
+  chorus*)
+    case $cc_basename in
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+
+  cygwin* | mingw* | pw32*)
+    # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+    # as there is no search path for DLLs.
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+    _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+    _LT_AC_TAGVAR(always_export_symbols, $1)=no
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+
+    if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+      # If the export-symbols file already is a .def file (1st line
+      # is EXPORTS), use it as is; otherwise, prepend...
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+       cp $export_symbols $output_objdir/$soname.def;
+      else
+       echo EXPORTS > $output_objdir/$soname.def;
+       cat $export_symbols >> $output_objdir/$soname.def;
+      fi~
+      $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+  ;;
+
+  darwin* | rhapsody*)
+  if test "$GXX" = yes; then
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    case "$host_os" in
+    rhapsody* | darwin1.[[012]])
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress'
+      ;;
+    *) # Darwin 1.3 on
+      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+      else
+        case ${MACOSX_DEPLOYMENT_TARGET} in
+          10.[[012]])
+            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+            ;;
+          10.*)
+            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup'
+            ;;
+        esac
+      fi
+      ;;
+    esac
+    lt_int_apple_cc_single_mod=no
+    output_verbose_link_cmd='echo'
+    if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then
+      lt_int_apple_cc_single_mod=yes
+    fi
+    if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+    else
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+    fi
+    _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+
+    # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+    if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    else
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    fi
+    _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+    _LT_AC_TAGVAR(hardcode_direct, $1)=no
+    _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+    _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+    _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience'
+    _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+  else
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+  fi
+    ;;
+
+  dgux*)
+    case $cc_basename in
+      ec++)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      ghcx)
+       # Green Hills C++ Compiler
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  freebsd[12]*)
+    # C++ shared libraries reported to be fairly broken before switch to ELF
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  freebsd-elf*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    ;;
+  freebsd* | kfreebsd*-gnu)
+    # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF
+    # conventions
+    _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+    ;;
+  gnu*)
+    ;;
+  hpux9*)
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+    _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+    _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                               # but as the default
+                               # location of the library.
+
+    case $cc_basename in
+    CC)
+      # FIXME: insert proper C++ library support
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    aCC)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      # Commands to make compiler produce verbose output that lists
+      # what "hidden" libraries, object files and flags are used when
+      # linking a shared library.
+      #
+      # There doesn't appear to be a way to prevent this compiler from
+      # explicitly linking system object files so we need to strip them
+      # from the output so that they don't get included in the library
+      # dependencies.
+      output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+      ;;
+    *)
+      if test "$GXX" = yes; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+        # FIXME: insert proper C++ library support
+        _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+    ;;
+  hpux10*|hpux11*)
+    if test $with_gnu_ld = no; then
+      case "$host_cpu" in
+      hppa*64*)
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+        ;;
+      ia64*)
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+        ;;
+      *)
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+        ;;
+      esac
+    fi
+    case "$host_cpu" in
+    hppa*64*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+    ia64*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                             # but as the default
+                                             # location of the library.
+      ;;
+    *)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH,
+                                             # but as the default
+                                             # location of the library.
+      ;;
+    esac
+
+    case $cc_basename in
+      CC)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      aCC)
+       case "$host_cpu" in
+       hppa*64*|ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+         ;;
+       esac
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test $with_gnu_ld = no; then
+           case "$host_cpu" in
+           ia64*|hppa*64*)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs'
+             ;;
+           *)
+             _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+             ;;
+           esac
+         fi
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  irix5* | irix6*)
+    case $cc_basename in
+      CC)
+       # SGI C++
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+       # Archives containing C++ object files must be created using
+       # "CC -ar", where "CC" is the IRIX C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs'
+       ;;
+      *)
+       if test "$GXX" = yes; then
+         if test "$with_gnu_ld" = no; then
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+         else
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib'
+         fi
+       fi
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+       ;;
+    esac
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+    ;;
+  linux*)
+    case $cc_basename in
+      KCC)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib'
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+       ;;
+      icpc)
+       # Intel C++
+       with_gnu_ld=yes
+       _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive'
+       ;;
+      cxx)
+       # Compaq C++
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname  -o $lib ${wl}-retain-symbols-file $wl$export_symbols'
+
+       runpath_var=LD_RUN_PATH
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+    esac
+    ;;
+  lynxos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  m88k*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  mvs*)
+    case $cc_basename in
+      cxx)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  netbsd*)
+    if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable  -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+    fi
+    # Workaround some broken pre-1.5 toolchains
+    output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"'
+    ;;
+  osf3*)
+    case $cc_basename in
+      KCC)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Archives containing C++ object files must be created using
+       # "CC -Bstatic", where "CC" is the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs'
+
+       ;;
+      RCC)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      cxx)
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  osf4* | osf5*)
+    case $cc_basename in
+      KCC)
+       # Kuck and Associates, Inc. (KAI) C++ Compiler
+
+       # KCC will only create a shared library if the output file
+       # ends with ".so" (or ".sl" for HP-UX), so rename the library
+       # to its proper name (with version) after linking.
+       _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Archives containing C++ object files must be created using
+       # the KAI C++ compiler.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs'
+       ;;
+      RCC)
+       # Rational C++ 2.4.1
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      cxx)
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~
+         echo "-hidden">> $lib.exp~
+         $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp  `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~
+         $rm $lib.exp'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+       _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+       ;;
+      *)
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib'
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+
+         # Commands to make compiler produce verbose output that lists
+         # what "hidden" libraries, object files and flags are used when
+         # linking a shared library.
+         output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"'
+
+       else
+         # FIXME: insert proper C++ library support
+         _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       fi
+       ;;
+    esac
+    ;;
+  psos*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  sco*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    case $cc_basename in
+      CC)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  sunos4*)
+    case $cc_basename in
+      CC)
+       # Sun C++ 4.x
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      lcc)
+       # Lucid
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  solaris*)
+    case $cc_basename in
+      CC)
+       # Sun C++ 4.2, 5.x and Centerline C++
+       _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       case $host_os in
+         solaris2.[0-5] | solaris2.[0-5].*) ;;
+         *)
+           # The C++ compiler is used as linker so we must use $wl
+           # flag to pass the commands to the underlying system
+           # linker.
+           # Supported since Solaris 2.6 (maybe 2.5.1?)
+           _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract'
+           ;;
+       esac
+       _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+       # Commands to make compiler produce verbose output that lists
+       # what "hidden" libraries, object files and flags are used when
+       # linking a shared library.
+       #
+       # There doesn't appear to be a way to prevent this compiler from
+       # explicitly linking system object files so we need to strip them
+       # from the output so that they don't get included in the library
+       # dependencies.
+       output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list'
+
+       # Archives containing C++ object files must be created using
+       # "CC -xar", where "CC" is the Sun C++ compiler.  This is
+       # necessary to make sure instantiated templates are included
+       # in the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs'
+       ;;
+      gcx)
+       # Green Hills C++ Compiler
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+
+       # The C++ compiler must be used to create the archive.
+       _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs'
+       ;;
+      *)
+       # GNU C++ compiler with Solaris linker
+       if test "$GXX" = yes && test "$with_gnu_ld" = no; then
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs'
+         if $CC --version | grep -v '^2\.7' > /dev/null; then
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         else
+           # g++ 2.7 appears to require `-G' NOT `-shared' on this
+           # platform.
+           _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib'
+           _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp'
+
+           # Commands to make compiler produce verbose output that lists
+           # what "hidden" libraries, object files and flags are used when
+           # linking a shared library.
+           output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\""
+         fi
+
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir'
+       fi
+       ;;
+    esac
+    ;;
+  sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*)
+    _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+    ;;
+  tandem*)
+    case $cc_basename in
+      NCC)
+       # NonStop-UX NCC 3.20
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+      *)
+       # FIXME: insert proper C++ library support
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       ;;
+    esac
+    ;;
+  vxworks*)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+  *)
+    # FIXME: insert proper C++ library support
+    _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    ;;
+esac
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$GXX"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_POSTDEP_PREDEP($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC=$lt_save_CC
+LDCXX=$LD
+LD=$lt_save_LD
+GCC=$lt_save_GCC
+with_gnu_ldcxx=$with_gnu_ld
+with_gnu_ld=$lt_save_with_gnu_ld
+lt_cv_path_LDCXX=$lt_cv_path_LD
+lt_cv_path_LD=$lt_save_path_LD
+lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld
+lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld
+])# AC_LIBTOOL_LANG_CXX_CONFIG
+
+# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME])
+# ------------------------
+# Figure out "hidden" library dependencies from verbose
+# compiler output when linking a shared library.
+# Parse the compiler output and extract the necessary
+# objects, libraries and library flags.
+AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[
+dnl we can't use the lt_simple_compile_test_code here,
+dnl because it contains code intended for an executable,
+dnl not a library.  It's possible we should let each
+dnl tag define a new lt_????_link_test_code variable,
+dnl but it's only used here...
+ifelse([$1],[],[cat > conftest.$ac_ext <<EOF
+int a;
+void foo (void) { a = 0; }
+EOF
+],[$1],[CXX],[cat > conftest.$ac_ext <<EOF
+class Foo
+{
+public:
+  Foo (void) { a = 0; }
+private:
+  int a;
+};
+EOF
+],[$1],[F77],[cat > conftest.$ac_ext <<EOF
+      subroutine foo
+      implicit none
+      integer*4 a
+      a=0
+      return
+      end
+EOF
+],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF
+public class foo {
+  private int a;
+  public void bar (void) {
+    a = 0;
+  }
+};
+EOF
+])
+dnl Parse the compiler output and extract the necessary
+dnl objects, libraries and library flags.
+if AC_TRY_EVAL(ac_compile); then
+  # Parse the compiler output and extract the necessary
+  # objects, libraries and library flags.
+
+  # Sentinel used to keep track of whether or not we are before
+  # the conftest object file.
+  pre_test_object_deps_done=no
+
+  # The `*' in the case matches for architectures that use `case' in
+  # $output_verbose_cmd can trigger glob expansion during the loop
+  # eval without this substitution.
+  output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`"
+
+  for p in `eval $output_verbose_link_cmd`; do
+    case $p in
+
+    -L* | -R* | -l*)
+       # Some compilers place space between "-{L,R}" and the path.
+       # Remove the space.
+       if test $p = "-L" \
+         || test $p = "-R"; then
+        prev=$p
+        continue
+       else
+        prev=
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        case $p in
+        -L* | -R*)
+          # Internal compiler library paths should come after those
+          # provided the user.  The postdeps already come after the
+          # user supplied libs so there is no need to process them.
+          if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then
+            _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}"
+          else
+            _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}"
+          fi
+          ;;
+        # The "-l" case would never come before the object being
+        # linked, so don't bother handling this case.
+        esac
+       else
+        if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then
+          _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}"
+        else
+          _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}"
+        fi
+       fi
+       ;;
+
+    *.$objext)
+       # This assumes that the test object file only shows up
+       # once in the compiler output.
+       if test "$p" = "conftest.$objext"; then
+        pre_test_object_deps_done=yes
+        continue
+       fi
+
+       if test "$pre_test_object_deps_done" = no; then
+        if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then
+          _LT_AC_TAGVAR(predep_objects, $1)="$p"
+        else
+          _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p"
+        fi
+       else
+        if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then
+          _LT_AC_TAGVAR(postdep_objects, $1)="$p"
+        else
+          _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p"
+        fi
+       fi
+       ;;
+
+    *) ;; # Ignore the rest.
+
+    esac
+  done
+
+  # Clean up.
+  rm -f a.out a.exe
+else
+  echo "libtool.m4: error: problem compiling $1 test program"
+fi
+
+$rm -f confest.$objext
+
+case " $_LT_AC_TAGVAR(postdeps, $1) " in
+*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;;
+esac
+])# AC_LIBTOOL_POSTDEP_PREDEP
+
+# AC_LIBTOOL_LANG_F77_CONFIG
+# ------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)])
+AC_DEFUN([_LT_AC_LANG_F77_CONFIG],
+[AC_REQUIRE([AC_PROG_F77])
+AC_LANG_PUSH(Fortran 77)
+
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+_LT_AC_TAGVAR(allow_undefined_flag, $1)=
+_LT_AC_TAGVAR(always_export_symbols, $1)=no
+_LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_direct, $1)=no
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+_LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+_LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+_LT_AC_TAGVAR(hardcode_automatic, $1)=no
+_LT_AC_TAGVAR(module_cmds, $1)=
+_LT_AC_TAGVAR(module_expsym_cmds, $1)=
+_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds
+_LT_AC_TAGVAR(no_undefined_flag, $1)=
+_LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+
+# Source file extension for f77 test sources.
+ac_ext=f
+
+# Object file extension for compiled f77 test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="      subroutine t\n      return\n      end\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="      program t\n      end\n"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${F77-"f77"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'`
+
+AC_MSG_CHECKING([if libtool supports shared libraries])
+AC_MSG_RESULT([$can_build_shared])
+
+AC_MSG_CHECKING([whether to build shared libraries])
+test "$can_build_shared" = "no" && enable_shared=no
+
+# On AIX, shared libraries and static libraries use the same namespace, and
+# are all built from PIC.
+case "$host_os" in
+aix3*)
+  test "$enable_shared" = yes && enable_static=no
+  if test -n "$RANLIB"; then
+    archive_cmds="$archive_cmds~\$RANLIB \$lib"
+    postinstall_cmds='$RANLIB $lib'
+  fi
+  ;;
+aix4*)
+  test "$enable_shared" = yes && enable_static=no
+  ;;
+esac
+AC_MSG_RESULT([$enable_shared])
+
+AC_MSG_CHECKING([whether to build static libraries])
+# Make sure either enable_shared or enable_static is yes.
+test "$enable_shared" = yes || enable_static=yes
+AC_MSG_RESULT([$enable_static])
+
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+_LT_AC_TAGVAR(GCC, $1)="$G77"
+_LT_AC_TAGVAR(LD, $1)="$LD"
+
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_POP
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_F77_CONFIG
+
+
+# AC_LIBTOOL_LANG_GCJ_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the C compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)])
+AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for Java test sources.
+ac_ext=java
+
+# Object file extension for compiled Java test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code="class foo {}\n"
+
+# Code to be used in simple link tests
+lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n'
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${GCJ-"gcj"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+
+# GCJ did not exist at the time GCC didn't implicitly link libc in.
+_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+
+AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1)
+AC_LIBTOOL_PROG_COMPILER_PIC($1)
+AC_LIBTOOL_PROG_CC_C_O($1)
+AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1)
+AC_LIBTOOL_PROG_LD_SHLIBS($1)
+AC_LIBTOOL_SYS_DYNAMIC_LINKER($1)
+AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1)
+AC_LIBTOOL_SYS_LIB_STRIP
+AC_LIBTOOL_DLOPEN_SELF($1)
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_GCJ_CONFIG
+
+
+# AC_LIBTOOL_LANG_RC_CONFIG
+# --------------------------
+# Ensure that the configuration vars for the Windows resource compiler are
+# suitably defined.  Those variables are subsequently used by
+# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'.
+AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)])
+AC_DEFUN([_LT_AC_LANG_RC_CONFIG],
+[AC_LANG_SAVE
+
+# Source file extension for RC test sources.
+ac_ext=rc
+
+# Object file extension for compiled RC test sources.
+objext=o
+_LT_AC_TAGVAR(objext, $1)=$objext
+
+# Code to be used in simple compile tests
+lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n'
+
+# Code to be used in simple link tests
+lt_simple_link_test_code="$lt_simple_compile_test_code"
+
+# ltmain only uses $CC for tagged configurations so make sure $CC is set.
+_LT_AC_SYS_COMPILER
+
+# Allow CC to be a program name with arguments.
+lt_save_CC="$CC"
+CC=${RC-"windres"}
+compiler=$CC
+_LT_AC_TAGVAR(compiler, $1)=$CC
+_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes
+
+AC_LIBTOOL_CONFIG($1)
+
+AC_LANG_RESTORE
+CC="$lt_save_CC"
+])# AC_LIBTOOL_LANG_RC_CONFIG
+
+
+# AC_LIBTOOL_CONFIG([TAGNAME])
+# ----------------------------
+# If TAGNAME is not passed, then create an initial libtool script
+# with a default configuration from the untagged config vars.  Otherwise
+# add code to config.status for appending the configuration named by
+# TAGNAME from the matching tagged config vars.
+AC_DEFUN([AC_LIBTOOL_CONFIG],
+[# The else clause should only fire when bootstrapping the
+# libtool distribution, otherwise you forgot to ship ltmain.sh
+# with your package, and you will get complaints that there are
+# no rules to generate ltmain.sh.
+if test -f "$ltmain"; then
+  # See if we are running on zsh, and set the options which allow our commands through
+  # without removal of \ escapes.
+  if test -n "${ZSH_VERSION+set}" ; then
+    setopt NO_GLOB_SUBST
+  fi
+  # Now quote all the things that may contain metacharacters while being
+  # careful not to overquote the AC_SUBSTed values.  We take copies of the
+  # variables and quote the copies for generation of the libtool script.
+  for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM \
+    SED SHELL STRIP \
+    libname_spec library_names_spec soname_spec extract_expsyms_cmds \
+    old_striplib striplib file_magic_cmd finish_cmds finish_eval \
+    deplibs_check_method reload_flag reload_cmds need_locks \
+    lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \
+    lt_cv_sys_global_symbol_to_c_name_address \
+    sys_lib_search_path_spec sys_lib_dlsearch_path_spec \
+    old_postinstall_cmds old_postuninstall_cmds \
+    _LT_AC_TAGVAR(compiler, $1) \
+    _LT_AC_TAGVAR(CC, $1) \
+    _LT_AC_TAGVAR(LD, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \
+    _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \
+    _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \
+    _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \
+    _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \
+    _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \
+    _LT_AC_TAGVAR(old_archive_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \
+    _LT_AC_TAGVAR(predep_objects, $1) \
+    _LT_AC_TAGVAR(postdep_objects, $1) \
+    _LT_AC_TAGVAR(predeps, $1) \
+    _LT_AC_TAGVAR(postdeps, $1) \
+    _LT_AC_TAGVAR(compiler_lib_search_path, $1) \
+    _LT_AC_TAGVAR(archive_cmds, $1) \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(postinstall_cmds, $1) \
+    _LT_AC_TAGVAR(postuninstall_cmds, $1) \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \
+    _LT_AC_TAGVAR(allow_undefined_flag, $1) \
+    _LT_AC_TAGVAR(no_undefined_flag, $1) \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \
+    _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \
+    _LT_AC_TAGVAR(hardcode_automatic, $1) \
+    _LT_AC_TAGVAR(module_cmds, $1) \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) \
+    _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \
+    _LT_AC_TAGVAR(exclude_expsyms, $1) \
+    _LT_AC_TAGVAR(include_expsyms, $1); do
+
+    case $var in
+    _LT_AC_TAGVAR(old_archive_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_cmds, $1) | \
+    _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(module_cmds, $1) | \
+    _LT_AC_TAGVAR(module_expsym_cmds, $1) | \
+    _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \
+    _LT_AC_TAGVAR(export_symbols_cmds, $1) | \
+    extract_expsyms_cmds | reload_cmds | finish_cmds | \
+    postinstall_cmds | postuninstall_cmds | \
+    old_postinstall_cmds | old_postuninstall_cmds | \
+    sys_lib_search_path_spec | sys_lib_dlsearch_path_spec)
+      # Double-quote double-evaled strings.
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\""
+      ;;
+    *)
+      eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\""
+      ;;
+    esac
+  done
+
+  case $lt_echo in
+  *'\[$]0 --fallback-echo"')
+    lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'`
+    ;;
+  esac
+
+ifelse([$1], [],
+  [cfgfile="${ofile}T"
+  trap "$rm \"$cfgfile\"; exit 1" 1 2 15
+  $rm -f "$cfgfile"
+  AC_MSG_NOTICE([creating $ofile])],
+  [cfgfile="$ofile"])
+
+  cat <<__EOF__ >> "$cfgfile"
+ifelse([$1], [],
+[#! $SHELL
+
+# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services.
+# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP)
+# NOTE: Changes made to this file will be lost: look at ltmain.sh.
+#
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001
+# Free Software Foundation, Inc.
+#
+# This file is part of GNU Libtool:
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# 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.
+#
+# 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.
+
+# A sed program that does not truncate output.
+SED=$lt_SED
+
+# Sed that helps us avoid accidentally triggering echo(1) options like -n.
+Xsed="$SED -e s/^X//"
+
+# The HP-UX ksh and POSIX shell print the target directory to stdout
+# if CDPATH is set.
+if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi
+
+# The names of the tagged configurations supported by this script.
+available_tags=
+
+# ### BEGIN LIBTOOL CONFIG],
+[# ### BEGIN LIBTOOL TAG CONFIG: $tagname])
+
+# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
+
+# Shell to use when invoking shell scripts.
+SHELL=$lt_SHELL
+
+# Whether or not to build shared libraries.
+build_libtool_libs=$enable_shared
+
+# Whether or not to build static libraries.
+build_old_libs=$enable_static
+
+# Whether or not to add -lc for building shared libraries.
+build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)
+
+# Whether or not to disallow shared libs when runtime libs are static
+allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)
+
+# Whether or not to optimize for fast installation.
+fast_install=$enable_fast_install
+
+# The host system.
+host_alias=$host_alias
+host=$host
+
+# An echo program that does not interpret backslashes.
+echo=$lt_echo
+
+# The archiver.
+AR=$lt_AR
+AR_FLAGS=$lt_AR_FLAGS
+
+# A C compiler.
+LTCC=$lt_LTCC
+
+# A language-specific compiler.
+CC=$lt_[]_LT_AC_TAGVAR(compiler, $1)
+
+# Is the compiler the GNU C compiler?
+with_gcc=$_LT_AC_TAGVAR(GCC, $1)
+
+# An ERE matcher.
+EGREP=$lt_EGREP
+
+# The linker used to build libraries.
+LD=$lt_[]_LT_AC_TAGVAR(LD, $1)
+
+# Whether we need hard or soft links.
+LN_S=$lt_LN_S
+
+# A BSD-compatible nm program.
+NM=$lt_NM
+
+# A symbol stripping program
+STRIP=$lt_STRIP
+
+# Used to examine libraries when file_magic_cmd begins "file"
+MAGIC_CMD=$MAGIC_CMD
+
+# Used on cygwin: DLL creation program.
+DLLTOOL="$DLLTOOL"
+
+# Used on cygwin: object dumper.
+OBJDUMP="$OBJDUMP"
+
+# Used on cygwin: assembler.
+AS="$AS"
+
+# The name of the directory that contains temporary libtool files.
+objdir=$objdir
+
+# How to create reloadable object files.
+reload_flag=$lt_reload_flag
+reload_cmds=$lt_reload_cmds
+
+# How to pass a linker flag through the compiler.
+wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+
+# Object file suffix (normally "o").
+objext="$ac_objext"
+
+# Old archive suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally ".so").
+shrext='$shrext'
+
+# Executable file suffix (normally "").
+exeext="$exeext"
+
+# Additional compiler flags for building library objects.
+pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)
+pic_mode=$pic_mode
+
+# What is the maximum length of a command?
+max_cmd_len=$lt_cv_sys_max_cmd_len
+
+# Does compiler simultaneously support -c and -o options?
+compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)
+
+# Must we lock files when doing compilation ?
+need_locks=$lt_need_locks
+
+# Do we need the lib prefix for modules?
+need_lib_prefix=$need_lib_prefix
+
+# Do we need a version for libraries?
+need_version=$need_version
+
+# Whether dlopen is supported.
+dlopen_support=$enable_dlopen
+
+# Whether dlopen of programs is supported.
+dlopen_self=$enable_dlopen_self
+
+# Whether dlopen of statically linked programs is supported.
+dlopen_self_static=$enable_dlopen_self_static
+
+# Compiler flag to prevent dynamic linking.
+link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1)
+
+# Compiler flag to turn off builtin functions.
+no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)
+
+# Compiler flag to allow reflexive dlopens.
+export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)
+
+# Compiler flag to generate shared objects directly from archives.
+whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1)
+
+# Compiler flag to generate thread-safe objects.
+thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1)
+
+# Library versioning type.
+version_type=$version_type
+
+# Format of library name prefix.
+libname_spec=$lt_libname_spec
+
+# List of archive names.  First name is the real one, the rest are links.
+# The last name is the one that the linker finds with -lNAME.
+library_names_spec=$lt_library_names_spec
+
+# The coded name of the library, if different from the real name.
+soname_spec=$lt_soname_spec
+
+# Commands used to build and install an old-style archive.
+RANLIB=$lt_RANLIB
+old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1)
+old_postinstall_cmds=$lt_old_postinstall_cmds
+old_postuninstall_cmds=$lt_old_postuninstall_cmds
+
+# Create an old-style archive from a shared archive.
+old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1)
+
+# Create a temporary old-style archive to link instead of a shared archive.
+old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)
+
+# Commands used to build and install a shared archive.
+archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1)
+archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1)
+postinstall_cmds=$lt_postinstall_cmds
+postuninstall_cmds=$lt_postuninstall_cmds
+
+# Commands used to build a loadable module (assumed same as above if empty)
+module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1)
+module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1)
+
+# Commands to strip libraries.
+old_striplib=$lt_old_striplib
+striplib=$lt_striplib
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1)
+
+# Dependencies to place before the objects being linked to create a
+# shared library.
+predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1)
+
+# Dependencies to place after the objects being linked to create a
+# shared library.
+postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1)
+
+# The library search path used internally by the compiler when linking
+# a shared library.
+compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1)
+
+# Method to check whether dependent libraries are shared objects.
+deplibs_check_method=$lt_deplibs_check_method
+
+# Command to use when deplibs_check_method == file_magic.
+file_magic_cmd=$lt_file_magic_cmd
+
+# Flag that allows shared libraries with undefined symbols to be built.
+allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1)
+
+# Flag that forces no undefined symbols.
+no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1)
+
+# Commands used to finish a libtool library installation in a directory.
+finish_cmds=$lt_finish_cmds
+
+# Same as above, but a single script fragment to be evaled but not shown.
+finish_eval=$lt_finish_eval
+
+# Take the output of nm and produce a listing of raw symbols and C names.
+global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe
+
+# Transform the output of nm in a proper C declaration
+global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl
+
+# Transform the output of nm in a C name address pair
+global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address
+
+# This is the shared library runtime path variable.
+runpath_var=$runpath_var
+
+# This is the shared library path variable.
+shlibpath_var=$shlibpath_var
+
+# Is shlibpath searched before the hard-coded library search path?
+shlibpath_overrides_runpath=$shlibpath_overrides_runpath
+
+# How to hardcode a shared library path into an executable.
+hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1)
+
+# Whether we should hardcode library paths into libraries.
+hardcode_into_libs=$hardcode_into_libs
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)
+
+# If ld is used when linking, flag to hardcode \$libdir into
+# a binary during linking. This must work even if \$libdir does
+# not exist.
+hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1)
+
+# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1)
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1)
+
+# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into
+# the resulting binary.
+hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)
+
+# Set to yes if building a shared library automatically hardcodes DIR into the library
+# and all subsequent libraries and executables linked against it.
+hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1)
+
+# Variables whose values should be saved in libtool wrapper scripts and
+# restored at relink time.
+variables_saved_for_relink="$variables_saved_for_relink"
+
+# Whether libtool must link a program against all its dependency libraries.
+link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1)
+
+# Compile-time system search path for libraries
+sys_lib_search_path_spec=$lt_sys_lib_search_path_spec
+
+# Run-time system search path for libraries
+sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec
+
+# Fix the shell variable \$srcfile for the compiler.
+fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)"
+
+# Set to yes if exported symbols are required.
+always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1)
+
+# The commands to list exported symbols.
+export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1)
+
+# The commands to extract the exported symbol list from a shared archive.
+extract_expsyms_cmds=$lt_extract_expsyms_cmds
+
+# Symbols that should not be listed in the preloaded symbols.
+exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1)
+
+# Symbols that must always be exported.
+include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1)
+
+ifelse([$1],[],
+[# ### END LIBTOOL CONFIG],
+[# ### END LIBTOOL TAG CONFIG: $tagname])
+
+__EOF__
+
+ifelse([$1],[], [
+  case $host_os in
+  aix3*)
+    cat <<\EOF >> "$cfgfile"
+
+# AIX sometimes has problems with the GCC collect2 program.  For some
+# reason, if we set the COLLECT_NAMES environment variable, the problems
+# vanish in a puff of smoke.
+if test "X${COLLECT_NAMES+set}" != Xset; then
+  COLLECT_NAMES=
+  export COLLECT_NAMES
+fi
+EOF
+    ;;
+  esac
+
+  # We use sed instead of cat because bash on DJGPP gets confused if
+  # if finds mixed CR/LF and LF-only lines.  Since sed operates in
+  # text mode, it properly converts lines to CR/LF.  This bash problem
+  # is reportedly fixed, but why not run on old versions too?
+  sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1)
+
+  mv -f "$cfgfile" "$ofile" || \
+    (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile")
+  chmod +x "$ofile"
+])
+else
+  # If there is no Makefile yet, we rely on a make rule to execute
+  # `config.status --recheck' to rerun these tests and create the
+  # libtool script then.
+  ltmain_in=`echo $ltmain | sed -e 's/\.sh$/.in/'`
+  if test -f "$ltmain_in"; then
+    test -f Makefile && make "$ltmain"
+  fi
+fi
+])# AC_LIBTOOL_CONFIG
+
+
+# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME])
+# -------------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI],
+[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl
+
+_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=
+
+if test "$GCC" = yes; then
+  _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin'
+
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions],
+    lt_cv_prog_compiler_rtti_exceptions,
+    [-fno-rtti -fno-exceptions], [],
+    [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"])
+fi
+])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI
+
+
+# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+# ---------------------------------
+AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_REQUIRE([AC_PROG_NM])
+AC_REQUIRE([AC_OBJEXT])
+# Check for command to grab the raw symbol name followed by C symbol from nm.
+AC_MSG_CHECKING([command to parse $NM output from $compiler object])
+AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe],
+[
+# These are sane defaults that work on at least a few old systems.
+# [They come from Ultrix.  What could be older than Ultrix?!! ;)]
+
+# Character class describing NM global symbol codes.
+symcode='[[BCDEGRST]]'
+
+# Regexp to match symbols that can be accessed directly from C.
+sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)'
+
+# Transform the above into a raw symbol and a C symbol.
+symxfrm='\1 \2\3 \3'
+
+# Transform an extracted symbol line into a proper C declaration
+lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'"
+
+# Transform an extracted symbol line into symbol name and symbol address
+lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+
+# Define system-specific variables.
+case $host_os in
+aix*)
+  symcode='[[BCDT]]'
+  ;;
+cygwin* | mingw* | pw32*)
+  symcode='[[ABCDGISTW]]'
+  ;;
+hpux*) # Its linker distinguishes data from code symbols
+  if test "$host_cpu" = ia64; then
+    symcode='[[ABCDEGRST]]'
+  fi
+  lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'"
+  lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/  {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/  {\"\2\", (lt_ptr) \&\2},/p'"
+  ;;
+irix* | nonstopux*)
+  symcode='[[BCDEGRST]]'
+  ;;
+osf*)
+  symcode='[[BCDEGQRST]]'
+  ;;
+solaris* | sysv5*)
+  symcode='[[BDRT]]'
+  ;;
+sysv4)
+  symcode='[[DFNSTU]]'
+  ;;
+esac
+
+# Handle CRLF in mingw tool chain
+opt_cr=
+case $build_os in
+mingw*)
+  opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp
+  ;;
+esac
+
+# If we're using GNU nm, then use its standard symbol codes.
+case `$NM -V 2>&1` in
+*GNU* | *'with BFD'*)
+  symcode='[[ABCDGIRSTW]]' ;;
+esac
+
+# Try without a prefix undercore, then with it.
+for ac_symprfx in "" "_"; do
+
+  # Write the raw and C identifiers.
+  lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[     ]]\($symcode$symcode*\)[[       ]][[    ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'"
+
+  # Check to see that the pipe works correctly.
+  pipe_works=no
+
+  rm -f conftest*
+  cat > conftest.$ac_ext <<EOF
+#ifdef __cplusplus
+extern "C" {
+#endif
+char nm_test_var;
+void nm_test_func(){}
+#ifdef __cplusplus
+}
+#endif
+int main(){nm_test_var='a';nm_test_func();return(0);}
+EOF
+
+  if AC_TRY_EVAL(ac_compile); then
+    # Now try to grab the symbols.
+    nlist=conftest.nm
+    if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then
+      # Try sorting and uniquifying the output.
+      if sort "$nlist" | uniq > "$nlist"T; then
+       mv -f "$nlist"T "$nlist"
+      else
+       rm -f "$nlist"T
+      fi
+
+      # Make sure that we snagged all the symbols we need.
+      if grep ' nm_test_var$' "$nlist" >/dev/null; then
+       if grep ' nm_test_func$' "$nlist" >/dev/null; then
+         cat <<EOF > conftest.$ac_ext
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+EOF
+         # Now generate the symbol file.
+         eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext'
+
+         cat <<EOF >> conftest.$ac_ext
+#if defined (__STDC__) && __STDC__
+# define lt_ptr_t void *
+#else
+# define lt_ptr_t char *
+# define const
+#endif
+
+/* The mapping between symbol names and symbols. */
+const struct {
+  const char *name;
+  lt_ptr_t address;
+}
+lt_preloaded_symbols[[]] =
+{
+EOF
+         $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/  {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext
+         cat <<\EOF >> conftest.$ac_ext
+  {0, (lt_ptr_t) 0}
+};
+
+#ifdef __cplusplus
+}
+#endif
+EOF
+         # Now try linking the two files.
+         mv conftest.$ac_objext conftstm.$ac_objext
+         lt_save_LIBS="$LIBS"
+         lt_save_CFLAGS="$CFLAGS"
+         LIBS="conftstm.$ac_objext"
+         CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)"
+         if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then
+           pipe_works=yes
+         fi
+         LIBS="$lt_save_LIBS"
+         CFLAGS="$lt_save_CFLAGS"
+       else
+         echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD
+       fi
+      else
+       echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD
+      fi
+    else
+      echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD
+    fi
+  else
+    echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD
+    cat conftest.$ac_ext >&5
+  fi
+  rm -f conftest* conftst*
+
+  # Do not use the global_symbol_pipe unless it works.
+  if test "$pipe_works" = yes; then
+    break
+  else
+    lt_cv_sys_global_symbol_pipe=
+  fi
+done
+])
+if test -z "$lt_cv_sys_global_symbol_pipe"; then
+  lt_cv_sys_global_symbol_to_cdecl=
+fi
+if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then
+  AC_MSG_RESULT(failed)
+else
+  AC_MSG_RESULT(ok)
+fi
+]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE
+
+
+# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME])
+# ---------------------------------------
+AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC],
+[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=
+
+AC_MSG_CHECKING([for $compiler option to produce PIC])
+ ifelse([$1],[CXX],[
+  # C++ specific cases for pic, static, wl, etc.
+  if test "$GXX" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+    aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+    beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+    mingw* | os2* | pw32*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+    *djgpp*)
+      # DJGPP does not support shared libraries at all
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+      ;;
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case "$host_cpu" in
+      hppa*64*|ia64*)
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    case $host_os in
+      aix4* | aix5*)
+       # All AIX code is PIC.
+       if test "$host_cpu" = ia64; then
+         # AIX 5 now supports IA64 processor
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+       else
+         _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+       fi
+       ;;
+      chorus*)
+       case $cc_basename in
+       cxch68)
+         # Green Hills C++ Compiler
+         # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a"
+         ;;
+       esac
+       ;;
+      dgux*)
+       case $cc_basename in
+         ec++)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         ghcx)
+           # Green Hills C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      freebsd* | kfreebsd*-gnu)
+       # FreeBSD uses GNU C++
+       ;;
+      hpux9* | hpux10* | hpux11*)
+       case $cc_basename in
+         CC)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+           if test "$host_cpu" != ia64; then
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+           fi
+           ;;
+         aCC)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive"
+           case "$host_cpu" in
+           hppa*64*|ia64*)
+             # +Z the default
+             ;;
+           *)
+             _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+             ;;
+           esac
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      irix5* | irix6* | nonstopux*)
+       case $cc_basename in
+         CC)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           # CC pic flag -KPIC is the default.
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      linux*)
+       case $cc_basename in
+         KCC)
+           # KAI C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         icpc)
+           # Intel C++
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+           ;;
+         cxx)
+           # Compaq C++
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      lynxos*)
+       ;;
+      m88k*)
+       ;;
+      mvs*)
+       case $cc_basename in
+         cxx)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      netbsd*)
+       ;;
+      osf3* | osf4* | osf5*)
+       case $cc_basename in
+         KCC)
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,'
+           ;;
+         RCC)
+           # Rational C++ 2.4.1
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         cxx)
+           # Digital/Compaq C++
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+           # Make sure the PIC flag is empty.  It appears that all Alpha
+           # Linux and Compaq Tru64 Unix objects are PIC.
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      psos*)
+       ;;
+      sco*)
+       case $cc_basename in
+         CC)
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      solaris*)
+       case $cc_basename in
+         CC)
+           # Sun C++ 4.2, 5.x and Centerline C++
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+           ;;
+         gcx)
+           # Green Hills C++ Compiler
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      sunos4*)
+       case $cc_basename in
+         CC)
+           # Sun C++ 4.x
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+           ;;
+         lcc)
+           # Lucid
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      tandem*)
+       case $cc_basename in
+         NCC)
+           # NonStop-UX NCC 3.20
+           _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+           ;;
+         *)
+           ;;
+       esac
+       ;;
+      unixware*)
+       ;;
+      vxworks*)
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+       ;;
+    esac
+  fi
+],
+[
+  if test "$GCC" = yes; then
+    _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+    _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+
+    case $host_os in
+      aix*)
+      # All AIX code is PIC.
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    amigaos*)
+      # FIXME: we need at least 68020 code to build shared libraries, but
+      # adding the `-m68020' flag to GCC prevents building anything better,
+      # like `-m68040'.
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4'
+      ;;
+
+    beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*)
+      # PIC is the default for these OSes.
+      ;;
+
+    mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+
+    darwin* | rhapsody*)
+      # PIC is the default on this platform
+      # Common symbols not allowed in MH_DYLIB files
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common'
+      ;;
+
+    msdosdjgpp*)
+      # Just because we use GCC doesn't mean we suddenly get shared libraries
+      # on systems that don't support them.
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      enable_shared=no
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic
+      fi
+      ;;
+
+    hpux*)
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case "$host_cpu" in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+       ;;
+      esac
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC'
+      ;;
+    esac
+  else
+    # PORTME Check for flag to pass linker flags through the system compiler.
+    case $host_os in
+    aix*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      if test "$host_cpu" = ia64; then
+       # AIX 5 now supports IA64 processor
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      else
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp'
+      fi
+      ;;
+
+    mingw* | pw32* | os2*)
+      # This hack is so that the source file can tell whether it is being
+      # built for inclusion in a dll (and should export symbols for example).
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT'
+      ;;
+
+    hpux9* | hpux10* | hpux11*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but
+      # not for PA HP-UX.
+      case "$host_cpu" in
+      hppa*64*|ia64*)
+       # +Z the default
+       ;;
+      *)
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z'
+       ;;
+      esac
+      # Is there a better lt_prog_compiler_static that works with the bundled CC?
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive'
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # PIC (with -KPIC) is the default.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    linux*)
+      case $CC in
+      icc* | ecc*)
+       _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static'
+        ;;
+      ccc*)
+        _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+        # All Alpha code is PIC.
+        _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+        ;;
+      esac
+      ;;
+
+    osf3* | osf4* | osf5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      # All OSF/1 code is PIC.
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared'
+      ;;
+
+    sco3.2v5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn'
+      ;;
+
+    solaris*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld '
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*)
+      _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,'
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec ;then
+       _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic'
+       _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      fi
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic'
+      _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic'
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)])
+
+#
+# Check to make sure the PIC flag actually works.
+#
+if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then
+  AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works],
+    _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1),
+    [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [],
+    [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in
+     "" | " "*) ;;
+     *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;;
+     esac],
+    [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+     _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no])
+fi
+case "$host_os" in
+  # For platforms which do not support PIC, -DPIC is meaningless:
+  *djgpp*)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=
+    ;;
+  *)
+    _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])"
+    ;;
+esac
+])
+
+
+# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME])
+# ------------------------------------
+# See if the linker supports building shared libraries.
+AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS],
+[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries])
+ifelse([$1],[CXX],[
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  case $host_os in
+  aix4* | aix5*)
+    # If we're using GNU nm, then we don't want the "-C" option.
+    # -C means demangle to AIX nm, but means don't demangle with GNU nm
+    if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    else
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+    fi
+    ;;
+  pw32*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds"
+  ;;
+  cygwin* | mingw*)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  *)
+    _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  ;;
+  esac
+],[
+  runpath_var=
+  _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+  _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no
+  _LT_AC_TAGVAR(archive_cmds, $1)=
+  _LT_AC_TAGVAR(archive_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)=
+  _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)=
+  _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=
+  _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+  _LT_AC_TAGVAR(thread_safe_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)=
+  _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+  _LT_AC_TAGVAR(hardcode_direct, $1)=no
+  _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+  _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+  _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown
+  _LT_AC_TAGVAR(hardcode_automatic, $1)=no
+  _LT_AC_TAGVAR(module_cmds, $1)=
+  _LT_AC_TAGVAR(module_expsym_cmds, $1)=
+  _LT_AC_TAGVAR(always_export_symbols, $1)=no
+  _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols'
+  # include_expsyms should be a list of space-separated symbols to be *always*
+  # included in the symbol list
+  _LT_AC_TAGVAR(include_expsyms, $1)=
+  # exclude_expsyms can be an extended regexp of symbols to exclude
+  # it will be wrapped by ` (' and `)$', so one must not match beginning or
+  # end of line.  Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc',
+  # as well as any symbol that contains `d'.
+  _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_"
+  # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out
+  # platforms (ab)use it in PIC code, but their linkers get confused if
+  # the symbol is explicitly referenced.  Since portable code cannot
+  # rely on this symbol name, it's probably fine to never include it in
+  # preloaded symbol tables.
+  extract_expsyms_cmds=
+
+  case $host_os in
+  cygwin* | mingw* | pw32*)
+    # FIXME: the MSVC++ port hasn't been tested in a loooong time
+    # When not using gcc, we currently assume that we are using
+    # Microsoft Visual C++.
+    if test "$GCC" != yes; then
+      with_gnu_ld=no
+    fi
+    ;;
+  openbsd*)
+    with_gnu_ld=no
+    ;;
+  esac
+
+  _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+  if test "$with_gnu_ld" = yes; then
+    # If archive_cmds runs LD, not CC, wlarc should be empty
+    wlarc='${wl}'
+
+    # See if GNU ld supports shared libraries.
+    case $host_os in
+    aix3* | aix4* | aix5*)
+      # On AIX/PPC, the GNU linker is very broken
+      if test "$host_cpu" != ia64; then
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<EOF 1>&2
+
+*** Warning: the GNU linker, at least up to release 2.9.1, is reported
+*** to be unable to reliably create shared libraries on AIX.
+*** Therefore, libtool is disabling shared libraries support.  If you
+*** really care for shared libraries, you may want to modify your PATH
+*** so that a non-GNU linker is found, and then restart.
+
+EOF
+      fi
+      ;;
+
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+
+      # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
+      # that the semantics of dynamic libraries on AmigaOS, at least up
+      # to version 4, is to share data among multiple programs linked
+      # with the same dynamic library.  Since this doesn't match the
+      # behavior of shared libraries on other platforms, we can't use
+      # them.
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    beos*)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+       # Joseph Beckenbach <jrb3@best.com> says some releases of gcc
+       # support --undefined.  This deserves some investigation.  FIXME
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless,
+      # as there is no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=no
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols'
+
+      if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib'
+       # If the export-symbols file already is a .def file (1st line
+       # is EXPORTS), use it as is; otherwise, prepend...
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then
+         cp $export_symbols $output_objdir/$soname.def;
+       else
+         echo EXPORTS > $output_objdir/$soname.def;
+         cat $export_symbols >> $output_objdir/$soname.def;
+       fi~
+       $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000  ${wl}--out-implib,$lib'
+      else
+       ld_shlibs=no
+      fi
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib'
+       wlarc=
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      fi
+      ;;
+
+    solaris* | sysv5*)
+      if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+       cat <<EOF 1>&2
+
+*** Warning: The releases 2.8.* of the GNU linker cannot reliably
+*** create shared libraries on Solaris systems.  Therefore, libtool
+*** is disabling shared libraries support.  We urge you to upgrade GNU
+*** binutils to release 2.9.1 or newer.  Another option is to modify
+*** your PATH or compiler configuration so that the native linker is
+*** used, and then restart.
+
+EOF
+      elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+
+    sunos4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      wlarc=
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+  linux*)
+    if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then
+        tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds"
+      supports_anon_versioning=no
+      case `$LD -v 2>/dev/null` in
+        *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11
+        *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ...
+        *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ...
+        *\ 2.11.*) ;; # other 2.11 versions
+        *) supports_anon_versioning=yes ;;
+      esac
+      if test $supports_anon_versioning = yes; then
+        _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~
+cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~
+$echo "local: *; };" >> $output_objdir/$libname.ver~
+        $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib'
+      else
+        _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds"
+      fi
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+    ;;
+
+    *)
+      if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib'
+      else
+       _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      fi
+      ;;
+    esac
+
+    if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then
+      runpath_var=LD_RUN_PATH
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic'
+      # ancient GNU ld didn't support --whole-archive et. al.
+      if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive'
+      else
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=
+      fi
+    fi
+  else
+    # PORTME fill in a description of your system's linker (not GNU ld)
+    case $host_os in
+    aix3*)
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname'
+      # Note: this linker hardcodes the directories in LIBPATH if there
+      # are no directories specified by -L.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      if test "$GCC" = yes && test -z "$link_static_flag"; then
+       # Neither direct hardcoding nor static linking is supported with a
+       # broken collect2.
+       _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+      fi
+      ;;
+
+    aix4* | aix5*)
+      if test "$host_cpu" = ia64; then
+       # On IA64, the linker does run time linking by default, so we don't
+       # have to do anything special.
+       aix_use_runtimelinking=no
+       exp_sym_flag='-Bexport'
+       no_entry_flag=""
+      else
+       # If we're using GNU nm, then we don't want the "-C" option.
+       # -C means demangle to AIX nm, but means don't demangle with GNU nm
+       if $NM -V 2>&1 | grep 'GNU' > /dev/null; then
+         _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+       else
+         _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols'
+       fi
+       aix_use_runtimelinking=no
+
+       # Test if we are trying to use run time linking or normal
+       # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+       # need to do runtime linking.
+       case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*)
+         for ld_flag in $LDFLAGS; do
+         if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+           aix_use_runtimelinking=yes
+           break
+         fi
+         done
+       esac
+
+       exp_sym_flag='-bexport'
+       no_entry_flag='-bnoentry'
+      fi
+
+      # When large executables or shared objects are built, AIX ld can
+      # have problems creating the table of contents.  If linking a library
+      # or program results in "error TOC overflow" add -mminimal-toc to
+      # CXXFLAGS/CFLAGS for g++/gcc.  In the cases where that is not
+      # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS.
+
+      _LT_AC_TAGVAR(archive_cmds, $1)=''
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+
+      if test "$GCC" = yes; then
+       case $host_os in aix4.[012]|aix4.[012].*)
+       # We only want to do this on AIX 4.2 and lower, the check
+       # below for broken collect2 doesn't work under 4.3+
+         collect2name=`${CC} -print-prog-name=collect2`
+         if test -f "$collect2name" && \
+          strings "$collect2name" | grep resolve_lib_name >/dev/null
+         then
+         # We have reworked collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+         else
+         # We have old collect2
+         _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported
+         # It fails to find uninstalled libraries when the uninstalled
+         # path is not listed in the libpath.  Setting hardcode_minus_L
+         # to unsupported forces relinking
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=
+         fi
+       esac
+       shared_flag='-shared'
+      else
+       # not using gcc
+       if test "$host_cpu" = ia64; then
+       # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release
+       # chokes on -Wl,-G. The following line is correct:
+         shared_flag='-G'
+       else
+       if test "$aix_use_runtimelinking" = yes; then
+           shared_flag='${wl}-G'
+         else
+           shared_flag='${wl}-bM:SRE'
+       fi
+       fi
+      fi
+
+      # It seems that -bexpall does not export symbols beginning with
+      # underscore (_), so it is better to generate a list of symbols to export.
+      _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+      if test "$aix_use_runtimelinking" = yes; then
+       # Warning - without using the other runtime loading flags (-brtl),
+       # -berok will link without error, but may produce a broken library.
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok'
+       # Determine the default libpath from the value encoded in an empty executable.
+       _LT_AC_SYS_LIBPATH_AIX
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag"
+       else
+       if test "$host_cpu" = ia64; then
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib'
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs"
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols"
+       else
+        # Determine the default libpath from the value encoded in an empty executable.
+        _LT_AC_SYS_LIBPATH_AIX
+        _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath"
+         # Warning - without using the other run time loading flags,
+         # -berok will link without error, but may produce a broken library.
+         _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok'
+         _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok'
+         # -bexpall does not export symbols beginning with underscore (_)
+         _LT_AC_TAGVAR(always_export_symbols, $1)=yes
+         # Exported symbols can be pulled into shared objects from archives
+         _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' '
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+         # This is similar to how AIX traditionally builds it's shared libraries.
+         _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname'
+       fi
+      fi
+      ;;
+
+    amigaos*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      # see comment about different semantics on the GNU ld section
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    bsdi4*)
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic
+      ;;
+
+    cygwin* | mingw* | pw32*)
+      # When not using gcc, we currently assume that we are using
+      # Microsoft Visual C++.
+      # hardcode_libdir_flag_spec is actually meaningless, as there is
+      # no search path for DLLs.
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' '
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      # Tell ltmain to make .lib files, not .a files.
+      libext=lib
+      # Tell ltmain to make .dll files, not .so files.
+      shrext=".dll"
+      # FIXME: Setting linknames here is a bad hack.
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames='
+      # The linker will automatically build a .lib file if we build a DLL.
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true'
+      # FIXME: Should let the user specify the lib program.
+      _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs'
+      fix_srcfile_path='`cygpath -w "$srcfile"`'
+      _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes
+      ;;
+
+    darwin* | rhapsody*)
+    if test "$GXX" = yes ; then
+      _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+      case "$host_os" in
+      rhapsody* | darwin1.[[012]])
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress'
+       ;;
+      *) # Darwin 1.3 on
+      if test -z ${MACOSX_DEPLOYMENT_TARGET} ; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+      else
+        case ${MACOSX_DEPLOYMENT_TARGET} in
+          10.[[012]])
+            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress'
+            ;;
+          10.*)
+            _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined dynamic_lookup'
+            ;;
+        esac
+      fi
+       ;;
+      esac
+       lt_int_apple_cc_single_mod=no
+       output_verbose_link_cmd='echo'
+       if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then
+         lt_int_apple_cc_single_mod=yes
+       fi
+       if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+       else
+        _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring'
+      fi
+      _LT_AC_TAGVAR(module_cmds, $1)='$CC ${wl}-bind_at_load $allow_undefined_flag -o $lib -bundle $libobjs $deplibs$compiler_flags'
+      # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's
+        if test "X$lt_int_apple_cc_single_mod" = Xyes ; then
+          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+        else
+          _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+        fi
+          _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[    ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC $allow_undefined_flag  -o $lib -bundle $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=no
+      _LT_AC_TAGVAR(hardcode_automatic, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported
+      _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience'
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+    else
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+    fi
+      ;;
+
+    dgux*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    freebsd1*)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+
+    # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor
+    # support.  Future versions do this automatically, but an explicit c++rt0.o
+    # does not break anything, and helps significantly (at the cost of a little
+    # extra space).
+    freebsd2.2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # Unfortunately, older versions of FreeBSD 2 do not have this feature.
+    freebsd2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    # FreeBSD 3 and greater uses gcc -shared to do shared libraries.
+    freebsd* | kfreebsd*-gnu)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    hpux9*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+
+      # hardcode_minus_L: Not really in the search PATH,
+      # but as the default location of the library.
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      ;;
+
+    hpux10* | hpux11*)
+      if test "$GCC" = yes -a "$with_gnu_ld" = no; then
+       case "$host_cpu" in
+       hppa*64*|ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'
+         ;;
+       esac
+      else
+       case "$host_cpu" in
+       hppa*64*|ia64*)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags'
+         ;;
+       *)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'
+         ;;
+       esac
+      fi
+      if test "$with_gnu_ld" = no; then
+       case "$host_cpu" in
+       hppa*64*)
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+         _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+         ;;
+       ia64*)
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+         _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       *)
+         _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir'
+         _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+         _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+
+         # hardcode_minus_L: Not really in the search PATH,
+         # but as the default location of the library.
+         _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+         ;;
+       esac
+      fi
+      ;;
+
+    irix5* | irix6* | nonstopux*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    netbsd*)
+      if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'  # a.out
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags'      # ELF
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    newsos6)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    openbsd*)
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+       _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E'
+      else
+       case $host_os in
+        openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*)
+          _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags'
+          _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+          ;;
+        *)
+          _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags'
+          _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir'
+          ;;
+       esac
+      fi
+      ;;
+
+    os2*)
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported
+      _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def'
+      _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def'
+      ;;
+
+    osf3*)
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+      else
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    osf4* | osf5*)     # as osf3* with the addition of -msym flag
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir'
+      else
+       _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*'
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~
+       $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp'
+
+       # Both c and cxx compiler support -rpath directly
+       _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=:
+      ;;
+
+    sco3.2v5*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport'
+      runpath_var=LD_RUN_PATH
+      hardcode_runpath_var=yes
+      ;;
+
+    solaris*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+         $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+       $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      case $host_os in
+      solaris2.[[0-5]] | solaris2.[[0-5]].*) ;;
+      *) # Supported since Solaris 2.6 (maybe 2.5.1?)
+       _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;;
+      esac
+      _LT_AC_TAGVAR(link_all_deplibs, $1)=yes
+      ;;
+
+    sunos4*)
+      if test "x$host_vendor" = xsequent; then
+       # Use $CC to link under sequent, because it throws in some extra .o
+       # files that make .init and .fini sections work.
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags'
+      fi
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4)
+      case $host_vendor in
+       sni)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true???
+       ;;
+       siemens)
+         ## LD is ld it makes a PLAMLIB
+         ## CC just makes a GrossModule.
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no
+        ;;
+       motorola)
+         _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+         _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie
+       ;;
+      esac
+      runpath_var='LD_RUN_PATH'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv4.3*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport'
+      ;;
+
+    sysv4*MP*)
+      if test -d /usr/nec; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+       _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+       runpath_var=LD_RUN_PATH
+       hardcode_runpath_var=yes
+       _LT_AC_TAGVAR(ld_shlibs, $1)=yes
+      fi
+      ;;
+
+    sysv4.2uw2*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_direct, $1)=yes
+      _LT_AC_TAGVAR(hardcode_minus_L, $1)=no
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      hardcode_runpath_var=yes
+      runpath_var=LD_RUN_PATH
+      ;;
+
+   sysv5OpenUNIX8* | sysv5UnixWare7* |  sysv5uw[[78]]* | unixware7*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text'
+      if test "$GCC" = yes; then
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      else
+       _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags'
+      fi
+      runpath_var='LD_RUN_PATH'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    sysv5*)
+      _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text'
+      # $CC -shared without GNU ld will not create a library from C++
+      # object files and a static libstdc++, better avoid it by now
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~
+               $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      runpath_var='LD_RUN_PATH'
+      ;;
+
+    uts4*)
+      _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags'
+      _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir'
+      _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no
+      ;;
+
+    *)
+      _LT_AC_TAGVAR(ld_shlibs, $1)=no
+      ;;
+    esac
+  fi
+])
+AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)])
+test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no
+
+variables_saved_for_relink="PATH $shlibpath_var $runpath_var"
+if test "$GCC" = yes; then
+  variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH"
+fi
+
+#
+# Do we need to explicitly link libc?
+#
+case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in
+x|xyes)
+  # Assume -lc should be added
+  _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+
+  if test "$enable_shared" = yes && test "$GCC" = yes; then
+    case $_LT_AC_TAGVAR(archive_cmds, $1) in
+    *'~'*)
+      # FIXME: we may have to deal with multi-command sequences.
+      ;;
+    '$CC '*)
+      # Test whether the compiler implicitly links with -lc since on some
+      # systems, -lgcc has to come before -lc. If gcc already passes -lc
+      # to ld, don't add -lc before -lgcc.
+      AC_MSG_CHECKING([whether -lc should be explicitly linked in])
+      $rm conftest*
+      printf "$lt_simple_compile_test_code" > conftest.$ac_ext
+
+      if AC_TRY_EVAL(ac_compile) 2>conftest.err; then
+        soname=conftest
+        lib=conftest
+        libobjs=conftest.$ac_objext
+        deplibs=
+        wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)
+        compiler_flags=-v
+        linker_flags=-v
+        verstring=
+        output_objdir=.
+        libname=conftest
+        lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1)
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=
+        if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1)
+        then
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no
+        else
+         _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes
+        fi
+        _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag
+      else
+        cat conftest.err 1>&5
+      fi
+      $rm conftest*
+      AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)])
+      ;;
+    esac
+  fi
+  ;;
+esac
+])# AC_LIBTOOL_PROG_LD_SHLIBS
+
+
+# _LT_AC_FILE_LTDLL_C
+# -------------------
+# Be careful that the start marker always follows a newline.
+AC_DEFUN([_LT_AC_FILE_LTDLL_C], [
+# /* ltdll.c starts here */
+# #define WIN32_LEAN_AND_MEAN
+# #include <windows.h>
+# #undef WIN32_LEAN_AND_MEAN
+# #include <stdio.h>
+#
+# #ifndef __CYGWIN__
+# #  ifdef __CYGWIN32__
+# #    define __CYGWIN__ __CYGWIN32__
+# #  endif
+# #endif
+#
+# #ifdef __cplusplus
+# extern "C" {
+# #endif
+# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved);
+# #ifdef __cplusplus
+# }
+# #endif
+#
+# #ifdef __CYGWIN__
+# #include <cygwin/cygwin_dll.h>
+# DECLARE_CYGWIN_DLL( DllMain );
+# #endif
+# HINSTANCE __hDllInstance_base;
+#
+# BOOL APIENTRY
+# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved)
+# {
+#   __hDllInstance_base = hInst;
+#   return TRUE;
+# }
+# /* ltdll.c ends here */
+])# _LT_AC_FILE_LTDLL_C
+
+
+# _LT_AC_TAGVAR(VARNAME, [TAGNAME])
+# ---------------------------------
+AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])])
+
+
+# old names
+AC_DEFUN([AM_PROG_LIBTOOL],   [AC_PROG_LIBTOOL])
+AC_DEFUN([AM_ENABLE_SHARED],  [AC_ENABLE_SHARED($@)])
+AC_DEFUN([AM_ENABLE_STATIC],  [AC_ENABLE_STATIC($@)])
+AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)])
+AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)])
+AC_DEFUN([AM_PROG_LD],        [AC_PROG_LD])
+AC_DEFUN([AM_PROG_NM],        [AC_PROG_NM])
+
+# This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])
+
+AC_DEFUN([LT_AC_PROG_GCJ],
+[AC_CHECK_TOOL(GCJ, gcj, no)
+  test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2"
+  AC_SUBST(GCJFLAGS)
+])
+
+AC_DEFUN([LT_AC_PROG_RC],
+[AC_CHECK_TOOL(RC, windres, no)
+])
+
+# NOTE: This macro has been submitted for inclusion into   #
+#  GNU Autoconf as AC_PROG_SED.  When it is available in   #
+#  a released version of Autoconf we should remove this    #
+#  macro and use it instead.                               #
+# LT_AC_PROG_SED
+# --------------
+# Check for a fully-functional sed program, that truncates
+# as few characters as possible.  Prefer GNU sed if found.
+AC_DEFUN([LT_AC_PROG_SED],
+[AC_MSG_CHECKING([for a sed that does not truncate output])
+AC_CACHE_VAL(lt_cv_path_SED,
+[# Loop through the user's path and test for sed and gsed.
+# Then use that list of sed's as ones to test for truncation.
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for lt_ac_prog in sed gsed; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then
+        lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext"
+      fi
+    done
+  done
+done
+lt_ac_max=0
+lt_ac_count=0
+# Add /usr/xpg4/bin/sed as it is typically found on Solaris
+# along with /bin/sed that truncates output.
+for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do
+  test ! -f $lt_ac_sed && break
+  cat /dev/null > conftest.in
+  lt_ac_count=0
+  echo $ECHO_N "0123456789$ECHO_C" >conftest.in
+  # Check for GNU sed and select it if it is found.
+  if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then
+    lt_cv_path_SED=$lt_ac_sed
+    break
+  fi
+  while true; do
+    cat conftest.in conftest.in >conftest.tmp
+    mv conftest.tmp conftest.in
+    cp conftest.in conftest.nl
+    echo >>conftest.nl
+    $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break
+    cmp -s conftest.out conftest.nl || break
+    # 10000 chars as input seems more than enough
+    test $lt_ac_count -gt 10 && break
+    lt_ac_count=`expr $lt_ac_count + 1`
+    if test $lt_ac_count -gt $lt_ac_max; then
+      lt_ac_max=$lt_ac_count
+      lt_cv_path_SED=$lt_ac_sed
+    fi
+  done
+done
+SED=$lt_cv_path_SED
+])
+AC_MSG_RESULT([$SED])
+])
+
+#                                                        -*- Autoconf -*-
+# Copyright (C) 2002, 2003  Free Software Foundation, Inc.
+# Generated from amversion.in; do not edit by hand.
+
+# 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
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+AC_DEFUN([AM_AUTOMAKE_VERSION], [am__api_version="1.8"])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION so it can be traced.
+# This function is AC_REQUIREd by AC_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+        [AM_AUTOMAKE_VERSION([1.8.3])])
+
+# AM_AUX_DIR_EXPAND
+
+# Copyright (C) 2001, 2003 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.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                              -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003 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.
+
+# serial 6
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])
+AC_SUBST([$1_FALSE])
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.])
+fi])])
+
+# Do all the work for Automake.                            -*- Autoconf -*-
+
+# This macro actually does too much some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# 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.
+
+# serial 11
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.58])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+# test to see if srcdir already configured
+if test "`cd $srcdir && pwd`" != "`pwd`" &&
+   test -f $srcdir/config.status; then
+  AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AM_MISSING_PROG(AMTAR, tar)
+AM_PROG_INSTALL_SH
+AM_PROG_INSTALL_STRIP
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                  [_AM_DEPENDENCIES(CC)],
+                  [define([AC_PROG_CC],
+                          defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                  [_AM_DEPENDENCIES(CXX)],
+                  [define([AC_PROG_CXX],
+                          defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+])
+])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $1 | $1:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count])
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+
+# Copyright (C) 2001, 2003 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.
+
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+install_sh=${install_sh-"$am_aux_dir/install-sh"}
+AC_SUBST(install_sh)])
+
+#                                                          -*- Autoconf -*-
+# Copyright (C) 2003  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.
+
+# serial 1
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+
+# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+# 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.
+
+# serial 4
+
+# AM_PROG_LEX
+# -----------
+# Autoconf leaves LEX=: if lex or flex can't be found.  Change that to a
+# "missing" invocation, for better error output.
+AC_DEFUN([AM_PROG_LEX],
+[AC_PREREQ(2.50)dnl
+AC_REQUIRE([AM_MISSING_HAS_RUN])dnl
+AC_REQUIRE([AC_PROG_LEX])dnl
+if test "$LEX" = :; then
+  LEX=${am_missing_run}flex
+fi])
+
+# Add --enable-maintainer-mode option to configure.
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 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.
+
+# serial 3
+
+AC_DEFUN([AM_MAINTAINER_MODE],
+[AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles])
+  dnl maintainer-mode is disabled by default
+  AC_ARG_ENABLE(maintainer-mode,
+[  --enable-maintainer-mode  enable make rules and dependencies not useful
+                         (and sometimes confusing) to the casual installer],
+      USE_MAINTAINER_MODE=$enableval,
+      USE_MAINTAINER_MODE=no)
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL(MAINTAINER_MODE, [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST(MAINT)dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+#  -*- Autoconf -*-
+
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003 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.
+
+# serial 3
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing"
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check whether `mkdir -p' is supported, fallback to mkinstalldirs otherwise.
+
+# Copyright (C) 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.
+
+# Automake 1.8 used `mkdir -m 0755 -p --' to ensure that directories
+# created by `make install' are always world readable, even if the
+# installer happens to have an overly restrictive umask (e.g. 077).
+# This was a mistake.  There are at least two reasons why we must not
+# use `-m 0755':
+#   - it causes special bits like SGID to be ignored,
+#   - it may be too restrictive (some setups expect 775 directories).
+#
+# Do not use -m 0755 and let people choose whatever they expect by
+# setting umask.
+#
+# We cannot accept any implementation of `mkdir' that recognizes `-p'.
+# Some implementations (such as Solaris 8's) are not thread-safe: if a
+# parallel make tries to run `mkdir -p a/b' and `mkdir -p a/c'
+# concurrently, both version can detect that a/ is missing, but only
+# one can create it and the other will error out.  Consequently we
+# restrict ourselves to GNU make (using the --version option ensures
+# this.)
+AC_DEFUN([AM_PROG_MKDIR_P],
+[if mkdir -p --version . >/dev/null 2>&1 && test ! -d ./--version; then
+  # Keeping the `.' argument allows $(mkdir_p) to be used without
+  # argument.  Indeed, we sometimes output rules like
+  #   $(mkdir_p) $(somedir)
+  # where $(somedir) is conditionally defined.
+  # (`test -n '$(somedir)' && $(mkdir_p) $(somedir)' is a more
+  # expensive solution, as it forces Make to start a sub-shell.)
+  mkdir_p='mkdir -p -- .'
+else
+  # On NextStep and OpenStep, the `mkdir' command does not
+  # recognize any option.  It will interpret all options as
+  # directories to create, and then abort because `.' already
+  # exists.
+  for d in ./-p ./--version;
+  do
+    test -d $d && rmdir $d
+  done
+  # $(mkinstalldirs) is defined by Automake if mkinstalldirs exists.
+  if test -f "$ac_aux_dir/mkinstalldirs"; then
+    mkdir_p='$(mkinstalldirs)'
+  else
+    mkdir_p='$(install_sh) -d'
+  fi
+fi
+AC_SUBST([mkdir_p])])
+
+# Helper functions for option handling.                    -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003  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.
+
+# serial 2
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+#
+# Check to make sure that the build environment is sane.
+#
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003 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.
+
+# serial 3
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t $srcdir/configure conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# AM_PROG_INSTALL_STRIP
+
+# Copyright (C) 2001, 2003 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.
+
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+m4_include([cf/aix.m4])
+m4_include([cf/auth-modules.m4])
+m4_include([cf/broken-getaddrinfo.m4])
+m4_include([cf/broken-getnameinfo.m4])
+m4_include([cf/broken-glob.m4])
+m4_include([cf/broken-realloc.m4])
+m4_include([cf/broken-snprintf.m4])
+m4_include([cf/broken.m4])
+m4_include([cf/broken2.m4])
+m4_include([cf/c-attribute.m4])
+m4_include([cf/capabilities.m4])
+m4_include([cf/check-compile-et.m4])
+m4_include([cf/check-getpwnam_r-posix.m4])
+m4_include([cf/check-man.m4])
+m4_include([cf/check-netinet-ip-and-tcp.m4])
+m4_include([cf/check-type-extra.m4])
+m4_include([cf/check-var.m4])
+m4_include([cf/check-x.m4])
+m4_include([cf/check-xau.m4])
+m4_include([cf/crypto.m4])
+m4_include([cf/db.m4])
+m4_include([cf/destdirs.m4])
+m4_include([cf/dlopen.m4])
+m4_include([cf/find-func-no-libs.m4])
+m4_include([cf/find-func-no-libs2.m4])
+m4_include([cf/find-func.m4])
+m4_include([cf/find-if-not-broken.m4])
+m4_include([cf/have-struct-field.m4])
+m4_include([cf/have-type.m4])
+m4_include([cf/irix.m4])
+m4_include([cf/krb-bigendian.m4])
+m4_include([cf/krb-func-getlogin.m4])
+m4_include([cf/krb-ipv6.m4])
+m4_include([cf/krb-prog-ln-s.m4])
+m4_include([cf/krb-readline.m4])
+m4_include([cf/krb-struct-spwd.m4])
+m4_include([cf/krb-struct-winsize.m4])
+m4_include([cf/largefile.m4])
+m4_include([cf/mips-abi.m4])
+m4_include([cf/misc.m4])
+m4_include([cf/need-proto.m4])
+m4_include([cf/osfc2.m4])
+m4_include([cf/otp.m4])
+m4_include([cf/proto-compat.m4])
+m4_include([cf/pthreads.m4])
+m4_include([cf/retsigtype.m4])
+m4_include([cf/roken-frag.m4])
+m4_include([cf/sunos.m4])
+m4_include([cf/telnet.m4])
+m4_include([cf/test-package.m4])
+m4_include([cf/wflags.m4])
+m4_include([cf/win32.m4])
+m4_include([cf/with-all.m4])
+m4_include([acinclude.m4])
diff --git a/src/kerberosV/src/admin/CVS/Entries b/src/kerberosV/src/admin/CVS/Entries
new file mode 100644 (file)
index 0000000..c70df70
--- /dev/null
@@ -0,0 +1,14 @@
+/ChangeLog/1.1.1.1/Fri Apr 14 07:31:51 2006//
+/add.c/1.1.1.5/Fri Apr 14 07:31:51 2006//
+/change.c/1.1.1.5/Fri Apr 14 07:31:51 2006//
+/copy.c/1.1.1.4/Fri Apr 14 07:31:51 2006//
+/get.c/1.1.1.6/Fri Apr 14 07:31:51 2006//
+/ktutil-commands.in/1.1.1.1/Fri Apr 14 07:31:51 2006//
+/ktutil.8/1.1.1.5/Fri Apr 14 07:31:51 2006//
+/ktutil.c/1.4/Fri Apr 14 08:15:03 2006//
+/ktutil_locl.h/1.4/Fri Apr 14 08:15:03 2006//
+/list.c/1.6/Fri Apr 14 08:15:03 2006//
+/purge.c/1.1.1.4/Fri Apr 14 07:31:52 2006//
+/remove.c/1.1.1.4/Fri Apr 14 07:31:52 2006//
+/rename.c/1.1.1.2/Fri Apr 14 07:31:52 2006//
+D
diff --git a/src/kerberosV/src/admin/CVS/Repository b/src/kerberosV/src/admin/CVS/Repository
new file mode 100644 (file)
index 0000000..b99a55e
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/admin
diff --git a/src/kerberosV/src/admin/CVS/Root b/src/kerberosV/src/admin/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/admin/ChangeLog b/src/kerberosV/src/admin/ChangeLog
new file mode 100644 (file)
index 0000000..b9a6471
--- /dev/null
@@ -0,0 +1,50 @@
+2005-05-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * change.c (kt_change): plug memory leak from
+       krb5_kt_remove_entry, print principal on error.
+
+2005-05-02  Dave Love  <d.love@dl.ac.uk>
+
+       * ktutil.c (help): Don't use non-constant initializer for `fake'.
+
+2005-04-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ktutil_locl.h: include <hex.h>
+
+2005-04-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * add.c: add option -H --hex to the add command
+       
+       * ktutil-commands.in: add option -H --hex to the add command
+       
+       * ktutil.8: document option -H --hex to the add command
+
+2004-09-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * list.c: un c99'ify, from Anders.Magnusson@ltu.se
+
+2004-09-23 Johan Danielsson <joda@pdc.kth.se>
+
+       * purge.c: convert to slc; don't purge keys older that a certain
+       time, instead purge keys that have newer versions that are at
+       least a certain age
+
+       * rename.c: convert to slc
+       
+       * remove.c: convert to slc
+       
+       * get.c: convert to slc; warn if resetting disallow-all-tix
+       
+       * copy.c: convert to slc
+       
+       * change.c: convert to slc
+       
+       * add.c: convert to slc
+       
+       * list.c: convert to slc
+       
+       * ktutil_locl.h: convert to slc
+       
+       * ktutil.c: convert to slc
+       
+       * ktutil-commands.in: slc source file
diff --git a/src/kerberosV/src/admin/add.c b/src/kerberosV/src/admin/add.c
new file mode 100644 (file)
index 0000000..38d3660
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: add.c,v 1.8 2005/04/14 16:45:14 lha Exp $");
+
+static char *
+readstring(const char *prompt, char *buf, size_t len)
+{
+    printf("%s", prompt);
+    if (fgets(buf, len, stdin) == NULL)
+       return NULL;
+    buf[strcspn(buf, "\r\n")] = '\0';
+    return buf;
+}
+
+int
+kt_add(struct add_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_keytab keytab;
+    krb5_keytab_entry entry;
+    char buf[1024];
+    krb5_enctype enctype;
+
+    if((keytab = ktutil_open_keytab()) == NULL)
+       return 1;
+
+    memset(&entry, 0, sizeof(entry));
+    if(opt->principal_string == NULL) {
+       if(readstring("Principal: ", buf, sizeof(buf)) == NULL)
+           return 1;
+       opt->principal_string = buf;
+    }
+    ret = krb5_parse_name(context, opt->principal_string, &entry.principal);
+    if(ret) {
+       krb5_warn(context, ret, "%s", opt->principal_string);
+       goto out;
+    }
+    if(opt->enctype_string == NULL) {
+       if(readstring("Encryption type: ", buf, sizeof(buf)) == NULL) {
+           ret = 1;
+           goto out;
+       }
+       opt->enctype_string = buf;
+    }
+    ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
+    if(ret) {
+       int t;
+       if(sscanf(opt->enctype_string, "%d", &t) == 1)
+           enctype = t;
+       else {
+           krb5_warn(context, ret, "%s", opt->enctype_string);
+           goto out;
+       }
+    }
+    if(opt->kvno_integer == -1) {
+       if(readstring("Key version: ", buf, sizeof(buf)) == NULL) {
+           ret = 1;
+           goto out;
+       }
+       if(sscanf(buf, "%u", &opt->kvno_integer) != 1)
+           goto out;
+    }
+    if(opt->password_string == NULL && opt->random_flag == 0) {
+       if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 1)) {
+           ret = 1;
+           goto out;
+       }
+       opt->password_string = buf;
+    }
+    if(opt->password_string) {
+       if (opt->hex_flag) {
+           size_t len;
+           void *data;
+           
+           len = (strlen(opt->password_string) + 1) / 2;
+
+           data = malloc(len);
+           if (data == NULL) {
+               krb5_warn(context, ENOMEM, "malloc");
+               goto out;
+           }
+
+           if (hex_decode(opt->password_string, data, len) != len) {
+               free(data);
+               krb5_warn(context, ENOMEM, "hex decode failed");
+               goto out;
+           }
+
+           ret = krb5_keyblock_init(context, enctype, 
+                                    data, len, &entry.keyblock);
+           free(data);
+       } else if (!opt->salt_flag) {
+           krb5_salt salt;
+           krb5_data pw;
+
+           salt.salttype         = KRB5_PW_SALT;
+           salt.saltvalue.data   = NULL;
+           salt.saltvalue.length = 0;
+           pw.data = (void*)opt->password_string;
+           pw.length = strlen(opt->password_string);
+           ret = krb5_string_to_key_data_salt(context, enctype, pw, salt,
+                                              &entry.keyblock);
+        } else {
+           ret = krb5_string_to_key(context, enctype, opt->password_string, 
+                                    entry.principal, &entry.keyblock);
+       }
+       memset (opt->password_string, 0, strlen(opt->password_string));
+    } else {
+       ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock);
+    }
+    if(ret) {
+       krb5_warn(context, ret, "add");
+       goto out;
+    }
+    entry.vno = opt->kvno_integer;
+    entry.timestamp = time (NULL);
+    ret = krb5_kt_add_entry(context, keytab, &entry);
+    if(ret)
+       krb5_warn(context, ret, "add");
+ out:
+    krb5_kt_free_entry(context, &entry);
+    krb5_kt_close(context, keytab);
+    return ret != 0;
+}
diff --git a/src/kerberosV/src/admin/change.c b/src/kerberosV/src/admin/change.c
new file mode 100644 (file)
index 0000000..3b45468
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: change.c,v 1.7 2005/05/19 14:03:16 lha Exp $");
+
+static krb5_error_code
+change_entry (krb5_context context, krb5_keytab keytab,
+             krb5_principal principal, krb5_kvno kvno,
+             const char *realm, const char *admin_server, int server_port)
+{
+    krb5_error_code ret;
+    kadm5_config_params conf;
+    void *kadm_handle;
+    char *client_name;
+    krb5_keyblock *keys;
+    int num_keys;
+    int i;
+
+    ret = krb5_unparse_name (context, principal, &client_name);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_unparse_name");
+       return ret;
+    }
+
+    memset (&conf, 0, sizeof(conf));
+
+    if(realm)
+       conf.realm = (char *)realm;
+    else
+       conf.realm = (char*)krb5_principal_get_realm(context, principal);
+    conf.mask |= KADM5_CONFIG_REALM;
+    
+    if (admin_server) {
+       conf.admin_server = (char *)admin_server;
+       conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
+    }
+
+    if (server_port) {
+       conf.kadmind_port = htons(server_port);
+       conf.mask |= KADM5_CONFIG_KADMIND_PORT;
+    }
+
+    ret = kadm5_init_with_skey_ctx (context,
+                                   client_name,
+                                   keytab_string,
+                                   KADM5_ADMIN_SERVICE,
+                                   &conf, 0, 0,
+                                   &kadm_handle);
+    if (ret) {
+       krb5_warn (context, ret,
+                  "kadm5_c_init_with_skey_ctx: %s:", client_name);
+       free (client_name);
+       return ret;
+    }
+    ret = kadm5_randkey_principal (kadm_handle, principal, &keys, &num_keys);
+    kadm5_destroy (kadm_handle);
+    if (ret) {
+       krb5_warn(context, ret, "kadm5_randkey_principal: %s:", client_name);
+       free (client_name);
+       return ret;
+    }
+    free (client_name);
+    for (i = 0; i < num_keys; ++i) {
+       krb5_keytab_entry new_entry;
+
+       new_entry.principal = principal;
+       new_entry.timestamp = time (NULL);
+       new_entry.vno = kvno + 1;
+       new_entry.keyblock  = keys[i];
+
+       ret = krb5_kt_add_entry (context, keytab, &new_entry);
+       if (ret)
+           krb5_warn (context, ret, "krb5_kt_add_entry");
+       krb5_free_keyblock_contents (context, &keys[i]);
+    }
+    return ret;
+}
+
+/*
+ * loop over all the entries in the keytab (or those given) and change
+ * their keys, writing the new keys
+ */
+
+struct change_set {
+    krb5_principal principal;
+    krb5_kvno kvno;
+};
+
+int
+kt_change (struct change_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_keytab keytab;
+    krb5_kt_cursor cursor;
+    krb5_keytab_entry entry;
+    int i, j, max;
+    struct change_set *changeset;
+    int errors = 0;
+    
+    if((keytab = ktutil_open_keytab()) == NULL)
+       return 1;
+
+    j = 0;
+    max = 0;
+    changeset = NULL;
+
+    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+    if(ret){
+       krb5_warn(context, ret, "%s", keytab_string);
+       goto out;
+    }
+
+    while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
+       int add = 0;
+
+       for (i = 0; i < j; ++i) {
+           if (krb5_principal_compare (context, changeset[i].principal,
+                                       entry.principal)) {
+               if (changeset[i].kvno < entry.vno)
+                   changeset[i].kvno = entry.vno;
+               break;
+           }
+       }
+       if (i < j) {
+           krb5_kt_free_entry (context, &entry);
+           continue;
+       }
+
+       if (argc == 0) {
+           add = 1;
+       } else {
+           for (i = 0; i < argc; ++i) {
+               krb5_principal princ;
+
+               ret = krb5_parse_name (context, argv[i], &princ);
+               if (ret) {
+                   krb5_warn (context, ret, "%s", argv[i]);
+                   continue;
+               }
+               if (krb5_principal_compare (context, princ, entry.principal))
+                   add = 1;
+
+               krb5_free_principal (context, princ);
+           }
+       }
+
+       if (add) {
+           if (j >= max) {
+               void *tmp;
+
+               max = max(max * 2, 1);
+               tmp = realloc (changeset, max * sizeof(*changeset));
+               if (tmp == NULL) {
+                   krb5_kt_free_entry (context, &entry);
+                   krb5_warnx (context, "realloc: out of memory");
+                   ret = ENOMEM;
+                   break;
+               }
+               changeset = tmp;
+           }
+           ret = krb5_copy_principal (context, entry.principal,
+                                      &changeset[j].principal);
+           if (ret) {
+               krb5_warn (context, ret, "krb5_copy_principal");
+               krb5_kt_free_entry (context, &entry);
+               break;
+           }
+           changeset[j].kvno = entry.vno;
+           ++j;
+       }
+       krb5_kt_free_entry (context, &entry);
+    }
+    krb5_kt_end_seq_get(context, keytab, &cursor);
+
+    if (ret == KRB5_KT_END) {
+       ret = 0;
+       for (i = 0; i < j; i++) {
+           if (verbose_flag) {
+               char *client_name;
+
+               ret = krb5_unparse_name (context, changeset[i].principal, 
+                                        &client_name);
+               if (ret) {
+                   krb5_warn (context, ret, "krb5_unparse_name");
+               } else {
+                   printf("Changing %s kvno %d\n", 
+                          client_name, changeset[i].kvno);
+                   free(client_name);
+               }
+           }
+           ret = change_entry (context, keytab, 
+                               changeset[i].principal, changeset[i].kvno,
+                               opt->realm_string, 
+                               opt->admin_server_string, 
+                               opt->server_port_integer);
+           if (ret != 0)
+               errors = 1;
+       }
+    } else
+       errors = 1;
+    for (i = 0; i < j; i++)
+       krb5_free_principal (context, changeset[i].principal);
+    free (changeset);
+
+ out:
+    krb5_kt_close(context, keytab);
+    return errors;
+}
diff --git a/src/kerberosV/src/admin/copy.c b/src/kerberosV/src/admin/copy.c
new file mode 100644 (file)
index 0000000..e4a227c
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: copy.c,v 1.10 2004/09/23 14:43:53 joda Exp $");
+
+
+static krb5_boolean
+compare_keyblock(const krb5_keyblock *a, const krb5_keyblock *b)
+{
+    if(a->keytype != b->keytype ||
+       a->keyvalue.length != b->keyvalue.length ||
+       memcmp(a->keyvalue.data, b->keyvalue.data, a->keyvalue.length) != 0)
+       return FALSE;
+    return TRUE;
+}
+
+static int
+kt_copy_int (const char *from, const char *to)
+{
+    krb5_error_code ret;
+    krb5_keytab src_keytab, dst_keytab;
+    krb5_kt_cursor cursor;
+    krb5_keytab_entry entry, dummy;
+
+    ret = krb5_kt_resolve (context, from, &src_keytab);
+    if (ret) {
+       krb5_warn (context, ret, "resolving src keytab `%s'", from);
+       return 1;
+    }
+
+    ret = krb5_kt_resolve (context, to, &dst_keytab);
+    if (ret) {
+       krb5_kt_close (context, src_keytab);
+       krb5_warn (context, ret, "resolving dst keytab `%s'", to);
+       return 1;
+    }
+
+    ret = krb5_kt_start_seq_get (context, src_keytab, &cursor);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_kt_start_seq_get %s", keytab_string);
+       goto out;
+    }
+
+    if (verbose_flag)
+       fprintf(stderr, "copying %s to %s\n", from, to);
+
+    while((ret = krb5_kt_next_entry(context, src_keytab,
+                                   &entry, &cursor)) == 0) {
+       char *name_str;
+       char *etype_str;
+       ret = krb5_unparse_name (context, entry.principal, &name_str);
+       if(ret) {
+           krb5_warn(context, ret, "krb5_unparse_name");
+           name_str = NULL; /* XXX */
+       }
+       ret = krb5_enctype_to_string(context, entry.keyblock.keytype, &etype_str);
+       if(ret) {
+           krb5_warn(context, ret, "krb5_enctype_to_string");
+           etype_str = NULL; /* XXX */
+       }
+       ret = krb5_kt_get_entry(context, dst_keytab, 
+                               entry.principal, 
+                               entry.vno, 
+                               entry.keyblock.keytype,
+                               &dummy);
+       if(ret == 0) {
+           /* this entry is already in the new keytab, so no need to
+               copy it; if the keyblocks are not the same, something
+               is weird, so complain about that */
+           if(!compare_keyblock(&entry.keyblock, &dummy.keyblock)) {
+               krb5_warnx(context, "entry with different keyvalue "
+                          "already exists for %s, keytype %s, kvno %d", 
+                          name_str, etype_str, entry.vno);
+           }
+           krb5_kt_free_entry(context, &dummy);
+           krb5_kt_free_entry (context, &entry);
+           free(name_str);
+           free(etype_str);
+           continue;
+       } else if(ret != KRB5_KT_NOTFOUND) {
+           krb5_warn (context, ret, "%s: fetching %s/%s/%u", 
+                      to, name_str, etype_str, entry.vno);
+           krb5_kt_free_entry (context, &entry);
+           free(name_str);
+           free(etype_str);
+           break;
+       }
+       if (verbose_flag)
+           fprintf (stderr, "copying %s, keytype %s, kvno %d\n", name_str, 
+                    etype_str, entry.vno);
+       ret = krb5_kt_add_entry (context, dst_keytab, &entry);
+       krb5_kt_free_entry (context, &entry);
+       if (ret) {
+           krb5_warn (context, ret, "%s: adding %s/%s/%u", 
+                      to, name_str, etype_str, entry.vno);
+           free(name_str);
+           free(etype_str);
+           break;
+       }
+       free(name_str);
+       free(etype_str);
+    }
+    krb5_kt_end_seq_get (context, src_keytab, &cursor);
+
+  out:
+    krb5_kt_close (context, src_keytab);
+    krb5_kt_close (context, dst_keytab);
+    return ret != 0;
+}
+
+int
+kt_copy (void *opt, int argc, char **argv)
+{
+    return kt_copy_int(argv[0], argv[1]);
+}
+
+int
+srvconv(struct srvconvert_options *opt, int argc, char **argv)
+{
+    char kt4[1024], kt5[1024];
+
+    snprintf(kt4, sizeof(kt4), "krb4:%s", opt->srvtab_string);
+
+    if(keytab_string != NULL)
+       return kt_copy_int(kt4, keytab_string);
+
+    krb5_kt_default_modify_name(context, kt5, sizeof(kt5));
+    return kt_copy_int(kt4, kt5);
+}
+
+int
+srvcreate(struct srvcreate_options *opt, int argc, char **argv)
+{
+    char kt4[1024], kt5[1024];
+
+    snprintf(kt4, sizeof(kt4), "krb4:%s", opt->srvtab_string);
+
+    if(keytab_string != NULL)
+       return kt_copy_int(keytab_string, kt4);
+
+    krb5_kt_default_name(context, kt5, sizeof(kt5));
+    return kt_copy_int(kt5, kt4);
+}
diff --git a/src/kerberosV/src/admin/get.c b/src/kerberosV/src/admin/get.c
new file mode 100644 (file)
index 0000000..8082921
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: get.c,v 1.24 2004/09/23 14:44:57 joda Exp $");
+
+static void*
+open_kadmin_connection(char *principal,
+                      const char *realm, 
+                      char *admin_server, 
+                      int server_port)
+{
+    static kadm5_config_params conf;
+    krb5_error_code ret;
+    void *kadm_handle;
+    memset(&conf, 0, sizeof(conf));
+
+    if(realm) {
+       conf.realm = (char*)realm;
+       conf.mask |= KADM5_CONFIG_REALM;
+    }
+    
+    if (admin_server) {
+       conf.admin_server = admin_server;
+       conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
+    }
+
+    if (server_port) {
+       conf.kadmind_port = htons(server_port);
+       conf.mask |= KADM5_CONFIG_KADMIND_PORT;
+    }
+
+    /* should get realm from each principal, instead of doing
+       everything with the same (local) realm */
+
+    ret = kadm5_init_with_password_ctx(context, 
+                                      principal,
+                                      NULL,
+                                      KADM5_ADMIN_SERVICE,
+                                      &conf, 0, 0, 
+                                      &kadm_handle);
+    if(ret) {
+       krb5_warn(context, ret, "kadm5_init_with_password");
+       return NULL;
+    }
+    return kadm_handle;
+}
+
+int
+kt_get(struct get_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret = 0;
+    krb5_keytab keytab;
+    void *kadm_handle = NULL;
+    krb5_enctype *etypes = NULL;
+    size_t netypes = 0;
+    int i = 0, j;
+    unsigned int failed = 0;
+    
+    if((keytab = ktutil_open_keytab()) == NULL)
+       return 1;
+
+    if(opt->realm_string)
+       krb5_set_default_realm(context, opt->realm_string);
+
+    if (opt->enctypes_strings.num_strings != 0) {
+       int i;
+
+       etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
+       if (etypes == NULL) {
+           krb5_warnx(context, "malloc failed");
+           goto out;
+       }
+       netypes = opt->enctypes_strings.num_strings;
+       for(i = 0; i < netypes; i++) {
+           ret = krb5_string_to_enctype(context, 
+                                        opt->enctypes_strings.strings[i], 
+                                        &etypes[i]);
+           if(ret) {
+               krb5_warnx(context, "unrecognized enctype: %s",
+                          opt->enctypes_strings.strings[i]);
+               goto out;
+           }
+       }
+    }
+
+    
+    for(i = 0; i < argc; i++){
+       krb5_principal princ_ent;
+       kadm5_principal_ent_rec princ;
+       int mask = 0;
+       krb5_keyblock *keys;
+       int n_keys;
+       int created = 0;
+       krb5_keytab_entry entry;
+
+       ret = krb5_parse_name(context, argv[i], &princ_ent);
+       if (ret) {
+           krb5_warn(context, ret, "can't parse principal %s", argv[i]);
+           failed++;
+           continue;
+       }
+       memset(&princ, 0, sizeof(princ));
+       princ.principal = princ_ent;
+       mask |= KADM5_PRINCIPAL;
+       princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+       mask |= KADM5_ATTRIBUTES;
+       princ.princ_expire_time = 0;
+       mask |= KADM5_PRINC_EXPIRE_TIME;
+
+       if(kadm_handle == NULL) {
+           const char *r;
+           if(opt->realm_string != NULL)
+               r = opt->realm_string;
+           else
+               r = krb5_principal_get_realm(context, princ_ent);
+           kadm_handle = open_kadmin_connection(opt->principal_string, 
+                                                r, 
+                                                opt->admin_server_string, 
+                                                opt->server_port_integer);
+           if(kadm_handle == NULL)
+               break;
+       }
+       
+       ret = kadm5_create_principal(kadm_handle, &princ, mask, "x");
+       if(ret == 0)
+           created = 1;
+       else if(ret != KADM5_DUP) {
+           krb5_warn(context, ret, "kadm5_create_principal(%s)", argv[i]);
+           krb5_free_principal(context, princ_ent);
+           failed++;
+           continue;
+       }
+       ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
+       if (ret) {
+           krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[i]);
+           krb5_free_principal(context, princ_ent);
+           failed++;
+           continue;
+       }
+       
+       ret = kadm5_get_principal(kadm_handle, princ_ent, &princ, 
+                             KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
+       if (ret) {
+           krb5_warn(context, ret, "kadm5_get_principal(%s)", argv[i]);
+           for (j = 0; j < n_keys; j++)
+               krb5_free_keyblock_contents(context, &keys[j]);
+           krb5_free_principal(context, princ_ent);
+           failed++;
+           continue;
+       }
+       if(!created && (princ.attributes & KRB5_KDB_DISALLOW_ALL_TIX))
+           krb5_warnx(context, "%s: disallow-all-tix flag set - clearing", argv[i]);
+       princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
+       mask = KADM5_ATTRIBUTES;
+       if(created) {
+           princ.kvno = 1;
+           mask |= KADM5_KVNO;
+       }
+       ret = kadm5_modify_principal(kadm_handle, &princ, mask);
+       if (ret) {
+           krb5_warn(context, ret, "kadm5_modify_principal(%s)", argv[i]);
+           for (j = 0; j < n_keys; j++)
+               krb5_free_keyblock_contents(context, &keys[j]);
+           krb5_free_principal(context, princ_ent);
+           failed++;
+           continue;
+       }
+       for(j = 0; j < n_keys; j++) {
+           int do_add = TRUE;
+
+           if (netypes) {
+               int i;
+
+               do_add = FALSE;
+               for (i = 0; i < netypes; ++i)
+                   if (keys[j].keytype == etypes[i]) {
+                       do_add = TRUE;
+                       break;
+                   }
+           }
+           if (do_add) {
+               entry.principal = princ_ent;
+               entry.vno = princ.kvno;
+               entry.keyblock = keys[j];
+               entry.timestamp = time (NULL);
+               ret = krb5_kt_add_entry(context, keytab, &entry);
+               if (ret)
+                   krb5_warn(context, ret, "krb5_kt_add_entry");
+           }
+           krb5_free_keyblock_contents(context, &keys[j]);
+       }
+       
+       kadm5_free_principal_ent(kadm_handle, &princ);
+       krb5_free_principal(context, princ_ent);
+    }
+ out:
+    free(etypes);
+    if (kadm_handle)
+       kadm5_destroy(kadm_handle);
+    krb5_kt_close(context, keytab);
+    return ret != 0 || failed > 0;
+}
diff --git a/src/kerberosV/src/admin/ktutil-commands.in b/src/kerberosV/src/admin/ktutil-commands.in
new file mode 100644 (file)
index 0000000..f004ab2
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+/* $KTH: ktutil-commands.in,v 1.2 2005/04/14 16:44:30 lha Exp $ */
+
+command = {
+       name = "add"
+       option = {
+               long = "principal"
+               short = "p"
+               type = "string"
+               help = "principal to add"
+               argument = "principal"
+               default = ""
+       }
+       option = {
+               long = "kvno"
+               short = "V"
+               type = "integer"
+               help = "key version number"
+               default = "-1"
+       }
+       option = {
+               long = "enctype"
+               short = "e"
+               type = "string"
+               argument = "enctype"
+               help = "encryption type"
+       }
+       option = {
+               long = "password"
+               short = "w"
+               type = "string"
+               help = "password for key"
+       }
+       option = {
+               long = "salt"
+               short = "s"
+               type = "-flag"
+               help = "use unsalted keys"
+               default = "1"
+       }
+       option = {
+               long = "random"
+               short = "r"
+               type = "flag"
+               help = "generate random key"
+       }
+       option = {
+               long = "hex"
+               short = "H"
+               type = "flag"
+               help = "password is a hexadecimal string"
+       }
+       function = "kt_add"
+       help = "Adds a key to a keytab."
+       max_args = "0"
+}
+command = {
+       name = "change"
+       option = {
+               long = "realm"
+               short = "r"
+               type = "string"
+               argument = "realm"
+               help = "realm to use"
+       }
+       option = {
+               long = "admin-server"
+               short = "a"
+               type = "string"
+               argument = "host"
+               help = "server to contact"
+       }
+       option = {
+               long = "server-port"
+               short = "s"
+               type = "integer"
+               argument = "port number"
+               help = "port number on server"
+       }
+       function = "kt_change"
+       argument = "[principal...]"
+       help = "Change keys for specified principals (default all)."
+}
+command = {
+       name = "copy"
+       function = "kt_copy"
+       argument = "source destination"
+       min_args = "2"
+       max_args = "2"
+       help = "Copies one keytab to another."
+}
+command = {
+       name = "get"
+       option = {
+               long = "principal"
+               short = "p"
+               type = "string"
+               help = "admin principal"
+               argument = "principal"
+       }
+       option = {
+               long = "enctypes"
+               short = "e"
+               type = "strings"
+               help = "encryption types to use"
+               argument = "enctype"
+       }
+       option = {
+               long = "realm"
+               short = "r"
+               type = "string"
+               argument = "realm"
+               help = "realm to use"
+       }
+       option = {
+               long = "admin-server"
+               short = "a"
+               type = "string"
+               argument = "host"
+               help = "server to contact"
+       }
+       option = {
+               long = "server-port"
+               short = "s"
+               type = "integer"
+               argument = "port number"
+               help = "port number on server"
+       }
+       function = "kt_get"
+       min_args = "1"
+       argument = "principal..."
+       help = "Change keys for specified principals, and add them to the keytab."
+}
+command = {
+       name = "list"
+       option = {
+               long = "keys"
+               type = "flag"
+               help = "show key values"
+       }
+       option = {
+               long = "timestamp"
+               type = "flag"
+               help = "show timestamps"
+       }
+       max_args = "0"
+       function = "kt_list"
+       help = "Show contents of keytab."
+}
+command = {
+       name = "purge"
+       option = {
+               long = "age"
+               type = "string"
+               help = "age to retiere"
+               default = "1 week";
+               argument = "time"
+       }
+       max_args = "0"
+       function = "kt_purge"
+       help = "Remove superceded keys from keytab."
+}
+command = {
+       name = "remove"
+       name = "delete"
+       option = {
+               long = "principal"
+               short = "p"
+               type = "string"
+               help = "principal to remove"
+               argument = "principal"
+       }
+       option = {
+               long = "kvno"
+               short = "V"
+               type = "integer"
+               help = "key version to remove"
+               argument = "enctype"
+               default = "0"
+       }
+       option = {
+               long = "enctype"
+               short = "e"
+               type = "string"
+               help = "enctype to remove"
+               argument = "enctype"
+       }
+       max_args = "0"
+       function = "kt_remove"
+       help = "Remove keys from keytab."
+}
+command = {
+       name = "rename"
+       function = "kt_rename"
+       argument = "from to"
+       min_args = "2"
+       max_args = "2"
+       help = "Renames an entry in the keytab."
+}
+command = {
+       name = "srvconvert"
+       name = "srv2keytab"
+       option = {
+               long = "srvtab"
+               short = "s"
+               type = "string"
+               argument = "file"
+               help = "name of Kerberos 4 srvtab"
+               default = "/etc/srvtab"
+       }
+       max_args = "0"
+       function = "srvconv"
+       help = "Convert a Kerberos 4 srvtab to a keytab."
+}
+command = {
+       name = "srvcreate"
+       name = "key2srvtab"
+       option = {
+               long = "srvtab"
+               short = "s"
+               type = "string"
+               argument = "file"
+               help = "name of Kerberos 4 srvtab"
+               default = "/etc/srvtab"
+       }
+       max_args = "0"
+       function = "srvcreate"
+       help = "Convert a keytab to a Kerberos 4 srvtab."
+}
+command = {
+       name = "help"
+       argument = "command"
+       max_args = "1"
+       function = "help"
+}
diff --git a/src/kerberosV/src/admin/ktutil.8 b/src/kerberosV/src/admin/ktutil.8
new file mode 100644 (file)
index 0000000..91bd3a7
--- /dev/null
@@ -0,0 +1,196 @@
+.\" Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: ktutil.8,v 1.21 2005/04/14 16:43:57 lha Exp $
+.\"
+.Dd April 14, 2005
+.Dt KTUTIL 8
+.Os HEIMDAL
+.Sh NAME
+.Nm ktutil
+.Nd manage Kerberos keytabs
+.Sh SYNOPSIS
+.Nm
+.Oo Fl k Ar keytab \*(Ba Xo
+.Fl -keytab= Ns Ar keytab
+.Xc
+.Oc
+.Op Fl v | Fl -verbose
+.Op Fl -version
+.Op Fl h | Fl -help
+.Ar command
+.Op Ar args
+.Sh DESCRIPTION
+.Nm
+is a program for managing keytabs.
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl v ,
+.Fl -verbose
+.Xc
+Verbose output.
+.El
+.Pp
+.Ar command
+can be one of the following:
+.Bl -tag -width srvconvert
+.It add Xo
+.Op Fl p Ar principal
+.Op Fl -principal= Ns Ar principal
+.Op Fl V Ar kvno
+.Op Fl -kvno= Ns Ar kvno
+.Op Fl e Ar enctype
+.Op Fl -enctype= Ns Ar enctype
+.Op Fl w Ar password
+.Op Fl -password= Ns Ar password
+.Op Fl r
+.Op Fl -random
+.Op Fl s
+.Op Fl -no-salt
+.Op Fl H
+.Op Fl -hex
+.Xc
+Adds a key to the keytab. Options that are not specified will be
+prompted for. This requires that you know the password or the hex key of the
+principal to add; if what you really want is to add a new principal to
+the keytab, you should consider the
+.Ar get
+command, which talks to the kadmin server.
+.It change Xo
+.Op Fl r Ar realm
+.Op Fl -realm= Ns Ar realm
+.Op Fl -a Ar host
+.Op Fl -admin-server= Ns Ar host
+.Op Fl -s Ar port
+.Op Fl -server-port= Ns Ar port
+.Xc
+Update one or several keys to new versions.  By default, use the admin
+server for the realm of a keytab entry.  Otherwise it will use the
+values specified by the options.
+.Pp
+If no principals are given, all the ones in the keytab are updated.
+.It copy Xo
+.Ar keytab-src
+.Ar keytab-dest
+.Xc
+Copies all the entries from
+.Ar keytab-src
+to
+.Ar keytab-dest .
+.It get Xo
+.Op Fl p Ar admin principal
+.Op Fl -principal= Ns Ar admin principal
+.Op Fl e Ar enctype
+.Op Fl -enctypes= Ns Ar enctype
+.Op Fl r Ar realm
+.Op Fl -realm= Ns Ar realm
+.Op Fl a Ar admin server
+.Op Fl -admin-server= Ns Ar admin server
+.Op Fl s Ar server port
+.Op Fl -server-port= Ns Ar server port
+.Ar principal ...
+.Xc
+For each
+.Ar principal ,
+generate a new key for it (creating it if it doesn't already exist),
+and put that key in the keytab.
+.Pp
+If no
+.Ar realm
+is specified, the realm to operate on is taken from the first
+principal.
+.It list Xo
+.Op Fl -keys
+.Op Fl -timestamp
+.Xc
+List the keys stored in the keytab.
+.It remove Xo
+.Op Fl p Ar principal
+.Op Fl -principal= Ns Ar principal
+.Op Fl V kvno
+.Op Fl -kvno= Ns Ar kvno
+.Op Fl e enctype
+.Op Fl -enctype= Ns Ar enctype
+.Xc
+Removes the specified key or keys. Not specifying a
+.Ar kvno
+removes keys with any version number. Not specifying an
+.Ar enctype
+removes keys of any type.
+.It rename Xo
+.Ar from-principal
+.Ar to-principal
+.Xc
+Renames all entries in the keytab that match the
+.Ar from-principal
+to
+.Ar to-principal .
+.It purge Xo
+.Op Fl -age= Ns Ar age
+.Xc
+Removes all old versions of a key for which there is a newer version
+that is at least
+.Ar age
+(default one week) old.
+.It srvconvert
+.It srv2keytab Xo
+.Op Fl s Ar srvtab
+.Op Fl -srvtab= Ns Ar srvtab
+.Xc
+Converts the version 4 srvtab in
+.Ar srvtab
+to a version 5 keytab and stores it in
+.Ar keytab .
+Identical to:
+.Bd -ragged -offset indent
+.Li ktutil copy
+.Li krb4: Ns Ar srvtab
+.Ar keytab
+.Ed
+.It srvcreate
+.It key2srvtab Xo
+.Op Fl s Ar srvtab
+.Op Fl -srvtab= Ns Ar srvtab
+.Xc
+Converts the version 5 keytab in
+.Ar keytab
+to a version 4 srvtab and stores it in
+.Ar srvtab .
+Identical to:
+.Bd -ragged -offset indent
+.Li ktutil copy
+.Ar keytab
+.Li krb4: Ns Ar srvtab
+.Ed
+.El
+.Sh SEE ALSO
+.Xr kadmin 8
diff --git a/src/kerberosV/src/admin/ktutil.c b/src/kerberosV/src/admin/ktutil.c
new file mode 100644 (file)
index 0000000..f9c001d
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+#include <err.h>
+
+RCSID("$KTH: ktutil.c,v 1.38 2005/05/02 19:10:19 lha Exp $");
+
+static int help_flag;
+static int version_flag;
+int verbose_flag;
+char *keytab_string; 
+static char keytab_buf[256];
+
+static struct getargs args[] = {
+    { 
+       "version",
+       0,
+       arg_flag,
+       &version_flag,
+       NULL,
+       NULL 
+    },
+    { 
+       "help",     
+       'h',   
+       arg_flag, 
+       &help_flag, 
+       NULL, 
+       NULL
+    },
+    { 
+       "keytab",           
+       'k',   
+       arg_string, 
+       &keytab_string, 
+       "keytab", 
+       "keytab to operate on" 
+    },
+    {
+       "verbose",
+       'v',
+       arg_flag,
+       &verbose_flag,
+       "verbose",
+       "run verbosely"
+    }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+krb5_context context;
+
+krb5_keytab
+ktutil_open_keytab(void)
+{
+    krb5_error_code ret;
+    krb5_keytab keytab;
+    if (keytab_string == NULL) {
+       ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf));
+       if (ret) {
+           krb5_warn(context, ret, "krb5_kt_default_name");
+           return NULL;
+       }
+       keytab_string = keytab_buf;
+    }
+    ret = krb5_kt_resolve(context, keytab_string, &keytab);
+    if (ret) {
+       krb5_warn(context, ret, "resolving keytab %s", keytab_string);
+       return NULL;
+    }
+    if (verbose_flag)
+       fprintf (stderr, "Using keytab %s\n", keytab_string);
+       
+    return keytab;
+}
+
+int
+help(void *opt, int argc, char **argv)
+{
+    if(argc == 0) {
+       sl_help(commands, 1, argv - 1 /* XXX */);
+    } else {
+       SL_cmd *c = sl_match (commands, argv[0], 0);
+       if(c == NULL) {
+           fprintf (stderr, "No such command: %s. "
+                    "Try \"help\" for a list of commands\n",
+                    argv[0]);
+       } else {
+           if(c->func) {
+               char *fake[] = { NULL, "--help", NULL };
+               fake[0] = argv[0];
+               (*c->func)(2, fake);
+               fprintf(stderr, "\n");
+           }
+           if(c->help && *c->help)
+               fprintf (stderr, "%s\n", c->help);
+           if((++c)->name && c->func == NULL) {
+               int f = 0;
+               fprintf (stderr, "Synonyms:");
+               while (c->name && c->func == NULL) {
+                   fprintf (stderr, "%s%s", f ? ", " : " ", (c++)->name);
+                   f = 1;
+               }
+               fprintf (stderr, "\n");
+           }
+       }
+    }
+    return 0;
+}
+
+static void
+usage(int status)
+{
+    arg_printusage(args, num_args, NULL, "command");
+    exit(status);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    krb5_error_code ret;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    argc -= optind;
+    argv += optind;
+    if(argc == 0)
+       usage(1);
+    ret = sl_command(commands, argc, argv);
+    if(ret == -1)
+       krb5_warnx (context, "unrecognized command: %s", argv[0]);
+    return ret;
+}
diff --git a/src/kerberosV/src/admin/ktutil_locl.h b/src/kerberosV/src/admin/ktutil_locl.h
new file mode 100644 (file)
index 0000000..6450d66
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* 
+ * $KTH: ktutil_locl.h,v 1.20 2005/04/15 05:02:39 lha Exp $
+ */
+
+#ifndef __KTUTIL_LOCL_H__
+#define __KTUTIL_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <parse_time.h>
+#include <roken.h>
+
+#include "crypto-headers.h"
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm5_err.h>
+
+#include <sl.h>
+#include <getarg.h>
+#include <hex.h>
+
+extern krb5_context context;
+
+extern int verbose_flag;
+extern char *keytab_string; 
+
+krb5_keytab ktutil_open_keytab(void);
+
+#include "ktutil-commands.h"
+
+#endif /* __KTUTIL_LOCL_H__ */
diff --git a/src/kerberosV/src/admin/list.c b/src/kerberosV/src/admin/list.c
new file mode 100644 (file)
index 0000000..5b49534
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+#include <rtbl.h>
+
+RCSID("$KTH: list.c,v 1.13 2004/09/29 11:17:13 lha Exp $");
+
+static int
+do_list(struct list_options *opt, const char *keytab_string)
+{
+    krb5_error_code ret;
+    krb5_keytab keytab;
+    krb5_keytab_entry entry;
+    krb5_kt_cursor cursor;
+    rtbl_t table;
+
+    /* XXX specialcase the ANY type */
+    if(strncasecmp(keytab_string, "ANY:", 4) == 0) {
+       int flag = 0;
+       char buf[1024];
+       keytab_string += 4;
+       ret = 0;
+       while (strsep_copy((const char**)&keytab_string, ",", 
+                          buf, sizeof(buf)) != -1) {
+           if(flag)
+               printf("\n");
+           if(do_list(opt, buf))
+               ret = 1;
+           flag = 1;
+       }
+       return ret;
+    }
+
+    ret = krb5_kt_resolve(context, keytab_string, &keytab);
+    if (ret) {
+       krb5_warn(context, ret, "resolving keytab %s", keytab_string);
+       return ret;
+    }
+
+    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+    if(ret) {
+       krb5_warn(context, ret, "krb5_kt_start_seq_get %s", keytab_string);
+       krb5_kt_close(context, keytab);
+       return ret;
+    }
+
+    printf ("%s:\n\n", keytab_string);
+       
+    table = rtbl_create();
+    rtbl_add_column_by_id(table, 0, "Vno", RTBL_ALIGN_RIGHT);
+    rtbl_add_column_by_id(table, 1, "Type", 0);
+    rtbl_add_column_by_id(table, 2, "Principal", 0);
+    if (opt->timestamp_flag)
+       rtbl_add_column_by_id(table, 3, "Date", 0);
+    if(opt->keys_flag)
+       rtbl_add_column_by_id(table, 4, "Key", 0);
+    rtbl_set_separator(table, "  ");
+
+    while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
+       char buf[1024], *s;
+
+       snprintf(buf, sizeof(buf), "%d", entry.vno);
+       rtbl_add_column_entry_by_id(table, 0, buf);
+
+       ret = krb5_enctype_to_string(context, 
+                                    entry.keyblock.keytype, &s);
+       if (ret != 0) {
+           snprintf(buf, sizeof(buf), "unknown (%d)", entry.keyblock.keytype);
+           rtbl_add_column_entry_by_id(table, 1, buf);
+       } else {
+           rtbl_add_column_entry_by_id(table, 1, s);
+           free(s);
+       }
+
+       krb5_unparse_name_fixed(context, entry.principal, buf, sizeof(buf));
+       rtbl_add_column_entry_by_id(table, 2, buf);
+
+       if (opt->timestamp_flag) {
+           krb5_format_time(context, entry.timestamp, buf, 
+                            sizeof(buf), FALSE);
+           rtbl_add_column_entry_by_id(table, 3, buf);
+       }
+       if(opt->keys_flag) {
+           int i;
+           s = malloc(2 * entry.keyblock.keyvalue.length + 1);
+           for(i = 0; i < entry.keyblock.keyvalue.length; i++)
+               snprintf(s + 2 * i, 3, "%02x", 
+                        ((unsigned char*)entry.keyblock.keyvalue.data)[i]);
+           rtbl_add_column_entry_by_id(table, 4, s);
+           free(s);
+       }
+       krb5_kt_free_entry(context, &entry);
+    }
+    ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+    rtbl_format(table, stdout);
+    rtbl_destroy(table);
+
+    krb5_kt_close(context, keytab);
+    return ret;
+}
+
+int
+kt_list(struct list_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    char kt[1024];
+
+    if(verbose_flag)
+       opt->timestamp_flag = 1;
+
+    if (keytab_string == NULL) {
+       if((ret = krb5_kt_default_name(context, kt, sizeof(kt))) != 0) {
+           krb5_warn(context, ret, "getting default keytab name");
+           return 1;
+       }
+       keytab_string = kt;
+    }
+    return do_list(opt, keytab_string) != 0;
+}
diff --git a/src/kerberosV/src/admin/purge.c b/src/kerberosV/src/admin/purge.c
new file mode 100644 (file)
index 0000000..35b841c
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: purge.c,v 1.7 2004/09/23 14:46:43 joda Exp $");
+
+/*
+ * keep track of the highest version for every principal.
+ */
+
+struct e {
+    krb5_principal principal;
+    int max_vno;
+    time_t timestamp;
+    struct e *next;
+};
+
+static struct e *
+get_entry (krb5_principal princ, struct e *head)
+{
+    struct e *e;
+
+    for (e = head; e != NULL; e = e->next)
+       if (krb5_principal_compare (context, princ, e->principal))
+           return e;
+    return NULL;
+}
+
+static void
+add_entry (krb5_principal princ, int vno, time_t timestamp, struct e **head)
+{
+    krb5_error_code ret;
+    struct e *e;
+
+    e = get_entry (princ, *head);
+    if (e != NULL) {
+       if(e->max_vno < vno) {
+           e->max_vno = vno;
+           e->timestamp = timestamp;
+       }
+       return;
+    }
+    e = malloc (sizeof (*e));
+    if (e == NULL)
+       krb5_errx (context, 1, "malloc: out of memory");
+    ret = krb5_copy_principal (context, princ, &e->principal);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_copy_principal");
+    e->max_vno = vno;
+    e->timestamp = timestamp;
+    e->next    = *head;
+    *head      = e;
+}
+
+static void
+delete_list (struct e *head)
+{
+    while (head != NULL) {
+       struct e *next = head->next;
+       krb5_free_principal (context, head->principal);
+       free (head);
+       head = next;
+    }
+}
+
+/*
+ * Remove all entries that have newer versions and that are older
+ * than `age'
+ */
+
+int
+kt_purge(struct purge_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret = 0;
+    krb5_kt_cursor cursor;
+    krb5_keytab keytab;
+    krb5_keytab_entry entry;
+    int age;
+    struct e *head = NULL;
+    time_t judgement_day;
+
+    age = parse_time(opt->age_string, "s");
+    if(age < 0) {
+       krb5_warnx(context, "unparasable time `%s'", opt->age_string);
+       return 1;
+    }
+
+    if((keytab = ktutil_open_keytab()) == NULL)
+       return 1;
+
+    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+    if(ret){
+       krb5_warn(context, ret, "%s", keytab_string);
+       goto out;
+    }
+
+    while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
+       add_entry (entry.principal, entry.vno, entry.timestamp, &head);
+       krb5_kt_free_entry(context, &entry);
+    }
+    ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+
+    judgement_day = time (NULL);
+
+    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+    if(ret){
+       krb5_warn(context, ret, "%s", keytab_string);
+       goto out;
+    }
+
+    while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
+       struct e *e = get_entry (entry.principal, head);
+
+       if (e == NULL) {
+           krb5_warnx (context, "ignoring extra entry");
+           continue;
+       }
+
+       if (entry.vno < e->max_vno
+           && judgement_day - e->timestamp > age) {
+           if (verbose_flag) {
+               char *name_str;
+
+               krb5_unparse_name (context, entry.principal, &name_str);
+               printf ("removing %s vno %d\n", name_str, entry.vno);
+               free (name_str);
+           }
+           ret = krb5_kt_remove_entry (context, keytab, &entry);
+           if (ret)
+               krb5_warn (context, ret, "remove");
+       }
+       krb5_kt_free_entry(context, &entry);
+    }
+    ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+
+    delete_list (head);
+
+ out:
+    krb5_kt_close (context, keytab);
+    return ret != 0;
+}
diff --git a/src/kerberosV/src/admin/remove.c b/src/kerberosV/src/admin/remove.c
new file mode 100644 (file)
index 0000000..6807af7
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: remove.c,v 1.4 2004/09/23 14:45:18 joda Exp $");
+
+int
+kt_remove(struct remove_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret = 0;
+    krb5_keytab_entry entry;
+    krb5_keytab keytab;
+    krb5_principal principal = NULL;
+    krb5_enctype enctype = 0;
+
+    if(opt->principal_string) {
+       ret = krb5_parse_name(context, opt->principal_string, &principal);
+       if(ret) {
+           krb5_warn(context, ret, "%s", opt->principal_string);
+           return 1;
+       }
+    }
+    if(opt->enctype_string) {
+       ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
+       if(ret) {
+           int t;
+           if(sscanf(opt->enctype_string, "%d", &t) == 1)
+               enctype = t;
+           else {
+               krb5_warn(context, ret, "%s", opt->enctype_string);
+               if(principal)
+                   krb5_free_principal(context, principal);
+               return 1;
+           }
+       }
+    }
+    if (!principal && !enctype && !opt->kvno_integer) {
+       krb5_warnx(context, 
+                  "You must give at least one of "
+                  "principal, enctype or kvno.");
+       return 1;
+    }
+
+    if((keytab = ktutil_open_keytab()) == NULL)
+       return 1;
+
+    entry.principal = principal;
+    entry.keyblock.keytype = enctype;
+    entry.vno = opt->kvno_integer;
+    ret = krb5_kt_remove_entry(context, keytab, &entry);
+    krb5_kt_close(context, keytab);
+    if(ret)
+       krb5_warn(context, ret, "remove");
+    if(principal)
+       krb5_free_principal(context, principal);
+    return ret != 0;
+}
+
diff --git a/src/kerberosV/src/admin/rename.c b/src/kerberosV/src/admin/rename.c
new file mode 100644 (file)
index 0000000..d8b762a
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2001-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "ktutil_locl.h"
+
+RCSID("$KTH: rename.c,v 1.2 2004/09/23 14:45:29 joda Exp $");
+
+int
+kt_rename(void *opt, int argc, char **argv)
+{
+    krb5_error_code ret = 0;
+    krb5_keytab_entry entry;
+    krb5_keytab keytab;
+    krb5_kt_cursor cursor;
+    krb5_principal from_princ, to_princ;
+
+    ret = krb5_parse_name(context, argv[0], &from_princ);
+    if(ret != 0) {
+       krb5_warn(context, ret, "%s", argv[0]);
+       return 1;
+    }
+
+    ret = krb5_parse_name(context, argv[1], &to_princ);
+    if(ret != 0) {
+       krb5_free_principal(context, from_princ);
+       krb5_warn(context, ret, "%s", argv[1]);
+       return 1;
+    }
+
+    if((keytab = ktutil_open_keytab()) == NULL) {
+       krb5_free_principal(context, from_princ);
+       krb5_free_principal(context, to_princ);
+       return 1;
+    }
+
+    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+    if(ret) {
+       krb5_kt_close(context, keytab);
+       krb5_free_principal(context, from_princ);
+       krb5_free_principal(context, to_princ);
+       return 1;
+    }
+    while(1) {
+       ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
+       if(ret != 0) {
+           if(ret != KRB5_CC_END && ret != KRB5_KT_END)
+               krb5_warn(context, ret, "getting entry from keytab");
+           else
+               ret = 0;
+           break;
+       }
+       if(krb5_principal_compare(context, entry.principal, from_princ)) {
+           krb5_free_principal(context, entry.principal);
+           entry.principal = to_princ;
+           ret = krb5_kt_add_entry(context, keytab, &entry);
+           if(ret) {
+               entry.principal = NULL;
+               krb5_kt_free_entry(context, &entry);
+               krb5_warn(context, ret, "adding entry");
+               break;
+           }
+           entry.principal = from_princ;
+           ret = krb5_kt_remove_entry(context, keytab, &entry);
+           if(ret) {
+               entry.principal = NULL;
+               krb5_kt_free_entry(context, &entry);
+               krb5_warn(context, ret, "removing entry");
+               break;
+           }
+           entry.principal = NULL;
+       }
+       krb5_kt_free_entry(context, &entry);
+    }
+    krb5_kt_end_seq_get(context, keytab, &cursor);
+
+    krb5_free_principal(context, from_princ);
+    krb5_free_principal(context, to_princ);
+
+    return ret != 0;
+}
+
diff --git a/src/kerberosV/src/appl/CVS/Entries b/src/kerberosV/src/appl/CVS/Entries
new file mode 100644 (file)
index 0000000..ed35090
--- /dev/null
@@ -0,0 +1,5 @@
+D/afsutil////
+D/login////
+D/popper////
+D/su////
+D/test////
diff --git a/src/kerberosV/src/appl/CVS/Repository b/src/kerberosV/src/appl/CVS/Repository
new file mode 100644 (file)
index 0000000..ba8b567
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/appl
diff --git a/src/kerberosV/src/appl/CVS/Root b/src/kerberosV/src/appl/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/appl/afsutil/CVS/Entries b/src/kerberosV/src/appl/afsutil/CVS/Entries
new file mode 100644 (file)
index 0000000..3e02297
--- /dev/null
@@ -0,0 +1,6 @@
+/ChangeLog/1.1.1.5/Fri Apr 14 07:31:53 2006//
+/afslog.1/1.1.1.1/Sun May 11 02:14:15 2003//
+/afslog.c/1.8/Fri Apr 14 08:15:03 2006//
+/pagsh.1/1.1.1.1/Fri Apr 14 07:31:53 2006//
+/pagsh.c/1.5/Thu May 17 10:58:01 2007//
+D
diff --git a/src/kerberosV/src/appl/afsutil/CVS/Repository b/src/kerberosV/src/appl/afsutil/CVS/Repository
new file mode 100644 (file)
index 0000000..e0219d5
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/appl/afsutil
diff --git a/src/kerberosV/src/appl/afsutil/CVS/Root b/src/kerberosV/src/appl/afsutil/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/appl/afsutil/ChangeLog b/src/kerberosV/src/appl/afsutil/ChangeLog
new file mode 100644 (file)
index 0000000..600d049
--- /dev/null
@@ -0,0 +1,103 @@
+2005-02-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: man_MANS += pagsh.1
+
+       * pagsh.c: add --cache-type that allows the user to control the
+       resulting credential cache type, inherit the type from the
+       invoking process
+
+       * pagsh.1: manpage for pagsh
+
+2004-09-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afslog.c: use negative string help string for arg_negative_flag
+       Pointed out by Harald Barth
+       
+2004-07-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * pagsh.c: use setprogname, if we stripped off -c, try use the
+       fallback code
+       
+2003-10-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * pagsh.c: mkstemp formats must end in exactly six X's
+
+2003-07-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afslog.c (do_afslog): is cell is unset, set it "<default cell>"
+       for error printing
+
+       * pagsh.c: unconditionally set KRBTKFILE
+       
+2003-04-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afslog.c (log_func): drop the error number
+       
+2003-04-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afslog.c: set kafs log function if verbose is turned on
+       
+2003-03-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * Makefile.am (LDADD): use LIB_kafs
+       
+       * afslog.1: --no-v4, --no-v5
+       
+       * Makefile.am: always build afsutils now
+       
+       * afslog.c: make build without KRB4
+       
+2002-11-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * afslog.c: remove plural form in help string
+
+       * Makefile.am: add afslog manpage
+
+       * afslog.1: manpage
+
+       * afslog.c: try more files when trying to expand a cell name
+
+       * afslog.c: create a list of cells to get tokens for, before
+       actually doing anything, and try to get tokens via krb4 if krb5
+       fails, and give it a chance to work with krb4-only; also some bug
+       fixes, partially from Tomas Olsson.
+
+2002-08-23  Assar Westerlund  <assar@kth.se>
+
+       * pagsh.c: make it handle --version/--help
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * afslog.c (main): call free_getarg_strings
+
+2000-12-31  Assar Westerlund  <assar@sics.se>
+
+       * afslog.c (main): handle krb5_init_context failure consistently
+
+2000-12-25  Assar Westerlund  <assar@sics.se>
+
+       * afslog.c: clarify usage strings
+
+1999-08-04  Assar Westerlund  <assar@sics.se>
+
+       * pagsh.c (main): use mkstemp to generate temporary file names.
+       From Miroslav Ruda <ruda@ics.muni.cz>
+
+1999-07-04  Assar Westerlund  <assar@sics.se>
+
+       * afslog.c (expand_cell_name): terminate on #.  From Miroslav Ruda
+       <ruda@ics.muni.cz>
+
+1999-06-27  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (bin_PROGRAMS): only include pagsh if KRB4
+
+1999-06-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add pagsh
+
+       * pagsh.c: new file.  contributed by Miroslav Ruda <ruda@ics.muni.cz>
+
+Sat Mar 27 12:49:43 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * afslog.c: cleanup option parsing
diff --git a/src/kerberosV/src/appl/afsutil/afslog.1 b/src/kerberosV/src/appl/afsutil/afslog.1
new file mode 100644 (file)
index 0000000..49ea503
--- /dev/null
@@ -0,0 +1,137 @@
+.\" Copyright (c) 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: afslog.1,v 1.3 2003/03/18 04:29:34 lha Exp $
+.\"
+.Dd November 26, 2002
+.Dt AFSLOG 1
+.Os HEIMDAL
+.Sh NAME
+.Nm afslog
+.Nd
+obtain AFS tokens
+.Sh SYNOPSIS
+.Nm
+.Oo Fl c Ar cell \*(Ba Xo
+.Fl -cell= Ns Ar cell
+.Xc
+.Oc
+.Oo Fl p Ar path \*(Ba Xo
+.Fl -file= Ns Ar path
+.Xc
+.Oc
+.Oo Fl k Ar realm \*(Ba Xo
+.Fl -realm= Ns Ar realm
+.Xc
+.Oc
+.Op Fl -no-v4
+.Op Fl -no-v5
+.Op Fl u | Fl -unlog
+.Op Fl v | Fl -verbose
+.Op Fl -version
+.Op Fl h | Fl -help
+.Op Ar cell | path ...
+.Sh DESCRIPTION
+.Nm
+obtains AFS tokens for a number of cells. What cells to get tokens for
+can either be specified as an explicit list, as file paths to get
+tokens for, or be left unspecified, in which case
+.Nm
+will use whatever magic 
+.Xr krb_afslog 3
+decides upon.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar cell,
+.Fl -cell= Ns Ar cell
+.Xc
+This specified one or more cell names to get tokens for.
+.It Xo
+.Fl p Ar path ,
+.Fl -file= Ns Ar path
+.Xc
+This specified one or more file paths for which tokens should be
+obtained.
+.It Xo
+.Fl k Ar realm ,
+.Fl -realm= Ns Ar realm
+.Xc
+This is the Kerberos realm the AFS servers live in, this should
+normally not be specified.
+.It Fl -no-v4
+This makes
+.Nm
+not try using Kerberos 4.
+.It Fl -no-v5
+This makes
+.Nm
+not try using Kerberos 5.
+.It Xo
+.Fl u ,
+.Fl -unlog
+.Xc
+Destroy tokens instead of obtaining new. If this is specified, all
+other options are ignored (except for
+.Fl -help
+and
+.Fl -version ) .
+.It Xo
+.Fl v ,
+.Fl -verbose
+.Xc
+Adds more verbosity for what is actually going on.
+.El
+Instead of using
+.Fl c
+and
+.Fl p ,
+you may also pass a list of cells and file paths after any other
+options. These arguments are considered files if they are either 
+the strings
+.Do . Dc
+or
+.Dq .. 
+or they contain a slash, or if there exists a file by that name.
+.Sh EXAMPLES
+Assuming that there is no file called 
+.Dq openafs.org
+in the current directory, and that 
+.Pa /afs/openafs.org
+points to that cell, the follwing should be identical:
+.Bd -literal -offset indent
+$ afslog -c openafs.org
+$ afslog openafs.org
+$ afslog /afs/openafs.org/some/file
+.Ed 
+.Sh SEE ALSO
+.Xr krb_afslog 3
diff --git a/src/kerberosV/src/appl/afsutil/afslog.c b/src/kerberosV/src/appl/afsutil/afslog.c
new file mode 100644 (file)
index 0000000..aec953a
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: afslog.c,v 1.24 2004/09/03 12:11:40 lha Exp $");
+#endif
+#include <ctype.h>
+#ifdef KRB5
+#include <krb5.h>
+#endif
+#ifdef KRB4
+#include <krb.h>
+#endif
+#include <kafs.h>
+#include <roken.h>
+#include <getarg.h>
+#include <err.h>
+
+static int help_flag;
+static int version_flag;
+#if 0
+static int create_user;
+#endif
+static getarg_strings cells;
+static char *realm;
+static getarg_strings files;
+static int unlog_flag;
+static int verbose;
+#ifdef KRB4
+static int use_krb4 = 1;
+#endif
+#ifdef KRB5
+static int use_krb5 = 1;
+#endif
+
+struct getargs args[] = {
+    { "cell",  'c', arg_strings, &cells, "cells to get tokens for", "cell" },
+    { "file",  'p', arg_strings, &files, "files to get tokens for", "path" },
+    { "realm", 'k', arg_string, &realm, "realm for afs cell", "realm" },
+    { "unlog", 'u', arg_flag, &unlog_flag, "remove tokens" },
+#ifdef KRB4
+    { "v4",     0, arg_negative_flag, &use_krb4, "don't use Kerberos 4" },
+#endif
+#ifdef KRB5
+    { "v5",     0, arg_negative_flag, &use_krb5, "don't use Kerberos 5" },
+#endif
+#if 0
+    { "create-user", 0, arg_flag, &create_user, "create user if not found" },
+#endif
+    { "verbose",'v', arg_flag, &verbose },
+    { "version", 0,  arg_flag, &version_flag },
+    { "help",  'h', arg_flag, &help_flag },
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+#ifdef KRB5
+krb5_context context;
+krb5_ccache id;
+#endif
+
+static const char *
+expand_one_file(FILE *f, const char *cell)
+{
+    static char buf[1024];
+    char *p;
+
+    while (fgets (buf, sizeof(buf), f) != NULL) {
+       if(buf[0] == '>') {
+           for(p = buf; *p && !isspace((unsigned char)*p) && *p != '#'; p++)
+               ;
+           *p = '\0';
+           if(strncmp(buf + 1, cell, strlen(cell)) == 0)
+               return buf + 1;
+       }
+       buf[0] = '\0';
+    }
+    return NULL;
+}
+
+static const char *
+expand_cell_name(const char *cell)
+{
+    FILE *f;
+    const char *c;
+    const char **fn, *files[] = { _PATH_CELLSERVDB,
+                                 _PATH_ARLA_CELLSERVDB,
+#if 0
+                                 _PATH_OPENAFS_DEBIAN_CELLSERVDB,
+                                 _PATH_ARLA_DEBIAN_CELLSERVDB,
+#endif
+                                 NULL };
+    for(fn = files; *fn; fn++) {
+       f = fopen(*fn, "r");
+       if(f == NULL)
+           continue;
+       c = expand_one_file(f, cell);
+       fclose(f);
+       if(c)
+           return c;
+    }
+    return cell;
+}
+
+#if 0
+static int
+createuser (char *cell)
+{
+    char cellbuf[64];
+    char name[ANAME_SZ];
+    char instance[INST_SZ];
+    char realm[REALM_SZ];
+    char cmd[1024];
+
+    if (cell == NULL) {
+       FILE *f;
+       int len;
+
+       f = fopen (_PATH_THISCELL, "r");
+       if (f == NULL)
+           err (1, "open(%s)", _PATH_THISCELL);
+       if (fgets (cellbuf, sizeof(cellbuf), f) == NULL)
+           err (1, "read cellname from %s", _PATH_THISCELL);
+       len = strlen(cellbuf);
+       if (cellbuf[len-1] == '\n')
+           cellbuf[len-1] = '\0';
+       cell = cellbuf;
+    }
+
+    if(krb_get_default_principal(name, instance, realm))
+       errx (1, "Could not even figure out who you are");
+
+    snprintf (cmd, sizeof(cmd),
+             "pts createuser %s%s%s@%s -cell %s",
+             name, *instance ? "." : "", instance, strlwr(realm),
+             cell);
+    DEBUG("Executing %s", cmd);
+    return system(cmd);
+}
+#endif
+
+static void
+usage(int ecode)
+{
+    arg_printusage(args, num_args, NULL, "[cell|path]...");
+    exit(ecode);
+}
+
+struct cell_list {
+    char *cell;
+    struct cell_list *next;
+} *cell_list;
+
+static int
+afslog_cell(const char *cell, int expand)
+{
+    struct cell_list *p, **q;
+    const char *c = cell;
+    if(expand){
+       c = expand_cell_name(cell);
+       if(c == NULL){
+           warnx("No cell matching \"%s\" found.", cell);
+           return -1;
+       }
+       if(verbose && strcmp(c, cell) != 0)
+           warnx("Cell \"%s\" expanded to \"%s\"", cell, c);
+    }
+    /* add to list of cells to get tokens for, and also remove
+       duplicates; the actual afslog takes place later */
+    for(p = cell_list, q = &cell_list; p; q = &p->next, p = p->next)
+       if(strcmp(p->cell, c) == 0)
+           return 0;
+    p = malloc(sizeof(*p));
+    if(p == NULL)
+       return -1;
+    p->cell = strdup(c);
+    if(p->cell == NULL) {
+       free(p);
+       return -1;
+    }
+    p->next = NULL;
+    *q = p;
+    return 0;
+}
+
+static int
+afslog_file(const char *path)
+{
+    char cell[64];
+    if(k_afs_cell_of_file(path, cell, sizeof(cell))){
+       warnx("No cell found for file \"%s\".", path);
+       return -1;
+    }
+    if(verbose)
+       warnx("File \"%s\" lives in cell \"%s\"", path, cell);
+    return afslog_cell(cell, 0);
+}
+
+static int
+do_afslog(const char *cell)
+{
+    int k5ret, k4ret;
+
+    k5ret = k4ret = 0;
+
+#ifdef KRB5
+    if(context != NULL && id != NULL && use_krb5) {
+       k5ret = krb5_afslog(context, id, cell, NULL);
+       if(k5ret == 0)
+           return 0;
+    }
+#endif
+#if KRB4
+    if (use_krb4) {
+       k4ret = krb_afslog(cell, NULL);
+       if(k4ret == 0)
+           return 0;
+    }
+#endif
+    if (cell == NULL)
+       cell = "<default cell>";
+#ifdef KRB5
+    if (k5ret)
+       warnx("krb5_afslog(%s): %s", cell, krb5_get_err_text(context, k5ret));
+#endif
+#ifdef KRB4
+    if (k4ret)
+       warnx("krb_afslog(%s): %s", cell, krb_get_err_text(k4ret));
+#endif
+    if (k5ret || k4ret)
+       return 1;
+    return 0;
+}
+
+static void
+log_func(void *ctx, const char *str)
+{
+    fprintf(stderr, "%s\n", str);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    int i;
+    int num;
+    int ret = 0;
+    int failed = 0;
+    struct cell_list *p;
+    
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if(!k_hasafs())
+       errx(1, "AFS does not seem to be present on this machine");
+
+    if(unlog_flag){
+       k_unlog();
+       exit(0);
+    }
+#ifdef KRB5
+    ret = krb5_init_context(&context);
+    if (ret)
+       context = NULL;
+    else
+       if(krb5_cc_default(context, &id) != 0)
+           id = NULL;
+#endif
+
+    if (verbose)
+       kafs_set_verbose(log_func, NULL);
+
+    num = 0;
+    for(i = 0; i < files.num_strings; i++){
+       afslog_file(files.strings[i]);
+       num++;
+    }
+    free_getarg_strings (&files);
+    for(i = 0; i < cells.num_strings; i++){
+       afslog_cell(cells.strings[i], 1);
+       num++;
+    }
+    free_getarg_strings (&cells);
+    for(i = optind; i < argc; i++){
+       num++;
+       if(strcmp(argv[i], ".") == 0 ||
+          strcmp(argv[i], "..") == 0 ||
+          strchr(argv[i], '/') ||
+          access(argv[i], F_OK) == 0)
+           afslog_file(argv[i]);
+       else
+           afslog_cell(argv[i], 1);
+    }    
+    if(num == 0) {
+       if(do_afslog(NULL))
+           failed++;
+    } else
+       for(p = cell_list; p; p = p->next) {
+           if(verbose)
+               warnx("Getting tokens for cell \"%s\"", p->cell);
+           if(do_afslog(p->cell))
+               failed++;
+    }
+
+    return failed;
+}
diff --git a/src/kerberosV/src/appl/afsutil/pagsh.1 b/src/kerberosV/src/appl/afsutil/pagsh.1
new file mode 100644 (file)
index 0000000..7c733b8
--- /dev/null
@@ -0,0 +1,92 @@
+.\" Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: pagsh.1,v 1.2 2005/04/18 10:20:31 lha Exp $
+.\"
+.Dd February 12, 2005
+.Dt PAGSH 1
+.Os Heimdal
+.Sh NAME
+.Nm pagsh
+.Nd
+creates a new credential cache sandbox
+.Sh SYNOPSIS
+.Nm
+.Op Fl c
+.Op Fl -cache-type= Ns Ar string
+.Op Fl -version
+.Op Fl h | Fl -help
+.Ar command [args...]
+.Sh DESCRIPTION
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl c
+.Xc
+.It Xo
+.Fl -cache-type= Ns Ar string
+.Xc
+.It Xo
+.Fl -version
+.Xc
+.It Xo
+.Fl h ,
+.Fl -help
+.Xc
+.El
+.Pp
+.Nm
+creates a new credential cache sandbox for the user to live in.
+If AFS is installed on the computer, the user is put in a newly
+created PAG.
+.Pp
+For Kerberos 5, the credential cache type that is used is the same as
+the credential cache type that was used at the time of
+.Nm
+invocation.
+The credential cache type can be controlled by the option
+.Fl -cache-type .
+.Sh EXAMPLES
+Create a new sandbox where new credentials can be used, while the old
+credentials can be used by other processes.
+.Bd -literal -offset indent
+$ klist
+Credentials cache: FILE:/tmp/krb5cc_913
+        Principal: lha@E.KTH.SE
+
+  Issued           Expires          Principal
+Feb 12 10:08:31  Feb 12 20:06:36  krbtgt/E.KTH.SE@E.KTH.SE
+$ pagsh
+$ klist
+klist: No ticket file: /tmp/krb5cc_03014a
+.Ed
+.Sh SEE ALSO
+.Nm afslog 1
diff --git a/src/kerberosV/src/appl/afsutil/pagsh.c b/src/kerberosV/src/appl/afsutil/pagsh.c
new file mode 100644 (file)
index 0000000..f7cd72e
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1995 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: pagsh.c,v 1.10 2005/02/12 14:23:28 lha Exp $");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#include <time.h>
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+
+#ifdef KRB5
+#include <krb5.h>
+#endif
+#ifdef KRB4
+#include <krb.h>
+#endif
+#include <kafs.h>
+
+#include <err.h>
+#include <roken.h>
+#include <getarg.h>
+
+#ifndef TKT_ROOT
+#define TKT_ROOT "/tmp/tkt"
+#endif
+
+static int help_flag;
+static int version_flag;
+static int c_flag;
+#ifdef KRB5
+static char *typename_arg;
+#endif
+
+struct getargs getargs[] = {
+    { NULL,    'c', arg_flag, &c_flag },
+#ifdef KRB5
+    { "cache-type", 0,  arg_string, &typename_arg },
+#endif
+    { "version", 0,  arg_flag, &version_flag },
+    { "help",  'h', arg_flag, &help_flag },
+};
+
+static int num_args = sizeof(getargs) / sizeof(getargs[0]);
+
+static void
+usage(int ecode)
+{
+    arg_printusage(getargs, num_args, NULL, "command [args...]");
+    exit(ecode);
+}
+
+/*
+ * Run command with a new ticket file / credentials cache / token
+ */
+
+int
+main(int argc, char **argv)
+{
+    int f;
+    char tf[1024];
+    char *p;
+
+    char *path;
+    char **args;
+    int i;
+    int optind = 0;
+
+    if(getarg(getargs, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+#ifdef KRB5
+    {
+       const krb5_cc_ops *type;
+       krb5_error_code ret;
+       krb5_context context;
+       krb5_ccache id;
+       const char *name;
+
+       ret = krb5_init_context(&context);
+       if (ret) /* XXX should this really call exit ? */
+           errx(1, "no kerberos 5 support");
+
+       if (typename_arg == NULL) {
+           char *s;
+
+           name = krb5_cc_default_name(context);
+           if (name == NULL)
+               krb5_errx(context, 1, "Failed getting default "
+                         "credential cache type");
+           
+           typename_arg = strdup(name);
+           if (typename_arg == NULL)
+               errx(1, "strdup");
+           
+           s = strchr(typename_arg, ':');
+           if (s)
+               *s = '\0';
+       }
+
+       type = krb5_cc_get_prefix_ops(context, typename_arg);
+       if (type == NULL)
+           krb5_err(context, 1, ret, "Failed getting ops for %s "
+                    "credential cache", typename_arg);
+     
+       ret = krb5_cc_gen_new(context, type, &id);
+       if (ret)
+           krb5_err(context, 1, ret, "Failed generating credential cache");
+
+       name = krb5_cc_get_name(context, id);
+       if (name == NULL)
+           krb5_errx(context, 1, "Generated credential cache have no name");
+
+       snprintf(tf, sizeof(tf), "%s:%s", typename_arg, name);
+
+       ret = krb5_cc_close(context, id);
+       if (ret)
+           krb5_err(context, 1, ret, "Failed closing credential cache");
+
+       krb5_free_context(context);
+
+       esetenv("KRB5CCNAME", tf, 1);
+    }
+#endif
+
+    snprintf (tf, sizeof(tf), "%s_XXXXXXXXXX", TKT_ROOT);
+    f = mkstemp (tf);
+    if (f < 0)
+       err(1, "mkstemp failed");
+    close (f);
+    unlink (tf);
+    esetenv("KRBTKFILE", tf, 1);
+
+    i = 0;
+
+    args = (char **) malloc((argc + 10)*sizeof(char *));
+    if (args == NULL)
+       errx (1, "Out of memory allocating %lu bytes",
+             (unsigned long)((argc + 10)*sizeof(char *)));
+  
+    if(*argv == NULL) {
+       path = getenv("SHELL");
+       if(path == NULL){
+           struct passwd *pw = k_getpwuid(geteuid());
+           if (pw == NULL)
+               errx(1, "effective user not found");
+           path = strdup(pw->pw_shell);
+       }
+    } else {
+       path = strdup(*argv++);
+    }
+    if (path == NULL)
+       errx (1, "Out of memory copying path");
+  
+    p=strrchr(path, '/');
+    if(p)
+       args[i] = strdup(p+1);
+    else
+       args[i] = strdup(path);
+
+    if (args[i++] == NULL)
+       errx (1, "Out of memory copying arguments");
+  
+    while(*argv)
+       args[i++] = *argv++;
+
+    args[i++] = NULL;
+
+    if(k_hasafs())
+       k_setpag();
+
+    unsetenv("PAGPID");
+    execvp(path, args);
+    if (errno == ENOENT || c_flag) {
+       char **sh_args = malloc ((i + 2) * sizeof(char *));
+       int j;
+
+       if (sh_args == NULL)
+           errx (1, "Out of memory copying sh arguments");
+       for (j = 1; j < i; ++j)
+           sh_args[j + 2] = args[j];
+       sh_args[0] = "sh";
+       sh_args[1] = "-c";
+       sh_args[2] = path;
+       execv ("/bin/sh", sh_args);
+    }
+    err (1, "execvp");
+}
diff --git a/src/kerberosV/src/appl/login/CVS/Entries b/src/kerberosV/src/appl/login/CVS/Entries
new file mode 100644 (file)
index 0000000..4f9fe90
--- /dev/null
@@ -0,0 +1,2 @@
+/limits_conf.c/1.3/Thu Nov  2 18:10:40 2006//
+D
diff --git a/src/kerberosV/src/appl/login/CVS/Repository b/src/kerberosV/src/appl/login/CVS/Repository
new file mode 100644 (file)
index 0000000..05c8f4b
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/appl/login
diff --git a/src/kerberosV/src/appl/login/CVS/Root b/src/kerberosV/src/appl/login/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/appl/login/limits_conf.c b/src/kerberosV/src/appl/login/limits_conf.c
new file mode 100644 (file)
index 0000000..70fc42b
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "login_locl.h"
+
+RCSID("$KTH: limits_conf.c,v 1.3 2005/05/02 13:52:28 lha Exp $");
+
+#include <errno.h>
+#include <limits.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+struct limit {
+    const char *name;
+    int resource;
+    int scale;
+    int has_limit;
+    struct rlimit limit;
+} limits[] = {
+#define LIM(X, S) { #X, RLIMIT_##X, S, 0 }
+    LIM(CORE, 1024),
+    LIM(CPU, 60),
+    LIM(DATA, 1024),
+    LIM(FSIZE, 1024),
+#ifdef RLIMIT_MEMLOCK
+    LIM(MEMLOCK, 1024),
+#endif
+    LIM(NOFILE, 1),
+#ifdef RLIMIT_NPROC
+    LIM(NPROC, 1),
+#endif
+#ifdef RLIMIT_RSS
+    LIM(RSS, 1024),
+#endif
+    LIM(STACK, 1024),
+
+#ifdef RLIMIT_AS
+    LIM(AS, 1024),
+#endif
+#ifdef RLIMIT_LOCKS
+    LIM(LOCKS, 1),
+#endif
+    /*
+      maxlogins
+      priority
+    */
+    { NULL, 0 }
+};
+
+static struct limit *
+find_limit(const char *name)
+{
+    struct limit *l;
+    for(l = limits; l->name != NULL; l++)
+       if(strcasecmp(name, l->name) == 0)
+           return l;
+    return NULL;
+}
+
+/* this function reads limits.conf files similar to pam_limits
+   unimplemented features include:
+       % maxlogins
+       "-" no limits, 
+       priorities etc that are not set via setrlimit
+   XXX uses static storage, and clobbers getgr*
+*/
+
+int
+read_limits_conf(const char *file, const struct passwd *pwd)
+{
+    FILE *f;
+    char *args[4];
+    int lineno = 0;
+    char buf[1024];
+    struct limit *l;
+    rlim_t value;
+
+    f = fopen(file, "r");
+    if(f == NULL) {
+       if(errno != ENOENT && errno != ENOTDIR)
+           syslog(LOG_ERR, "%s: %m", file);
+       return -1;
+    }
+
+    while(fgets(buf, sizeof(buf), f) != NULL) {
+       char *last = NULL;
+       char *end = NULL;
+       int level;
+
+       lineno++;
+
+       if(buf[0] == '\0') {
+           syslog(LOG_ERR, "%s: line %d: NUL character", file, lineno);
+           continue;
+       }
+       if(buf[strlen(buf) - 1] != '\n') {
+           /* file did not end with a newline, figure out if we're at
+               the EOF, or if our buffer was too small */
+           int eof = 1;
+           int c;
+           while((c = fgetc(f)) != EOF) {
+               eof = 0;
+               if(c == '\n') 
+                   break;
+           }
+           if(!eof) {
+               syslog(LOG_ERR, "%s: line %d: line too long", file, lineno);
+               continue;
+           }
+       }
+       buf[strcspn(buf, "#\r\n")] = '\0';
+       if((args[0] = strtok_r(buf, " \t", &last)) == NULL ||
+          (args[1] = strtok_r(NULL, " \t", &last)) == NULL ||
+          (args[2] = strtok_r(NULL, " \t", &last)) == NULL ||
+          (args[3] = strtok_r(NULL, " \t", &last)) == NULL) {
+           if(args[0] != NULL) /* this would include comment lines */
+               syslog(LOG_ERR, "%s: line %d: malformed line", file, lineno);
+           continue;
+       }
+
+       l = find_limit(args[2]);
+       if(l == NULL) {
+           syslog(LOG_ERR, "%s: line %d: unknown limit %s", file, lineno, args[2]);
+           continue;
+       }
+       if(strcmp(args[3], "-") == 0) {
+           value = RLIM_INFINITY;
+       } else {
+           errno = 0;
+           value = strtol(args[3], &end, 10);
+           if(*end != '\0') {
+               syslog(LOG_ERR, "%s: line %d: bad value %s", file, lineno, args[3]);
+               continue;
+           }
+           if((value == LONG_MIN || value == LONG_MAX) && errno == ERANGE) {
+               syslog(LOG_ERR, "%s: line %d: bad value %s", file, lineno, args[3]);
+               continue;
+           }
+           if(value * l->scale < value)
+               value = RLIM_INFINITY;
+           else
+               value *= l->scale;
+       }
+       level = 0;
+       /* XXX unclear: if you set group hard and user soft limit,
+           should the hard limit still apply? this code doesn't. */
+       if(strcmp(args[0], pwd->pw_name) == 0)
+           level = 3;
+       if(*args[0] == '@') {
+           struct group *gr;
+           gr = getgrnam(args[0] + 1);
+           if(gr != NULL && gr->gr_gid == pwd->pw_gid)
+               level = 2;
+       }
+       if(strcmp(args[0], "*") == 0)
+           level = 1;
+       if(level == 0 || level < l->has_limit) /* not for us */
+           continue;
+       if(l->has_limit < level) {
+           if(getrlimit(l->resource, &l->limit) < 0)
+               continue;
+           l->has_limit = level;
+       }
+       
+       /* XXX unclear: if you soft to more than default hard, should
+           we set hard to soft? this code doesn't. */
+       if(strcasecmp(args[1], "soft") == 0 || strcmp(args[1], "-") == 0)
+           l->limit.rlim_cur = value;
+       if(strcasecmp(args[1], "hard") == 0 || strcmp(args[1], "-") == 0) 
+           l->limit.rlim_max = value;
+    }
+    fclose(f);
+    for(l = limits; l->name != NULL; l++) {
+       if(l->has_limit) {
+           if(l->limit.rlim_cur > l->limit.rlim_max)
+               l->limit.rlim_cur = l->limit.rlim_max;
+           if(setrlimit(l->resource, &l->limit) != 0)
+               syslog(LOG_ERR, "setrlimit RLIM_%s failed: %m", l->name);
+       }
+       l->has_limit = 0;
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/appl/popper/CVS/Entries b/src/kerberosV/src/appl/popper/CVS/Entries
new file mode 100644 (file)
index 0000000..9141602
--- /dev/null
@@ -0,0 +1,4 @@
+/auth_gssapi.c/1.1.1.1/Fri Apr 14 07:32:14 2006//
+/auth_krb4.c/1.1.1.1/Fri Apr 14 07:32:15 2006//
+/pop_auth.h/1.1.1.1/Fri Apr 14 07:32:16 2006//
+D
diff --git a/src/kerberosV/src/appl/popper/CVS/Repository b/src/kerberosV/src/appl/popper/CVS/Repository
new file mode 100644 (file)
index 0000000..6d9b386
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/appl/popper
diff --git a/src/kerberosV/src/appl/popper/CVS/Root b/src/kerberosV/src/appl/popper/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/appl/popper/auth_gssapi.c b/src/kerberosV/src/appl/popper/auth_gssapi.c
new file mode 100644 (file)
index 0000000..702f8c6
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <popper.h>
+#include <base64.h>
+#include <pop_auth.h>
+RCSID("$KTH: auth_gssapi.c,v 1.2 2004/06/15 11:24:21 joda Exp $");
+
+
+#if defined(SASL) && defined(KRB5)
+#include <gssapi.h>
+
+extern krb5_context gssapi_krb5_context;
+
+struct gss_state {
+    gss_ctx_id_t context_hdl;
+    gss_OID mech_oid;
+    gss_name_t client_name;
+    int stage;
+};
+
+static void
+gss_set_error (struct gss_state *gs, int min_stat)
+{
+    OM_uint32 new_stat;
+    OM_uint32 msg_ctx = 0;
+    gss_buffer_desc status_string;
+    OM_uint32 ret;
+
+    do {
+       ret = gss_display_status (&new_stat,
+                                 min_stat,
+                                 GSS_C_MECH_CODE,
+                                 gs->mech_oid,
+                                 &msg_ctx,
+                                 &status_string);
+       pop_auth_set_error(status_string.value);
+       gss_release_buffer (&new_stat, &status_string);
+    } while (!GSS_ERROR(ret) && msg_ctx != 0);
+}
+
+static int
+gss_loop(POP *p, void *state, 
+        /* const */ void *input, size_t input_length,
+        void **output, size_t *output_length)
+{
+    struct gss_state *gs = state;
+    gss_buffer_desc real_input_token, real_output_token;
+    gss_buffer_t input_token = &real_input_token,
+       output_token = &real_output_token;
+    OM_uint32 maj_stat, min_stat;
+    gss_channel_bindings_t bindings = GSS_C_NO_CHANNEL_BINDINGS;
+
+    if(gs->stage == 0) {
+       /* we require an initial response, so ask for one if not
+           present */
+       gs->stage++;
+       if(input == NULL && input_length == 0) {
+           /* XXX this could be done better */
+           fputs("+ \r\n", p->output);
+           fflush(p->output);
+           return POP_AUTH_CONTINUE;
+       }
+    }
+    if(gs->stage == 1) {
+       input_token->value = input;
+       input_token->length = input_length;
+       maj_stat =
+           gss_accept_sec_context (&min_stat,
+                                   &gs->context_hdl,
+                                   GSS_C_NO_CREDENTIAL,
+                                   input_token,
+                                   bindings,
+                                   &gs->client_name,
+                                   &gs->mech_oid,
+                                   output_token,
+                                   NULL,
+                                   NULL,
+                                   NULL);
+       if (GSS_ERROR(maj_stat)) {
+           gss_set_error(gs, min_stat);
+           return POP_AUTH_FAILURE;
+       }
+       if (output_token->length != 0) {
+           *output = output_token->value;
+           *output_length = output_token->length;
+       }
+       if(maj_stat == GSS_S_COMPLETE)
+           gs->stage++;
+
+       return POP_AUTH_CONTINUE;
+    }
+
+    if(gs->stage == 2) {
+       /* send wanted protection levels */
+       unsigned char x[4] = { 1, 0, 0, 0 };
+
+       input_token->value = x;
+       input_token->length = 4;
+
+       maj_stat = gss_wrap(&min_stat, 
+                           gs->context_hdl, 
+                           FALSE,
+                           GSS_C_QOP_DEFAULT,
+                           input_token, 
+                           NULL, 
+                           output_token);
+       if (GSS_ERROR(maj_stat)) {
+           gss_set_error(gs, min_stat);
+           return POP_AUTH_FAILURE;
+       }
+       *output = output_token->value;
+       *output_length = output_token->length;
+       gs->stage++;
+       return POP_AUTH_CONTINUE;
+    }
+    if(gs->stage == 3) {
+       /* receive protection levels and username */
+       char *name;
+       krb5_principal principal;
+       gss_buffer_desc export_name;
+       gss_OID oid;
+       unsigned char *ptr;
+
+       input_token->value = input;
+       input_token->length = input_length;
+
+       maj_stat = gss_unwrap (&min_stat,
+                              gs->context_hdl,
+                              input_token, 
+                              output_token,
+                              NULL, 
+                              NULL);
+       if (GSS_ERROR(maj_stat)) {
+           gss_set_error(gs, min_stat);
+           return POP_AUTH_FAILURE;
+       }
+       if(output_token->length < 5) {
+           pop_auth_set_error("response too short");
+           return POP_AUTH_FAILURE;
+       }
+       ptr = output_token->value;
+       if(ptr[0] != 1) {
+           pop_auth_set_error("must use clear text");
+           return POP_AUTH_FAILURE;
+       }
+       memmove(output_token->value, ptr + 4, output_token->length - 4);
+       ptr[output_token->length - 4] = '\0';
+
+       maj_stat = gss_display_name(&min_stat, gs->client_name,
+                                   &export_name, &oid);
+       if(maj_stat != GSS_S_COMPLETE) {
+           gss_set_error(gs, min_stat);
+           return POP_AUTH_FAILURE;
+       }
+       /* XXX kerberos */
+       if(oid != GSS_KRB5_NT_PRINCIPAL_NAME) {
+           pop_auth_set_error("unexpected gss name type");
+           gss_release_buffer(&min_stat, &export_name);
+           return POP_AUTH_FAILURE;
+       }
+       name = malloc(export_name.length + 1);
+       if(name == NULL) {
+           pop_auth_set_error("out of memory");
+           gss_release_buffer(&min_stat, &export_name);
+           return POP_AUTH_FAILURE;
+       }
+       memcpy(name, export_name.value, export_name.length);
+       name[export_name.length] = '\0';
+       gss_release_buffer(&min_stat, &export_name);
+       krb5_parse_name(gssapi_krb5_context, name, &principal);
+
+       if(!krb5_kuserok(gssapi_krb5_context, principal, ptr)) {
+           pop_auth_set_error("Permission denied");
+           return POP_AUTH_FAILURE;
+       }
+
+
+       strlcpy(p->user, ptr, sizeof(p->user));
+       return POP_AUTH_COMPLETE;
+    }
+    return POP_AUTH_FAILURE;
+}
+
+
+static int
+gss_init(POP *p, void **state)
+{
+    struct gss_state *gs = malloc(sizeof(*gs));
+    if(gs == NULL) {
+       pop_auth_set_error("out of memory");
+       return POP_AUTH_FAILURE;
+    }
+    gs->context_hdl = GSS_C_NO_CONTEXT;
+    gs->stage = 0;
+    *state = gs;
+    return POP_AUTH_CONTINUE;
+}
+
+static int
+gss_cleanup(POP *p, void *state)
+{
+    OM_uint32 min_stat;
+    struct gss_state *gs = state;
+    if(gs->context_hdl != GSS_C_NO_CONTEXT)
+       gss_delete_sec_context(&min_stat, &gs->context_hdl, GSS_C_NO_BUFFER);
+    free(state);
+    return POP_AUTH_CONTINUE;
+}
+
+struct auth_mech gssapi_mech = {
+    "GSSAPI", gss_init, gss_loop, gss_cleanup
+};
+
+#endif /* KRB5 */
diff --git a/src/kerberosV/src/appl/popper/auth_krb4.c b/src/kerberosV/src/appl/popper/auth_krb4.c
new file mode 100644 (file)
index 0000000..e97e4c5
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <popper.h>
+#include <base64.h>
+#include <pop_auth.h>
+RCSID("$KTH: auth_krb4.c,v 1.2 2004/06/15 11:24:21 joda Exp $");
+
+
+#if defined(SASL) && defined(KRB4)
+#include <krb.h>
+#include <des.h>
+
+struct krb4_state {
+    int stage;
+    u_int32_t nonce;
+};
+
+static int
+krb4_loop(POP *p, void *state, 
+        /* const */ void *input, size_t input_length,
+        void **output, size_t *output_length)
+{
+    struct krb4_state *ks = state;
+
+    int ret;
+    des_cblock key;
+    unsigned char *data;
+    char instance[INST_SZ];  
+    des_key_schedule schedule;
+
+    if(ks->stage == 0) {
+       if(input_length > 0)
+           return POP_AUTH_FAILURE;
+       /* S -> C: 32 bit nonce in MSB base64 */
+#ifdef HAVE_OPENSSL
+#define des_new_random_key des_random_key
+#endif
+       des_new_random_key(key);
+       ks->nonce = (key[0] | (key[1] << 8) | (key[2] << 16) | (key[3] << 24)
+                    | key[4] | (key[5] << 8) | (key[6] << 16) | (key[7] << 24));
+       *output = malloc(4);
+       if(*output == NULL) {
+           pop_auth_set_error("out of memory");
+           return POP_AUTH_FAILURE;
+       }
+       krb_put_int(ks->nonce, *output, 4, 4);
+       *output_length = 4;
+       ks->stage++;
+       return POP_AUTH_CONTINUE;
+    }
+
+    if(ks->stage == 1) {
+       KTEXT_ST authent;
+       /* C -> S: ticket and authenticator */
+
+       if (input_length > sizeof(authent.dat)) {
+           pop_auth_set_error("data packet too long");
+           return POP_AUTH_FAILURE;
+       }
+       memcpy(authent.dat, input, input_length);
+       authent.length = input_length;
+
+       k_getsockinst (0, instance, sizeof(instance));
+       ret = krb_rd_req(&authent, "pop", instance,
+                        0 /* XXX p->in_addr.sin_addr.s_addr */,
+                        &p->kdata, NULL);
+       if (ret != 0) {
+           pop_auth_set_error(krb_get_err_text(ret));
+           return POP_AUTH_FAILURE;
+       }
+       if (p->kdata.checksum != ks->nonce) {
+           pop_auth_set_error("data stream modified");
+           return POP_AUTH_FAILURE;
+       }
+       /* S -> C: nonce + 1 | bit | max segment */
+
+       *output = malloc(8);
+       if(*output == NULL) {
+           pop_auth_set_error("out of memory");
+           return POP_AUTH_FAILURE;
+       }
+       data = *output;
+       krb_put_int(ks->nonce + 1, data, 8, 4);
+       data[4] = 1;
+       data[5] = 0;
+       data[6] = 0;
+       data[7] = 0;
+       des_key_sched(&p->kdata.session, schedule);
+       des_pcbc_encrypt((des_cblock*)data,
+                        (des_cblock*)data, 8,
+                        schedule,
+                        &p->kdata.session,
+                        DES_ENCRYPT);
+       *output_length = 8;
+       ks->stage++;
+       return POP_AUTH_CONTINUE;
+    }
+
+    if(ks->stage == 2) {
+       u_int32_t nonce_reply;
+       /* C -> S: nonce | bit | max segment | username */
+
+       if (input_length % 8 != 0) {
+           pop_auth_set_error("reply is not a multiple of 8 bytes");
+           return POP_AUTH_FAILURE;
+       }
+
+       des_key_sched(&p->kdata.session, schedule);
+       des_pcbc_encrypt((des_cblock*)input,
+                        (des_cblock*)input,
+                        input_length,
+                        schedule,
+                        &p->kdata.session,
+                        DES_DECRYPT);
+
+       data = input;
+       krb_get_int(data, &nonce_reply, 4, 0);
+       if (nonce_reply != ks->nonce) {
+           pop_auth_set_error("data stream modified");
+           return POP_AUTH_FAILURE;
+       }
+       if(data[4] != 1) {
+
+       }
+       if(data[input_length - 1] != '\0') {
+           pop_auth_set_error("bad format of username");
+           return POP_AUTH_FAILURE;
+       }
+       strlcpy(p->user, data + 8, sizeof(p->user));
+       if (kuserok(&p->kdata, p->user)) {
+           pop_log(p, POP_PRIORITY,
+                   "%s: (%s.%s@%s) tried to retrieve mail for %s.",
+                   p->client, p->kdata.pname, p->kdata.pinst,
+                   p->kdata.prealm, p->user);
+           pop_auth_set_error("Permission denied");
+           return POP_AUTH_FAILURE;
+       }
+       pop_log(p, POP_INFO, "%s: %s.%s@%s -> %s",
+               p->ipaddr,
+               p->kdata.pname, p->kdata.pinst, p->kdata.prealm,
+               p->user);
+       return POP_AUTH_COMPLETE;
+    }
+    return POP_AUTH_FAILURE;
+}
+
+
+static int
+krb4_init(POP *p, void **state)
+{
+    struct krb4_state *ks = malloc(sizeof(*ks));
+    if(ks == NULL) {
+       pop_auth_set_error("out of memory");
+       return POP_AUTH_FAILURE;
+    }
+    ks->stage = 0;
+    *state = ks;
+    return POP_AUTH_CONTINUE;
+}
+
+static int
+krb4_cleanup(POP *p, void *state)
+{
+    free(state);
+    return POP_AUTH_CONTINUE;
+}
+
+struct auth_mech krb4_mech = {
+    "KERBEROS_V4", krb4_init, krb4_loop, krb4_cleanup
+};
+
+#endif /* KRB5 */
diff --git a/src/kerberosV/src/appl/popper/pop_auth.h b/src/kerberosV/src/appl/popper/pop_auth.h
new file mode 100644 (file)
index 0000000..3ac0dd7
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: pop_auth.h,v 1.2 2004/06/15 11:24:21 joda Exp $ */
+
+#ifndef __pop_auth_h__
+#define __pop_auth_h__
+
+struct auth_mech {
+    const char *name;
+    int (*init)(POP*, void**);
+    int (*loop)(POP*, void*, void*, size_t, void**, size_t*);
+    int (*cleanup)(POP*, void*);
+};
+
+#define POP_AUTH_CONTINUE      0
+#define POP_AUTH_FAILURE       1
+#define POP_AUTH_COMPLETE      2
+
+void pop_auth_set_error(const char *message);
+
+#ifdef KRB5
+extern struct auth_mech gssapi_mech;
+#endif
+#ifdef KRB4
+extern struct auth_mech krb4_mech;
+#endif
+
+
+#endif /* __pop_auth_h__ */
diff --git a/src/kerberosV/src/appl/su/CVS/Entries b/src/kerberosV/src/appl/su/CVS/Entries
new file mode 100644 (file)
index 0000000..6970b17
--- /dev/null
@@ -0,0 +1,2 @@
+/su.1/1.1.1.1/Fri Apr 14 07:32:00 2006//
+D
diff --git a/src/kerberosV/src/appl/su/CVS/Repository b/src/kerberosV/src/appl/su/CVS/Repository
new file mode 100644 (file)
index 0000000..bf5be5c
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/appl/su
diff --git a/src/kerberosV/src/appl/su/CVS/Root b/src/kerberosV/src/appl/su/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/appl/su/su.1 b/src/kerberosV/src/appl/su/su.1
new file mode 100644 (file)
index 0000000..e2aef97
--- /dev/null
@@ -0,0 +1,112 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: su.1,v 1.1 2004/03/23 14:42:57 lha Exp $
+.\"
+.Dd March 23, 2004
+.Dt SU 1
+.Os HEIMDAL
+.Sh NAME
+.Nm su
+.Nd substitute user identity
+.Sh SYNOPSIS
+.Nm su
+.Op Fl K | Fl -no-kerberos
+.Op Fl f
+.Op Fl l | Fl -full
+.Op Fl m
+.Oo Fl i Ar instance \*(Ba Xo
+.Fl -instance= Ns Ar instance
+.Xc
+.Oc
+.Oo Fl c Ar command \*(Ba Xo
+.Fl -command= Ns Ar command
+.Xc
+.Oc
+.Op Ar login Op Ar "shell arguments"
+.Sh DESCRIPTION
+.Nm su
+will use Kerberos authentication provided that an instance for the
+user wanting to change effective UID is present in a file named
+.Pa .k5login
+in the target user id's home directory
+.Pp
+A special case exists for
+.Ql root
+where roots
+.Pa ~/.k5login
+needs to contain a row like:
+.Qo
+user/root@REALM
+.Qc
+for su to succed.  
+.Pp
+In the absence of either an entry for current user in said file or
+other problems like missing host/hostname@REALM keys in systems
+keytab, or user typing the wrong password, 
+.Nm su
+will fall back to traditional
+.Pa /etc/passwd
+authentication.
+.Pp
+The options are as follows:
+.Bl -item -width Ds
+.It
+.Fl K ,
+.Fl -no-kerberos
+don't use Kerberos.
+.It
+.Fl f
+don't read .cshrc.
+.It
+.Fl l ,
+.Fl -full
+simulate full login.
+.It
+.Fl m
+leave environment unmodified.
+.It
+.Fl i Ar instance ,
+.Fl -instance= Ns Ar instance
+root instance to use.
+.It
+.Fl c Ar command ,
+.Fl -command= Ns Ar command
+command to execute.
+.El
+.Pp
+.Sh BUGS
+Note that on BSD systems, where system 
+.Nm su
+honors wheel group and denies 
+.Nm su
+to others, all users may become root if they know the root password,
+regardless of wheel membership.
diff --git a/src/kerberosV/src/appl/test/CVS/Entries b/src/kerberosV/src/appl/test/CVS/Entries
new file mode 100644 (file)
index 0000000..52926a5
--- /dev/null
@@ -0,0 +1,16 @@
+/common.c/1.1.1.2/Fri Apr 14 07:32:00 2006//
+/gss_common.c/1.1.1.2/Fri Apr 14 07:32:00 2006//
+/gss_common.h/1.1.1.2/Fri Apr 14 07:32:00 2006//
+/gssapi_client.c/1.1.1.2/Fri Apr 14 07:32:00 2006//
+/gssapi_server.c/1.1.1.2/Fri Apr 14 07:32:01 2006//
+/http_client.c/1.2/Tue Mar 20 03:44:18 2007//
+/nt_gss_client.c/1.1.1.1/Fri May 25 07:45:30 2001//
+/nt_gss_common.c/1.1.1.1/Fri May 25 07:45:30 2001//
+/nt_gss_common.h/1.1.1.1/Fri May 25 07:45:30 2001//
+/nt_gss_server.c/1.1.1.2/Fri Apr 14 07:32:01 2006//
+/tcp_client.c/1.1.1.1/Fri May 25 07:45:31 2001//
+/tcp_server.c/1.1.1.1/Fri May 25 07:45:31 2001//
+/test_locl.h/1.1.1.2/Fri Apr 14 07:32:01 2006//
+/uu_client.c/1.1.1.2/Fri Apr 14 07:32:01 2006//
+/uu_server.c/1.1.1.1/Fri May 25 07:45:31 2001//
+D
diff --git a/src/kerberosV/src/appl/test/CVS/Repository b/src/kerberosV/src/appl/test/CVS/Repository
new file mode 100644 (file)
index 0000000..2037454
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/appl/test
diff --git a/src/kerberosV/src/appl/test/CVS/Root b/src/kerberosV/src/appl/test/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/appl/test/common.c b/src/kerberosV/src/appl/test/common.c
new file mode 100644 (file)
index 0000000..40b6400
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+
+RCSID("$KTH: common.c,v 1.12 2003/09/09 03:38:04 lha Exp $");
+
+static int help_flag;
+static int version_flag;
+static char *port_str;
+static char *keytab_str;
+krb5_keytab keytab;
+char *service = SERVICE;
+char *mech = "krb5";
+int fork_flag;
+
+static struct getargs args[] = {
+    { "port", 'p', arg_string, &port_str, "port to listen to", "port" },
+    { "service", 's', arg_string, &service, "service to use", "service" },
+    { "keytab", 'k', arg_string, &keytab_str, "keytab to use", "keytab" },
+    { "mech", 'm', arg_string, &mech, "gssapi mech to use", "mech" },
+    { "fork", 'f', arg_flag, &fork_flag, "do fork" },
+    { "help", 'h', arg_flag, &help_flag },
+    { "version", 0, arg_flag, &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+server_usage(int code, struct getargs *args, int num_args)
+{
+    arg_printusage(args, num_args, NULL, "");
+    exit(code);
+}
+
+static void
+client_usage(int code, struct getargs *args, int num_args)
+{
+    arg_printusage(args, num_args, NULL, "host");
+    exit(code);
+}
+
+
+static int
+common_setup(krb5_context *context, int *argc, char **argv, 
+            void (*usage)(int, struct getargs*, int))
+{
+    int port = 0;
+    *argc = krb5_program_setup(context, *argc, argv, args, num_args, usage);
+
+    if(help_flag)
+       (*usage)(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    
+    if(port_str){
+       struct servent *s = roken_getservbyname(port_str, "tcp");
+       if(s)
+           port = s->s_port;
+       else {
+           char *ptr;
+
+           port = strtol (port_str, &ptr, 10);
+           if (port == 0 && ptr == port_str)
+               errx (1, "Bad port `%s'", port_str);
+           port = htons(port);
+       }
+    }
+
+    if (port == 0)
+       port = krb5_getportbyname (*context, PORT, "tcp", 4711);
+    
+    return port;
+}
+
+int
+server_setup(krb5_context *context, int argc, char **argv)
+{
+    int port = common_setup(context, &argc, argv, server_usage);
+    krb5_error_code ret;
+
+    if(argv[argc] != NULL)
+       server_usage(1, args, num_args);
+    if (keytab_str != NULL)
+       ret = krb5_kt_resolve (*context, keytab_str, &keytab);
+    else
+       ret = krb5_kt_default (*context, &keytab);
+    if (ret)
+       krb5_err (*context, 1, ret, "krb5_kt_resolve/default");
+    return port;
+}
+
+int
+client_setup(krb5_context *context, int *argc, char **argv)
+{
+    int optind = *argc;
+    int port = common_setup(context, &optind, argv, client_usage);
+    if(*argc - optind != 1)
+       client_usage(1, args, num_args);
+    *argc = optind;
+    return port;
+}
+
+int
+client_doit (const char *hostname, int port, const char *service,
+            int (*func)(int, const char *hostname, const char *service))
+{
+    struct addrinfo *ai, *a;
+    struct addrinfo hints;
+    int error;
+    char portstr[NI_MAXSERV];
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    snprintf (portstr, sizeof(portstr), "%u", ntohs(port));
+
+    error = getaddrinfo (hostname, portstr, &hints, &ai);
+    if (error) {
+       errx (1, "%s: %s", hostname, gai_strerror(error));
+       return -1;
+    }
+
+    for (a = ai; a != NULL; a = a->ai_next) {
+       int s;
+
+       s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (s < 0)
+           continue;
+       if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+           warn ("connect(%s)", hostname);
+           close (s);
+           continue;
+       }
+       freeaddrinfo (ai);
+       return (*func) (s, hostname, service);
+    }
+    warnx ("failed to contact %s", hostname);
+    freeaddrinfo (ai);
+    return 1;
+}
diff --git a/src/kerberosV/src/appl/test/gss_common.c b/src/kerberosV/src/appl/test/gss_common.c
new file mode 100644 (file)
index 0000000..fa4327e
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include "gss_common.h"
+RCSID("$KTH: gss_common.c,v 1.11 2005/03/19 03:10:56 lha Exp $");
+
+void
+write_token (int sock, gss_buffer_t buf)
+{
+    u_int32_t len, net_len;
+    OM_uint32 min_stat;
+
+    len = buf->length;
+
+    net_len = htonl(len);
+
+    if (net_write (sock, &net_len, 4) != 4)
+       err (1, "write");
+    if (net_write (sock, buf->value, len) != len)
+       err (1, "write");
+
+    gss_release_buffer (&min_stat, buf);
+}
+
+static void
+enet_read(int fd, void *buf, size_t len)
+{
+    ssize_t ret;
+
+    ret = net_read (fd, buf, len);
+    if (ret == 0)
+       errx (1, "EOF in read");
+    else if (ret < 0)
+       errx (1, "read");
+}
+
+void
+read_token (int sock, gss_buffer_t buf)
+{
+    u_int32_t len, net_len;
+
+    enet_read (sock, &net_len, 4);
+    len = ntohl(net_len);
+    buf->length = len;
+    buf->value  = emalloc(len);
+    enet_read (sock, buf->value, len);
+}
+
+void
+gss_print_errors (int min_stat)
+{
+    OM_uint32 new_stat;
+    OM_uint32 msg_ctx = 0;
+    gss_buffer_desc status_string;
+    OM_uint32 ret;
+
+    do {
+       ret = gss_display_status (&new_stat,
+                                 min_stat,
+                                 GSS_C_MECH_CODE,
+                                 GSS_C_NO_OID,
+                                 &msg_ctx,
+                                 &status_string);
+       fprintf (stderr, "%s\n", (char *)status_string.value);
+       gss_release_buffer (&new_stat, &status_string);
+    } while (!GSS_ERROR(ret) && msg_ctx != 0);
+}
+
+void
+gss_verr(int exitval, int status, const char *fmt, va_list ap)
+{
+    vwarnx (fmt, ap);
+    gss_print_errors (status);
+    exit (exitval);
+}
+
+void
+gss_err(int exitval, int status, const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    gss_verr (exitval, status, fmt, args);
+    va_end(args);
+}
+
+gss_OID
+select_mech(const char *mech)
+{
+    if (strcasecmp(mech, "krb5") == 0)
+       return GSS_KRB5_MECHANISM;
+    else if (strcasecmp(mech, "spnego") == 0)
+       return GSS_SPNEGO_MECHANISM;
+    else if (strcasecmp(mech, "no-oid") == 0)
+       return GSS_C_NO_OID;
+    else
+       errx (1, "Unknown mechanism '%s' (spnego, krb5, no-oid)", mech);
+}
+
+void
+print_gss_name(const char *prefix, gss_name_t name)
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc name_token;
+
+    maj_stat = gss_display_name (&min_stat,
+                                name,
+                                &name_token,
+                                NULL);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_display_name");
+
+    fprintf (stderr, "%s `%.*s'\n", prefix,
+            (int)name_token.length,
+            (char *)name_token.value);
+
+    gss_release_buffer (&min_stat, &name_token);
+
+}
diff --git a/src/kerberosV/src/appl/test/gss_common.h b/src/kerberosV/src/appl/test/gss_common.h
new file mode 100644 (file)
index 0000000..3558219
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: gss_common.h,v 1.7 2005/03/19 03:13:14 lha Exp $ */
+
+void write_token (int sock, gss_buffer_t buf);
+void read_token (int sock, gss_buffer_t buf);
+
+void gss_print_errors (int min_stat);
+
+void gss_verr(int exitval, int status, const char *fmt, va_list ap)
+    __attribute__ ((format (printf, 3, 0)));
+
+void gss_err(int exitval, int status, const char *fmt, ...)
+    __attribute__ ((format (printf, 3, 4)));
+
+gss_OID select_mech(const char *);
+
+void print_gss_name(const char *, gss_name_t);
diff --git a/src/kerberosV/src/appl/test/gssapi_client.c b/src/kerberosV/src/appl/test/gssapi_client.c
new file mode 100644 (file)
index 0000000..ed69083
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include "gss_common.h"
+RCSID("$KTH: gssapi_client.c,v 1.19 2003/09/10 09:32:42 lha Exp $");
+
+static int
+do_trans (int sock, gss_ctx_id_t context_hdl)
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc real_input_token, real_output_token;
+    gss_buffer_t input_token = &real_input_token,
+       output_token = &real_output_token;
+
+    /* get_mic */
+
+    input_token->length = 3;
+    input_token->value  = strdup("hej");
+
+    maj_stat = gss_get_mic(&min_stat,
+                          context_hdl,
+                          GSS_C_QOP_DEFAULT,
+                          input_token,
+                          output_token);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_get_mic");
+
+    write_token (sock, input_token);
+    write_token (sock, output_token);
+
+    /* wrap */
+
+    input_token->length = 7;
+    input_token->value  = "hemligt";
+
+    maj_stat = gss_wrap (&min_stat,
+                        context_hdl,
+                        0,
+                        GSS_C_QOP_DEFAULT,
+                        input_token,
+                        NULL,
+                        output_token);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_wrap");
+
+    write_token (sock, output_token);
+
+    maj_stat = gss_wrap (&min_stat,
+                        context_hdl,
+                        1,
+                        GSS_C_QOP_DEFAULT,
+                        input_token,
+                        NULL,
+                        output_token);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_wrap");
+
+    write_token (sock, output_token);
+
+    return 0;
+}
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+    struct sockaddr_in remote, local;
+    socklen_t addrlen;
+
+    int context_established = 0;
+    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+    gss_buffer_desc real_input_token, real_output_token;
+    gss_buffer_t input_token = &real_input_token,
+       output_token = &real_output_token;
+    OM_uint32 maj_stat, min_stat;
+    gss_name_t server;
+    gss_buffer_desc name_token;
+    struct gss_channel_bindings_struct input_chan_bindings;
+    u_char init_buf[4];
+    u_char acct_buf[4];
+    gss_OID mech_oid;
+
+    mech_oid = select_mech(mech);
+
+    name_token.length = asprintf ((char **)&name_token.value,
+                                 "%s@%s", service, hostname);
+
+    maj_stat = gss_import_name (&min_stat,
+                               &name_token,
+                               GSS_C_NT_HOSTBASED_SERVICE,
+                               &server);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat,
+                "Error importing name `%s@%s':\n", service, hostname);
+
+    addrlen = sizeof(local);
+    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+       || addrlen != sizeof(local))
+       err (1, "getsockname(%s)", hostname);
+
+    addrlen = sizeof(remote);
+    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+       || addrlen != sizeof(remote))
+       err (1, "getpeername(%s)", hostname);
+
+    input_token->length = 0;
+    output_token->length = 0;
+
+    input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
+    input_chan_bindings.initiator_address.length = 4;
+    init_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
+    init_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
+    init_buf[2] = (local.sin_addr.s_addr >>  8) & 0xFF;
+    init_buf[3] = (local.sin_addr.s_addr >>  0) & 0xFF;
+    input_chan_bindings.initiator_address.value = init_buf;
+
+    input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
+    input_chan_bindings.acceptor_address.length = 4;
+    acct_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
+    acct_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
+    acct_buf[2] = (remote.sin_addr.s_addr >>  8) & 0xFF;
+    acct_buf[3] = (remote.sin_addr.s_addr >>  0) & 0xFF;
+    input_chan_bindings.acceptor_address.value = acct_buf;
+    
+#if 0
+    input_chan_bindings.application_data.value = emalloc(4);
+    * (unsigned short*)input_chan_bindings.application_data.value = local.sin_port;
+    * ((unsigned short *)input_chan_bindings.application_data.value + 1) = remote.sin_port;
+    input_chan_bindings.application_data.length = 4;
+#else
+    input_chan_bindings.application_data.length = 0;
+    input_chan_bindings.application_data.value = NULL;
+#endif
+
+    while(!context_established) {
+       maj_stat =
+           gss_init_sec_context(&min_stat,
+                                GSS_C_NO_CREDENTIAL,
+                                &context_hdl,
+                                server,
+                                mech_oid,
+                                GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG
+                                | GSS_C_DELEG_FLAG,
+                                0,
+                                &input_chan_bindings,
+                                input_token,
+                                NULL,
+                                output_token,
+                                NULL,
+                                NULL);
+       if (GSS_ERROR(maj_stat))
+           gss_err (1, min_stat, "gss_init_sec_context");
+       if (output_token->length != 0)
+           write_token (sock, output_token);
+       if (GSS_ERROR(maj_stat)) {
+           if (context_hdl != GSS_C_NO_CONTEXT)
+               gss_delete_sec_context (&min_stat,
+                                       &context_hdl,
+                                       GSS_C_NO_BUFFER);
+           break;
+       }
+       if (maj_stat & GSS_S_CONTINUE_NEEDED) {
+           read_token (sock, input_token);
+       } else {
+           context_established = 1;
+       }
+
+    }
+    if (fork_flag) {
+       pid_t pid;
+       int pipefd[2];
+
+       if (pipe (pipefd) < 0)
+           err (1, "pipe");
+
+       pid = fork ();
+       if (pid < 0)
+           err (1, "fork");
+       if (pid != 0) {
+           gss_buffer_desc buf;
+
+           maj_stat = gss_export_sec_context (&min_stat,
+                                              &context_hdl,
+                                              &buf);
+           if (GSS_ERROR(maj_stat))
+               gss_err (1, min_stat, "gss_export_sec_context");
+           write_token (pipefd[1], &buf);
+           exit (0);
+       } else {
+           gss_ctx_id_t context_hdl;
+           gss_buffer_desc buf;
+
+           close (pipefd[1]);
+           read_token (pipefd[0], &buf);
+           close (pipefd[0]);
+           maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
+           if (GSS_ERROR(maj_stat))
+               gss_err (1, min_stat, "gss_import_sec_context");
+           gss_release_buffer (&min_stat, &buf);
+           return do_trans (sock, context_hdl);
+       }
+    } else {
+       return do_trans (sock, context_hdl);
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context; /* XXX */
+    int port = client_setup(&context, &argc, argv);
+    return client_doit (argv[argc], port, service, proto);
+}
diff --git a/src/kerberosV/src/appl/test/gssapi_server.c b/src/kerberosV/src/appl/test/gssapi_server.c
new file mode 100644 (file)
index 0000000..9856807
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include "gss_common.h"
+RCSID("$KTH: gssapi_server.c,v 1.21 2005/04/10 14:47:41 lha Exp $");
+
+static int
+process_it(int sock,
+          gss_ctx_id_t context_hdl,
+          gss_name_t client_name
+          )
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_buffer_desc real_input_token, real_output_token;
+    gss_buffer_t input_token = &real_input_token,
+       output_token = &real_output_token;
+    gss_name_t server_name;
+    int conf_flag;
+
+    print_gss_name("User is", client_name);
+
+    maj_stat = gss_inquire_context(&min_stat,
+                                  context_hdl,
+                                  NULL,
+                                  &server_name,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  NULL);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_inquire_context");
+
+    print_gss_name("Server is", server_name);
+
+    maj_stat = gss_release_name(&min_stat, &server_name);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_release_name");
+
+    /* gss_verify_mic */
+
+    read_token (sock, input_token);
+    read_token (sock, output_token);
+
+    maj_stat = gss_verify_mic (&min_stat,
+                              context_hdl,
+                              input_token,
+                              output_token,
+                              NULL);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_verify_mic");
+
+    fprintf (stderr, "gss_verify_mic: %.*s\n", (int)input_token->length,
+           (char *)input_token->value);
+
+    gss_release_buffer (&min_stat, input_token);
+    gss_release_buffer (&min_stat, output_token);
+
+    /* gss_unwrap */
+
+    read_token (sock, input_token);
+
+    maj_stat = gss_unwrap (&min_stat,
+                          context_hdl,
+                          input_token,
+                          output_token,
+                          &conf_flag,
+                          NULL);
+    if(GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_unwrap");
+
+    fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
+           (char *)output_token->value,
+            conf_flag ? "CONF" : "INT");
+
+    gss_release_buffer (&min_stat, input_token);
+    gss_release_buffer (&min_stat, output_token);
+
+    read_token (sock, input_token);
+
+    maj_stat = gss_unwrap (&min_stat,
+                          context_hdl,
+                          input_token,
+                          output_token,
+                          &conf_flag,
+                          NULL);
+    if(GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_unwrap");
+
+    fprintf (stderr, "gss_unwrap: %.*s %s\n", (int)output_token->length,
+            (char *)output_token->value,
+            conf_flag ? "CONF" : "INT");
+
+    gss_release_buffer (&min_stat, input_token);
+    gss_release_buffer (&min_stat, output_token);
+
+    return 0;
+}
+
+static int
+proto (int sock, const char *service)
+{
+    struct sockaddr_in remote, local;
+    socklen_t addrlen;
+    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+    gss_buffer_desc real_input_token, real_output_token;
+    gss_buffer_t input_token = &real_input_token,
+       output_token = &real_output_token;
+    OM_uint32 maj_stat, min_stat;
+    gss_name_t client_name;
+    struct gss_channel_bindings_struct input_chan_bindings;
+    gss_cred_id_t delegated_cred_handle = NULL;
+    krb5_ccache ccache;
+    u_char init_buf[4];
+    u_char acct_buf[4];
+    gss_OID mech_oid;
+    char *mech, *p;
+
+    addrlen = sizeof(local);
+    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+       || addrlen != sizeof(local))
+       err (1, "getsockname)");
+
+    addrlen = sizeof(remote);
+    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+       || addrlen != sizeof(remote))
+       err (1, "getpeername");
+
+    input_chan_bindings.initiator_addrtype = GSS_C_AF_INET;
+    input_chan_bindings.initiator_address.length = 4;
+    init_buf[0] = (remote.sin_addr.s_addr >> 24) & 0xFF;
+    init_buf[1] = (remote.sin_addr.s_addr >> 16) & 0xFF;
+    init_buf[2] = (remote.sin_addr.s_addr >>  8) & 0xFF;
+    init_buf[3] = (remote.sin_addr.s_addr >>  0) & 0xFF;
+
+    input_chan_bindings.initiator_address.value = init_buf;
+    input_chan_bindings.acceptor_addrtype = GSS_C_AF_INET;
+
+    input_chan_bindings.acceptor_address.length = 4;
+    acct_buf[0] = (local.sin_addr.s_addr >> 24) & 0xFF;
+    acct_buf[1] = (local.sin_addr.s_addr >> 16) & 0xFF;
+    acct_buf[2] = (local.sin_addr.s_addr >>  8) & 0xFF;
+    acct_buf[3] = (local.sin_addr.s_addr >>  0) & 0xFF;
+    input_chan_bindings.acceptor_address.value = acct_buf;
+    input_chan_bindings.application_data.value = emalloc(4);
+#if 0
+    * (unsigned short *)input_chan_bindings.application_data.value =
+                          remote.sin_port;
+    * ((unsigned short *)input_chan_bindings.application_data.value + 1) =
+                          local.sin_port;
+    input_chan_bindings.application_data.length = 4;
+#else
+    input_chan_bindings.application_data.length = 0;
+    input_chan_bindings.application_data.value = NULL;
+#endif
+    
+    delegated_cred_handle = GSS_C_NO_CREDENTIAL;
+    
+    do {
+       read_token (sock, input_token);
+       maj_stat =
+           gss_accept_sec_context (&min_stat,
+                                   &context_hdl,
+                                   GSS_C_NO_CREDENTIAL,
+                                   input_token,
+                                   &input_chan_bindings,
+                                   &client_name,
+                                   &mech_oid,
+                                   output_token,
+                                   NULL,
+                                   NULL,
+                                   &delegated_cred_handle);
+       if(GSS_ERROR(maj_stat))
+           gss_err (1, min_stat, "gss_accept_sec_context");
+       if (output_token->length != 0)
+           write_token (sock, output_token);
+       if (GSS_ERROR(maj_stat)) {
+           if (context_hdl != GSS_C_NO_CONTEXT)
+               gss_delete_sec_context (&min_stat,
+                                       &context_hdl,
+                                       GSS_C_NO_BUFFER);
+           break;
+       }
+    } while(maj_stat & GSS_S_CONTINUE_NEEDED);
+    
+    p = (char *)mech_oid->elements;
+    if (mech_oid->length == GSS_KRB5_MECHANISM->length
+       && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_oid->length) == 0)
+       mech = "Kerberos 5";
+    else if (mech_oid->length == GSS_SPNEGO_MECHANISM->length
+       && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_oid->length) == 0)
+       mech = "SPNEGO"; /* XXX Silly, wont show up */
+    else
+       mech = "Unknown";
+
+    printf("Using mech: %s\n", mech);
+
+    if (delegated_cred_handle != GSS_C_NO_CREDENTIAL) {
+       krb5_context context;
+
+       printf("Delegated cred found\n");
+
+       maj_stat = krb5_init_context(&context);
+       maj_stat = krb5_cc_resolve(context, "FILE:/tmp/krb5cc_test", &ccache);
+       maj_stat = gss_krb5_copy_ccache(&min_stat,
+                                      delegated_cred_handle,
+                                      ccache);
+       if (maj_stat == 0) {
+          krb5_principal p;
+          maj_stat = krb5_cc_get_principal(context, ccache, &p);
+          if (maj_stat == 0) {
+              char *name;
+              maj_stat = krb5_unparse_name(context, p, &name);
+              if (maj_stat == 0) {
+                  printf("Delegated user is: `%s'\n", name);
+                  free(name);
+              }
+              krb5_free_principal(context, p);
+          }
+       }
+       krb5_cc_close(context, ccache);
+       gss_release_cred(&min_stat, &delegated_cred_handle);
+    }
+
+    if (fork_flag) {
+       pid_t pid;
+       int pipefd[2];
+
+       if (pipe (pipefd) < 0)
+           err (1, "pipe");
+
+       pid = fork ();
+       if (pid < 0)
+           err (1, "fork");
+       if (pid != 0) {
+           gss_buffer_desc buf;
+
+           maj_stat = gss_export_sec_context (&min_stat,
+                                              &context_hdl,
+                                              &buf);
+           if (GSS_ERROR(maj_stat))
+               gss_err (1, min_stat, "gss_export_sec_context");
+           write_token (pipefd[1], &buf);
+           exit (0);
+       } else {
+           gss_ctx_id_t context_hdl;
+           gss_buffer_desc buf;
+
+           close (pipefd[1]);
+           read_token (pipefd[0], &buf);
+           close (pipefd[0]);
+           maj_stat = gss_import_sec_context (&min_stat, &buf, &context_hdl);
+           if (GSS_ERROR(maj_stat))
+               gss_err (1, min_stat, "gss_import_sec_context");
+           gss_release_buffer (&min_stat, &buf);
+           return process_it (sock, context_hdl, client_name);
+       }
+    } else {
+       return process_it (sock, context_hdl, client_name);
+    }
+}
+
+static int
+doit (int port, const char *service)
+{
+    int sock, sock2;
+    struct sockaddr_in my_addr;
+    int one = 1;
+
+    sock = socket (AF_INET, SOCK_STREAM, 0);
+    if (sock < 0)
+       err (1, "socket");
+
+    memset (&my_addr, 0, sizeof(my_addr));
+    my_addr.sin_family      = AF_INET;
+    my_addr.sin_port        = port;
+    my_addr.sin_addr.s_addr = INADDR_ANY;
+
+    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+                   (void *)&one, sizeof(one)) < 0)
+       warn ("setsockopt SO_REUSEADDR");
+
+    if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+       err (1, "bind");
+
+    if (listen (sock, 1) < 0)
+       err (1, "listen");
+
+    sock2 = accept (sock, NULL, NULL);
+    if (sock2 < 0)
+       err (1, "accept");
+
+    return proto (sock2, service);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context = NULL; /* XXX */
+    int port = server_setup(&context, argc, argv);
+    return doit (port, service);
+}
diff --git a/src/kerberosV/src/appl/test/http_client.c b/src/kerberosV/src/appl/test/http_client.c
new file mode 100644 (file)
index 0000000..e066d89
--- /dev/null
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include "gss_common.h"
+#include <base64.h>
+
+RCSID("$KTH: http_client.c,v 1.10 2005/04/20 10:38:37 lha Exp $");
+
+/*
+ * A simplistic client implementing draft-brezak-spnego-http-04.txt
+ */
+
+static int
+do_connect (const char *hostname, const char *port)
+{
+    struct addrinfo *ai, *a;
+    struct addrinfo hints;
+    int error;
+    int s = -1;
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_family = PF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+
+    error = getaddrinfo (hostname, port, &hints, &ai);
+    if (error)
+       errx (1, "getaddrinfo(%s): %s", hostname, gai_strerror(error));
+
+    for (a = ai; a != NULL; a = a->ai_next) {
+       s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (s < 0)
+           continue;
+       if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+           warn ("connect(%s)", hostname);
+           close (s);
+           continue;
+       }
+       break;
+    }
+    freeaddrinfo (ai);
+    if (a == NULL)
+       errx (1, "failed to contact %s", hostname);
+
+    return s;
+}
+
+static void
+fdprintf(int s, const char *fmt, ...)
+{
+    size_t len;
+    ssize_t ret;
+    va_list ap;
+    char *str, *buf;
+    
+    va_start(ap, fmt);
+    vasprintf(&str, fmt, ap);
+    va_end(ap);
+
+    if (str == NULL)
+       errx(1, "vasprintf");
+
+    buf = str;
+    len = strlen(buf);
+    while (len) {
+       ret = write(s, buf, len);
+       if (ret == 0)
+           err(1, "connection closed");
+       else if (ret < 0)
+           err(1, "error");
+       len -= ret;
+       buf += ret;
+    }
+    free(str);
+}
+
+static int help_flag;
+static int version_flag;
+static int verbose_flag;
+static int mutual_flag = 1;
+static int delegate_flag;
+static char *port_str = "http";
+static char *gss_service = "HTTP";
+
+static struct getargs http_args[] = {
+    { "verbose", 'v', arg_flag, &verbose_flag, "verbose logging", },
+    { "port", 'p', arg_string, &port_str, "port to connect to", "port" },
+    { "delegate", 0, arg_flag, &delegate_flag, "gssapi delegate credential" },
+    { "gss-service", 's', arg_string, &gss_service, "gssapi service to use",
+      "service" },
+    { "mech", 'm', arg_string, &mech, "gssapi mech to use", "mech" },
+    { "mutual", 0, arg_negative_flag, &mutual_flag, "no gssapi mutual auth" },
+    { "help", 'h', arg_flag, &help_flag },
+    { "version", 0, arg_flag, &version_flag }
+};
+
+static int num_http_args = sizeof(http_args) / sizeof(http_args[0]);
+
+static void
+usage(int code)
+{
+    arg_printusage(http_args, num_http_args, NULL, "host [page]");
+    exit(code);
+}
+
+/*
+ *
+ */
+
+struct http_req {
+    char *response;
+    char **headers;
+    int num_headers;
+    void *body;
+    size_t body_size;
+};
+
+
+static void
+http_req_zero(struct http_req *req)
+{
+    req->response = NULL;
+    req->headers = NULL;
+    req->num_headers = 0;
+    req->body = NULL;
+    req->body_size = 0;
+}
+
+static void
+http_req_free(struct http_req *req)
+{
+    int i;
+
+    free(req->response);
+    for (i = 0; i < req->num_headers; i++)
+       free(req->headers[i]);
+    free(req->headers);
+    free(req->body);
+    http_req_zero(req);
+}
+
+static const char *
+http_find_header(struct http_req *req, const char *header)
+{
+    int i, len = strlen(header);
+
+    for (i = 0; i < req->num_headers; i++) {
+       if (strncasecmp(header, req->headers[i], len) == 0) {
+           return req->headers[i] + len + 1;
+       }
+    }
+    return NULL;
+}
+
+
+static int
+http_query(const char *host, const char *page, 
+          char **headers, int num_headers, struct http_req *req)
+{
+    enum { RESPONSE, HEADER, BODY } state;
+    ssize_t ret;
+    char in_buf[1024], *in_ptr = in_buf;
+    size_t in_len = 0;
+    int s, i;
+
+    http_req_zero(req);
+
+    s = do_connect(host, port_str);
+    if (s < 0)
+       errx(1, "connection failed");
+
+    fdprintf(s, "GET %s HTTP/1.0\r\n", page);
+    for (i = 0; i < num_headers; i++)
+       fdprintf(s, "%s\r\n", headers[i]);
+    fdprintf(s, "Host: %s\r\n\r\n", host);
+
+    state = RESPONSE;
+
+    while (1) {
+       ret = read (s, in_ptr, sizeof(in_buf) - in_len - 1);
+       if (ret == 0)
+           break;
+       else if (ret < 0)
+           err (1, "read: %lu", (unsigned long)ret);
+       
+       in_buf[ret + in_len] = '\0';
+
+       if (state == HEADER || state == RESPONSE) {
+           char *p;
+
+           in_len += ret;
+           in_ptr += ret;
+
+           while (1) {
+               p = strstr(in_buf, "\r\n");
+
+               if (p == NULL) {
+                   break;
+               } else if (p == in_buf) {
+                   memmove(in_buf, in_buf + 2, sizeof(in_buf) - 2);
+                   state = BODY;
+                   in_len -= 2;
+                   in_ptr -= 2;
+                   break;
+               } else if (state == RESPONSE) {
+                   req->response = strndup(in_buf, p - in_buf);
+                   state = HEADER;
+               } else {
+                   req->headers = realloc(req->headers,
+                                          (req->num_headers + 1) * sizeof(req->headers[0]));
+                   req->headers[req->num_headers] = strndup(in_buf, p - in_buf);
+                   if (req->headers[req->num_headers] == NULL)
+                       errx(1, "strdup");
+                   req->num_headers++;
+               }
+               memmove(in_buf, p + 2, sizeof(in_buf) - (p - in_buf) - 2);
+               in_len -= (p - in_buf) + 2;
+               in_ptr -= (p - in_buf) + 2;
+           }
+       }
+
+       if (state == BODY) {
+
+           req->body = erealloc(req->body, req->body_size + ret + 1);
+
+           memcpy((char *)req->body + req->body_size, in_buf, ret);
+           req->body_size += ret;
+           ((char *)req->body)[req->body_size] = '\0';
+
+           in_ptr = in_buf;
+           in_len = 0;
+       } else
+           abort();
+    }
+
+    if (verbose_flag) {
+       int i;
+       printf("response: %s\n", req->response);
+       for (i = 0; i < req->num_headers; i++)
+           printf("header[%d] %s\n", i, req->headers[i]);
+       printf("body: %.*s\n", (int)req->body_size, (char *)req->body);
+    }
+
+    close(s);
+    return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+    struct http_req req;
+    const char *host, *page;
+    int i, done, print_body, gssapi_done, gssapi_started;
+    char *headers[10]; /* XXX */
+    int num_headers;
+    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+    gss_name_t server = GSS_C_NO_NAME;
+    int optind = 0;
+    gss_OID mech_oid;
+    OM_uint32 flags;
+
+    setprogname(argv[0]);
+
+    if(getarg(http_args, num_http_args, argc, argv, &optind))
+       usage(1);
+
+    if (help_flag)
+       usage (0);
+
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    mech_oid = select_mech(mech);
+
+    if (argc != 1 && argc != 2)
+       errx(1, "usage: %s host [page]", getprogname());
+    host = argv[0];
+    if (argc == 2)
+       page = argv[1];
+    else
+       page = "/";
+
+    flags = 0;
+    if (delegate_flag)
+       flags |= GSS_C_DELEG_FLAG;
+    if (mutual_flag)
+       flags |= GSS_C_MUTUAL_FLAG;
+
+    done = 0;
+    num_headers = 0;
+    gssapi_done = 1;
+    gssapi_started = 0;
+    do {
+       print_body = 0;
+
+       http_query(host, page, headers, num_headers, &req);
+       for (i = 0 ; i < num_headers; i++) 
+           free(headers[i]);
+       num_headers = 0;
+
+       if (strstr(req.response, " 200 ") != NULL) {
+           print_body = 1;
+           done = 1;
+       } else if (strstr(req.response, " 401 ") != NULL) {
+           if (http_find_header(&req, "WWW-Authenticate:") == NULL)
+               errx(1, "Got %s but missed `WWW-Authenticate'", req.response);
+           gssapi_done = 0;
+       }
+
+       if (!gssapi_done) {
+           const char *h = http_find_header(&req, "WWW-Authenticate:");
+           if (h == NULL)
+               errx(1, "Got %s but missed `WWW-Authenticate'", req.response);
+
+           if (strncasecmp(h, "Negotiate", 9) == 0) {
+               OM_uint32 maj_stat, min_stat;
+               gss_buffer_desc input_token, output_token;
+
+               if (verbose_flag)
+                   printf("Negotiate found\n");
+               
+               if (server == GSS_C_NO_NAME) {
+                   char *name;
+                   asprintf(&name, "%s@%s", gss_service, host);
+                   input_token.length = strlen(name);
+                   input_token.value = name;
+
+                   maj_stat = gss_import_name(&min_stat,
+                                              &input_token,
+                                              GSS_C_NT_HOSTBASED_SERVICE,
+                                              &server);
+                   if (GSS_ERROR(maj_stat))
+                       gss_err (1, min_stat, "gss_inport_name");
+                   free(name);
+                   input_token.length = 0;
+                   input_token.value = NULL;
+               }
+
+               i = 9;
+               while(isspace((unsigned char)h[i]))
+                   i++;
+               if (h[i] != '\0') {
+                   int len = strlen(&h[i]);
+                   if (len == 0)
+                       errx(1, "invalid Negotiate token");
+                   input_token.value = emalloc(len);
+                   len = base64_decode(&h[i], input_token.value);
+                   if (len < 0)
+                       errx(1, "invalid base64 Negotiate token %s", &h[i]);
+                   input_token.length = len;
+               } else {
+                   if (gssapi_started)
+                       errx(1, "Negotiate already started");
+                   gssapi_started = 1;
+
+                   input_token.length = 0;
+                   input_token.value = NULL;
+               }
+
+               maj_stat =
+                   gss_init_sec_context(&min_stat,
+                                        GSS_C_NO_CREDENTIAL,
+                                        &context_hdl,
+                                        server,
+                                        mech_oid,
+                                        flags,
+                                        0,
+                                        GSS_C_NO_CHANNEL_BINDINGS,
+                                        &input_token,
+                                        NULL,
+                                        &output_token,
+                                        NULL,
+                                        NULL);
+               if (GSS_ERROR(maj_stat))
+                   gss_err (1, min_stat, "gss_init_sec_context");
+               else if (maj_stat & GSS_S_CONTINUE_NEEDED)
+                   gssapi_done = 0;
+               else {
+                   gss_name_t targ_name, src_name;
+                   gss_buffer_desc name_buffer;
+                   gss_OID mech_type;
+
+                   gssapi_done = 1;
+
+                   printf("Negotiate done: %s\n", mech);
+
+                   maj_stat = gss_inquire_context(&min_stat,
+                                                  context_hdl,
+                                                  &src_name,
+                                                  &targ_name,
+                                                  NULL,
+                                                  &mech_type,
+                                                  NULL,
+                                                  NULL,
+                                                  NULL);
+                   if (GSS_ERROR(maj_stat))
+                       gss_err (1, min_stat, "gss_inquire_context");
+
+                   maj_stat = gss_display_name(&min_stat,
+                                               src_name,
+                                               &name_buffer,
+                                               NULL);
+                   if (GSS_ERROR(maj_stat))
+                       gss_err (1, min_stat, "gss_display_name");
+
+                   printf("Source: %.*s\n",
+                          (int)name_buffer.length,
+                          (char *)name_buffer.value);
+
+                   gss_release_buffer(&min_stat, &name_buffer);
+
+                   maj_stat = gss_display_name(&min_stat,
+                                               targ_name,
+                                               &name_buffer,
+                                               NULL);
+                   if (GSS_ERROR(maj_stat))
+                       gss_err (1, min_stat, "gss_display_name");
+
+                   printf("Target: %.*s\n",
+                          (int)name_buffer.length,
+                          (char *)name_buffer.value);
+
+                   gss_release_name(&min_stat, &targ_name);
+                   gss_release_buffer(&min_stat, &name_buffer);
+               }
+
+               if (output_token.length) {
+                   char *neg_token;
+
+                   base64_encode(output_token.value,
+                                 output_token.length,
+                                 &neg_token);
+                   
+                   asprintf(&headers[0], "Authorization: Negotiate %s",
+                            neg_token);
+
+                   num_headers = 1;
+                   free(neg_token);
+                   gss_release_buffer(&min_stat, &output_token);
+               }
+               if (input_token.length)
+                   free(input_token.value);
+
+           } else
+               done = 1;
+       } else
+           done = 1;
+
+       if (verbose_flag) {
+           printf("%s\n\n", req.response);
+
+           for (i = 0; i < req.num_headers; i++)
+               printf("%s\n", req.headers[i]);
+           printf("\n");
+       }
+       if (print_body || verbose_flag)
+           printf("%.*s\n", (int)req.body_size, (char *)req.body);
+
+       http_req_free(&req);
+    } while (!done);
+
+    if (gssapi_done == 0)
+       errx(1, "gssapi not done but http dance done");
+
+    return 0;
+}
diff --git a/src/kerberosV/src/appl/test/nt_gss_client.c b/src/kerberosV/src/appl/test/nt_gss_client.c
new file mode 100644 (file)
index 0000000..95a2456
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include "nt_gss_common.h"
+
+RCSID("$KTH: nt_gss_client.c,v 1.4 2000/08/09 20:53:07 assar Exp $");
+
+/*
+ * This program tries to act as a client for the sample in `Sample
+ * SSPI Code' in Windows 2000 RC1 SDK.
+ */
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+    struct sockaddr_in remote, local;
+    socklen_t addrlen;
+
+    int context_established = 0;
+    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+    gss_buffer_t input_token, output_token;
+    gss_buffer_desc real_input_token, real_output_token;
+    OM_uint32 maj_stat, min_stat;
+    gss_name_t server;
+    gss_buffer_desc name_token;
+
+    name_token.length = asprintf ((char **)&name_token.value,
+                                 "%s@%s", service, hostname);
+
+    maj_stat = gss_import_name (&min_stat,
+                               &name_token,
+                               GSS_C_NT_HOSTBASED_SERVICE,
+                               &server);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat,
+                "Error importing name `%s@%s':\n", service, hostname);
+
+    addrlen = sizeof(local);
+    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+       || addrlen != sizeof(local))
+       err (1, "getsockname(%s)", hostname);
+
+    addrlen = sizeof(remote);
+    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+       || addrlen != sizeof(remote))
+       err (1, "getpeername(%s)", hostname);
+
+    input_token = &real_input_token;
+    output_token = &real_output_token;
+
+    input_token->length = 0;
+    output_token->length = 0;
+
+    while(!context_established) {
+       maj_stat =
+           gss_init_sec_context(&min_stat,
+                                GSS_C_NO_CREDENTIAL,
+                                &context_hdl,
+                                server,
+                                GSS_C_NO_OID,
+                                GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG,
+                                0,
+                                GSS_C_NO_CHANNEL_BINDINGS,
+                                input_token,
+                                NULL,
+                                output_token,
+                                NULL,
+                                NULL);
+       if (GSS_ERROR(maj_stat))
+           gss_err (1, min_stat, "gss_init_sec_context");
+       if (output_token->length != 0)
+           nt_write_token (sock, output_token);
+       if (GSS_ERROR(maj_stat)) {
+           if (context_hdl != GSS_C_NO_CONTEXT)
+               gss_delete_sec_context (&min_stat,
+                                       &context_hdl,
+                                       GSS_C_NO_BUFFER);
+           break;
+       }
+       if (maj_stat & GSS_S_CONTINUE_NEEDED) {
+           nt_read_token (sock, input_token);
+       } else {
+           context_established = 1;
+       }
+
+    }
+
+    /* get_mic */
+
+    input_token->length = 3;
+    input_token->value  = strdup("hej");
+
+    maj_stat = gss_get_mic(&min_stat,
+                          context_hdl,
+                          GSS_C_QOP_DEFAULT,
+                          input_token,
+                          output_token);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_get_mic");
+
+    nt_write_token (sock, input_token);
+    nt_write_token (sock, output_token);
+
+    /* wrap */
+
+    input_token->length = 7;
+    input_token->value  = "hemligt";
+
+
+    maj_stat = gss_wrap (&min_stat,
+                        context_hdl,
+                        1,
+                        GSS_C_QOP_DEFAULT,
+                        input_token,
+                        NULL,
+                        output_token);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_wrap");
+
+    nt_write_token (sock, output_token);
+
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context; /* XXX */
+    int port = client_setup(&context, &argc, argv);
+    return client_doit (argv[argc], port, service, proto);
+}
diff --git a/src/kerberosV/src/appl/test/nt_gss_common.c b/src/kerberosV/src/appl/test/nt_gss_common.c
new file mode 100644 (file)
index 0000000..4dd5a6c
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include "nt_gss_common.h"
+
+RCSID("$KTH: nt_gss_common.c,v 1.3 1999/12/02 17:04:57 joda Exp $");
+
+/*
+ * These are functions that are needed to interoperate with the
+ * `Sample SSPI Code' in Windows 2000 RC1 SDK.
+ */
+
+/*
+ * Write the `gss_buffer_t' in `buf' onto the fd `sock', but remember that 
+ * the length is written in little-endian-order.
+ */
+
+void
+nt_write_token (int sock, gss_buffer_t buf)
+{
+    unsigned char net_len[4];
+    u_int32_t len;
+    OM_uint32 min_stat;
+
+    len = buf->length;
+
+    net_len[0] = (len >>  0) & 0xFF;
+    net_len[1] = (len >>  8) & 0xFF;
+    net_len[2] = (len >> 16) & 0xFF;
+    net_len[3] = (len >> 24) & 0xFF;
+
+    if (write (sock, net_len, 4) != 4)
+       err (1, "write");
+    if (write (sock, buf->value, len) != len)
+       err (1, "write");
+
+    gss_release_buffer (&min_stat, buf);
+}
+
+/*
+ *
+ */
+
+void
+nt_read_token (int sock, gss_buffer_t buf)
+{
+    unsigned char net_len[4];
+    u_int32_t len;
+
+    if (read(sock, net_len, 4) != 4)
+       err (1, "read");
+    len = (net_len[0] <<  0)
+       | (net_len[1] <<  8)
+       | (net_len[2] << 16)
+       | (net_len[3] << 24);
+
+    buf->length = len;
+    buf->value  = malloc(len);
+    if (read (sock, buf->value, len) != len)
+       err (1, "read");
+}
+
+void
+gss_print_errors (int min_stat)
+{
+    OM_uint32 new_stat;
+    OM_uint32 msg_ctx = 0;
+    gss_buffer_desc status_string;
+    OM_uint32 ret;
+
+    do {
+       ret = gss_display_status (&new_stat,
+                                 min_stat,
+                                 GSS_C_MECH_CODE,
+                                 GSS_C_NO_OID,
+                                 &msg_ctx,
+                                 &status_string);
+       fprintf (stderr, "%s\n", (char *)status_string.value);
+       gss_release_buffer (&new_stat, &status_string);
+    } while (!GSS_ERROR(ret) && msg_ctx != 0);
+}
+
+void
+gss_verr(int exitval, int status, const char *fmt, va_list ap)
+{
+    vwarnx (fmt, ap);
+    gss_print_errors (status);
+    exit (exitval);
+}
+
+void
+gss_err(int exitval, int status, const char *fmt, ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    gss_verr (exitval, status, fmt, args);
+    va_end(args);
+}
diff --git a/src/kerberosV/src/appl/test/nt_gss_common.h b/src/kerberosV/src/appl/test/nt_gss_common.h
new file mode 100644 (file)
index 0000000..f41bbf0
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: nt_gss_common.h,v 1.2 1999/12/02 17:04:57 joda Exp $ */
+
+void nt_write_token (int sock, gss_buffer_t buf);
+void nt_read_token (int sock, gss_buffer_t buf);
+
+void gss_print_errors (int min_stat);
+
+void gss_verr(int exitval, int status, const char *fmt, va_list ap)
+    __attribute__ ((format (printf, 3, 0)));
+
+void gss_err(int exitval, int status, const char *fmt, ...)
+    __attribute__ ((format (printf, 3, 4)));
diff --git a/src/kerberosV/src/appl/test/nt_gss_server.c b/src/kerberosV/src/appl/test/nt_gss_server.c
new file mode 100644 (file)
index 0000000..02a5503
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+#include <gssapi.h>
+#include <krb5.h>
+#include "nt_gss_common.h"
+
+RCSID("$KTH: nt_gss_server.c,v 1.6 2003/05/21 15:15:34 lha Exp $");
+
+/*
+ * This program tries to act as a server for the sample in `Sample
+ * SSPI Code' in Windows 2000 RC1 SDK.
+ *
+ * use --dump-auth to get a binary dump of the authorization data in the ticket
+ */
+
+static int help_flag;
+static int version_flag;
+static char *port_str;
+char *service = SERVICE;
+static char *auth_file;
+
+static struct getargs args[] = {
+    { "port", 'p', arg_string, &port_str, "port to listen to", "port" },
+    { "service", 's', arg_string, &service, "service to use", "service" },
+    { "dump-auth", 0, arg_string, &auth_file, "dump authorization data",
+      "file" },
+    { "help", 'h', arg_flag, &help_flag },
+    { "version", 0, arg_flag, &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static int
+proto (int sock, const char *service)
+{
+    struct sockaddr_in remote, local;
+    socklen_t addrlen;
+    gss_ctx_id_t context_hdl = GSS_C_NO_CONTEXT;
+    gss_buffer_t input_token, output_token;
+    gss_buffer_desc real_input_token, real_output_token;
+    OM_uint32 maj_stat, min_stat;
+    gss_name_t client_name;
+    gss_buffer_desc name_token;
+
+    addrlen = sizeof(local);
+    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+       || addrlen != sizeof(local))
+       err (1, "getsockname)");
+
+    addrlen = sizeof(remote);
+    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+       || addrlen != sizeof(remote))
+       err (1, "getpeername");
+
+    input_token = &real_input_token;
+    output_token = &real_output_token;
+
+    do {
+       nt_read_token (sock, input_token);
+       maj_stat =
+           gss_accept_sec_context (&min_stat,
+                                   &context_hdl,
+                                   GSS_C_NO_CREDENTIAL,
+                                   input_token,
+                                   GSS_C_NO_CHANNEL_BINDINGS,
+                                   &client_name,
+                                   NULL,
+                                   output_token,
+                                   NULL,
+                                   NULL,
+                                   NULL);
+       if(GSS_ERROR(maj_stat))
+           gss_err (1, min_stat, "gss_accept_sec_context");
+       if (output_token->length != 0)
+           nt_write_token (sock, output_token);
+       if (GSS_ERROR(maj_stat)) {
+           if (context_hdl != GSS_C_NO_CONTEXT)
+               gss_delete_sec_context (&min_stat,
+                                       &context_hdl,
+                                       GSS_C_NO_BUFFER);
+           break;
+       }
+    } while(maj_stat & GSS_S_CONTINUE_NEEDED);
+
+    if (auth_file != NULL) {
+       int fd = open (auth_file, O_WRONLY | O_CREAT, 0666);
+#if 0
+       krb5_ticket *ticket;
+       krb5_data *data;
+
+       ticket = context_hdl->ticket;
+       data = &ticket->ticket.authorization_data->val[0].ad_data;
+
+       if(fd < 0)
+           err (1, "open %s", auth_file);
+       if (write (fd, data->data, data->length) != data->length)
+           errx (1, "write to %s failed", auth_file);
+#endif
+       if (close (fd))
+           err (1, "close %s", auth_file);
+    }
+
+    maj_stat = gss_display_name (&min_stat,
+                                client_name,
+                                &name_token,
+                                NULL);
+    if (GSS_ERROR(maj_stat))
+       gss_err (1, min_stat, "gss_display_name");
+
+    fprintf (stderr, "User is `%.*s'\n", (int)name_token.length,
+           (char *)name_token.value);
+
+    /* write something back */
+
+    output_token->value  = strdup ("hejsan");
+    output_token->length = strlen (output_token->value) + 1;
+    nt_write_token (sock, output_token);
+
+    output_token->value  = strdup ("hoppsan");
+    output_token->length = strlen (output_token->value) + 1;
+    nt_write_token (sock, output_token);
+
+    return 0;
+}
+
+static int
+doit (int port, const char *service)
+{
+    int sock, sock2;
+    struct sockaddr_in my_addr;
+    int one = 1;
+
+    sock = socket (AF_INET, SOCK_STREAM, 0);
+    if (sock < 0)
+       err (1, "socket");
+
+    memset (&my_addr, 0, sizeof(my_addr));
+    my_addr.sin_family      = AF_INET;
+    my_addr.sin_port        = port;
+    my_addr.sin_addr.s_addr = INADDR_ANY;
+
+    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,
+                   (void *)&one, sizeof(one)) < 0)
+       warn ("setsockopt SO_REUSEADDR");
+
+    if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+       err (1, "bind");
+
+    if (listen (sock, 1) < 0)
+       err (1, "listen");
+
+    sock2 = accept (sock, NULL, NULL);
+    if (sock2 < 0)
+       err (1, "accept");
+
+    return proto (sock2, service);
+}
+
+static void
+usage(int code, struct getargs *args, int num_args)
+{
+    arg_printusage(args, num_args, NULL, "");
+    exit(code);
+}
+
+static int
+common_setup(krb5_context *context, int *argc, char **argv, 
+            void (*usage)(int, struct getargs*, int))
+{
+    int port = 0;
+    *argc = krb5_program_setup(context, *argc, argv, args, num_args, usage);
+
+    if(help_flag)
+       (*usage)(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    
+    if(port_str){
+       struct servent *s = roken_getservbyname(port_str, "tcp");
+       if(s)
+           port = s->s_port;
+       else {
+           char *ptr;
+
+           port = strtol (port_str, &ptr, 10);
+           if (port == 0 && ptr == port_str)
+               errx (1, "Bad port `%s'", port_str);
+           port = htons(port);
+       }
+    }
+
+    if (port == 0)
+       port = krb5_getportbyname (*context, PORT, "tcp", 4711);
+    
+    return port;
+}
+
+static int
+setup(krb5_context *context, int argc, char **argv)
+{
+    int port = common_setup(context, &argc, argv, usage);
+    if(argv[argc] != NULL)
+       usage(1, args, num_args);
+    return port;
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context = NULL; /* XXX */
+    int port = setup(&context, argc, argv);
+    return doit (port, service);
+}
diff --git a/src/kerberosV/src/appl/test/tcp_client.c b/src/kerberosV/src/appl/test/tcp_client.c
new file mode 100644 (file)
index 0000000..64df06a
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+RCSID("$KTH: tcp_client.c,v 1.15 1999/12/16 10:30:17 assar Exp $");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+    krb5_auth_context auth_context;
+    krb5_error_code status;
+    krb5_principal server;
+    krb5_data data;
+    krb5_data packet;
+    u_int32_t len, net_len;
+
+    status = krb5_auth_con_init (context, &auth_context);
+    if (status)
+       krb5_err (context, 1, status, "krb5_auth_con_init");
+
+    status = krb5_auth_con_setaddrs_from_fd (context,
+                                            auth_context,
+                                            &sock);
+    if (status)
+       krb5_err (context, 1, status, "krb5_auth_con_setaddrs_from_fd");
+
+    status = krb5_sname_to_principal (context,
+                                     hostname,
+                                     service,
+                                     KRB5_NT_SRV_HST,
+                                     &server);
+    if (status)
+       krb5_err (context, 1, status, "krb5_sname_to_principal");
+
+    status = krb5_sendauth (context,
+                           &auth_context,
+                           &sock,
+                           VERSION,
+                           NULL,
+                           server,
+                           AP_OPTS_MUTUAL_REQUIRED,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL,
+                           NULL);
+    if (status)
+       krb5_err (context, 1, status, "krb5_sendauth");
+
+    data.data   = "hej";
+    data.length = 3;
+
+    krb5_data_zero (&packet);
+
+    status = krb5_mk_safe (context,
+                          auth_context,
+                          &data,
+                          &packet,
+                          NULL);
+    if (status)
+       krb5_err (context, 1, status, "krb5_mk_safe");
+
+    len = packet.length;
+    net_len = htonl(len);
+
+    if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+       err (1, "krb5_net_write");
+    if (krb5_net_write (context, &sock, packet.data, len) != len)
+       err (1, "krb5_net_write");
+
+    data.data   = "hemligt";
+    data.length = 7;
+
+    krb5_data_free (&packet);
+
+    status = krb5_mk_priv (context,
+                          auth_context,
+                          &data,
+                          &packet,
+                          NULL);
+    if (status)
+       krb5_err (context, 1, status, "krb5_mk_priv");
+
+    len = packet.length;
+    net_len = htonl(len);
+
+    if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+       err (1, "krb5_net_write");
+    if (krb5_net_write (context, &sock, packet.data, len) != len)
+       err (1, "krb5_net_write");
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    int port = client_setup(&context, &argc, argv);
+    return client_doit (argv[argc], port, service, proto);
+}
diff --git a/src/kerberosV/src/appl/test/tcp_server.c b/src/kerberosV/src/appl/test/tcp_server.c
new file mode 100644 (file)
index 0000000..633638d
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+RCSID("$KTH: tcp_server.c,v 1.16 1999/12/16 10:31:08 assar Exp $");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *service)
+{
+    krb5_auth_context auth_context;
+    krb5_error_code status;
+    krb5_principal server;
+    krb5_ticket *ticket;
+    char *name;
+    char hostname[MAXHOSTNAMELEN];
+    krb5_data packet;
+    krb5_data data;
+    u_int32_t len, net_len;
+    ssize_t n;
+
+    status = krb5_auth_con_init (context, &auth_context);
+    if (status)
+       krb5_err (context, 1, status, "krb5_auth_con_init");
+
+    status = krb5_auth_con_setaddrs_from_fd (context,
+                                            auth_context,
+                                            &sock);
+
+    if (status)
+       krb5_err (context, 1, status, "krb5_auth_con_setaddrs_from_fd");
+
+    if(gethostname (hostname, sizeof(hostname)) < 0)
+       krb5_err (context, 1, errno, "gethostname");
+
+    status = krb5_sname_to_principal (context,
+                                     hostname,
+                                     service,
+                                     KRB5_NT_SRV_HST,
+                                     &server);
+    if (status)
+       krb5_err (context, 1, status, "krb5_sname_to_principal");
+
+    status = krb5_recvauth (context,
+                           &auth_context,
+                           &sock,
+                           VERSION,
+                           server,
+                           0,
+                           NULL,
+                           &ticket);
+    if (status)
+       krb5_err (context, 1, status, "krb5_recvauth");
+
+    status = krb5_unparse_name (context,
+                               ticket->client,
+                               &name);
+    if (status)
+       krb5_err (context, 1, status, "krb5_unparse_name");
+
+    fprintf (stderr, "User is `%s'\n", name);
+    free (name);
+
+    krb5_data_zero (&data);
+    krb5_data_zero (&packet);
+
+    n = krb5_net_read (context, &sock, &net_len, 4);
+    if (n == 0)
+       krb5_errx (context, 1, "EOF in krb5_net_read");
+    if (n < 0)
+       krb5_err (context, 1, errno, "krb5_net_read");
+
+    len = ntohl(net_len);
+
+    krb5_data_alloc (&packet, len);
+
+    n = krb5_net_read (context, &sock, packet.data, len);
+    if (n == 0)
+       krb5_errx (context, 1, "EOF in krb5_net_read");
+    if (n < 0)
+       krb5_err (context, 1, errno, "krb5_net_read");
+    
+    status = krb5_rd_safe (context,
+                          auth_context,
+                          &packet,
+                          &data,
+                          NULL);
+    if (status)
+       krb5_err (context, 1, status, "krb5_rd_safe");
+
+    fprintf (stderr, "safe packet: %.*s\n", (int)data.length,
+           (char *)data.data);
+
+    n = krb5_net_read (context, &sock, &net_len, 4);
+    if (n == 0)
+       krb5_errx (context, 1, "EOF in krb5_net_read");
+    if (n < 0)
+       krb5_err (context, 1, errno, "krb5_net_read");
+
+    len = ntohl(net_len);
+
+    krb5_data_alloc (&packet, len);
+
+    n = krb5_net_read (context, &sock, packet.data, len);
+    if (n == 0)
+       krb5_errx (context, 1, "EOF in krb5_net_read");
+    if (n < 0)
+       krb5_err (context, 1, errno, "krb5_net_read");
+    
+    status = krb5_rd_priv (context,
+                          auth_context,
+                          &packet,
+                          &data,
+                          NULL);
+    if (status)
+       krb5_err (context, 1, status, "krb5_rd_priv");
+
+    fprintf (stderr, "priv packet: %.*s\n", (int)data.length,
+           (char *)data.data);
+
+    return 0;
+}
+
+static int
+doit (int port, const char *service)
+{
+    mini_inetd (port);
+
+    return proto (STDIN_FILENO, service);
+}
+
+int
+main(int argc, char **argv)
+{
+    int port = server_setup(&context, argc, argv);
+    return doit (port, service);
+}
diff --git a/src/kerberosV/src/appl/test/test_locl.h b/src/kerberosV/src/appl/test/test_locl.h
new file mode 100644 (file)
index 0000000..4eb06bb
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: test_locl.h,v 1.10 2003/09/09 03:38:51 lha Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <errno.h>
+#include <roken.h>
+#include <getarg.h>
+#include <err.h>
+#include <krb5.h>
+
+#define SERVICE "test"
+
+#define PORT "test"
+
+extern char *service;
+extern char *mech;
+extern krb5_keytab keytab;
+extern int fork_flag;
+int server_setup(krb5_context*, int, char**);
+int client_setup(krb5_context*, int*, char**);
+int client_doit (const char *hostname, int port, const char *service,
+                int (*func)(int, const char *hostname, const char *service));
diff --git a/src/kerberosV/src/appl/test/uu_client.c b/src/kerberosV/src/appl/test/uu_client.c
new file mode 100644 (file)
index 0000000..4c3583d
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+RCSID("$KTH: uu_client.c,v 1.11 2005/04/03 19:53:32 lha Exp $");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *hostname, const char *service)
+{
+    struct sockaddr_in remote, local;
+    socklen_t addrlen;
+    krb5_address remote_addr, local_addr;
+    krb5_context context;
+    krb5_ccache ccache;
+    krb5_auth_context auth_context;
+    krb5_error_code status;
+    krb5_principal client;
+    krb5_data data;
+    krb5_data packet;
+    krb5_creds mcred, cred;
+    krb5_ticket *ticket;
+
+    addrlen = sizeof(local);
+    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+       || addrlen != sizeof(local))
+       err (1, "getsockname(%s)", hostname);
+
+    addrlen = sizeof(remote);
+    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+       || addrlen != sizeof(remote))
+       err (1, "getpeername(%s)", hostname);
+
+    status = krb5_init_context(&context);
+    if (status)
+       errx(1, "krb5_init_context failed: %d", status);
+
+    status = krb5_cc_default (context, &ccache);
+    if (status)
+       krb5_err(context, 1, status, "krb5_cc_default");
+
+    status = krb5_auth_con_init (context, &auth_context);
+    if (status)
+       krb5_err(context, 1, status, "krb5_auth_con_init");
+
+    local_addr.addr_type = AF_INET;
+    local_addr.address.length = sizeof(local.sin_addr);
+    local_addr.address.data   = &local.sin_addr;
+
+    remote_addr.addr_type = AF_INET;
+    remote_addr.address.length = sizeof(remote.sin_addr);
+    remote_addr.address.data   = &remote.sin_addr;
+
+    status = krb5_auth_con_setaddrs (context,
+                                    auth_context,
+                                    &local_addr,
+                                    &remote_addr);
+    if (status)
+       krb5_err(context, 1, status, "krb5_auth_con_setaddr");
+
+    krb5_cc_clear_mcred(&mcred);
+
+    status = krb5_cc_get_principal(context, ccache, &client);
+    if(status)
+       krb5_err(context, 1, status, "krb5_cc_get_principal");
+    status = krb5_make_principal(context, &mcred.server,
+                                *krb5_princ_realm(context, client), 
+                                "krbtgt", 
+                                *krb5_princ_realm(context, client),
+                                NULL);
+    if(status)
+       krb5_err(context, 1, status, "krb5_make_principal");
+    mcred.client = client;
+    
+    status = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
+    if(status)
+       krb5_err(context, 1, status, "krb5_cc_retrieve_cred");
+
+    {
+       char *client_name;
+       krb5_data data;
+       status = krb5_unparse_name(context, cred.client, &client_name);
+       if(status)
+           krb5_err(context, 1, status, "krb5_unparse_name");
+       data.data = client_name;
+       data.length = strlen(client_name) + 1;
+       status = krb5_write_message(context, &sock, &data);
+       if(status)
+           krb5_err(context, 1, status, "krb5_write_message");
+       free(client_name);
+    }
+
+    status = krb5_write_message(context, &sock, &cred.ticket);
+    if(status)
+       krb5_err(context, 1, status, "krb5_write_message");
+
+    status = krb5_auth_con_setuserkey(context, auth_context, &cred.session);
+    if(status)
+       krb5_err(context, 1, status, "krb5_auth_con_setuserkey");
+    
+    status = krb5_recvauth(context, &auth_context, &sock, 
+                          VERSION, client, 0, NULL, &ticket);
+
+    if (status)
+       krb5_err(context, 1, status, "krb5_recvauth");
+    
+    if (ticket->ticket.authorization_data) {
+       AuthorizationData *authz;
+       int i;
+
+       printf("Authorization data:\n");
+
+       authz = ticket->ticket.authorization_data;
+       for (i = 0; i < authz->len; i++) {
+           printf("\ttype %d, length %lu\n",
+                  authz->val[i].ad_type,
+                  (unsigned long)authz->val[i].ad_data.length);
+       }
+    }
+
+    data.data   = "hej";
+    data.length = 3;
+
+    krb5_data_zero (&packet);
+
+    status = krb5_mk_safe (context,
+                          auth_context,
+                          &data,
+                          &packet,
+                          NULL);
+    if (status)
+       krb5_err(context, 1, status, "krb5_mk_safe");
+
+    status = krb5_write_message(context, &sock, &packet);
+    if(status)
+       krb5_err(context, 1, status, "krb5_write_message");
+
+    data.data   = "hemligt";
+    data.length = 7;
+
+    krb5_data_free (&packet);
+
+    status = krb5_mk_priv (context,
+                          auth_context,
+                          &data,
+                          &packet,
+                          NULL);
+    if (status)
+       krb5_err(context, 1, status, "krb5_mk_priv");
+
+    status = krb5_write_message(context, &sock, &packet);
+    if(status)
+       krb5_err(context, 1, status, "krb5_write_message");
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    int port = client_setup(&context, &argc, argv);
+    return client_doit (argv[argc], port, service, proto);
+}
diff --git a/src/kerberosV/src/appl/test/uu_server.c b/src/kerberosV/src/appl/test/uu_server.c
new file mode 100644 (file)
index 0000000..d554489
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "test_locl.h"
+RCSID("$KTH: uu_server.c,v 1.7 2000/08/09 20:53:08 assar Exp $");
+
+krb5_context context;
+
+static int
+proto (int sock, const char *service)
+{
+    struct sockaddr_in remote, local;
+    socklen_t addrlen;
+    krb5_address remote_addr, local_addr;
+    krb5_ccache ccache;
+    krb5_auth_context auth_context;
+    krb5_error_code status;
+    krb5_data packet;
+    krb5_data data;
+    krb5_data client_name;
+    krb5_creds in_creds, *out_creds;
+
+    addrlen = sizeof(local);
+    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
+       || addrlen != sizeof(local))
+       err (1, "getsockname)");
+
+    addrlen = sizeof(remote);
+    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
+       || addrlen != sizeof(remote))
+       err (1, "getpeername");
+
+    status = krb5_auth_con_init (context, &auth_context);
+    if (status)
+       errx (1, "krb5_auth_con_init: %s",
+             krb5_get_err_text(context, status));
+
+    local_addr.addr_type = AF_INET;
+    local_addr.address.length = sizeof(local.sin_addr);
+    local_addr.address.data   = &local.sin_addr;
+
+    remote_addr.addr_type = AF_INET;
+    remote_addr.address.length = sizeof(remote.sin_addr);
+    remote_addr.address.data   = &remote.sin_addr;
+
+    status = krb5_auth_con_setaddrs (context,
+                                    auth_context,
+                                    &local_addr,
+                                    &remote_addr);
+    if (status)
+       errx (1, "krb5_auth_con_setaddr: %s",
+             krb5_get_err_text(context, status));
+
+    status = krb5_read_message(context, &sock, &client_name);
+    if(status)
+       krb5_err(context, 1, status, "krb5_read_message");
+    
+    memset(&in_creds, 0, sizeof(in_creds));
+    status = krb5_cc_default(context, &ccache);
+    status = krb5_cc_get_principal(context, ccache, &in_creds.client);
+
+    status = krb5_read_message(context, &sock, &in_creds.second_ticket);
+    if(status)
+       krb5_err(context, 1, status, "krb5_read_message");
+
+    status = krb5_parse_name(context, client_name.data, &in_creds.server);
+    if(status)
+       krb5_err(context, 1, status, "krb5_parse_name");
+    
+    status = krb5_get_credentials(context, KRB5_GC_USER_USER, ccache, 
+                                 &in_creds, &out_creds);
+    if(status)
+       krb5_err(context, 1, status, "krb5_get_credentials");
+
+    status = krb5_cc_default(context, &ccache);
+
+    status = krb5_sendauth(context, 
+                          &auth_context,
+                          &sock, 
+                          VERSION, 
+                          in_creds.client,
+                          in_creds.server,
+                          AP_OPTS_USE_SESSION_KEY,
+                          NULL,
+                          out_creds,
+                          ccache,
+                          NULL,
+                          NULL,
+                          NULL);
+                          
+    if (status)
+       krb5_err(context, 1, status, "krb5_sendauth");
+    
+    fprintf (stderr, "User is `%.*s'\n", (int)client_name.length,
+           (char *)client_name.data);
+
+    krb5_data_zero (&data);
+    krb5_data_zero (&packet);
+
+    status = krb5_read_message(context, &sock, &packet);
+    if(status)
+       krb5_err(context, 1, status, "krb5_read_message");
+    
+    status = krb5_rd_safe (context,
+                          auth_context,
+                          &packet,
+                          &data,
+                          NULL);
+    if (status)
+       errx (1, "krb5_rd_safe: %s",
+             krb5_get_err_text(context, status));
+
+    fprintf (stderr, "safe packet: %.*s\n", (int)data.length,
+           (char *)data.data);
+
+    status = krb5_read_message(context, &sock, &packet);
+    if(status)
+       krb5_err(context, 1, status, "krb5_read_message");
+    
+    status = krb5_rd_priv (context,
+                          auth_context,
+                          &packet,
+                          &data,
+                          NULL);
+    if (status)
+       errx (1, "krb5_rd_priv: %s",
+             krb5_get_err_text(context, status));
+
+    fprintf (stderr, "priv packet: %.*s\n", (int)data.length,
+           (char *)data.data);
+
+    return 0;
+}
+
+static int
+doit (int port, const char *service)
+{
+    int sock, sock2;
+    struct sockaddr_in my_addr;
+    int one = 1;
+
+    sock = socket (AF_INET, SOCK_STREAM, 0);
+    if (sock < 0)
+       err (1, "socket");
+
+    memset (&my_addr, 0, sizeof(my_addr));
+    my_addr.sin_family      = AF_INET;
+    my_addr.sin_port        = port;
+    my_addr.sin_addr.s_addr = INADDR_ANY;
+
+    if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, 
+                   (void *)&one, sizeof(one)) < 0)
+       warn ("setsockopt SO_REUSEADDR");
+
+    if (bind (sock, (struct sockaddr *)&my_addr, sizeof(my_addr)) < 0)
+       err (1, "bind");
+
+    if (listen (sock, 1) < 0)
+       err (1, "listen");
+
+    sock2 = accept (sock, NULL, NULL);
+    if (sock2 < 0)
+       err (1, "accept");
+
+    return proto (sock2, service);
+}
+
+int
+main(int argc, char **argv)
+{
+    int port = server_setup(&context, argc, argv);
+    return doit (port, service);
+}
diff --git a/src/kerberosV/src/cf/CVS/Entries b/src/kerberosV/src/cf/CVS/Entries
new file mode 100644 (file)
index 0000000..4041511
--- /dev/null
@@ -0,0 +1,6 @@
+/check-symbols.sh/1.1.1.1/Fri Apr 14 07:34:02 2006//
+/largefile.m4/1.1.1.1/Fri Apr 14 07:34:02 2006//
+/pthreads.m4/1.1.1.1/Fri Apr 14 07:34:03 2006//
+/vararray.m4/1.1.1.1/Fri Apr 14 07:34:03 2006//
+/win32.m4/1.1.1.1/Fri Apr 14 07:34:03 2006//
+D
diff --git a/src/kerberosV/src/cf/CVS/Repository b/src/kerberosV/src/cf/CVS/Repository
new file mode 100644 (file)
index 0000000..1149eb0
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/cf
diff --git a/src/kerberosV/src/cf/CVS/Root b/src/kerberosV/src/cf/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/cf/check-symbols.sh b/src/kerberosV/src/cf/check-symbols.sh
new file mode 100644 (file)
index 0000000..04c86a9
--- /dev/null
@@ -0,0 +1,49 @@
+#!/bin/sh
+# check library exported symbols
+# $KTH: check-symbols.sh,v 1.10.2.1 2005/06/15 01:25:48 lha Exp $
+
+LANG=C
+export LANG
+
+exit 0 #disable test on release branch
+
+esym=
+symbols=
+
+# AIX has different default output format
+nmargs=""
+if [ "`uname`" = AIX ]; then
+       nmargs="-B"
+fi
+
+while test $# != 0 ;do 
+  case "$1" in
+    -lib) lib="$2" ; shift;;
+    -com_err)
+       esym="${esym} com_right\$ free_error_table\$ initialize_error_table_r\$"
+       esym="${esym} com_err error_message\$ error_table_name\$"
+       esym="${esym} init_error_table\$ add_to_error_table\$"
+       esym="${esym} reset_com_err_hook\$ set_com_err_hook\$ _et_list\$"
+       esym="${esym} et_[A-Za-z0-9]*_error_table"
+       esym="${esym} initialize_[A-Za-z0-9]*_error_table et_*_error_table" ;;
+    -version)
+       esym="${esym} print_version\$" ;;
+    -asn1compile)
+       esym="${esym} copy_ free_ length_ decode_ encode_ length_ "
+       esym="${esym} *.2int\$ int2 asn1_[A-Za-z0-9]*_units\$" ;;
+    -*) echo "unknown option $1" ; exit 1 ;;
+    *) break ;;
+  esac
+  shift
+done
+
+for a in "$@" $esym; do
+    symbols="\$3 !~ /^_?${a}/ ${symbols:+&&} ${symbols}"
+done
+
+# F filename, N debugsymbols, W weak symbols, U undefined
+
+(nm $nmargs .libs/lib${lib}.a || nm $nmargs .libs/lib${lib}.so*)  |
+awk "BEGIN { stat = 0 }
+NF == 3 && \$2 ~ /[A-EG-MO-TVX-Z]/ && $symbols { printf \"%s should not be exported (type %s)\\n\", \$3, \$2; ++stat } END { exit stat }"
+
diff --git a/src/kerberosV/src/cf/largefile.m4 b/src/kerberosV/src/cf/largefile.m4
new file mode 100644 (file)
index 0000000..8f982a9
--- /dev/null
@@ -0,0 +1,16 @@
+dnl $KTH: largefile.m4,v 1.1 2004/04/24 21:51:32 joda Exp $
+dnl
+dnl Figure out what flags we need for 64-bit file access, and also set
+dnl them on the command line.
+dnl
+AC_DEFUN([rk_SYS_LARGEFILE],[
+AC_REQUIRE([AC_SYS_LARGEFILE])dnl
+dnl need to set this on the command line, since it might otherwise break
+dnl with generated code, such as lex
+if test "$enable_largefile" != no -a "$ac_cv_sys_large_files" != no; then
+       CPPFLAGS="$CPPFLAGS -D_LARGE_FILES=$ac_cv_sys_large_files"
+fi
+if test "$enable_largefile" != no -a "$ac_cv_sys_file_offset_bits" != no; then
+       CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=$ac_cv_sys_file_offset_bits"
+fi
+])
diff --git a/src/kerberosV/src/cf/pthreads.m4 b/src/kerberosV/src/cf/pthreads.m4
new file mode 100644 (file)
index 0000000..557daf3
--- /dev/null
@@ -0,0 +1,72 @@
+dnl $KTH: pthreads.m4,v 1.10.2.1 2005/06/16 16:22:24 lha Exp $
+
+AC_DEFUN([KRB_PTHREADS], [
+AC_MSG_CHECKING(if compiling threadsafe libraries)
+
+AC_ARG_ENABLE(pthread-support,
+       AS_HELP_STRING([--enable-pthread-support],
+                       [if you want thread safe libraries]),
+       [],[enable_pthread_support=maybe])
+
+case "$host" in 
+*-*-solaris2*)
+       native_pthread_support=yes
+       if test "$GCC" = yes; then
+               PTHREADS_CFLAGS=-pthreads
+               PTHREADS_LIBS=-pthreads
+       else
+               PTHREADS_CFLAGS=-mt
+               PTHREADS_LIBS=-mt
+       fi
+       ;;
+*-*-netbsd*)
+       native_pthread_support="if running netbsd 1.6T or newer"
+       dnl heim_threads.h knows this
+       PTHREADS_LIBS=""
+       ;;
+*-*-freebsd5*)
+       native_pthread_support=yes
+       ;;
+*-*-linux* | *-*-linux-gnu)
+       case `uname -r` in
+       2.*)
+               native_pthread_support=yes
+               PTHREADS_CFLAGS=-pthread
+               PTHREADS_LIBS=-pthread
+               ;;
+       esac
+       ;;
+*-*-aix*)
+       dnl AIX is disabled since we don't handle the utmp/utmpx
+        dnl problems that aix causes when compiling with pthread support
+       native_pthread_support=no
+       ;;
+mips-sgi-irix6.[[5-9]])  # maybe works for earlier versions too
+       native_pthread_support=yes
+       PTHREADS_LIBS="-lpthread"
+       ;;
+*)
+       native_pthread_support=no
+       ;;
+esac
+
+if test "$enable_pthread_support" = maybe ; then
+       enable_pthread_support="$native_pthread_support"
+fi
+       
+if test "$enable_pthread_support" != no; then
+    AC_DEFINE(ENABLE_PTHREAD_SUPPORT, 1,
+       [Define if you want have a thread safe libraries])
+    dnl This sucks, but libtool doesn't save the depenecy on -pthread
+    dnl for libraries.
+    LIBS="$PTHREADS_LIBS $LIBS"
+else
+  PTHREADS_CFLAGS=""
+  PTHREADS_LIBS=""
+fi
+
+AC_SUBST(PTHREADS_CFLAGS)
+AC_SUBST(PTHREADS_LIBS)
+
+AC_MSG_RESULT($enable_pthread_support)
+])
diff --git a/src/kerberosV/src/cf/vararray.m4 b/src/kerberosV/src/cf/vararray.m4
new file mode 100644 (file)
index 0000000..a6a961e
--- /dev/null
@@ -0,0 +1,16 @@
+dnl
+dnl $KTH: vararray.m4,v 1.3 2004/08/26 12:35:42 joda Exp $
+dnl
+dnl Test for variable size arrays.
+dnl
+
+AC_DEFUN([rk_C_VARARRAY], [
+       AC_CACHE_CHECK([if the compiler supports variable-length arrays],[rk_cv_c_vararray],[
+       AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[int x = 0; { int y[x]; }]])],
+               [rk_cv_c_vararray=yes],
+               [rk_cv_c_vararray=no])])
+       if test "$rk_cv_c_vararray" = yes; then
+               AC_DEFINE([HAVE_VARIABLE_LENGTH_ARRAY], [1],
+                       [Define if your compiler supports variable-length arrays.])
+       fi
+])
diff --git a/src/kerberosV/src/cf/win32.m4 b/src/kerberosV/src/cf/win32.m4
new file mode 100644 (file)
index 0000000..c73a801
--- /dev/null
@@ -0,0 +1,12 @@
+dnl $KTH: win32.m4,v 1.1 2004/04/13 14:29:47 lha Exp $
+dnl rk_WIN32_EXPORT buildsymbol symbol-that-export
+AC_DEFUN([rk_WIN32_EXPORT],[AH_TOP([#ifdef $1
+#ifndef $2
+#ifdef _WIN32_
+#define $2 _export _stdcall
+#else
+#define $2
+#endif
+#endif
+#endif
+])])
diff --git a/src/kerberosV/src/compile b/src/kerberosV/src/compile
new file mode 100755 (executable)
index 0000000..a81e000
--- /dev/null
@@ -0,0 +1,136 @@
+#! /bin/sh
+# Wrapper for compilers which do not understand `-c -o'.
+
+scriptversion=2003-11-09.00
+
+# Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# 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 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.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: compile [--help] [--version] PROGRAM [ARGS]
+
+Wrapper for compilers which do not understand `-c -o'.
+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
+arguments, and rename the output as expected.
+
+If you are trying to build a whole package this is not the
+right script to run: please start by reading the file `INSTALL'.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit 0
+    ;;
+  -v | --v*)
+    echo "compile $scriptversion"
+    exit 0
+    ;;
+esac
+
+
+prog=$1
+shift
+
+ofile=
+cfile=
+args=
+while test $# -gt 0; do
+  case "$1" in
+    -o)
+      # configure might choose to run compile as `compile cc -o foo foo.c'.
+      # So we do something ugly here.
+      ofile=$2
+      shift
+      case "$ofile" in
+       *.o | *.obj)
+         ;;
+       *)
+         args="$args -o $ofile"
+         ofile=
+         ;;
+      esac
+       ;;
+    *.c)
+      cfile=$1
+      args="$args $1"
+      ;;
+    *)
+      args="$args $1"
+      ;;
+  esac
+  shift
+done
+
+if test -z "$ofile" || test -z "$cfile"; then
+  # If no `-o' option was seen then we might have been invoked from a
+  # pattern rule where we don't need one.  That is ok -- this is a
+  # normal compilation that the losing compiler can handle.  If no
+  # `.c' file was seen then we are probably linking.  That is also
+  # ok.
+  exec "$prog" $args
+fi
+
+# Name of file we expect compiler to create.
+cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+# Note: use `[/.-]' here to ensure that we don't use the same name
+# that we are using for the .o file.  Also, base the name on the expected
+# object file name, since that is what matters with a parallel build.
+lockdir=`echo $cofile | sed -e 's|[/.-]|_|g'`.d
+while true; do
+  if mkdir $lockdir > /dev/null 2>&1; then
+    break
+  fi
+  sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir $lockdir; exit 1" 1 2 15
+
+# Run the compile.
+"$prog" $args
+status=$?
+
+if test -f "$cofile"; then
+  mv "$cofile" "$ofile"
+fi
+
+rmdir $lockdir
+exit $status
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# 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/src/kerberosV/src/config.guess b/src/kerberosV/src/config.guess
new file mode 100644 (file)
index 0000000..d8d4d86
--- /dev/null
@@ -0,0 +1,1409 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-03-03'
+
+# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # 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 -q "$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 ;'
+
+# 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 0 ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:MirBSD:*:*)
+       echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+       exit 0 ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit 0 ;;
+    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 0 ;;
+    Alpha*:OpenVMS:*:*)
+       echo alpha-hp-vms
+       exit 0 ;;
+    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 0 ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit 0 ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit 0;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit 0 ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit 0 ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit 0 ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit 0;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit 0;;
+    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 0 ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit 0 ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit 0 ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7 && exit 0 ;;
+       esac ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    i86pc:SunOS:5.*:*)
+       echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    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 0 ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit 0 ;;
+    # 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 0 ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit 0 ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit 0 ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit 0 ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit 0 ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit 0 ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit 0 ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit 0 ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit 0 ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c \
+         && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && exit 0
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit 0 ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit 0 ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit 0 ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit 0 ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit 0 ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit 0 ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit 0 ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    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 0 ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit 0 ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit 0 ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit 0 ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit 0 ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit 0 ;;
+    ????????: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 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit 0 ;;
+    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 0 ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+               echo rs6000-ibm-aix3.2.5
+       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 0 ;;
+    *: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 0 ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit 0 ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit 0 ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit 0 ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit 0 ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit 0 ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit 0 ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           # avoid double evaluation of $set_cc_for_build
+           test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit 0 ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+       echo unknown-hitachi-hiuxwe2
+       exit 0 ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit 0 ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit 0 ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit 0 ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit 0 ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit 0 ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit 0 ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit 0 ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit 0 ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit 0 ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit 0 ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit 0 ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit 0 ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    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 0 ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    *:UNICOS/mp:*:*)
+       echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit 0 ;;
+    *:FreeBSD:*:*)
+       # Determine whether the default compiler uses glibc.
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #if __GLIBC__ >= 2
+       LIBC=gnu
+       #else
+       LIBC=
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       # GNU/KFreeBSD systems have a "k" prefix to indicate we are using
+       # FreeBSD's kernel, but not the complete OS.
+       case ${LIBC} in gnu) kernel_only='k' ;; esac
+       echo ${UNAME_MACHINE}-unknown-${kernel_only}freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+       exit 0 ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit 0 ;;
+    i*:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit 0 ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit 0 ;;
+    x86:Interix*:[34]*)
+       echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
+       exit 0 ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit 0 ;;
+    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 0 ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit 0 ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit 0 ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit 0 ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit 0 ;;
+    *: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 0 ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit 0 ;;
+    arm*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit 0 ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    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 | grep ^CPU=`
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       ;;
+    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 | grep ^CPU=`
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
+       ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit 0 ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit 0 ;;
+    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 0 ;;
+    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 0 ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit 0 ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit 0 ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit 0 ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit 0 ;;
+    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 0 ;;
+         coff-i386)
+               echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+               exit 0 ;;
+         "")
+               # 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 0 ;;
+       esac
+       # Determine whether the default compiler is a.out or elf
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #ifdef __ELF__
+       # ifdef __GLIBC__
+       #  if __GLIBC__ >= 2
+       LIBC=gnu
+       #  else
+       LIBC=gnulibc1
+       #  endif
+       # else
+       LIBC=gnulibc1
+       # endif
+       #else
+       #ifdef __INTEL_COMPILER
+       LIBC=gnu
+       #else
+       LIBC=gnuaout
+       #endif
+       #endif
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+       ;;
+    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 0 ;;
+    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 0 ;;
+    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 0 ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit 0 ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit 0 ;;
+       i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit 0 ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit 0 ;;
+    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 0 ;;
+    i*86:*:5:[78]*)
+       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 0 ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit 0 ;;
+    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 0 ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit 0 ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit 0 ;;
+    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 0 ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit 0 ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit 0 ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit 0 ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    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)
+       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 0
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && echo i486-ncr-sysv4 && exit 0 ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit 0 ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit 0 ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit 0 ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit 0 ;;
+    *: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 0 ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit 0 ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit 0 ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit 0 ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit 0 ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit 0 ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit 0 ;;
+    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 0 ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit 0 ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit 0 ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit 0 ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit 0 ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit 0 ;;
+    *:Darwin:*:*)
+       case `uname -p` in
+           *86) UNAME_PROCESSOR=i686 ;;
+           powerpc) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit 0 ;;
+    *: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 0 ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit 0 ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit 0 ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit 0 ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit 0 ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit 0 ;;
+    *: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 0 ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit 0 ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit 0 ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit 0 ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit 0 ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit 0 ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit 0 ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit 0 ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# 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 0 ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit 0 ;;
+    c34*)
+       echo c34-convex-bsd
+       exit 0 ;;
+    c38*)
+       echo c38-convex-bsd
+       exit 0 ;;
+    c4*)
+       echo c4-convex-bsd
+       exit 0 ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+    ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/src/kerberosV/src/config.sub b/src/kerberosV/src/config.sub
new file mode 100644 (file)
index 0000000..264f820
--- /dev/null
@@ -0,0 +1,1549 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+
+timestamp='2004-02-23'
+
+# 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., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+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 0 ;;
+    --version | -v )
+       echo "$version" ; exit 0 ;;
+    --help | --h* | -h )
+       echo "$usage"; exit 0 ;;
+    -- )     # 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 0;;
+
+    * )
+       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-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)
+               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
+               ;;
+       -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/'`
+               ;;
+       -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 \
+       | 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 \
+       | m32r | m68000 | m68k | m88k | mcore \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64vr | mips64vrel \
+       | mips64orion | mips64orionel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | msp430 \
+       | ns16k | ns32k \
+       | openrisc | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+       | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xscale | 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)
+               ;;
+
+       # 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-* \
+       | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | 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-* \
+       | m32r-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | mcore-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | msp430-* \
+       | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* \
+       | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+       | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+       | tron-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | 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
+               ;;
+       cr16c)
+               basic_machine=cr16c-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       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
+               ;;
+       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
+               ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       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
+               ;;
+       nv1)
+               basic_machine=nv1-cray
+               os=-unicosmp
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       or32 | or32-*)
+               basic_machine=or32-unknown
+               os=-coff
+               ;;
+       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
+               ;;
+       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
+               ;;
+       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
+               ;;
+       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
+               ;;
+       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
+               ;;
+       sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparc | sparcv9 | sparcv9b)
+               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* \
+             | -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-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*)
+       # 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* \
+             | -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
+               ;;
+       -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
+       *-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
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-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 0
+
+# 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/src/kerberosV/src/doc/CVS/Entries b/src/kerberosV/src/doc/CVS/Entries
new file mode 100644 (file)
index 0000000..3730157
--- /dev/null
@@ -0,0 +1,20 @@
+/ack.texi/1.1.1.5/Fri Apr 14 07:32:30 2006//
+/apps.texi/1.1.1.1/Fri Apr 14 07:32:30 2006//
+/heimdal.info/1.1.1.7/Fri Apr 14 07:32:33 2006//
+/heimdal.info-1/1.1.1.4/Fri Apr 14 07:32:34 2006//
+/heimdal.info-2/1.1.1.4/Fri Apr 14 07:32:34 2006//
+/heimdal.texi/1.4/Fri Apr 14 08:15:03 2006//
+/init-creds/1.1.1.2/Fri Apr 14 07:32:30 2006//
+/install.texi/1.1.1.4/Fri Apr 14 07:32:30 2006//
+/intro.texi/1.1.1.2/Sun May 11 02:14:23 2003//
+/kerberos4.texi/1.1.1.3/Wed Feb  6 08:53:07 2002//
+/latin1.tex/1.1.1.1/Fri May 25 07:46:44 2001//
+/layman.asc/1.1.1.1/Fri May 25 07:46:46 2001//
+/mdate-sh/1.1.1.1/Fri May 25 07:46:46 2001//
+/migration.texi/1.1.1.2/Fri Jun 22 21:17:20 2001//
+/misc.texi/1.1.1.4/Fri Apr 14 07:32:31 2006//
+/programming.texi/1.1.1.4/Fri Apr 14 07:32:32 2006//
+/setup.texi/1.9/Sun Oct  7 12:06:38 2007//
+/whatis.texi/1.1.1.2/Fri Apr 14 07:32:32 2006//
+/win2k.texi/1.1.1.4/Fri Apr 14 07:32:32 2006//
+D
diff --git a/src/kerberosV/src/doc/CVS/Repository b/src/kerberosV/src/doc/CVS/Repository
new file mode 100644 (file)
index 0000000..468bc2b
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/doc
diff --git a/src/kerberosV/src/doc/CVS/Root b/src/kerberosV/src/doc/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/doc/ack.texi b/src/kerberosV/src/doc/ack.texi
new file mode 100644 (file)
index 0000000..72a9d1d
--- /dev/null
@@ -0,0 +1,81 @@
+@c $KTH: ack.texi,v 1.21 2005/05/10 19:34:57 lha Exp $
+
+@node  Acknowledgments, , Migration, Top
+@comment  node-name,  next,  previous,  up
+@appendix Acknowledgments
+
+Eric Young wrote ``libdes''. Heimdal used to use libdes, without it
+kth-krb would never have existed. 
+
+All functions in libdes have been re-implemented or used available
+public domain code. The core AES function where written by Vincent
+Rijmen, Antoon Bosselaers and Paulo Barreto.  The core DES SBOX
+transformation was written by Richard Outerbridge.
+
+The University of California at Berkeley initially wrote @code{telnet},
+and @code{telnetd}.  The authentication and encryption code of
+@code{telnet} and @code{telnetd} was added by David Borman (then of Cray
+Research, Inc).  The encryption code was removed when this was exported
+and then added back by Juha Eskelinen, @email{esc@@magic.fi}.
+
+The @code{popper} was also a Berkeley program initially.
+
+Some of the functions in @file{libroken} also come from Berkeley by way
+of NetBSD/FreeBSD.
+
+@code{editline} was written by Simmule Turner and Rich Salz. Heimdal
+contains a modifed copy.
+
+The @code{getifaddrs} implementation for Linux was written by Hideaki
+YOSHIFUJI for the Usagi project.
+
+Bugfixes, documentation, encouragement, and code has been contributed by:
+@table @asis
+@item Derrick J Brashear
+@email{shadow@@dementia.org}
+@item Ken Hornstein
+@email{kenh@@cmf.nrl.navy.mil}
+@item Johan Ihrén
+@email{johani@@pdc.kth.se}
+@item Love Hörnquist Ã…strand
+@email{lha@@kth.se}
+@item Magnus Ahltorp
+@email{map@@stacken.kth.se}
+@item Mark Eichin
+@email{eichin@@cygnus.com}
+@item Marc Horowitz
+@email{marc@@cygnus.com}
+@item Luke Howard
+@email{lukeh@@PADL.COM}
+@item Brandon S. Allbery KF8NH
+@email{allbery@@kf8nh.apk.net}
+@item Jun-ichiro itojun Hagino
+@email{itojun@@kame.net}
+@item Daniel Kouril
+@email{kouril@@informatics.muni.cz}
+@item Ã…ke Sandgren 
+@email{ake@@cs.umu.se}
+@item Michal Vocu
+@email{michal@@karlin.mff.cuni.cz}
+@item Miroslav Ruda
+@email{ruda@@ics.muni.cz}
+@item Brian A May
+@email{bmay@@snoopy.apana.org.au}
+@item Chaskiel M Grundman
+@email{cg2v@@andrew.cmu.edu}
+@item Richard Nyberg
+@email{rnyberg@@it.su.se}
+@item Frank van der Linden
+@email{fvdl@@netbsd.org}
+@item Cizzi Storm
+@email{cizzi@@it.su.se}
+@item Petr Holub
+@email{Holub.Petr@@atlas.cz}
+@item Mario Strasser
+@email{mario.strasser@@zhwin.ch}
+@item David Love
+@email{fx@@gnu.org}
+@item and we hope that those not mentioned here will forgive us.
+@end table
+
+All bugs were introduced by ourselves.
diff --git a/src/kerberosV/src/doc/apps.texi b/src/kerberosV/src/doc/apps.texi
new file mode 100644 (file)
index 0000000..a771f70
--- /dev/null
@@ -0,0 +1,244 @@
+@c $KTH: apps.texi,v 1.2 2005/01/12 18:23:15 lha Exp $
+
+@node Applications, Things in search for a better place, Setting up a realm, Top
+
+@chapter Applications
+
+@menu
+* Authentication modules::
+* AFS::
+@end menu
+
+@node  Authentication modules, AFS, Applications, Applications
+@section Authentication modules
+
+The problem of having different authentication mechanisms has been
+recognised by several vendors, and several solutions has appeared. In
+most cases these solutions involve some kind of shared modules that are
+loaded at run-time.  Modules for some of these systems can be found in
+@file{lib/auth}.  Presently there are modules for Digital's SIA,
+and IRIX' @code{login} and @code{xdm} (in
+@file{lib/auth/afskauthlib}).
+
+@menu
+* Digital SIA::                 
+* IRIX::                        
+@end menu
+
+@node Digital SIA, IRIX, Authentication modules, Authentication modules
+@subsection Digital SIA
+
+How to install the SIA module depends on which OS version you're
+running. Tru64 5.0 have a new command, @file{siacfg}, which makes this
+process quite simple. If you have this program, you should just be able
+to run:
+@example
+siacfg -a KRB5 /usr/athena/lib/libsia_krb5.so
+@end example
+
+On older versions, or if you want to do it by hand, you have to do the
+following (not tested by us on Tru64 5.0):
+
+@itemize @bullet
+
+@item
+Make sure @file{libsia_krb5.so} is available in
+@file{/usr/athena/lib}. If @file{/usr/athena} is not on local disk, you
+might want to put it in @file{/usr/shlib} or someplace else. If you do,
+you'll have to edit @file{krb5_matrix.conf} to reflect the new location
+(you will also have to do this if you installed in some other directory
+than @file{/usr/athena}). If you built with shared libraries, you will
+have to copy the shared @file{libkrb.so}, @file{libdes.so},
+@file{libkadm.so}, and @file{libkafs.so} to a place where the loader can
+find them (such as @file{/usr/shlib}).
+@item
+Copy (your possibly edited) @file{krb5_matrix.conf} to @file{/etc/sia}.
+@item
+Apply @file{security.patch} to @file{/sbin/init.d/security}.
+@item
+Turn on KRB5 security by issuing @kbd{rcmgr set SECURITY KRB5} and
+@kbd{rcmgr set KRB5_MATRIX_CONF krb5_matrix.conf}.
+@item
+Digital thinks you should reboot your machine, but that really shouldn't
+be necessary.  It's usually sufficient just to run
+@kbd{/sbin/init.d/security start} (and restart any applications that use
+SIA, like @code{xdm}.)
+@end itemize
+
+Users with local passwords (like @samp{root}) should be able to login
+safely.
+
+When using Digital's xdm the @samp{KRB5CCNAME} environment variable isn't
+passed along as it should (since xdm zaps the environment). Instead you
+have to set @samp{KRB5CCNAME} to the correct value in
+@file{/usr/lib/X11/xdm/Xsession}. Add a line similar to
+@example
+KRB5CCNAME=FILE:/tmp/krb5cc`id -u`_`ps -o ppid= -p $$`; export KRB5CCNAME
+@end example
+If you use CDE, @code{dtlogin} allows you to specify which additional
+environment variables it should export. To add @samp{KRB5CCNAME} to this
+list, edit @file{/usr/dt/config/Xconfig}, and look for the definition of
+@samp{exportList}. You want to add something like:
+@example
+Dtlogin.exportList:     KRB5CCNAME
+@end example
+
+@subsubheading Notes to users with Enhanced security
+
+Digital's @samp{ENHANCED} (C2) security, and Kerberos solves two
+different problems. C2 deals with local security, adds better control of
+who can do what, auditing, and similar things. Kerberos deals with
+network security.
+
+To make C2 security work with Kerberos you will have to do the
+following.
+
+@itemize @bullet
+@item
+Replace all occurencies of @file{krb5_matrix.conf} with
+@file{krb5+c2_matrix.conf} in the directions above.
+@item
+You must enable ``vouching'' in the @samp{default} database.  This will
+make the OSFC2 module trust other SIA modules, so you can login without
+giving your C2 password. To do this use @samp{edauth} to edit the
+default entry @kbd{/usr/tcb/bin/edauth -dd default}, and add a
+@samp{d_accept_alternate_vouching} capability, if not already present.
+@item
+For each user that does @emph{not} have a local C2 password, you should
+set the password expiration field to zero. You can do this for each
+user, or in the @samp{default} table. To do this use @samp{edauth} to
+set (or change) the @samp{u_exp} capability to @samp{u_exp#0}.
+@item
+You also need to be aware that the shipped @file{login}, @file{rcp}, and
+@file{rshd}, doesn't do any particular C2 magic (such as checking to
+various forms of disabled accounts), so if you rely on those features,
+you shouldn't use those programs. If you configure with
+@samp{--enable-osfc2}, these programs will, however, set the login
+UID. Still: use at your own risk.
+@end itemize
+
+At present @samp{su} does not accept the vouching flag, so it will not
+work as expected.
+
+Also, kerberised ftp will not work with C2 passwords. You can solve this
+by using both Digital's ftpd and our on different ports.
+
+@strong{Remember}, if you do these changes you will get a system that
+most certainly does @emph{not} fulfill the requirements of a C2
+system. If C2 is what you want, for instance if someone else is forcing
+you to use it, you're out of luck.  If you use enhanced security because
+you want a system that is more secure than it would otherwise be, you
+probably got an even more secure system. Passwords will not be sent in
+the clear, for instance.
+
+@node IRIX, , Digital SIA, Authentication modules
+@subsection IRIX
+
+The IRIX support is a module that is compatible with Transarc's
+@file{afskauthlib.so}.  It should work with all programs that use this
+library. This should include @command{login} and @command{xdm}.
+
+The interface is not very documented but it seems that you have to copy
+@file{libkafs.so}, @file{libkrb.so}, and @file{libdes.so} to
+@file{/usr/lib}, or build your @file{afskauthlib.so} statically.
+
+The @file{afskauthlib.so} itself is able to reside in
+@file{/usr/vice/etc}, @file{/usr/afsws/lib}, or the current directory
+(wherever that is).
+
+IRIX 6.4 and newer seems to have all programs (including @command{xdm} and
+@command{login}) in the N32 object format, whereas in older versions they
+were O32. For it to work, the @file{afskauthlib.so} library has to be in
+the same object format as the program that tries to load it. This might
+require that you have to configure and build for O32 in addition to the
+default N32.
+
+Appart from this it should ``just work'', there are no configuration
+files.
+
+Note that recent Irix 6.5 versions (at least 6.5.22) have PAM,
+including a @file{pam_krb5.so} module.  Not all relevant programs use
+PAM, though, e.g.@: @command{ssh}. In particular, for console
+graphical login you need to turn off @samp{visuallogin} and turn on
+@samp{xdm} with @command{chkconfig}.
+
+@node AFS, , Authentication modules, Applications
+@section AFS
+
+@cindex AFS
+AFS is a distributed filesystem that uses Kerberos for authentication.
+
+@cindex OpenAFS
+@cindex Arla
+For more information about AFS see OpenAFS
+@url{http://www.openafs.org/} and Arla
+@url{http://www.stacken.kth.se/projekt/arla/}.
+
+@subsection How to get a KeyFile
+
+@file{ktutil -k AFSKEYFILE:KeyFile get afs@@MY.REALM}
+
+or you can extract it with kadmin
+
+@example
+kadmin> ext -k AFSKEYFILE:/usr/afs/etc/KeyFile afs@@My.CELL.NAME
+@end example
+
+You have to make sure you have a @code{des-cbc-md5} encryption type since that
+is the enctype that will be converted.
+
+@subsection How to convert a srvtab to a KeyFile
+
+You need a @file{/usr/vice/etc/ThisCell} containing the cellname of you
+AFS-cell.
+
+@file{ktutil copy krb4:/root/afs-srvtab AFSKEYFILE:/usr/afs/etc/KeyFile}.
+
+If keyfile already exists, this will add the new key in afs-srvtab to
+KeyFile.
+
+@section Using 2b tokens with AFS
+
+@subsection What is 2b ?
+
+2b is the name of the proposal that was implemented to give basic
+Kerberos 5 support to AFS in rxkad. Its not real Kerberos 5 support
+since it still uses fcrypt for data encryption and not Kerberos
+encryption types.
+
+Its only possible (in all cases) to do this for DES encryption types
+because only then the token (the AFS equivalent of a ticket) will be
+be smaller than the maximum size that can fit in the token cache in
+OpenAFS/Transarc client. Its so tight fit that some extra wrapping on
+the ASN1/DER encoding is removed from the Kerberos ticket.
+
+2b uses a Kerberos 5 EncTicketPart instead of a Kerberos 4 ditto for
+the part of the ticket that is encrypted with the service's key. The
+client doesn't know what's inside the encrypted data so to the client
+it doesn't matter.
+
+To  differentiate between Kerberos 4 tickets and Kerberos 5 tickets 2b
+uses a special kvno, 213 for 2b tokens and 255 for Kerberos 5 tokens.
+
+Its a requirement that all AFS servers that support 2b also support
+native Kerberos 5 in rxkad.
+
+@subsection Configuring a Heimdal kdc to use 2b tokens
+
+Support for 2b tokens in the kdc are turned on for specific principals
+by adding them to the string list option @code{[kdc]use_2b} in the
+kdc's @file{krb5.conf} file.
+
+@example
+[kdc]
+       use_2b = @{
+               afs@@SU.SE = yes
+               afs/it.su.se@@SU.SE = yes
+       @}
+@end example
+
+@subsection Configuring AFS clients for 2b support
+
+There is no need to configure AFS clients for 2b support. The only
+software that needs to be installed/upgrade is a Kerberos 5 enabled
+@file{afslog}.
diff --git a/src/kerberosV/src/doc/heimdal.info b/src/kerberosV/src/doc/heimdal.info
new file mode 100644 (file)
index 0000000..75248ce
--- /dev/null
@@ -0,0 +1,65 @@
+This is heimdal.info, produced by makeinfo version 4.0 from
+heimdal.texi.
+
+INFO-DIR-SECTION Heimdal
+START-INFO-DIR-ENTRY
+* Heimdal: (heimdal).           The Kerberos 5 distribution from KTH
+END-INFO-DIR-ENTRY
+
+\1f
+Indirect:
+heimdal.info-1: 210
+heimdal.info-2: 49488
+\1f
+Tag Table:
+(Indirect)
+Node: Top\7f210
+Node: Introduction\7f582
+Node: What is Kerberos?\7f3460
+Node: Building and Installing\7f8533
+Node: Setting up a realm\7f12151
+Node: Configuration file\7f13002
+Node: Creating the database\7f15761
+Node: Modifying the database\7f18682
+Node: keytabs\7f20216
+Node: Serving Kerberos 4/524/kaserver\7f21080
+Node: Remote administration\7f22532
+Node: Password changing\7f24486
+Node: Testing clients and servers\7f28102
+Node: Slave Servers\7f28422
+Node: Incremental propagation\7f30171
+Node: Salting\7f32791
+Node: Cross realm\7f34629
+Node: Transit policy\7f37163
+Node: Setting up DNS\7f38814
+Node: Using LDAP to store the database\7f41235
+Node: Providing Kerberos credentials to servers and programs\7f46689
+Node: Applications\7f48707
+Node: Authentication modules\7f48903
+Node: Digital SIA\7f49488
+Node: IRIX\7f53865
+Node: AFS\7f55145
+Node: Things in search for a better place\7f57706
+Node: Kerberos 4 issues\7f60423
+Node: Principal conversion issues\7f60925
+Ref: Principal conversion issues-Footnote-1\7f63148
+Ref: Principal conversion issues-Footnote-2\7f63216
+Node: Converting a version 4 database\7f63269
+Node: kaserver\7f68297
+Node: Windows 2000 compatability\7f70036
+Node: Configuring Windows 2000 to use a Heimdal KDC\7f71232
+Node: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC\7f73210
+Node: Create account mappings\7f76225
+Node: Encryption types\7f76979
+Node: Authorization data\7f77576
+Node: Quirks of Windows 2000 KDC\7f78720
+Node: Useful links when reading about the Windows 2000\7f80016
+Node: Programming with Kerberos\7f81820
+Node: Kerberos 5 API Overview\7f82268
+Node: Walkthru a sample Kerberos 5 client\7f84059
+Node: Validating a password in a server application\7f91875
+Node: API diffrences to MIT Kerberos\7f92195
+Node: Migration\7f93597
+Node: Acknowledgments\7f94851
+\1f
+End Tag Table
diff --git a/src/kerberosV/src/doc/heimdal.info-1 b/src/kerberosV/src/doc/heimdal.info-1
new file mode 100644 (file)
index 0000000..085f146
--- /dev/null
@@ -0,0 +1,1327 @@
+This is heimdal.info, produced by makeinfo version 4.0 from
+heimdal.texi.
+
+INFO-DIR-SECTION Heimdal
+START-INFO-DIR-ENTRY
+* Heimdal: (heimdal).           The Kerberos 5 distribution from KTH
+END-INFO-DIR-ENTRY
+
+\1f
+File: heimdal.info,  Node: Top,  Next: Introduction,  Prev: (dir),  Up: (dir)
+
+Heimdal
+*******
+
+* Menu:
+
+* Introduction::
+* What is Kerberos?::
+* Building and Installing::
+* Setting up a realm::
+* Applications::
+* Things in search for a better place::
+* Kerberos 4 issues::
+* Windows 2000 compatability::
+* Programming with Kerberos::
+* Migration::
+* Acknowledgments::
+
+\1f
+File: heimdal.info,  Node: Introduction,  Next: What is Kerberos?,  Prev: Top,  Up: Top
+
+Introduction
+************
+
+What is Heimdal?
+================
+
+Heimdal is a free implementation of Kerberos 5. The goals are to:
+
+   * have an implementation that can be freely used by anyone
+
+   * be protocol compatible with existing implementations and, if not in
+     conflict, with RFC 1510 (and any future updated RFC)
+
+   * be reasonably compatible with the M.I.T Kerberos V5 API
+
+   * have support for Kerberos V5 over GSS-API (RFC1964)
+
+   * include the most important and useful application programs (rsh,
+     telnet, popper, etc.)
+
+   * include enough backwards compatibility with Kerberos V4
+
+Status
+======
+
+Heimdal has the following features (this does not mean any of this
+works):
+
+   * a stub generator and a library to encode/decode/whatever ASN.1/DER
+     stuff
+
+   * a `libkrb5' library that should be possible to get to work with
+     simple applications
+
+   * a GSS-API library that should have all the important functions for
+     building applications
+
+   * Eric Young's `libdes'
+
+   * `kinit', `klist', `kdestroy'
+
+   * `telnet', `telnetd'
+
+   * `rsh', `rshd'
+
+   * `popper', `push' (a movemail equivalent)
+
+   * `ftp', and `ftpd'
+
+   * a library `libkafs' for authenticating to AFS and a program
+     `afslog' that uses it
+
+   * some simple test programs
+
+   * a KDC that supports most things; optionally, it may also support
+     Kerberos V4 and kaserver,
+
+   * simple programs for distributing databases between a KDC master and
+     slaves
+
+   * a password changing daemon `kpasswdd', library functions for
+     changing passwords and a simple client
+
+   * some kind of administration system
+
+   * Kerberos V4 support in many of the applications.
+
+Bug reports
+===========
+
+If you find bugs in this software, make sure it is a genuine bug and not
+just a part of the code that isn't implemented.
+
+Bug reports should be sent to <heimdal-bugs@pdc.kth.se>. Please include
+information on what machine and operating system (including version)
+you are running, what you are trying to do, what happens, what you
+think should have happened, an example for us to repeat, the output you
+get when trying the example, and a patch for the problem if you have
+one. Please make any patches with `diff -u' or `diff -c'.
+
+Suggestions, comments and other non bug reports are also welcome.
+
+Mailing list
+============
+
+There are two mailing lists with talk about Heimdal.
+<heimdal-announce@sics.se> is a low-volume announcement list, while
+<heimdal-discuss@sics.se> is for general discussion.  Send a message to
+<majordomo@sics.se> to subscribe.
+
+Heimdal source code, binaries and the manual
+============================================
+
+The source code for heimdal, links to binaries and the manual (this
+document) can be found on our web-page at
+<http://www.pdc.kth.se/heimdal/>.
+
+\1f
+File: heimdal.info,  Node: What is Kerberos?,  Next: Building and Installing,  Prev: Introduction,  Up: Top
+
+What is Kerberos?
+*****************
+
+     Now this Cerberus had three heads of dogs,
+             the tail of a dragon, and on his back the
+             heads of all sorts of snakes.
+             -- Pseudo-Apollodorus Library 2.5.12
+
+Kerberos is a system for authenticating users and services on a network.
+It is built upon the assumption that the network is "unsafe".  For
+example, data sent over the network can be eavesdropped and altered, and
+addresses can also be faked.  Therefore they cannot be used for
+authentication purposes.
+
+Kerberos is a trusted third-party service.  That means that there is a
+third party (the kerberos server) that is trusted by all the entities on
+the network (users and services, usually called "principals").  All
+principals share a secret password (or key) with the kerberos server and
+this enables principals to verify that the messages from the kerberos
+server are authentic.  Thus trusting the kerberos server, users and
+services can authenticate each other.
+
+Basic mechanism
+===============
+
+     *Note* This discussion is about Kerberos version 4, but version 5
+     works similarly.
+
+In Kerberos, principals use "tickets" to prove that they are who they
+claim to be. In the following example, A is the initiator of the
+authentication exchange, usually a user, and B is the service that A
+wishes to use.
+
+To obtain a ticket for a specific service, A sends a ticket request to
+the kerberos server. The request contains A's and B's names (along with
+some other fields). The kerberos server checks that both A and B are
+valid principals.
+
+Having verified the validity of the principals, it creates a packet
+containing A's and B's names, A's network address (A<ADDR>), the
+current time (T<ISSUE>), the lifetime of the ticket (LIFE), and a
+secret "session key" (K<AB>). This packet is encrypted with B's secret
+key (K<B>).  The actual ticket (T<AB>) looks like this: ({A, B,
+A<ADDR>, T<ISSUE>, LIFE, K<AB>}K<B>).
+
+The reply to A consists of the ticket (T<AB>), B's name, the current
+time, the lifetime of the ticket, and the session key, all encrypted in
+A's secret key ({B, T<ISSUE>, LIFE, K<AB>, T<AB>}K<A>). A decrypts the
+reply and retains it for later use.
+
+
+Before sending a message to B, A creates an authenticator consisting of
+A's name, A's address, the current time, and a "checksum" chosen by A,
+all encrypted with the secret session key ({A, A<ADDR>, T<CURRENT>,
+CHECKSUM}K<AB>). This is sent together with the ticket received from
+the kerberos server to B.  Upon reception, B decrypts the ticket using
+B's secret key.  Since the ticket contains the session key that the
+authenticator was encrypted with, B can now also decrypt the
+authenticator. To verify that A really is A, B now has to compare the
+contents of the ticket with that of the authenticator. If everything
+matches, B now considers A as properly authenticated.
+
+Different attacks
+=================
+
+Impersonating A
+---------------
+
+An impostor, C could steal the authenticator and the ticket as it is
+transmitted across the network, and use them to impersonate A. The
+address in the ticket and the authenticator was added to make it more
+difficult to perform this attack.  To succeed C will have to either use
+the same machine as A or fake the source addresses of the packets. By
+including the time stamp in the authenticator, C does not have much
+time in which to mount the attack.
+
+Impersonating B
+---------------
+
+C can hijack B's network address, and when A sends her credentials, C
+just pretend to verify them. C can't be sure that she is talking to A.
+
+Defense strategies
+==================
+
+It would be possible to add a "replay cache" to the server side.  The
+idea is to save the authenticators sent during the last few minutes, so
+that B can detect when someone is trying to retransmit an already used
+message. This is somewhat impractical (mostly regarding efficiency),
+and is not part of Kerberos 4; MIT Kerberos 5 contains it.
+
+To authenticate B, A might request that B sends something back that
+proves that B has access to the session key. An example of this is the
+checksum that A sent as part of the authenticator. One typical
+procedure is to add one to the checksum, encrypt it with the session
+key and send it back to A.  This is called "mutual authentication".
+
+The session key can also be used to add cryptographic checksums to the
+messages sent between A and B (known as "message integrity").
+Encryption can also be added ("message confidentiality"). This is
+probably the best approach in all cases.
+
+Further reading
+===============
+
+The original paper on Kerberos from 1988 is `Kerberos: An
+Authentication Service for Open Network Systems', by Jennifer Steiner,
+Clifford Neuman and Jeffrey I. Schiller.
+
+A less technical description can be found in `Designing an
+Authentication System: a Dialogue in Four Scenes' by Bill Bryant, also
+from 1988.
+
+These documents can be found on our web-page at
+<http://www.pdc.kth.se/kth-krb/>.
+
+\1f
+File: heimdal.info,  Node: Building and Installing,  Next: Setting up a realm,  Prev: What is Kerberos?,  Up: Top
+
+Building and Installing
+***********************
+
+Heimdal uses GNU Autoconf to configure for specific hosts, and GNU
+Automake to manage makefiles. If this is new to you, the short
+instruction is to run the `configure' script in the top level
+directory, and when that finishes `make'.
+
+If you want to build the distribution in a different directory from the
+source directory, you will need a make that implements VPATH correctly,
+such as GNU make.
+
+You will need to build the distribution:
+
+   * A compiler that supports a "loose" ANSI C mode, such as `gcc'.
+
+   * lex or flex
+
+   * awk
+
+   * yacc or bison
+
+   * a socket library
+
+   * NDBM or Berkeley DB for building the server side.
+
+When everything is built, you can install by doing `make install'. The
+default location for installation is `/usr/heimdal', but this can be
+changed by running `configure' with `--prefix=/some/other/place'.
+
+If you need to change the default behavior, configure understands the
+following options:
+
+`--without-berkeley-db'
+     DB is preferred before NDBM, but if you for some reason want to
+     use NDBM instead, you can use this option.
+
+`--with-krb4=`dir''
+     Gives the location of Kerberos 4 libraries and headers. This
+     enables Kerberos 4 support in the applications (telnet, rsh,
+     popper, etc) and the KDC. It is automatically check for in
+     `/usr/athena'. If you keep libraries and headers in different
+     places, you can instead give the path to each with the
+     `--with-krb4-lib=`dir'', and `--with-krb4-include=`dir'' options.
+
+     You will need a fairly recent version of our Kerberos 4
+     distribution for `rshd' and `popper' to support version 4 clients.
+
+`--enable-dce'
+     Enables support for getting DCE credentials and tokens.  See the
+     README files in `appl/dceutils' for more information.
+
+`--disable-otp'
+     By default some of the application programs will build with
+     support for one-time passwords (OTP).  Use this option to disable
+     that support.
+
+`--enable-osfc2'
+     Enable some C2 support for OSF/Digital Unix/Tru64.  Use this
+     option if you are running your OSF operating system in C2 mode.
+
+`--with-readline=`dir''
+     Gives the path for the GNU Readline library, which will be used in
+     some programs. If no readline library is found, the (simpler)
+     editline library will be used instead.
+
+`--with-hesiod=`dir''
+     Enables hesiod support in push.
+
+`--enable-netinfo'
+     Add support for using netinfo to lookup configuration information.
+     Probably only useful (and working) on NextStep/Mac OS X.
+
+`--without-ipv6'
+     Disable the IPv6 support.
+
+`--with-openldap'
+     Compile Heimdal with support for storing the database in LDAP.
+     Requires OpenLDAP <http://www.openldap.org>.  See
+     <http://www.padl.com/Research/Heimdal.html> for more information.
+
+`--enable-bigendian'
+
+`--enable-littleendian'
+     Normally, the build process will figure out by itself if the
+     machine is big or little endian.  It might fail in some cases when
+     cross-compiling.  If it does fail to figure it out, use the
+     relevant of these two options.
+
+`--with-mips-abi=ABI'
+     On Irix there are three different ABIs that can be used (`32',
+     `n32', or `64').  This option allows you to override the automatic
+     selection.
+
+`--disable-mmap'
+     Do not use the mmap system call.  Normally, configure detects if
+     there is a working mmap and it is only used if there is one.  Only
+     try this option if it fails to work anyhow.
+
+\1f
+File: heimdal.info,  Node: Setting up a realm,  Next: Applications,  Prev: Building and Installing,  Up: Top
+
+Setting up a realm
+******************
+
+* Menu:
+
+* Configuration file::
+* Creating the database::
+* Modifying the database::
+* keytabs::
+* Serving Kerberos 4/524/kaserver::
+* Remote administration::
+* Password changing::
+* Testing clients and servers::
+* Slave Servers::
+* Incremental propagation::
+* Salting::
+* Cross realm::
+* Transit policy::
+* Setting up DNS::
+* Using LDAP to store the database::
+* Providing Kerberos credentials to servers and programs::
+
+A realm is an administrative domain.  The name of a Kerberos realm is
+usually the Internet domain name in uppercase.  Call your realm the same
+as your Internet domain name if you do not have strong reasons for not
+doing so.  It will make life easier for you and everyone else.
+
+\1f
+File: heimdal.info,  Node: Configuration file,  Next: Creating the database,  Prev: Setting up a realm,  Up: Setting up a realm
+
+Configuration file
+==================
+
+To setup a realm you will first have to create a configuration file:
+`/etc/krb5.conf'. The `krb5.conf' file can contain many configuration
+options, some of which are described here.
+
+There is a sample `krb5.conf' supplied with the distribution.
+
+The configuration file is a hierarchical structure consisting of
+sections, each containing a list of bindings (either variable
+assignments or subsections). A section starts with `[`section-name']'.
+A binding consists of a left hand side, an equal (`=') and a right hand
+side (the left hand side tag must be separated from the equal with some
+whitespace). Subsections has a `{' as the first non-whitespace
+character after the equal. All other bindings are treated as variable
+assignments. The value of a variable extends to the end of the line.
+
+     [section1]
+             a-subsection = {
+                     var = value1
+                     other-var = value with {}
+                     sub-sub-section = {
+                             var = 123
+                     }
+             }
+             var = some other value
+     [section2]
+             var = yet another value
+
+In this manual, names of sections and bindings will be given as strings
+separated by slashes (`/'). The `other-var' variable will thus be
+`section1/a-subsection/other-var'.
+
+For in-depth information about the contents of the configuration file,
+refer to the `krb5.conf' manual page. Some of the more important
+sections are briefly described here.
+
+The `libdefaults' section contains a list of library configuration
+parameters, such as the default realm and the timeout for KDC
+responses. The `realms' section contains information about specific
+realms, such as where they hide their KDC. This section serves the same
+purpose as the Kerberos 4 `krb.conf' file, but can contain more
+information. Finally the `domain_realm' section contains a list of
+mappings from domains to realms, equivalent to the Kerberos 4
+`krb.realms' file.
+
+To continue with the realm setup, you will have to create a
+configuration file, with contents similar to the following.
+
+     [libdefaults]
+             default_realm = MY.REALM
+     [realms]
+             MY.REALM = {
+                     kdc = my.kdc my.slave.kdc
+                     kdc = my.third.kdc
+             }
+     [domain_realm]
+             .my.domain = MY.REALM
+
+If you use a realm name equal to your domain name, you can omit the
+`libdefaults', and `domain_realm', sections. If you have a DNS
+SRV-record for your realm, or your Kerberos server has DNS CNAME
+`kerberos.my.realm', you can omit the `realms' section too.
+
+\1f
+File: heimdal.info,  Node: Creating the database,  Next: Modifying the database,  Prev: Configuration file,  Up: Setting up a realm
+
+Creating the database
+=====================
+
+The database library will look for the database in the directory
+`/var/heimdal', so you should probably create that directory.  Make
+sure the directory has restrictive permissions.
+
+     # mkdir /var/heimdal
+
+The keys of all the principals are stored in the database.  If you
+choose to, these can be encrypted with a master key.  You do not have to
+remember this key (or password), but just to enter it once and it will
+be stored in a file (`/var/heimdal/m-key').  If you want to have a
+master key, run `kstash' to create this master key:
+
+     # kstash
+     Master key:
+     Verifying password - Master key:
+
+If you want to generate a random master key you can use the -random-key
+to kstash. This will make sure you have a good key on which attackers
+can't do a dictionary attack.
+
+If you have a master key, make sure you make a backup of your master
+key file; without it backups of the database are of no use.
+
+To initialise the database use the `kadmin' program, with the `-l'
+option (to enable local database mode). First issue a `init MY.REALM'
+command. This will create the database and insert default principals
+for that realm. You can have more than one realm in one database, so
+`init' does not destroy any old database.
+
+Before creating the database, `init' will ask you some questions about
+maximum ticket lifetimes.
+
+After creating the database you should probably add yourself to it. You
+do this with the `add' command. It takes as argument the name of a
+principal. The principal should contain a realm, so if you haven't set
+up a default realm, you will need to explicitly include the realm.
+
+     # kadmin -l
+     kadmin> init MY.REALM
+     Realm max ticket life [unlimited]:
+     Realm max renewable ticket life [unlimited]:
+     kadmin> add me
+     Max ticket life [unlimited]:
+     Max renewable life [unlimited]:
+     Attributes []:
+     Password:
+     Verifying password - Password:
+
+Now start the KDC and try getting a ticket.
+
+     # kdc &
+     # kinit me
+     me@MY.REALMS's Password:
+     # klist
+     Credentials cache: /tmp/krb5cc_0
+             Principal: me@MY.REALM
+     
+       Issued           Expires          Principal
+     Aug 25 07:25:55  Aug 25 17:25:55  krbtgt/MY.REALM@MY.REALM
+
+If you are curious you can use the `dump' command to list all the
+entries in the database.  It should look something similar to the
+following example (note that the entries here are truncated for
+typographical reasons):
+
+     kadmin> dump
+     me@MY.REALM 1:0:1:0b01d3cb7c293b57:-:0:7:8aec316b9d1629e3baf8 ...
+     kadmin/admin@MY.REALM 1:0:1:e5c8a2675b37a443:-:0:7:cb913ebf85 ...
+     krbtgt/MY.REALM@MY.REALM 1:0:1:52b53b61c875ce16:-:0:7:c8943be ...
+     kadmin/changepw@MY.REALM 1:0:1:f48c8af2b340e9fb:-:0:7:e3e6088 ...
+
+\1f
+File: heimdal.info,  Node: Modifying the database,  Next: keytabs,  Prev: Creating the database,  Up: Setting up a realm
+
+Modifying the database
+======================
+
+All modifications of principals are done with with kadmin.
+
+A principal have several attributes and lifetimes associated with it.
+
+Principals are added, renamed, modified, and deleted with the kadmin
+commands `add', `rename', `modify', `delete'.  Both interactive editing
+and command switches can be used (use -help to list the available
+options).
+
+There are different kind of types for the fields in the database,
+attributes, absolute time times and relative times.
+
+Attributes
+----------
+
+When doing interactive editing, attributes are listed with `?'.
+
+The attributes are given in a comma (`,') separated list.  Attributes
+are removed from the list by prefixing them with `-'.
+
+     kadmin> modify me
+     Max ticket life [1 day]:
+     Max renewable life [1 week]:
+     Principal expiration time [never]:
+     Password expiration time [never]:
+     Attributes [disallow-renewable]: requires-pre-auth,-disallow-renewable
+     kadmin> get me
+                 Principal: me@MY.REALM
+     [...]
+                Attributes: requires-pre-auth
+
+Absolute times
+--------------
+
+The format for absolute times are any of the following
+
+     never
+     now
+     YYYY-mm-dd
+     YYYY-mm-dd HH:MM:SS
+
+Relative times
+--------------
+
+The format for relative times are any of the following combined
+
+     N year
+     M month
+     O day
+     P hour
+     Q minute
+     R second
+
+\1f
+File: heimdal.info,  Node: keytabs,  Next: Serving Kerberos 4/524/kaserver,  Prev: Modifying the database,  Up: Setting up a realm
+
+keytabs
+=======
+
+To extract a service ticket from the database and put it in a keytab,
+you need to first create the principal in the database with `ank'
+(using the `--random-key' flag to get a random key) and then extract it
+with `ext_keytab'.
+
+     kadmin> add --random-key host/my.host.name
+     Max ticket life [unlimited]:
+     Max renewable life [unlimited]:
+     Attributes []:
+     kadmin> ext host/my.host.name
+     kadmin> exit
+     # ktutil list
+     Version  Type             Principal
+          1   des-cbc-md5      host/my.host.name@MY.REALM
+          1   des-cbc-md4      host/my.host.name@MY.REALM
+          1   des-cbc-crc      host/my.host.name@MY.REALM
+          1   des3-cbc-sha1    host/my.host.name@MY.REALM
+
+\1f
+File: heimdal.info,  Node: Serving Kerberos 4/524/kaserver,  Next: Remote administration,  Prev: keytabs,  Up: Setting up a realm
+
+Serving Kerberos 4/524/kaserver
+===============================
+
+Heimdal can be configured to support 524, Kerberos 4 or kaserver. All
+these services turned off by default. Kerberos 4 support also depends
+on if Kerberos 4 support being compiled in with Heimdal.
+
+524
+---
+
+524 is a service that allows the KDC to convert Kerberos 5 tickets to
+Kerberos 4 tickets for backward compatibility. See also Using 2b tokens
+with AFS in *Note Things in search for a better place::.
+
+524 can be turned on by adding this to the configuration file
+
+     [kdc]
+       enable-524 = yes
+
+Kerberos 4
+----------
+
+Kerberos 4 is the predecessor to to Kerberos 5. It only supports single
+DES. You should only enable Kerberos 4 support if you have a need for
+for compatibility with an installed base of Kerberos 4 clients/servers.
+
+Kerberos 4 can be turned on by adding this to the configuration file
+
+     [kdc]
+       enable-kerberos4 = yes
+
+kaserver
+--------
+
+Kaserver is a Kerberos 4 that is used in AFS.  The protocol have some
+extra features over plain Kerberos 4, but like Kerberos 4, only use
+single DES.
+
+You should only enable Kaserver support if you have a need for for
+compatibility with an installed base of AFS machines.
+
+Kaserver can be turned on by adding this to the configuration file
+
+     [kdc]
+       enable-kaserver = yes
+
+\1f
+File: heimdal.info,  Node: Remote administration,  Next: Password changing,  Prev: Serving Kerberos 4/524/kaserver,  Up: Setting up a realm
+
+Remote administration
+=====================
+
+The administration server, `kadmind', can be started by `inetd' (which
+isn't recommended) or run as a normal daemon. If you want to start it
+from `inetd' you should add a line similar to the one below to your
+`/etc/inetd.conf'.
+
+     kerberos-adm stream     tcp     nowait  root /usr/heimdal/libexec/kadmind kadmind
+
+You might need to add `kerberos-adm' to your `/etc/services' as
+`749/tcp'.
+
+Access to the administration server is controlled by an ACL file,
+(default `/var/heimdal/kadmind.acl'.) The lines in the access file,
+have the following syntax:
+     principal       [priv1,priv2,...]       [glob-pattern]
+
+The matching is from top to bottom for matching principals (and if
+given, glob-pattern).  When there is a match, the access rights of that
+line are used.
+
+The privileges you can assign to a principal are: `add',
+`change-password' (or `cpw' for short), `delete', `get', `list', and
+`modify', or the special privilege `all'. All of these roughly
+corresponds to the different commands in `kadmin'.
+
+If a GLOB-PATTERN is given on a line, it restricts the access rights for
+the principal to only apply for the subjects that match the pattern.
+The patterns are of the same type as those used in shell globbing, see
+<none,,fnmatch(3)>.
+
+In the example below `lha/admin' can change every principal in the
+database. `jimmy/admin' can only modify principals that belong to the
+realm `E.KTH.SE'. `mille/admin' is working at the help desk, so he
+should only be able to change the passwords for single component
+principals (ordinary users). He will not be able to change any `/admin'
+principal.
+
+     lha/admin@E.KTH.SE        all
+     jimmy/admin@E.KTH.SE      all             *@E.KTH.SE
+     jimmy/admin@E.KTH.SE      all             */*@E.KTH.SE
+     mille/admin@E.KTH.SE      change-password *@E.KTH.SE
+
+\1f
+File: heimdal.info,  Node: Password changing,  Next: Testing clients and servers,  Prev: Remote administration,  Up: Setting up a realm
+
+Password changing
+=================
+
+To allow users to change their passwords, you should run `kpasswdd'.
+It is not run from `inetd'.
+
+You might need to add `kpasswd' to your `/etc/services' as `464/udp'.
+
+Password quality assurance
+--------------------------
+
+It is important that users have good passwords, both to make it harder
+to guess them and to avoid off-line attacks (although
+pre-authentication provides some defense against off-line attacks).  To
+ensure that the users choose good passwords, you can enable password
+quality controls in `kpasswdd' and `kadmind'.  The controls themselves
+are done in a shared library or an external program that is used by
+`kpasswdd'.  To configure in these controls, add lines similar to the
+following to your `/etc/krb5.conf':
+
+     [password_quality]
+       policies = external-check builtin:minimum-length module:policyname
+       external_program = /bin/false
+       policy_libraries = LIBRARY1.SO LIBRARY2.SO
+
+In `[password_quality]policies' the module name is optional if the
+policy name is unique in all modules (members of `policy_libraries').
+
+The builtin polices are
+
+   * external-check
+
+     Executes the program specified by
+     `[password_quality]external_program'.
+
+     A number of key/value pairs is passed as input to the program, one
+     per line, ending with the string `end'.  The key/value lines are of
+     the form
+          principal: PRINCIPAL
+          new-password: PASSWORD
+     where PASSWORD is the password to check for the previous PRINCIPAL.
+
+     If the external application approves the password, it should return
+     `APPROVED' on standard out and exit with exit code 0.  If it
+     doesn't approve the password, a one line error message explaining
+     the problem should be returned on standard error and the
+     application should exit with exit code 0.  In case of a fatal
+     error, the application should, if possible, print an error message
+     on standard error and exit with a non-zero error code.
+
+   * minimum-length
+
+     The minimum length password quality check reads the configuration
+     file stanza `[password_quality]min_length' and requires the
+     password to be at least this length.
+
+   * character-class
+
+     The character-class password quality check reads the configuration
+     file stanza `[password_quality]min_classes'. The policy requires
+     the password to have characters from at least that many characters
+     classes. Default value if not given is 3.
+
+     The four diffrent characters classes are, uppercase, lowercase,
+     number, special characters.
+
+
+If you want to write you own shared object that checks password
+policies, see the manual page `kadm5_pwcheck(3)'.
+
+Code for a password quality checking function that uses the cracklib
+library can be found in `lib/kadm5/sample_password_check.c' in the
+source code distribution.  It requires the cracklib library built with
+the patch available at
+<ftp://ftp.pdc.kth.se/pub/krb/src/cracklib.patch>.
+
+A sample policy external program is included in
+`lib/kadm5/check-cracklib.pl'.
+
+If no password quality checking function is configured, it is only
+verified that it is at least six characters long.
+
+The program `test_pw_quality', which is built in `lib/kadm5', but not
+installed, can be used to check password policy settings.  It may be
+convenient to set the environment variable `KRB5_CONFIG' to point to a
+test version of `krb5.conf' while you're testing the
+`[password_quality]' stanza that way.
+
+\1f
+File: heimdal.info,  Node: Testing clients and servers,  Next: Slave Servers,  Prev: Password changing,  Up: Setting up a realm
+
+Testing clients and servers
+===========================
+
+Now you should be able to run all the clients and servers.  Refer to the
+appropriate man pages for information on how to use them.
+
+\1f
+File: heimdal.info,  Node: Slave Servers,  Next: Incremental propagation,  Prev: Testing clients and servers,  Up: Setting up a realm
+
+Slave servers, Incremental propagation, Testing clients and servers, Setting up a realm
+=======================================================================================
+
+It is desirable to have at least one backup (slave) server in case the
+master server fails. It is possible to have any number of such slave
+servers but more than three usually doesn't buy much more redundancy.
+
+All Kerberos servers for a realm must have the same database so that
+they present the same service to all the users.  The `hprop' program,
+running on the master, will propagate the database to the slaves,
+running `hpropd' processes.
+
+Every slave needs a database directory, the master key (if it was used
+for the database) and a keytab with the principal `hprop/HOSTNAME'.
+Add the principal with the `ktutil' command and start `hpropd', as
+follows:
+
+     slave# ktutil get -p foo/admin hprop/`hostname`
+     slave# mkdir /var/heimdal
+     slave# hpropd
+
+The master will use the principal `kadmin/hprop' to authenticate to the
+slaves.  This principal should be added when running `kadmin -l init'
+but if you do not have it in your database for whatever reason, please
+add it with `kadmin -l add'.
+
+Then run `hprop' on the master:
+
+     master# hprop slave
+
+This was just an hands-on example to make sure that everything was
+working properly.  Doing it manually is of course the wrong way, and to
+automate this you will want to start `hpropd' from `inetd' on the
+slave(s) and regularly run `hprop' on the master to regularly propagate
+the database.  Starting the propagation once an hour from `cron' is
+probably a good idea.
+
+\1f
+File: heimdal.info,  Node: Incremental propagation,  Next: Salting,  Prev: Slave Servers,  Up: Setting up a realm
+
+Incremental propagation
+=======================
+
+There is also a newer, and still somewhat experimental, mechanism for
+doing incremental propagation in Heimdal.  Instead of sending the whole
+database regularly, it sends the changes as they happen on the master to
+the slaves.  The master keeps track of all the changes by assigning a
+version number to every change to the database.  The slaves know which
+was the latest version they saw and in this way it can be determined if
+they are in sync or not.  A log of all the changes is kept on the
+master, and when a slave is at an older version than the oldest one in
+the log, the whole database has to be sent.
+
+Protocol-wise, all the slaves connect to the master and as a greeting
+tell it the latest version that they have (`IHAVE' message).  The
+master then responds by sending all the changes between that version and
+the current version at the master (a series of `FORYOU' messages) or
+the whole database in a `TELLYOUEVERYTHING' message.  There is also a
+keep-alive protocol that makes sure all slaves are up and running.
+
+Configuring incremental propagation
+-----------------------------------
+
+The program that runs on the master is `ipropd-master' and all clients
+run `ipropd-slave'.
+
+Create the file `/var/heimdal/slaves' on the master containing all the
+slaves that the database should be propagated to.  Each line contains
+the full name of the principal (for example
+`iprop/hemligare.foo.se@FOO.SE').
+
+You should already have `iprop/tcp' defined as 2121, in your
+`/etc/services'.  Otherwise, or if you need to use a different port for
+some peculiar reason, you can use the `--port' option.  This is useful
+when you have multiple realms to distribute from one server.
+
+Then you need to create those principals that you added in the
+configuration file.  Create one `iprop/hostname' for the master and for
+every slave.
+
+     master# /usr/heimdal/sbin/ktutil get iprop/`hostname`
+
+The next step is to start the `ipropd-master' process on the master
+server.  The `ipropd-master' listens on the UNIX domain socket
+`/var/heimdal/signal' to know when changes have been made to the
+database so they can be propagated to the slaves.  There is also a
+safety feature of testing the version number regularly (every 30
+seconds) to see if it has been modified by some means that do not raise
+this signal.  Then, start `ipropd-slave' on all the slaves:
+
+     master# /usr/heimdal/libexec/ipropd-master &
+     slave#  /usr/heimdal/libexec/ipropd-slave master &
+
+\1f
+File: heimdal.info,  Node: Salting,  Next: Cross realm,  Prev: Incremental propagation,  Up: Setting up a realm
+
+Salting
+=======
+
+Salting is used to make it harder to precalculate all possible keys.
+Using a salt increases the search space to make it almost impossible to
+precalculate all keys. Salting is the process of mixing a public string
+(the salt) with the password, then sending it through an encryption
+type specific string-to-key function that will output the fixed size
+encryption key.
+
+In Kerberos 5 the salt is determined by the encryption-type, except in
+some special cases.
+
+In `des' there is the Kerberos 4 salt (none at all) or the afs-salt
+(using the cell (realm in AFS lingo)).
+
+In `arcfour' (the encryption type that Microsoft Windows 2000 uses)
+there is no salt. This is to be compatible with NTLM keys in Windows NT
+4.
+
+`[kadmin]default_keys' in `krb5.conf' controls what salting to use,
+
+The syntax of `[kadmin]default_keys' is
+`[etype:]salt-type[:salt-string]'. `etype' is the encryption type (des,
+des3, arcfour), `salt-type' is the type of salt (pw-salt or afs3-salt),
+and the salt-string is the string that will be used as salt (remember
+that if the salt is appended/prepended, the empty salt "" is the same
+thing as no salt at all).
+
+Common types of salting include
+
+   * `v4' (or `des:pw-salt:')
+
+     The Kerberos 4 salting is using no salt at all. Reason there is
+     colon at the end of the salt string is that it makes the salt the
+     empty string (same as no salt).
+
+   * `v5' (or `pw-salt')
+
+     `pw-salt' uses the default salt for each encryption type is
+     specified for. If the encryption type `etype' isn't given, all
+     default encryption will be used.
+
+   * `afs3-salt'
+
+     `afs3-salt' is the salt that is used with Transarc kaserver. Its
+     the cell name appended to the password.
+
+
+\1f
+File: heimdal.info,  Node: Cross realm,  Next: Transit policy,  Prev: Salting,  Up: Setting up a realm
+
+Cross realm
+===========
+
+Suppose you reside in the realm `MY.REALM', how do you authenticate to
+a server in `OTHER.REALM'? Having valid tickets in `MY.REALM' allows
+you to communicate with Kerberised services in that realm. However, the
+computer in the other realm does not have a secret key shared with the
+Kerberos server in your realm.
+
+It is possible to share keys between two realms that trust each other.
+When a client program, such as `telnet' or `ssh', finds that the other
+computer is in a different realm, it will try to get a ticket granting
+ticket for that other realm, but from the local Kerberos server. With
+that ticket granting ticket, it will then obtain service tickets from
+the Kerberos server in the other realm.
+
+For a two way trust between `MY.REALM' and `OTHER.REALM' add the
+following principals to each realm. The principals should be
+`krbtgt/OTHER.REALM@MY.REALM' and `krbtgt/MY.REALM@OTHER.REALM' in
+`MY.REALM', and `krbtgt/MY.REALM@OTHER.REALM' and
+`krbtgt/OTHER.REALM@MY.REALM'in `OTHER.REALM'.
+
+In Kerberos 5 the trust can be configured to be one way. So that users
+from `MY.REALM' can authenticate to services in `OTHER.REALM', but not
+the opposite. In the example above, the `krbtgt/MY.REALM@OTHER.REALM'
+then should be removed.
+
+The two principals must have the same key, key version number, and the
+same set of encryption types. Remember to transfer the two keys in a
+safe manner.
+
+     vr$ klist
+     Credentials cache: FILE:/tmp/krb5cc_913.console
+             Principal: lha@E.KTH.SE
+     
+       Issued           Expires          Principal
+     May  3 13:55:52  May  3 23:55:54  krbtgt/E.KTH.SE@E.KTH.SE
+     
+     vr$ telnet -l lha hummel.it.su.se
+     Trying 2001:6b0:5:1095:250:fcff:fe24:dbf...
+     Connected to hummel.it.su.se.
+     Escape character is '^]'.
+     Waiting for encryption to be negotiated...
+     [ Trying mutual KERBEROS5 (host/hummel.it.su.se@SU.SE)... ]
+     [ Kerberos V5 accepts you as ``lha@E.KTH.SE'' ]
+     Encryption negotiated.
+     Last login: Sat May  3 14:11:47 from vr.l.nxs.se
+     hummel$ exit
+     
+     vr$ klist
+     Credentials cache: FILE:/tmp/krb5cc_913.console
+             Principal: lha@E.KTH.SE
+     
+       Issued           Expires          Principal
+     May  3 13:55:52  May  3 23:55:54  krbtgt/E.KTH.SE@E.KTH.SE
+     May  3 13:55:56  May  3 23:55:54  krbtgt/SU.SE@E.KTH.SE
+     May  3 14:10:54  May  3 23:55:54  host/hummel.it.su.se@SU.SE
+
+\1f
+File: heimdal.info,  Node: Transit policy,  Next: Setting up DNS,  Prev: Cross realm,  Up: Setting up a realm
+
+Transit policy
+==============
+
+If you want to use cross realm authentication through an intermediate
+realm, it must be explicitly allowed by either the KDCs or the server
+receiving the request. This is done in `krb5.conf' in the `[capaths]'
+section.
+
+When the ticket transits through a realm to another realm, the
+destination realm adds its peer to the "transited-realms" field in the
+ticket. The field is unordered, since there is no way to know if know
+if one of the transited-realms changed the order of the list.
+
+The syntax for `[capaths]' section:
+
+     [capaths]
+             CLIENT-REALM = {
+                     SERVER-REALM = PERMITTED-CROSS-REALMS ...
+             }
+
+The realm `STACKEN.KTH.SE' allows clients from `SU.SE' and `DSV.SU.SE'
+to cross it. Since `STACKEN.KTH.SE' only have direct cross realm with
+`KTH.SE', and `DSV.SU.SE' only have direct cross realm with `SU.SE'
+they need to use both `SU.SE' and `KTH.SE' as transit realms.
+
+     [capaths]
+       SU.SE = {
+                         STACKEN.KTH.SE = KTH.SE
+       }
+       DSV.SU.SE = {
+                         STACKEN.KTH.SE = SU.SE KTH.SE
+       }
+
+The order of the `PERMITTED-CROSS-REALMS' is not important when doing
+transit cross realm verification.
+
+However the order is important when the `[capaths]' section is used to
+figure out the intermediate realm to go to when doing multi-realm
+transit. When figuring out the next realm, the first realm of the list
+of `PERMITTED-CROSS-REALMS' is chosen. This is done in both the client
+kerberos library and the KDC.
+
+\1f
+File: heimdal.info,  Node: Setting up DNS,  Next: Using LDAP to store the database,  Prev: Transit policy,  Up: Setting up a realm
+
+Setting up DNS
+==============
+
+Using DNS to find KDC
+---------------------
+
+If there is information about where to find the KDC or kadmind for a
+realm in the `krb5.conf' for a realm, that information will be
+preferred, and DNS will not be queried.
+
+Heimdal will try to use DNS to find the KDCs for a realm. First it will
+try to find a `SRV' resource record (RR) for the realm. If no SRV RRs
+are found, it will fall back to looking for an `A' RR for a machine
+named kerberos.REALM, and then kerberos-1.REALM, etc
+
+Adding this information to DNS makes the client have less configuration
+(in the common case, no configuration) and allows the system
+administrator to change the number of KDCs and on what machines they
+are running without caring about clients.
+
+The down side of using DNS that the client might be fooled to use the
+wrong server if someone fakes DNS replies/data, but storing the IP
+addresses of the KDC on all the clients makes it very hard to change
+the infrastructure.
+
+An example of the configuration for the realm `EXAMPLE.COM',
+
+
+     $ORIGIN example.com.
+     _kerberos._tcp          SRV     10 1 88 kerberos.example.com.
+     _kerberos._udp          SRV     10 1 88 kerberos.example.com.
+     _kerberos._tcp          SRV     10 1 88 kerberos-1.example.com.
+     _kerberos._udp          SRV     10 1 88 kerberos-1.example.com.
+     _kpasswd._udp           SRV     10 1 464 kerberos.example.com.
+     _kerberos-adm._tcp        SRV     10 1 749 kerberos.example.com.
+
+More information about DNS SRV resource records can be found in
+RFC-2782 (A DNS RR for specifying the location of services (DNS SRV)).
+
+Using DNS to map hostname to Kerberos realm
+-------------------------------------------
+
+Heimdal also supports a way to lookup a realm from a hostname. This to
+minimize configuration needed on clients. Using this has the drawback
+that clients can be redirected by an attacker to realms within the same
+cross realm trust and made to believe they are talking to the right
+server (since Kerberos authentication will succeed).
+
+An example configuration that informs clients that for the realms
+it.example.com and srv.example.com, they should use the realm
+EXAMPLE.COM:
+
+
+     $ORIGIN example.com.
+     _kerberos.it              TXT     "EXAMPLE.COM"
+     _kerberos.srv             TXT     "EXAMPLE.COM"
+
+\1f
+File: heimdal.info,  Node: Using LDAP to store the database,  Next: Providing Kerberos credentials to servers and programs,  Prev: Setting up DNS,  Up: Setting up a realm
+
+Using LDAP to store the database
+================================
+
+This document describes how to install the LDAP backend for Heimdal.
+Note that before attempting to configure such an installation, you
+should be aware of the implications of storing private information
+(such as users' keys) in a directory service primarily designed for
+public information. Nonetheless, with a suitable authorization policy,
+it is possible to set this up in a secure fashion. A knowledge of LDAP,
+Kerberos, and C is necessary to install this backend. The HDB schema
+was devised by Leif Johansson.
+
+Requirements:
+
+   * A current release of Heimdal, configured with
+     `--with-openldap=/usr/local' (adjust according to where you have
+     installed OpenLDAP).
+
+     You can verify that you manage to configure LDAP support by running
+     `kdc --builtin-hdb', and checking that `ldap:' is one entry in the
+     list.
+
+     Its also possible to configure the ldap backend as a shared module,
+     see option -hdb-openldap-module to configure.
+
+   * OpenLDAP 2.0.x. Configure OpenLDAP with `--enable-local' to enable
+     the local transport. (A patch to support SASL EXTERNAL
+     authentication is necessary in order to use OpenLDAP 2.1.x.)
+
+   * Add the hdb schema to the LDAP server, its included in the
+     source-tree in `lib/hdb/hdb.schema'. Example from slapd.conf:
+
+          include /usr/local/etc/openldap/schema/hdb.schema
+
+   * Configure the LDAP server ACLs to accept writes from clients over
+     the local transport. For example:
+
+          access to *
+                  by dn.exact="uid=heimdal,dc=services,dc=example,dc=com" write
+                  ...
+          
+          sasl-regexp "uidNumber=0\\\+gidNumber=.*,cn=peercred,cn=external,cn=auth"
+               "uid=heimdal,dc=services,dc=example,dc=com"
+
+     The sasl-regexp is for mapping between the SASL/EXTERNAL and a
+     user in a tree.  The user that the key is mapped to should be have
+     a krb5Principal aux object with krb5PrincipalName set so that the
+     "creator" and "modifier" is right in `kadmin'.
+
+     Another option is to create an admins group and add the dn to that
+     group.
+
+     Since Heimdal talkes to the LDAP server over a UNIX domain socket,
+     and uses external sasl authentication, its not possible to require
+     security layer quality (ssf in cyrus-sasl lingo). So that
+     requirement has to be turned off in OpenLDAP `slapd' configuration
+     file `slapd.conf'.
+
+          sasl-secprops minssf=0
+
+   *  Start `slapd' with the local listener (as well as the default
+     TCP/IP listener on port 389) as follows:
+
+              slapd -h "ldapi:/// ldap:///"
+
+     Note: These is a bug in `slapd' where it appears to corrupt the
+     krb5Key binary attribute on shutdown. This may be related to our
+     use of the V3 schema definition syntax instead of the old
+     UMich-style, V2 syntax.
+
+   * You should specify the distinguished name under which your
+     principals will be stored in `krb5.conf':
+
+          [kdc]
+                  database = {
+                          dbname = ldap:ou=KerberosPrincipals,dc=example,dc=com
+                          mkey_file = /path/to/mkey
+                  }
+
+     `mkey_file' can be excluded if you feel that you trust your ldap
+     directory to have the raw keys inside it.
+
+   * Once you have built Heimdal and started the LDAP server, run kadmin
+     (as usual) to initialize the database. Note that the instructions
+     for stashing a master key are as per any Heimdal installation.
+
+          kdc# kadmin -l
+          kadmin> init EXAMPLE.COM
+          Realm max ticket life [unlimited]:
+          Realm max renewable ticket life [unlimited]:
+          kadmin> ank lukeh
+          Max ticket life [1 day]:
+          Max renewable life [1 week]:
+          Principal expiration time [never]:
+          Password expiration time [never]:
+          Attributes []:
+          lukeh@EXAMPLE.COM's Password:
+          Verifying password - lukeh@EXAMPLE.COM's Password:
+          kadmin> exit
+
+     Verify that the principal database has indeed been stored in the
+     directory with the following command:
+
+          kdc# ldapsearch -L -h localhost -D cn=manager \
+           -w secret -b ou=KerberosPrincipals,dc=example,dc=com \
+           'objectclass=krb5KDCEntry'
+
+   * Now consider adding indexes to the database to speed up the
+     access, at least theses should be added to slapd.conf.
+
+          index        objectClass             eq
+          index        cn                      eq,sub,pres
+          index        uid                     eq,sub,pres
+          index        displayName             eq,sub,pres
+          index        krb5PrincipalName       eq
+
+
+Troubleshooting guide
+---------------------
+
+<https://sec.miljovern.no/bin/view/Info/TroubleshootingGuide>
+
+Using Samba LDAP password database
+----------------------------------
+
+Samba domain and the Kerberos realm can have diffrent names since
+arcfour's string to key function principal/realm independent.  So now
+will be your first and only chance name your Kerberos without needing
+to deal with old configuration files.
+
+First you should set up Samba and get that working with LDAP backend.
+
+Now you can proceed as in *Note Using LDAP to store the database::,
+Heimdal will pick up the Samba LDAP entries if they are in the same
+search space as the Kerberos entries.
+
+\1f
+File: heimdal.info,  Node: Providing Kerberos credentials to servers and programs,  Prev: Using LDAP to store the database,  Up: Setting up a realm
+
+Providing Kerberos credentials to servers and programs
+======================================================
+
+Some service require Kerberos credentials when they start to make
+connections to other services or use them when they have started.
+
+The easiest way to get ticket for the a service is to store the key in
+a keytab. Both ktutil get and kadmin ext can be used to get a keytab.
+ktutil get is better in that way it changes the key/password for the
+user. This the problem with the ktutil. It ktutil is used for the same
+service principal on several hosts, they keytab will only useful on the
+last host. In that case, run the command on host and copy the keytab
+around to all other hosts that needs it.
+
+     host# ktutil -k /etc/krb5-service.keytab \
+           get -p lha/admin@EXAMPLE.ORG service-principal@EXAMPLE.ORG
+     lha/admin@EXAMPLE.ORG's Password:
+
+To get a Kerberos credential file for the service, use kinit in the
+-keytab mode, this will not ask for a password but rather that the key
+from the keytab.
+
+     service@host$ kinit --cache=/var/run/service_krb5_cache \
+                    --keytab=/etc/krb5-service.keytab \
+            service-principal@EXAMPLE.ORG
+
+Long running services might need credentials longer then the expiration
+time of the tickets. kinit can run in a mode that refreshes the tickets
+before they expire. This is useful for services that write into AFS and
+other distributed file systems using Kerberos. To run the long running
+script, just append the program and arguments (if any) after the
+principal. kinit will stop refreshing credentials and remove the
+credentials when the script-to-start-service exits.
+
+     service@host$ kinit --cache=/var/run/service_krb5_cache \
+            --keytab=/etc/krb5-service.keytab \
+            service-principal@EXAMPLE.ORG \
+            script-to-start-service argument1 argument2
+
+\1f
+File: heimdal.info,  Node: Applications,  Next: Things in search for a better place,  Prev: Setting up a realm,  Up: Top
+
+Applications
+************
+
+* Menu:
+
+* Authentication modules::
+* AFS::
+
+\1f
+File: heimdal.info,  Node: Authentication modules,  Next: AFS,  Prev: Applications,  Up: Applications
+
+Authentication modules
+======================
+
+The problem of having different authentication mechanisms has been
+recognised by several vendors, and several solutions has appeared. In
+most cases these solutions involve some kind of shared modules that are
+loaded at run-time.  Modules for some of these systems can be found in
+`lib/auth'.  Presently there are modules for Digital's SIA, and IRIX'
+`login' and `xdm' (in `lib/auth/afskauthlib').
+
+* Menu:
+
+* Digital SIA::
+* IRIX::
+
diff --git a/src/kerberosV/src/doc/heimdal.info-2 b/src/kerberosV/src/doc/heimdal.info-2
new file mode 100644 (file)
index 0000000..3243b76
--- /dev/null
@@ -0,0 +1,1262 @@
+This is heimdal.info, produced by makeinfo version 4.0 from
+heimdal.texi.
+
+INFO-DIR-SECTION Heimdal
+START-INFO-DIR-ENTRY
+* Heimdal: (heimdal).           The Kerberos 5 distribution from KTH
+END-INFO-DIR-ENTRY
+
+\1f
+File: heimdal.info,  Node: Digital SIA,  Next: IRIX,  Prev: Authentication modules,  Up: Authentication modules
+
+Digital SIA
+-----------
+
+How to install the SIA module depends on which OS version you're
+running. Tru64 5.0 have a new command, `siacfg', which makes this
+process quite simple. If you have this program, you should just be able
+to run:
+     siacfg -a KRB5 /usr/athena/lib/libsia_krb5.so
+
+On older versions, or if you want to do it by hand, you have to do the
+following (not tested by us on Tru64 5.0):
+
+   * Make sure `libsia_krb5.so' is available in `/usr/athena/lib'. If
+     `/usr/athena' is not on local disk, you might want to put it in
+     `/usr/shlib' or someplace else. If you do, you'll have to edit
+     `krb5_matrix.conf' to reflect the new location (you will also have
+     to do this if you installed in some other directory than
+     `/usr/athena'). If you built with shared libraries, you will have
+     to copy the shared `libkrb.so', `libdes.so', `libkadm.so', and
+     `libkafs.so' to a place where the loader can find them (such as
+     `/usr/shlib').
+
+   * Copy (your possibly edited) `krb5_matrix.conf' to `/etc/sia'.
+
+   * Apply `security.patch' to `/sbin/init.d/security'.
+
+   * Turn on KRB5 security by issuing `rcmgr set SECURITY KRB5' and
+     `rcmgr set KRB5_MATRIX_CONF krb5_matrix.conf'.
+
+   * Digital thinks you should reboot your machine, but that really
+     shouldn't be necessary.  It's usually sufficient just to run
+     `/sbin/init.d/security start' (and restart any applications that
+     use SIA, like `xdm'.)
+
+Users with local passwords (like `root') should be able to login safely.
+
+When using Digital's xdm the `KRB5CCNAME' environment variable isn't
+passed along as it should (since xdm zaps the environment). Instead you
+have to set `KRB5CCNAME' to the correct value in
+`/usr/lib/X11/xdm/Xsession'. Add a line similar to
+     KRB5CCNAME=FILE:/tmp/krb5cc`id -u`_`ps -o ppid= -p $$`; export KRB5CCNAME
+If you use CDE, `dtlogin' allows you to specify which additional
+environment variables it should export. To add `KRB5CCNAME' to this
+list, edit `/usr/dt/config/Xconfig', and look for the definition of
+`exportList'. You want to add something like:
+     Dtlogin.exportList:     KRB5CCNAME
+
+Notes to users with Enhanced security
+.....................................
+
+Digital's `ENHANCED' (C2) security, and Kerberos solves two different
+problems. C2 deals with local security, adds better control of who can
+do what, auditing, and similar things. Kerberos deals with network
+security.
+
+To make C2 security work with Kerberos you will have to do the
+following.
+
+   * Replace all occurencies of `krb5_matrix.conf' with
+     `krb5+c2_matrix.conf' in the directions above.
+
+   * You must enable "vouching" in the `default' database.  This will
+     make the OSFC2 module trust other SIA modules, so you can login
+     without giving your C2 password. To do this use `edauth' to edit
+     the default entry `/usr/tcb/bin/edauth -dd default', and add a
+     `d_accept_alternate_vouching' capability, if not already present.
+
+   * For each user that does _not_ have a local C2 password, you should
+     set the password expiration field to zero. You can do this for each
+     user, or in the `default' table. To do this use `edauth' to set
+     (or change) the `u_exp' capability to `u_exp#0'.
+
+   * You also need to be aware that the shipped `login', `rcp', and
+     `rshd', doesn't do any particular C2 magic (such as checking to
+     various forms of disabled accounts), so if you rely on those
+     features, you shouldn't use those programs. If you configure with
+     `--enable-osfc2', these programs will, however, set the login UID.
+     Still: use at your own risk.
+
+At present `su' does not accept the vouching flag, so it will not work
+as expected.
+
+Also, kerberised ftp will not work with C2 passwords. You can solve this
+by using both Digital's ftpd and our on different ports.
+
+*Remember*, if you do these changes you will get a system that most
+certainly does _not_ fulfill the requirements of a C2 system. If C2 is
+what you want, for instance if someone else is forcing you to use it,
+you're out of luck.  If you use enhanced security because you want a
+system that is more secure than it would otherwise be, you probably got
+an even more secure system. Passwords will not be sent in the clear,
+for instance.
+
+\1f
+File: heimdal.info,  Node: IRIX,  Prev: Digital SIA,  Up: Authentication modules
+
+IRIX
+----
+
+The IRIX support is a module that is compatible with Transarc's
+`afskauthlib.so'.  It should work with all programs that use this
+library. This should include `login' and `xdm'.
+
+The interface is not very documented but it seems that you have to copy
+`libkafs.so', `libkrb.so', and `libdes.so' to `/usr/lib', or build your
+`afskauthlib.so' statically.
+
+The `afskauthlib.so' itself is able to reside in `/usr/vice/etc',
+`/usr/afsws/lib', or the current directory (wherever that is).
+
+IRIX 6.4 and newer seems to have all programs (including `xdm' and
+`login') in the N32 object format, whereas in older versions they were
+O32. For it to work, the `afskauthlib.so' library has to be in the same
+object format as the program that tries to load it. This might require
+that you have to configure and build for O32 in addition to the default
+N32.
+
+Appart from this it should "just work", there are no configuration
+files.
+
+Note that recent Irix 6.5 versions (at least 6.5.22) have PAM,
+including a `pam_krb5.so' module.  Not all relevant programs use PAM,
+though, e.g. `ssh'. In particular, for console graphical login you need
+to turn off `visuallogin' and turn on `xdm' with `chkconfig'.
+
+\1f
+File: heimdal.info,  Node: AFS,  Prev: Authentication modules,  Up: Applications
+
+AFS
+===
+
+AFS is a distributed filesystem that uses Kerberos for authentication.
+
+For more information about AFS see OpenAFS <http://www.openafs.org/>
+and Arla <http://www.stacken.kth.se/projekt/arla/>.
+
+How to get a KeyFile
+--------------------
+
+`ktutil -k AFSKEYFILE:KeyFile get afs@MY.REALM'
+
+or you can extract it with kadmin
+
+     kadmin> ext -k AFSKEYFILE:/usr/afs/etc/KeyFile afs@My.CELL.NAME
+
+You have to make sure you have a `des-cbc-md5' encryption type since
+that is the enctype that will be converted.
+
+How to convert a srvtab to a KeyFile
+------------------------------------
+
+You need a `/usr/vice/etc/ThisCell' containing the cellname of you
+AFS-cell.
+
+`ktutil copy krb4:/root/afs-srvtab AFSKEYFILE:/usr/afs/etc/KeyFile'.
+
+If keyfile already exists, this will add the new key in afs-srvtab to
+KeyFile.
+
+Using 2b tokens with AFS
+========================
+
+What is 2b ?
+------------
+
+2b is the name of the proposal that was implemented to give basic
+Kerberos 5 support to AFS in rxkad. Its not real Kerberos 5 support
+since it still uses fcrypt for data encryption and not Kerberos
+encryption types.
+
+Its only possible (in all cases) to do this for DES encryption types
+because only then the token (the AFS equivalent of a ticket) will be be
+smaller than the maximum size that can fit in the token cache in
+OpenAFS/Transarc client. Its so tight fit that some extra wrapping on
+the ASN1/DER encoding is removed from the Kerberos ticket.
+
+2b uses a Kerberos 5 EncTicketPart instead of a Kerberos 4 ditto for
+the part of the ticket that is encrypted with the service's key. The
+client doesn't know what's inside the encrypted data so to the client
+it doesn't matter.
+
+To  differentiate between Kerberos 4 tickets and Kerberos 5 tickets 2b
+uses a special kvno, 213 for 2b tokens and 255 for Kerberos 5 tokens.
+
+Its a requirement that all AFS servers that support 2b also support
+native Kerberos 5 in rxkad.
+
+Configuring a Heimdal kdc to use 2b tokens
+------------------------------------------
+
+Support for 2b tokens in the kdc are turned on for specific principals
+by adding them to the string list option `[kdc]use_2b' in the kdc's
+`krb5.conf' file.
+
+     [kdc]
+       use_2b = {
+               afs@SU.SE = yes
+               afs/it.su.se@SU.SE = yes
+       }
+
+Configuring AFS clients for 2b support
+--------------------------------------
+
+There is no need to configure AFS clients for 2b support. The only
+software that needs to be installed/upgrade is a Kerberos 5 enabled
+`afslog'.
+
+\1f
+File: heimdal.info,  Node: Things in search for a better place,  Next: Kerberos 4 issues,  Prev: Applications,  Up: Top
+
+Things in search for a better place
+***********************************
+
+Making things work on Ciscos
+============================
+
+Modern versions of Cisco IOS has some support for authenticating via
+Kerberos 5. This can be used both by having the router get a ticket when
+you login (boring), and by using Kerberos authenticated telnet to access
+your router (less boring). The following has been tested on IOS
+11.2(12), things might be different with other versions. Old versions
+are known to have bugs.
+
+To make this work, you will first have to configure your router to use
+Kerberos (this is explained in the documentation). A sample
+configuration looks like the following:
+
+     aaa new-model
+     aaa authentication login default krb5-telnet krb5 enable
+     aaa authorization exec krb5-instance
+     kerberos local-realm FOO.SE
+     kerberos srvtab entry host/router.foo.se 0 891725446 4 1 8 012345678901234567
+     kerberos server FOO.SE 10.0.0.1
+     kerberos instance map admin 15
+
+This tells you (among other things) that when logging in, the router
+should try to authenticate with kerberised telnet, and if that fails try
+to verify a plain text password via a Kerberos ticket exchange (as
+opposed to a local database, RADIUS or something similar), and if that
+fails try the local enable password. If you're not careful when you
+specify the `login default' authentication mechanism, you might not be
+able to login at all. The `instance map' and `authorization exec' lines
+says that people with `admin' instances should be given `enabled' shells
+when logging in.
+
+The numbers after the principal on the `srvtab' line are principal type,
+time stamp (in seconds since 1970), key version number (4), keytype (1
+== des), key length (always 8 with des), and then the key.
+
+To make the Heimdal KDC produce tickets that the Cisco can decode you
+might have to turn on the `encode_as_rep_as_tgs_rep' flag in the KDC.
+You will also have to specify that the router can't handle anything but
+`des-cbc-crc'. This can be done with the `del_enctype' command of
+`kadmin'.
+
+This all fine and so, but unless you have an IOS version with encryption
+(available only in the U.S) it doesn't really solve any problems. Sure
+you don't have to send your password over the wire, but since the telnet
+connection isn't protected it's still possible for someone to steal your
+session. This won't be fixed until someone adds integrity to the telnet
+protocol.
+
+A working solution would be to hook up a machine with a real operating
+system to the console of the Cisco and then use it as a backwards
+terminal server.
+
+\1f
+File: heimdal.info,  Node: Kerberos 4 issues,  Next: Windows 2000 compatability,  Prev: Things in search for a better place,  Up: Top
+
+Kerberos 4 issues
+*****************
+
+If compiled with version 4 support, the KDC can serve requests from a
+Kerberos 4 client. There are a few things you must do for this to work.
+
+The KDC will also have kaserver emulation and be able to handle
+AFS-clients that use `klog'.
+
+* Menu:
+
+* Principal conversion issues::
+* Converting a version 4 database::
+* kaserver::
+
+\1f
+File: heimdal.info,  Node: Principal conversion issues,  Next: Converting a version 4 database,  Prev: Kerberos 4 issues,  Up: Kerberos 4 issues
+
+Principal conversion issues
+===========================
+
+First, Kerberos 4 and Kerberos 5 principals are different. A version 4
+principal consists of a name, an instance, and a realm. A version 5
+principal has one or more components, and a realm (the terms "name" and
+"instance" are still used, for the first and second component,
+respectively).    Also, in some cases the name of a version 4 principal
+differs from the first component of the corresponding version 5
+principal. One notable example is the "host" type principals, where the
+version 4 name is `rcmd' (for "remote command"), and the version 5 name
+is `host'. For the class of principals that has a hostname as instance,
+there is an other major difference, Kerberos 4 uses only the first
+component of the hostname, whereas Kerberos 5 uses the fully qualified
+hostname.
+
+Because of this it can be hard or impossible to correctly convert a
+version 4 principal to a version 5 principal (1). The biggest problem is
+to know if the conversion resulted in a valid principal. To give an
+example, suppose you want to convert the principal `rcmd.foo'.
+
+The `rcmd' name suggests that the instance is a hostname (even if there
+are exceptions to this rule). To correctly convert the instance `foo'
+to a hostname, you have to know which host it is referring to. You can
+to this by either guessing (from the realm) which domain name to
+append, or you have to have a list of possible hostnames. In the
+simplest cases you can cover most principals with the first rule. If you
+have several domains sharing a single realm this will not usually work.
+If the exceptions are few you can probably come by with a lookup table
+for the exceptions.
+
+In a complex scenario you will need some kind of host lookup mechanism.
+Using DNS for this is tempting, but DNS is error prone, slow and unsafe
+(2).
+
+Fortunately, the KDC has a trump on hand: it can easily tell if a
+principal exists in the database. The KDC will use
+`krb5_425_conv_principal_ext' to convert principals when handling to
+version 4 requests.
+
+---------- Footnotes ----------
+
+(1) the other way is not always trivial either, but usually easier
+
+(2) at least until secure DNS is commonly available
+
+\1f
+File: heimdal.info,  Node: Converting a version 4 database,  Next: kaserver,  Prev: Principal conversion issues,  Up: Kerberos 4 issues
+
+Converting a version 4 database
+===============================
+
+If you want to convert an existing version 4 database, the principal
+conversion issue arises too.
+
+If you decide to convert your database once and for all, you will only
+have to do this conversion once. It is also possible to run a version 5
+KDC as a slave to a version 4 KDC. In this case this conversion will
+happen every time the database is propagated.  When doing this
+conversion, there are a few things to look out for. If you have stale
+entries in the database, these entries will not be converted. This might
+be because these principals are not used anymore, or it might be just
+because the principal couldn't be converted.
+
+You might also see problems with a many-to-one mapping of principals.
+For instance, if you are using DNS lookups and you have two principals
+`rcmd.foo' and `rcmd.bar', where `foo' is a CNAME for `bar', the
+resulting principals will be the same. Since the conversion function
+can't tell which is correct, these conflicts will have to be resolved
+manually.
+
+Conversion example
+------------------
+
+Given the following set of hosts and services:
+
+     foo.se          rcmd
+     mail.foo.se     rcmd, pop
+     ftp.bar.se      rcmd, ftp
+
+you have a database that consists of the following principals:
+
+`rcmd.foo', `rcmd.mail', `pop.mail', `rcmd.ftp', and `ftp.ftp'.
+
+lets say you also got these extra principals: `rcmd.gone',
+`rcmd.old-mail', where `gone.foo.se' was a machine that has now passed
+away, and `old-mail.foo.se' was an old mail machine that is now a CNAME
+for `mail.foo.se'.
+
+When you convert this database you want the following conversions to be
+done:
+     rcmd.foo         host/foo.se
+     rcmd.mail        host/mail.foo.se
+     pop.mail         pop/mail.foo.se
+     rcmd.ftp         host/ftp.bar.se
+     ftp.ftp          ftp/ftp.bar.se
+     rcmd.gone        removed
+     rcmd.old-mail    removed
+
+A `krb5.conf' that does this looks like:
+
+     [realms]
+             FOO.SE = {
+                     v4_name_convert = {
+                             host = {
+                                     ftp = ftp
+                                     pop = pop
+                                     rcmd = host
+                             }
+                     }
+                     v4_instance_convert = {
+                             foo = foo.se
+                             ftp = ftp.bar.se
+                     }
+                     default_domain = foo.se
+             }
+
+The `v4_name_convert' section says which names should be considered
+having an instance consisting of a hostname, and it also says how the
+names should be converted (for instance `rcmd' should be converted to
+`host'). The `v4_instance_convert' section says how a hostname should
+be qualified (this is just a hosts-file in disguise). Host-instances
+that aren't covered by `v4_instance_convert' are qualified by appending
+the contents of the `default_domain'.
+
+Actually, this example doesn't work. Or rather, it works to well. Since
+it has no way of knowing which hostnames are valid and which are not, it
+will happily convert `rcmd.gone' to `host/gone.foo.se'. This isn't a
+big problem, but if you have run your kerberos realm for a few years,
+chances are big that you have quite a few `junk' principals.
+
+If you don't want this you can remove the `default_domain' statement,
+but then you will have to add entries for _all_ your hosts in the
+`v4_instance_convert' section.
+
+Instead of doing this you can use DNS to convert instances. This is not
+a solution without problems, but it is probably easier than adding lots
+of static host entries.
+
+To enable DNS lookup you should turn on `v4_instance_resolve' in the
+`[libdefaults]' section.
+
+Converting a database
+---------------------
+
+The database conversion is done with `hprop'. You can run this command
+to propagate the database to the machine called `slave-server' (which
+should be running a `hpropd').
+
+     hprop --source=krb4-db --master-key=/.m slave-server
+
+This command can also be to use for converting the v4 database on the
+server:
+
+     hprop -n --source=krb4-db -d /var/kerberos/principal --master-key=/.m | hpropd -n
+
+Version 4 Kadmin
+================
+
+`kadmind' can act as a version 4 kadmind, and you can do most
+operations, but with some restrictions (since the version 4 kadmin
+protocol is, lets say, very ad hoc.) One example is that it only passes
+des keys when creating principals and changing passwords (modern kpasswd
+clients do send the password, so it's possible to to password quality
+checks). Because of this you can only create principals with des keys,
+and you can't set any flags or do any other fancy stuff.
+
+To get this to work, you have to add another entry to inetd (since
+version 4 uses port 751, not 749).
+
+_And then there are a many more things you can do; more on this in a
+later version of this manual. Until then, UTSL._
+
+\1f
+File: heimdal.info,  Node: kaserver,  Prev: Converting a version 4 database,  Up: Kerberos 4 issues
+
+kaserver
+========
+
+kaserver emulation
+------------------
+
+The Heimdal kdc can emulate a kaserver. The kaserver is a Kerberos 4
+server with pre-authentication using Rx as the on-wire protocol. The kdc
+contains a minimalistic Rx implementation.
+
+There are three parts of the kaserver; KAA (Authentication), KAT (Ticket
+Granting), and KAM (Maintenance). The KAA interface and KAT interface
+both passes over DES encrypted data-blobs (just like the
+Kerberos-protocol) and thus do not need any other protection.  The KAM
+interface uses `rxkad' (Kerberos authentication layer for Rx) for
+security and data protection, and is used for example for changing
+passwords.  This part is not implemented in the kdc.
+
+Another difference between the ka-protocol and the Kerberos 4 protocol
+is that the pass-phrase is salted with the cellname in the `string to
+key' function in the ka-protocol, while in the Kerberos 4 protocol there
+is no salting of the password at all. To make sure AFS-compatible keys
+are added to each principals when they are created or their password are
+changed, `afs3-salt' should be added to `[kadmin]default_keys'.
+
+Transarc AFS Windows client
+---------------------------
+
+The Transarc Windows client uses Kerberos 4 to obtain tokens, and thus
+does not need a kaserver. The Windows client assumes that the Kerberos
+server is on the same machine as the AFS-database server. If you do not
+like to do that you can add a small program that runs on the database
+servers that forward all kerberos requests to the real kerberos server.
+A program that does this is `krb-forward'
+(<ftp://ftp.stacken.kth.se/pub/projekts/krb-forward>).
+
+\1f
+File: heimdal.info,  Node: Windows 2000 compatability,  Next: Programming with Kerberos,  Prev: Kerberos 4 issues,  Up: Top
+
+Windows 2000 compatability
+**************************
+
+Windows 2000 (formerly known as Windows NT 5) from Microsoft implements
+Kerberos 5.  Their implementation, however, has some quirks,
+peculiarities, and bugs.  This chapter is a short summary of the things
+that we have found out while trying to test Heimdal against Windows
+2000.  Another big problem with the Kerberos implementation in Windows
+2000 is that the available documentation is more focused on getting
+things to work rather than how they work, and not that useful in
+figuring out how things really work.
+
+This information should apply to Heimdal 0.7 and Windows 2000
+Professional.  It's of course subject to change all the time and mostly
+consists of our not so inspired guesses.  Hopefully it's still somewhat
+useful.
+
+* Menu:
+
+* Configuring Windows 2000 to use a Heimdal KDC::
+* Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC::
+* Create account mappings::
+* Encryption types::
+* Authorization data::
+* Quirks of Windows 2000 KDC::
+* Useful links when reading about the Windows 2000::
+
+\1f
+File: heimdal.info,  Node: Configuring Windows 2000 to use a Heimdal KDC,  Next: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC,  Prev: Windows 2000 compatability,  Up: Windows 2000 compatability
+
+Configuring Windows 2000 to use a Heimdal KDC
+=============================================
+
+You need the command line program called `ksetup.exe' which is available
+in the file `SUPPORT/TOOLS/SUPPORT.CAB' on the Windows 2000 Professional
+CD-ROM. This program is used to configure the Kerberos settings on a
+Workstation.
+
+`Ksetup' store the domain information under the registry key:
+`HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA\Kerberos\Domains'.
+
+Use the `kadmin' program in Heimdal to create a host principal in the
+Kerberos realm.
+
+     unix% kadmin
+     kadmin> ank --password=password host/datan.example.com
+
+The name `datan.example.com' should be replaced with DNS name of the
+workstation.
+
+You must configure the workstation as a member of a workgroup, as
+opposed to a member in an NT domain, and specify the KDC server of the
+realm as follows:
+     C:> ksetup /setdomain EXAMPLE.COM
+     C:> ksetup /addkdc EXAMPLE.COM kdc.example.com
+
+Set the machine password, i.e. create the local keytab:
+     C:> ksetup /setmachpassword password
+
+The password used in `ksetup /setmachpassword' must be the same as the
+password used in the `kadmin ank' command.
+
+The workstation must now be rebooted.
+
+A mapping between local NT users and Kerberos principals must be
+specified.  You have two choices. First:
+
+     C:> ksetup /mapuser user@MY.REALM nt_user
+
+This will map a user to a specific principal; this allows you to have
+other usernames in the realm than in your NT user database. (Don't ask
+me why on earth you would want that....)
+
+You can also say:
+     C:> ksetup /mapuser * *
+The Windows machine will now map any user to the corresponding
+principal, for example `nisse' to the principal `nisse@MY.REALM'.
+(This is most likely what you want.)
+
+\1f
+File: heimdal.info,  Node: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC,  Next: Create account mappings,  Prev: Configuring Windows 2000 to use a Heimdal KDC,  Up: Windows 2000 compatability
+
+Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC
+===============================================================
+
+See also the Step-by-Step guide from Microsoft, referenced below.
+
+Install Windows 2000, and create a new controller (Active Directory
+Server) for the domain.
+
+By default the trust will be non-transitive. This means that only users
+directly from the trusted domain may authenticate. This can be changed
+to transitive by using the `netdom.exe' tool. `netdom.exe' can also be
+used to add the trust between two realms.
+
+You need to tell Windows 2000 on what hosts to find the KDCs for the
+non-Windows realm with `ksetup', see *Note Configuring Windows 2000 to
+use a Heimdal KDC::.
+
+This needs to be done on all computers that want enable cross-realm
+login with `Mapped Names'.  Then you need to add the inter-realm keys
+on the Windows KDC. Start the Domain Tree Management tool (found in
+Programs, Administrative tools, Active Directory Domains and Trusts).
+
+Right click on Properties of your domain, select the Trust tab.  Press
+Add on the appropriate trust windows and enter domain name and
+password. When prompted if this is a non-Windows Kerberos realm, press
+OK.
+
+Do not forget to add trusts in both directions (if that's what you
+want).
+
+If you want to use `netdom.exe' instead of the Domain Tree Management
+tool, you do it like this:
+
+     netdom trust NT.REALM.EXAMPLE.COM /Domain:EXAMPLE.COM /add /realm /passwordt:TrustPassword
+
+You also need to add the inter-realm keys to the Heimdal KDC. There are
+some tweaks that you need to do to `krb5.conf' beforehand.
+
+     [libdefaults]
+             default_etypes = des-cbc-crc
+             default_etypes_des = des-cbc-crc
+
+since otherwise checksum types that are not understood by Windows 2000
+will be generated (*note Quirks of Windows 2000 KDC::).
+
+Another issue is salting.  Since Windows 2000 does not seem to
+understand Kerberos 4 salted hashes you might need to turn off anything
+similar to the following if you have it, at least while adding the
+principals that are going to share keys with Windows 2000.
+
+     [kadmin]
+             default_keys = v5 v4
+
+So remove v4 from default keys.
+
+What you probably want to use is this:
+
+     [kadmin]
+             default_keys = des-cbc-crc:pw-salt arcfour-hmac-md5:pw-salt
+
+Note that before Windows 2003, arcfour-hmac-md5 wasn't supported beteen
+Windows realms and Non Windows realms.
+
+Once that is also done, you can add the required inter-realm keys:
+
+     kadmin add krbtgt/NT.REALM.EXAMPLE.COM@EXAMPLE.COM
+     kadmin add krbtgt/REALM.EXAMPLE.COM@NT.EXAMPLE.COM
+
+Use the same passwords for both keys.
+
+Do not forget to reboot before trying the new realm-trust (after
+running `ksetup'). It looks like it might work, but packets are never
+sent to the non-Windows KDC.
+
+\1f
+File: heimdal.info,  Node: Create account mappings,  Next: Encryption types,  Prev: Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC,  Up: Windows 2000 compatability
+
+Create account mappings
+=======================
+
+Start the `Active Directory Users and Computers' tool. Select the View
+menu, that is in the left corner just below the real menu (or press
+Alt-V), and select Advanced Features. Right click on the user that you
+are going to do a name mapping for and choose Name mapping.
+
+Click on the Kerberos Names tab and add a new principal from the
+non-Windows domain.
+
+This adds `authorizationNames' entry to the users LDAP entry to the
+Active Directory LDAP catalog. When you create users by script you can
+add this entry instead.
+
+\1f
+File: heimdal.info,  Node: Encryption types,  Next: Authorization data,  Prev: Create account mappings,  Up: Windows 2000 compatability
+
+Encryption types
+================
+
+Windows 2000 supports both the standard DES encryptions (`des-cbc-crc'
+and `des-cbc-md5') and its own proprietary encryption that is based on
+MD4 and RC4 that is documented in and is supposed to be described in
+`draft-brezak-win2k-krb-rc4-hmac-03.txt'.  New users will get both MD4
+and DES keys.  Users that are converted from a NT4 database, will only
+have MD4 passwords and will need a password change to get a DES key.
+
+\1f
+File: heimdal.info,  Node: Authorization data,  Next: Quirks of Windows 2000 KDC,  Prev: Encryption types,  Up: Windows 2000 compatability
+
+Authorization data
+==================
+
+The Windows 2000 KDC also adds extra authorization data in tickets.  It
+is at this point unclear what triggers it to do this.  The format of
+this data is only available under a "secret" license from Microsoft,
+which prohibits you implementing it.
+
+A simple way of getting hold of the data to be able to understand it
+better is described here.
+
+  1. Find the client example on using the SSPI in the SDK documentation.
+
+  2. Change "AuthSamp" in the source code to lowercase.
+
+  3. Build the program.
+
+  4. Add the "authsamp" principal with a known password to the
+     database.  Make sure it has a DES key.
+
+  5. Run `ktutil add' to add the key for that principal to a keytab.
+
+  6. Run `appl/test/nt_gss_server -p 2000 -s authsamp --dump-auth=FILE'
+     where FILE is an appropriate file.
+
+  7. It should authenticate and dump for you the authorization data in
+     the file.
+
+  8. The tool `lib/asn1/asn1_print' is somewhat useful for analyzing
+     the data.
+
+\1f
+File: heimdal.info,  Node: Quirks of Windows 2000 KDC,  Next: Useful links when reading about the Windows 2000,  Prev: Authorization data,  Up: Windows 2000 compatability
+
+Quirks of Windows 2000 KDC
+==========================
+
+There are some issues with salts and Windows 2000.  Using an empty
+salt--which is the only one that Kerberos 4 supported, and is therefore
+known as a Kerberos 4 compatible salt--does not work, as far as we can
+tell from out experiments and users' reports.  Therefore, you have to
+make sure you keep around keys with all the different types of salts
+that are required.  Microsoft have fixed this issue post Windows 2003.
+
+Microsoft seems also to have forgotten to implement the checksum
+algorithms `rsa-md4-des' and `rsa-md5-des'. This can make Name mapping
+(*note Create account mappings::) fail if a `des-cbc-md5' key is used.
+To make the KDC return only `des-cbc-crc' you must delete the
+`des-cbc-md5' key from the kdc using the `kadmin del_enctype' command.
+
+     kadmin del_enctype lha des-cbc-md5
+
+You should also add the following entries to the `krb5.conf' file:
+
+     [libdefaults]
+       default_etypes = des-cbc-crc
+       default_etypes_des = des-cbc-crc
+
+These configuration options will make sure that no checksums of the
+unsupported types are generated.
+
+\1f
+File: heimdal.info,  Node: Useful links when reading about the Windows 2000,  Prev: Quirks of Windows 2000 KDC,  Up: Windows 2000 compatability
+
+Useful links when reading about the Windows 2000
+================================================
+
+See also our paper presented at the 2001 usenix Annual Technical
+Conference, available in the proceedings or at
+`http://www.usenix.org/publications/library/proceedings/usenix01/freenix01/westerlund.html'.
+
+There are lots of texts about Kerberos on Microsoft's web site, here is
+a short list of the interesting documents that we have managed to find.
+
+   * Step-by-Step Guide to Kerberos 5 (krb5 1.0) Interoperability:
+     `http://www.microsoft.com/windows2000/library/planning/security/kerbsteps.asp'.
+     Kerberos GSS-API (in Windows-eze SSPI), Windows as a client in a
+     non-Windows KDC realm, adding unix clients to a Windows 2000 KDC,
+     and adding cross-realm trust (*note Inter-Realm keys (trust)
+     between Windows 2000 and a Heimdal KDC::).
+
+   * Windows 2000 Kerberos Authentication:
+     `http://www.microsoft.com/TechNet/win2000/win2ksrv/technote/kerberos.asp'.
+     White paper that describes how Kerberos is used in Windows 2000.
+
+   * Overview of Kerberos:
+     `http://support.microsoft.com/support/kb/articles/Q248/7/58.ASP'.
+     Links to useful other links.
+
+   * Event logging for Kerberos:
+     `http://support.microsoft.com/support/kb/articles/Q262/1/77.ASP'.
+     Basicly it say that you can add a registry key
+     `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\LogLevel'
+     with value DWORD equal to 1, and then you'll get logging in the
+     Event Logger.
+
+
+Other useful programs include these:
+
+   * pwdump2
+     `http://www.bindview.com/Support/RAZOR/Utilities/Windows/pwdump2_readme.cfm'
+
+\1f
+File: heimdal.info,  Node: Programming with Kerberos,  Next: Migration,  Prev: Windows 2000 compatability,  Up: Top
+
+Programming with Kerberos
+*************************
+
+First you need to know how the Kerberos model works, go read the
+introduction text (*note What is Kerberos?::).
+
+* Menu:
+
+* Kerberos 5 API Overview::
+* Walkthru a sample Kerberos 5 client::
+* Validating a password in a server application::
+* API diffrences to MIT Kerberos::
+
+\1f
+File: heimdal.info,  Node: Kerberos 5 API Overview,  Next: Walkthru a sample Kerberos 5 client,  Prev: Programming with Kerberos,  Up: Programming with Kerberos
+
+Kerberos 5 API Overview
+=======================
+
+Most functions are documenteded in manual pages.  This overview only
+tries to point to where to look for a specific function.
+
+Kerberos context
+----------------
+
+A kerberos context (`krb5_context') holds all per thread state. All
+global variables that are context specific are stored in this struture,
+including default encryption types, credential-cache (ticket file), and
+default realms.
+
+See the manual pages for `krb5_context(3)' and `krb5_init_context(3)'.
+
+Kerberos authenication context
+------------------------------
+
+Kerberos authentication context (`krb5_auth_context') holds all context
+related to an authenticated connection, in a similar way to the
+kerberos context that holds the context for the thread or process.
+
+The `krb5_auth_context' is used by various functions that are directly
+related to authentication between the server/client. Example of data
+that this structure contains are various flags, addresses of client and
+server, port numbers, keyblocks (and subkeys), sequence numbers, replay
+cache, and checksum types.
+
+See the manual page for `krb5_auth_context(3)'.
+
+Keytab management
+-----------------
+
+A keytab is a storage for locally stored keys. Heimdal includes keytab
+support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's, and
+for storing keys in memory.
+
+See also manual page for `krb5_keytab(3)'
+
+Kerberos principal
+------------------
+
+See also manual page for `krb5_principal(3)'
+
+Kerberos crypto
+---------------
+
+See also manual page for `krb5_crypto_init(3)', `krb5_keyblock(3)',
+`krb5_create_checksum(3)', and `krb5_encrypt(3)'.
+
+\1f
+File: heimdal.info,  Node: Walkthru a sample Kerberos 5 client,  Next: Validating a password in a server application,  Prev: Kerberos 5 API Overview,  Up: Programming with Kerberos
+
+Walkthru a sample Kerberos 5 client
+===================================
+
+This example contains parts of a sample TCP Kerberos 5 clients, if you
+want a real working client, please look in `appl/test' directory in the
+Heimdal distribution.
+
+All Kerberos error-codes that are returned from kerberos functions in
+this program are passed to `krb5_err', that will print a descriptive
+text of the error code and exit. Graphical programs can convert
+error-code to a humal readable error-string with the
+`krb5_get_err_text(3)' function.
+
+Note that you should not use any Kerberos function before
+`krb5_init_context()' have completed successfully. That is the reson
+`err()' is used when `krb5_init_context()' fails.
+
+First the client needs to call `krb5_init_context' to initialise the
+Kerberos 5 library. This is only needed once per thread in the program.
+If the function returns a non-zero value it indicates that either the
+Kerberos implemtation is failing or its disabled on this host.
+
+     #include <krb5.h>
+     
+     int
+     main(int argc, char **argv)
+     {
+             krb5_context context;
+     
+             if (krb5_context(&context))
+                     errx (1, "krb5_context");
+
+Now the client wants to connect to the host at the other end. The
+preferred way of doing this is using `getaddrinfo(3)' (for operating
+system that have this function implemented), since getaddrinfo is
+neutral to the address type and can use any protocol that is available.
+
+             struct addrinfo *ai, *a;
+             struct addrinfo hints;
+             int error;
+     
+             memset (&hints, 0, sizeof(hints));
+             hints.ai_socktype = SOCK_STREAM;
+             hints.ai_protocol = IPPROTO_TCP;
+     
+             error = getaddrinfo (hostname, "pop3", &hints, &ai);
+             if (error)
+                     errx (1, "%s: %s", hostname, gai_strerror(error));
+     
+             for (a = ai; a != NULL; a = a->ai_next) {
+                     int s;
+     
+                     s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+                     if (s < 0)
+                             continue;
+                     if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+                             warn ("connect(%s)", hostname);
+                                 close (s);
+                                 continue;
+                     }
+                     freeaddrinfo (ai);
+                     ai = NULL;
+             }
+             if (ai) {
+                         freeaddrinfo (ai);
+                         errx ("failed to contact %s", hostname);
+             }
+
+Before authenticating, an authentication context needs to be created.
+This context keeps all information for one (to be) authenticated
+connection (see `krb5_auth_context(3)').
+
+             status = krb5_auth_con_init (context, &auth_context);
+             if (status)
+                     krb5_err (context, 1, status, "krb5_auth_con_init");
+
+For setting the address in the authentication there is a help function
+`krb5_auth_con_setaddrs_from_fd' that does everthing that is needed
+when given a connected file descriptor to the socket.
+
+             status = krb5_auth_con_setaddrs_from_fd (context,
+                                                      auth_context,
+                                                      &sock);
+             if (status)
+                     krb5_err (context, 1, status,
+                               "krb5_auth_con_setaddrs_from_fd");
+
+The next step is to build a server principal for the service we want to
+connect to. (See also `krb5_sname_to_principal(3)'.)
+
+             status = krb5_sname_to_principal (context,
+                                               hostname,
+                                               service,
+                                               KRB5_NT_SRV_HST,
+                                               &server);
+             if (status)
+                     krb5_err (context, 1, status, "krb5_sname_to_principal");
+
+The client principal is not passed to `krb5_sendauth(3)' function, this
+causes the `krb5_sendauth' function to try to figure it out itself.
+
+The server program is using the function `krb5_recvauth(3)' to receive
+the Kerberos 5 authenticator.
+
+In this case, mutual authenication will be tried. That means that the
+server will authenticate to the client. Using mutual authenication is
+good since it enables the user to verify that they are talking to the
+right server (a server that knows the key).
+
+If you are using a non-blocking socket you will need to do all work of
+`krb5_sendauth' yourself. Basically you need to send over the
+authenticator from `krb5_mk_req(3)' and, in case of mutual
+authentication, verifying the result from the server with
+`krb5_rd_rep(3)'.
+
+             status = krb5_sendauth (context,
+                                     &auth_context,
+                                     &sock,
+                                     VERSION,
+                                     NULL,
+                                     server,
+                                     AP_OPTS_MUTUAL_REQUIRED,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL,
+                                     NULL);
+             if (status)
+                     krb5_err (context, 1, status, "krb5_sendauth");
+
+Once authentication has been performed, it is time to send some data.
+First we create a krb5_data structure, then we sign it with
+`krb5_mk_safe(3)' using the `auth_context' that contains the
+session-key that was exchanged in the
+`krb5_sendauth(3)'/`krb5_recvauth(3)' authentication sequence.
+
+             data.data   = "hej";
+             data.length = 3;
+     
+             krb5_data_zero (&packet);
+     
+             status = krb5_mk_safe (context,
+                                    auth_context,
+                                    &data,
+                                    &packet,
+                                    NULL);
+             if (status)
+                     krb5_err (context, 1, status, "krb5_mk_safe");
+
+And send it over the network.
+
+             len = packet.length;
+             net_len = htonl(len);
+     
+             if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+                     err (1, "krb5_net_write");
+             if (krb5_net_write (context, &sock, packet.data, len) != len)
+                     err (1, "krb5_net_write");
+
+To send encrypted (and signed) data `krb5_mk_priv(3)' should be used
+instead. `krb5_mk_priv(3)' works the same way as `krb5_mk_safe(3)',
+with the exception that it encrypts the data in addition to signing it.
+
+             data.data   = "hemligt";
+             data.length = 7;
+     
+             krb5_data_free (&packet);
+     
+             status = krb5_mk_priv (context,
+                                    auth_context,
+                                    &data,
+                                    &packet,
+                                    NULL);
+             if (status)
+                     krb5_err (context, 1, status, "krb5_mk_priv");
+
+And send it over the network.
+
+             len = packet.length;
+             net_len = htonl(len);
+     
+             if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+                     err (1, "krb5_net_write");
+             if (krb5_net_write (context, &sock, packet.data, len) != len)
+                     err (1, "krb5_net_write");
+
+The server is using `krb5_rd_safe(3)' and `krb5_rd_priv(3)' to verify
+the signature and decrypt the packet.
+
+\1f
+File: heimdal.info,  Node: Validating a password in a server application,  Next: API diffrences to MIT Kerberos,  Prev: Walkthru a sample Kerberos 5 client,  Up: Programming with Kerberos
+
+Validating a password in an application
+=======================================
+
+See the manual page for `krb5_verify_user(3)'.
+
+\1f
+File: heimdal.info,  Node: API diffrences to MIT Kerberos,  Prev: Validating a password in a server application,  Up: Programming with Kerberos
+
+API diffrences to MIT Kerberos
+==============================
+
+This section is somewhat disorganised, but so far there is no overall
+structure to the differences, though some of the have their root in
+that Heimdal uses an ASN.1 compiler and MIT doesn't.
+
+Principal and realms
+--------------------
+
+Heimdal stores the realm as a `krb5_realm', that is a `char *'.  MIT
+Kerberos uses a `krb5_data' to store a realm.
+
+In Heimdal `krb5_principal' doesn't contain the component `name_type';
+it's instead stored in component `name.name_type'. To get and set the
+nametype in Heimdal, use `krb5_principal_get_type(3)' and
+`krb5_principal_set_type(3)'.
+
+For more information about principal and realms, see
+`krb5_principal(3)'.
+
+Error messages
+--------------
+
+To get the error string, Heimdal uses `krb5_get_error_string(3)' or, if
+`NULL' is returned, `krb5_get_err_text(3)'. This is to return custom
+error messages (like "Can't find host/datan.example.com@EXAMPLE.COM in
+/etc/krb5.conf." instead of a "Key table entry not found" that
+`error_message(3)' returns.
+
+Heimdal uses a threadsafe(r) version of the com_err interface; the
+global `com_err' table isn't initialised.  Then `error_message(3)'
+returns quite a boring error string (just the error code itself).
+
+\1f
+File: heimdal.info,  Node: Migration,  Next: Acknowledgments,  Prev: Programming with Kerberos,  Up: Top
+
+Migration
+*********
+
+General issues
+==============
+
+When migrating from a Kerberos 4 KDC.
+
+Order in what to do things:
+===========================
+
+   * Convert the database, check all principals that hprop complains
+     about.
+
+     `hprop -n --source=<NNN>| hpropd -n'
+
+     Replace <NNN> with whatever source you have, like krb4-db or
+     krb4-dump.
+
+   * Run a Kerberos 5 slave for a while.
+
+   * Figure out if it does everything you want it to.
+
+     Make sure that all things that you use works for you.
+
+   * Let a small number of controlled users use Kerberos 5 tools.
+
+     Find a sample population of your users and check what programs
+     they use, you can also check the kdc-log to check what ticket are
+     checked out.
+
+   * Burn the bridge and change the master.
+
+   * Let all users use the Kerberos 5 tools by default.
+
+   * Turn off services that do not need Kerberos 4 authentication.
+
+     Things that might be hard to get away is old programs with support
+     for Kerberos 4. Example applications are old Eudora installations
+     using KPOP, and Zephyr. Eudora can use the Kerberos 4 kerberos in
+     the Heimdal kdc.
+
+
+\1f
+File: heimdal.info,  Node: Acknowledgments,  Prev: Migration,  Up: Top
+
+Acknowledgments
+***************
+
+Eric Young wrote "libdes". Heimdal used to use libdes, without it
+kth-krb would never have existed.
+
+All functions in libdes have been re-implemented or used available
+public domain code. The core AES function where written by Vincent
+Rijmen, Antoon Bosselaers and Paulo Barreto.  The core DES SBOX
+transformation was written by Richard Outerbridge.
+
+The University of California at Berkeley initially wrote `telnet', and
+`telnetd'.  The authentication and encryption code of `telnet' and
+`telnetd' was added by David Borman (then of Cray Research, Inc).  The
+encryption code was removed when this was exported and then added back
+by Juha Eskelinen, <esc@magic.fi>.
+
+The `popper' was also a Berkeley program initially.
+
+Some of the functions in `libroken' also come from Berkeley by way of
+NetBSD/FreeBSD.
+
+`editline' was written by Simmule Turner and Rich Salz. Heimdal
+contains a modifed copy.
+
+The `getifaddrs' implementation for Linux was written by Hideaki
+YOSHIFUJI for the Usagi project.
+
+Bugfixes, documentation, encouragement, and code has been contributed
+by:
+Derrick J Brashear
+     <shadow@dementia.org>
+
+Ken Hornstein
+     <kenh@cmf.nrl.navy.mil>
+
+Johan Ihrén
+     <johani@pdc.kth.se>
+
+Love Hörnquist Ã…strand
+     <lha@kth.se>
+
+Magnus Ahltorp
+     <map@stacken.kth.se>
+
+Mark Eichin
+     <eichin@cygnus.com>
+
+Marc Horowitz
+     <marc@cygnus.com>
+
+Luke Howard
+     <lukeh@PADL.COM>
+
+Brandon S. Allbery KF8NH
+     <allbery@kf8nh.apk.net>
+
+Jun-ichiro itojun Hagino
+     <itojun@kame.net>
+
+Daniel Kouril
+     <kouril@informatics.muni.cz>
+
+Ã…ke Sandgren
+     <ake@cs.umu.se>
+
+Michal Vocu
+     <michal@karlin.mff.cuni.cz>
+
+Miroslav Ruda
+     <ruda@ics.muni.cz>
+
+Brian A May
+     <bmay@snoopy.apana.org.au>
+
+Chaskiel M Grundman
+     <cg2v@andrew.cmu.edu>
+
+Richard Nyberg
+     <rnyberg@it.su.se>
+
+Frank van der Linden
+     <fvdl@netbsd.org>
+
+Cizzi Storm
+     <cizzi@it.su.se>
+
+Petr Holub
+     <Holub.Petr@atlas.cz>
+
+Mario Strasser
+     <mario.strasser@zhwin.ch>
+
+David Love
+     <fx@gnu.org>
+
+and we hope that those not mentioned here will forgive us.
+All bugs were introduced by ourselves.
+
+
diff --git a/src/kerberosV/src/doc/heimdal.texi b/src/kerberosV/src/doc/heimdal.texi
new file mode 100644 (file)
index 0000000..de635c6
--- /dev/null
@@ -0,0 +1,206 @@
+\input texinfo @c -*- texinfo -*-
+@c %**start of header
+@c $KTH: heimdal.texi,v 1.22 2005/04/24 09:18:32 lha Exp $
+@setfilename heimdal.info
+@settitle HEIMDAL
+@iftex
+@afourpaper
+@end iftex
+@c some sensible characters, please?
+@tex
+\input latin1.tex
+@end tex
+@setchapternewpage on
+@syncodeindex pg cp
+@c %**end of header
+
+@c @include version.texi
+@set UPDATED $Date: 2006/04/14 08:15:03 $
+@set EDITION 0.1
+@set VERSION 0.7
+
+@ifinfo
+@dircategory Heimdal
+@direntry
+* Heimdal: (heimdal).           The Kerberos 5 distribution from KTH
+@end direntry
+@end ifinfo
+
+@c title page
+@titlepage
+@title Heimdal
+@subtitle Kerberos 5 from KTH
+@subtitle Edition @value{EDITION}, for version @value{VERSION}
+@subtitle 2004
+@author Johan Danielsson
+@author Love Hörnquist Ã…strand
+@author Assar Westerlund
+@author last updated @value{UPDATED}
+
+@def@copynext{@vskip 20pt plus 1fil@penalty-1000}
+@def@copyrightstart{}
+@def@copyrightend{}
+@page
+@copyrightstart
+Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+@copynext
+
+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.  M.I.T. makes no representations about the suitability of
+this software for any purpose.  It is provided "as is" without express
+or implied warranty.
+
+@copynext
+
+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. 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.
+
+@copynext
+
+Copyright 1992 Simmule Turner and Rich Salz.  All rights reserved. 
+
+This software is not subject to any license of the American Telephone 
+and Telegraph Company or of the Regents of the University of California. 
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it freely, subject
+to the following restrictions:
+
+1. The authors are not responsible for the consequences of use of this
+   software, no matter how awful, even if they arise from flaws in it.
+
+2. The origin of this software must not be misrepresented, either by
+   explicit claim or by omission.  Since few users ever read sources,
+   credits must appear in the documentation.
+
+3. Altered versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.  Since few users
+   ever read sources, credits must appear in the documentation.
+
+4. This notice may not be removed or altered.
+
+@copyrightend
+@end titlepage
+
+@macro manpage{man, section}
+@cite{\man\(\section\)}
+@end macro
+
+@c Less filling! Tastes great!
+@iftex
+@parindent=0pt
+@global@parskip 6pt plus 1pt
+@global@chapheadingskip = 15pt plus 4pt minus 2pt 
+@global@secheadingskip = 12pt plus 3pt minus 2pt
+@global@subsecheadingskip = 9pt plus 2pt minus 2pt
+@end iftex
+@ifinfo
+@paragraphindent 0
+@end ifinfo
+
+@ifnottex
+@node Top, Introduction, (dir), (dir)
+@top Heimdal
+@end ifnottex
+
+@menu
+* Introduction::                
+* What is Kerberos?::           
+* Building and Installing::     
+* Setting up a realm::          
+* Applications::          
+* Things in search for a better place::  
+* Kerberos 4 issues::           
+* Windows 2000 compatability::
+* Programming with Kerberos::
+* Migration::
+* Acknowledgments::             
+
+@end menu
+
+@include intro.texi
+@include whatis.texi
+@include install.texi
+@include setup.texi
+@include apps.texi
+@include misc.texi
+@include kerberos4.texi
+@include win2k.texi
+@include programming.texi
+@include migration.texi
+@include ack.texi
+
+@c @shortcontents
+@contents
+
+@bye
diff --git a/src/kerberosV/src/doc/init-creds b/src/kerberosV/src/doc/init-creds
new file mode 100644 (file)
index 0000000..8892d29
--- /dev/null
@@ -0,0 +1,374 @@
+Currently, getting an initial ticket for a user involves many function
+calls, especially when a full set of features including password
+expiration and challenge preauthentication is desired.  In order to
+solve this problem, a new api is proposed.
+
+typedef struct _krb5_prompt {
+    char *prompt;
+    int hidden;
+    krb5_data *reply;
+} krb5_prompt;
+
+typedef int (*krb5_prompter_fct)(krb5_context context,
+                                void *data,
+                                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;
+       /* XXX the next three should not be used, as they may be
+       removed later */
+    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
+
+void krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt);
+
+void krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt,
+                                         krb5_deltat tkt_life);
+void krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt,
+                                           krb5_deltat renew_life);
+void krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt,
+                                            int forwardable);
+void krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt,
+                                          int proxiable);
+void krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt,
+                                           krb5_enctype *etype_list,
+                                           int etype_list_length);
+void krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt,
+                                             krb5_address **addresses);
+void krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
+                                             krb5_preauthtype *preauth_list,
+                                             int preauth_list_length);
+void krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt,
+                                     krb5_data *salt);
+
+krb5_error_code
+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);
+
+This function will attempt to acquire an initial ticket.  The function
+will perform whatever tasks are necessary to do so.  This may include
+changing an expired password, preauthentication.
+
+The arguments divide into two types.  Some arguments are basically
+invariant and arbitrary across all initial tickets, and if not
+specified are determined by configuration or library defaults.  Some
+arguments are different for each execution or application, and if not
+specified can be determined correctly from system configuration or
+environment.  The former arguments are contained in a structure whose
+pointer is passed to the function.  A bitmask specifies which elements
+of the structure should be used.  In most cases, a NULL pointer can be
+used.  The latter arguments are specified as individual arguments to
+the function.
+
+If a pointer to a credential is specified, the initial credential is
+filled in.  If the caller only wishes to do a simple password check
+and will not be doing any other kerberos functions, then a NULL
+pointer may be specified, and the credential will be destroyed.
+
+If the client name is non-NULL, the initial ticket requested will be
+for that principal.  Otherwise, the principal will be the username
+specified by the USER environment variable, or if the USER environment
+variable is not set, the username corresponding to the real user id of
+the caller.
+
+If the password is non-NULL, then this string is used as the password.
+Otherwise, the prompter function will be used to prompt the user for
+the password.
+
+If a prompter function is non-NULL, it will be used if additional user
+input is required, such as if the user's password has expired and
+needs to be changed, or if input preauthentication is necessary.  If
+no function is specified and input is required, then the login will
+fail.
+
+       The context argument is the same as that passed to krb5_login.
+       The data argument is passed unmodified to the prompter
+       function and is intended to be used to pass application data
+       (such as a display handle) to the prompter function.
+
+       The banner argument, if non-NULL, will indicate what sort of
+       input is expected from the user (for example, "Password has
+       expired and must be changed" or "Enter Activcard response for
+       challenge 012345678"), and should be displayed accordingly.
+       
+       The num_prompts argument indicates the number of values which
+       should be prompted for.  If num_prompts == 0, then the banner
+       contains an informational message which should be displayed to
+       the user.
+
+       The prompts argument contains an array describing the values
+       for which the user should be prompted.  The prompt member
+       indicates the prompt for each value ("Enter new
+       password"/"Enter it again", or "Challenge response").  The
+       hidden member is nonzero if the response should not be
+       displayed back to the user.  The reply member is a pointer to
+       krb5_data structure which has already been allocated.  The
+       prompter should fill in the structure with the NUL-terminated
+       response from the user.
+
+       If the response data does not fit, or if any other error
+       occurs, then the prompter function should return a non-zero
+       value which will be returned by the krb5_get_init_creds
+       function. Otherwise, zero should be returned.
+
+       The library function krb5_prompter_posix() implements
+       a prompter using a posix terminal for user in.  This function
+       does not use the data argument.
+
+If the start_time is zero, then the requested ticket will be valid
+beginning immediately.  Otherwise, the start_time indicates how far in
+the future the ticket should be postdated.
+
+If the in_tkt_service name is non-NULL, that principal name will be
+used as the server name for the initial ticket request.  The realm of
+the name specified will be ignored and will be set to the realm of the
+client name.  If no in_tkt_service name is specified,
+krbtgt/CLIENT-REALM@CLIENT-REALM will be used.
+
+For the rest of arguments, a configuration or library default will be
+used if no value is specified in the options structure.
+
+If a tkt_life is specified, that will be the lifetime of the ticket.
+The library default is 10 hours; there is no configuration variable
+(there should be, but it's not there now).
+
+If a renew_life is specified and non-zero, then the RENEWABLE option
+on the ticket will be set, and the value of the argument will be the
+the renewable lifetime.  The configuration variable [libdefaults]
+"renew_lifetime" is the renewable lifetime if none is passed in.  The
+library default is not to set the RENEWABLE option.
+
+If forwardable is specified, the FORWARDABLE option on the ticket will
+be set if and only if forwardable is non-zero.  The configuration
+variable [libdefaults] "forwardable" is used if no value is passed in.
+The option will be set if and only if the variable is "y", "yes",
+"true", "t", "1", or "on", case insensitive.  The library default is
+not to set the FORWARDABLE option.
+
+If proxiable is specified, the PROXIABLE option on the ticket will be
+set if and only if proxiable is non-zero.  The configuration variable
+[libdefaults] "proxiable" is used if no value is passed in.  The
+option will be set if and only if the variable is "y", "yes", "true",
+"t", "1", or "on", case insensitive.  The library default is not to
+set the PROXIABLE option.
+
+If etype_list is specified, it will be used as the list of desired
+encryption algorithms in the request.  The configuration variable
+[libdefaults] "default_tkt_enctypes" is used if no value is passed in.
+The library default is "des-cbc-md5 des-cbc-crc".
+
+If address_list is specified, it will be used as the list of addresses
+for which the ticket will be valid.  The library default is to use all
+local non-loopback addresses.  There is no configuration variable.
+
+If preauth_list is specified, it names preauth data types which will
+be included in the request.  The library default is to interact with
+the kdc to determine the required preauth types.  There is no
+configuration variable.
+
+If salt is specified, it specifies the salt which will be used when
+converting the password to a key.  The library default is to interact
+with the kdc to determine the correct salt.  There is no configuration
+variable.
+
+================================================================
+
+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_verify_init_creds_opt_init(krb5_init_creds_opt *options);
+void krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_init_creds_opt *options,
+                                                 int ap_req_nofail);
+
+krb5_error_code
+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 *options);
+
+This function will use the initial ticket in creds to make an AP_REQ
+and verify it to insure that the AS_REP has not been spoofed.
+
+If the ap_req_server name is non-NULL, then this service name will be
+used for the AP_REQ; otherwise, the default host key
+(host/hostname.domain@LOCAL-REALM) will be used.
+
+If ap_req_keytab is non-NULL, the service key for the verification
+will be read from that keytab; otherwise, the service key will be read
+from the default keytab. 
+
+If the service of the ticket in creds is the same as the service name
+for the AP_REQ, then this ticket will be used directly.  If the ticket
+is a tgt, then it will be used to obtain credentials for the service.
+Otherwise, the verification will fail, and return an error.
+
+Other failures of the AP_REQ verification may or may not be considered
+errors, as described below.
+
+If a pointer to a credential cache handle is specified, and the handle
+is NULL, a credential cache handle referring to all credentials
+obtained in the course of verifying the user will be returned.  In
+order to avoid potential setuid race conditions and other problems
+related to file system access, this handle will refer to a memory
+credential cache.  If the handle is non-NULL, then the credentials
+will be added to the existing ccache.  If the caller only wishes to
+verify the password and will not be doing any other kerberos
+functions, then a NULL pointer may be specified, and the credentials
+will be deleted before the function returns.
+
+If ap_req_nofail is specified, then failures of the AP_REQ
+verification are considered errors if and only if ap_req_nofail is
+non-zero.
+
+Whether or not AP_REQ validation is performed and what failures mean
+depends on these inputs:
+
+ A) The appropriate keytab exists and contains the named key.
+
+ B) An AP_REQ request to the kdc succeeds, and the resulting AP_REQ
+can be decrypted and verified.
+
+ C) The administrator has specified in a configuration file that
+AP_REQ validation must succeed.  This is basically a paranoid bit, and
+can be overridden by the application based on a command line flag or
+other application-specific info.  This flag is especially useful if
+the admin is concerned that DNS might be spoofed while determining the
+host/FQDN name.  The configuration variable [libdefaults]
+"verify_ap_req_nofail" is used if no value is passed in.  The library
+default is not to set this option.
+
+Initial ticket verification will succeed if and only if:
+
+ - A && B    or
+ - !A && !C
+
+================================================================
+
+For illustrative purposes, here's the invocations I expect some
+programs will use.  Of course, error checking needs to be added.
+
+kinit:
+
+    /* Fill in client from the command line || existing ccache, and,
+       start_time, and options.{tkt_life,renew_life,forwardable,proxiable}
+       from the command line.  Some or all may remain unset. */
+
+    krb5_get_init_creds(context, &creds, client,
+                       krb5_initial_prompter_posix, NULL,
+                       start_time, NULL, &options);
+    krb5_cc_store_cred(context, ccache, &creds);
+    krb5_free_cred_contents(context, &creds);
+
+login:
+
+    krb5_get_init_creds(context, &creds, client,
+                       krb5_initial_prompter_posix, NULL,
+                       0, NULL, NULL);
+    krb5_verify_init_creds(context, &creds, NULL, NULL, &vcc, NULL);
+    /* setuid */
+    krb5_cc_store_cred(context, ccache, &creds);
+    krb5_cc_copy(context, vcc, ccache);
+    krb5_free_cred_contents(context, &creds);
+    krb5_cc_destroy(context, vcc);
+
+xdm:
+
+    krb5_get_initial_creds(context, &creds, client,
+                          krb5_initial_prompter_xt, (void *) &xtstuff,
+                          0, NULL, NULL);
+    krb5_verify_init_creds(context, &creds, NULL, NULL, &vcc, NULL);
+    /* setuid */
+    krb5_cc_store_cred(context, ccache, &creds);
+    krb5_free_cred_contents(context, &creds);
+    krb5_cc_copy(context, vcc, ccache);
+    krb5_cc_destroy(context, vcc);
+
+passwd:
+
+    krb5_init_creds_opt_init(&options);
+    krb5_init_creds_opt_set_tkt_life = 300;
+    krb5_get_initial_creds(context, &creds, client,
+                          krb5_initial_prompter_posix, NULL,
+                          0, "kadmin/changepw", &options);
+    /* change password */
+    krb5_free_cred_contents(context, &creds);
+
+pop3d (simple password validator when no user interation possible):
+
+    krb5_get_initial_creds(context, &creds, client,
+                          NULL, NULL, 0, NULL, NULL);
+    krb5_verify_init_creds(context, &creds, NULL, NULL, &vcc, NULL);
+    krb5_cc_destroy(context, vcc);
+
+================================================================
+
+password expiration has a subtlety.  When a password expires and is
+changed, there is a delay between when the master gets the new key
+(immediately), and the slaves (propogation interval).  So, when
+getting an in_tkt, if the password is expired, the request should be
+reissued to the master (this kind of sucks if you have SAM, oh well).
+If this says expired, too, then the password should be changed, and
+then the initial ticket request should be issued to the master again.
+If the master times out, then a message that the password has expired
+and cannot be changed due to the master being unreachable should be
+displayed.
+
+================================================================
+
+get_init_creds reads config stuff from:
+
+[libdefaults]
+       varname1 = defvalue
+       REALM = {
+               varname1 = value
+               varname2 = value
+       }
+
+typedef struct _krb5_get_init_creds_opt {
+    krb5_flags flags;
+    krb5_deltat tkt_life;      /* varname = "ticket_lifetime" */
+    krb5_deltat renew_life;    /* varname = "renew_lifetime" */
+    int forwardable;           /* varname = "forwardable" */
+    int proxiable;             /* varname = "proxiable" */
+    krb5_enctype *etype_list;  /* varname = "default_tkt_enctypes" */
+    int etype_list_length;
+    krb5_address **address_list; /* no varname */
+    krb5_preauthtype *preauth_list; /* no varname */
+    int preauth_list_length;
+    krb5_data *salt;
+} krb5_get_init_creds_opt;
+
+
diff --git a/src/kerberosV/src/doc/install.texi b/src/kerberosV/src/doc/install.texi
new file mode 100644 (file)
index 0000000..c584ac8
--- /dev/null
@@ -0,0 +1,106 @@
+@c $KTH: install.texi,v 1.19 2003/07/18 08:04:58 lha Exp $
+
+@node Building and Installing, Setting up a realm, What is Kerberos?, Top
+@comment  node-name,  next,  previous,  up
+@chapter Building and Installing
+
+Heimdal uses GNU Autoconf to configure for specific hosts, and GNU
+Automake to manage makefiles. If this is new to you, the short
+instruction is to run the @code{configure} script in the top level
+directory, and when that finishes @code{make}.
+
+If you want to build the distribution in a different directory from the
+source directory, you will need a make that implements VPATH correctly,
+such as GNU make.
+
+You will need to build the distribution:
+
+@itemize @bullet
+@item
+A compiler that supports a ``loose'' ANSI C mode, such as @code{gcc}.
+@item
+lex or flex
+@item
+awk
+@item
+yacc or bison
+@item
+a socket library
+@item
+NDBM or Berkeley DB for building the server side.
+@end itemize
+
+When everything is built, you can install by doing @kbd{make
+install}. The default location for installation is @file{/usr/heimdal},
+but this can be changed by running @code{configure} with
+@samp{--prefix=/some/other/place}.
+
+If you need to change the default behavior, configure understands the
+following options:
+
+@table @asis
+@item @kbd{--without-berkeley-db}
+DB is preferred before NDBM, but if you for some reason want to use NDBM
+instead, you can use this option.
+
+@item @kbd{--with-krb4=@file{dir}}
+Gives the location of Kerberos 4 libraries and headers. This enables
+Kerberos 4 support in the applications (telnet, rsh, popper, etc) and
+the KDC. It is automatically check for in @file{/usr/athena}. If you
+keep libraries and headers in different places, you can instead give the
+path to each with the @kbd{--with-krb4-lib=@file{dir}}, and
+@kbd{--with-krb4-include=@file{dir}} options.
+
+You will need a fairly recent version of our Kerberos 4 distribution for
+@code{rshd} and @code{popper} to support version 4 clients.
+
+@item @kbd{--enable-dce}
+Enables support for getting DCE credentials and tokens.  See the README
+files in @file{appl/dceutils} for more information.
+
+@item @kbd{--disable-otp}
+By default some of the application programs will build with support for
+one-time passwords (OTP).  Use this option to disable that support.
+
+@item @kbd{--enable-osfc2}
+Enable some C2 support for OSF/Digital Unix/Tru64.  Use this option if
+you are running your OSF operating system in C2 mode.
+
+@item @kbd{--with-readline=@file{dir}}
+Gives the path for the GNU Readline library, which will be used in some
+programs. If no readline library is found, the (simpler) editline
+library will be used instead.
+
+@item @kbd{--with-hesiod=@file{dir}}
+Enables hesiod support in push.
+
+@item @kbd{--enable-netinfo}
+Add support for using netinfo to lookup configuration information.
+Probably only useful (and working) on NextStep/Mac OS X.
+
+@item @kbd{--without-ipv6}
+Disable the IPv6 support.
+
+@item @kbd{--with-openldap}
+Compile Heimdal with support for storing the database in LDAP.  Requires
+OpenLDAP @url{http://www.openldap.org}.  See
+@url{http://www.padl.com/Research/Heimdal.html} for more information.
+
+@item @kbd{--enable-bigendian}
+@item @kbd{--enable-littleendian}
+Normally, the build process will figure out by itself if the machine is
+big or little endian.  It might fail in some cases when
+cross-compiling.  If it does fail to figure it out, use the relevant of
+these two options.
+
+@item @kbd{--with-mips-abi=@var{abi}}
+On Irix there are three different ABIs that can be used (@samp{32},
+@samp{n32}, or @samp{64}).  This option allows you to override the
+automatic selection.
+
+@item @kbd{--disable-mmap}
+Do not use the mmap system call.  Normally, configure detects if there
+is a working mmap and it is only used if there is one.  Only try this
+option if it fails to work anyhow.
+
+@end table
diff --git a/src/kerberosV/src/doc/intro.texi b/src/kerberosV/src/doc/intro.texi
new file mode 100644 (file)
index 0000000..f4717d0
--- /dev/null
@@ -0,0 +1,101 @@
+@c $KTH: intro.texi,v 1.13 2003/03/15 13:42:16 lha Exp $
+
+@node Introduction, What is Kerberos?, Top, Top
+@c @node Introduction, What is Kerberos?, Top, Top
+@comment  node-name,  next,  previous,  up
+@chapter Introduction
+
+@heading What is Heimdal?
+
+Heimdal is a free implementation of Kerberos 5. The goals are to:
+
+@itemize @bullet
+@item
+have an implementation that can be freely used by anyone
+@item
+be protocol compatible with existing implementations and, if not in
+conflict, with RFC 1510 (and any future updated RFC)
+@item
+be reasonably compatible with the M.I.T Kerberos V5 API
+@item
+have support for Kerberos V5 over GSS-API (RFC1964)
+@item
+include the most important and useful application programs (rsh, telnet,
+popper, etc.)
+@item
+include enough backwards compatibility with Kerberos V4
+@end itemize
+
+@heading Status
+
+Heimdal has the following features (this does not mean any of this
+works):
+
+@itemize @bullet
+@item
+a stub generator and a library to encode/decode/whatever ASN.1/DER
+stuff
+@item
+a @code{libkrb5} library that should be possible to get to work with
+simple applications
+@item
+a GSS-API library that should have all the important functions for
+building applications
+@item
+Eric Young's @file{libdes}
+@item
+@file{kinit}, @file{klist}, @file{kdestroy}
+@item
+@file{telnet}, @file{telnetd}
+@item
+@file{rsh}, @file{rshd}
+@item
+@file{popper}, @file{push} (a movemail equivalent)
+@item
+@file{ftp}, and @file{ftpd}
+@item
+a library @file{libkafs} for authenticating to AFS and a program
+@file{afslog} that uses it
+@item
+some simple test programs
+@item
+a KDC that supports most things; optionally, it may also support
+Kerberos V4 and kaserver,
+@item
+simple programs for distributing databases between a KDC master and
+slaves
+@item
+a password changing daemon @file{kpasswdd}, library functions for
+changing passwords and a simple client
+@item
+some kind of administration system
+@item
+Kerberos V4 support in many of the applications.
+@end itemize
+
+@heading Bug reports
+
+If you find bugs in this software, make sure it is a genuine bug and not
+just a part of the code that isn't implemented.
+
+Bug reports should be sent to @email{heimdal-bugs@@pdc.kth.se}. Please
+include information on what machine and operating system (including
+version) you are running, what you are trying to do, what happens, what
+you think should have happened, an example for us to repeat, the output
+you get when trying the example, and a patch for the problem if you have
+one. Please make any patches with @code{diff -u} or @code{diff -c}.
+
+Suggestions, comments and other non bug reports are also welcome.
+
+@heading Mailing list
+
+There are two mailing lists with talk about
+Heimdal. @email{heimdal-announce@@sics.se} is a low-volume announcement
+list, while @email{heimdal-discuss@@sics.se} is for general discussion.
+Send a message to @email{majordomo@@sics.se} to subscribe.
+
+@heading Heimdal source code, binaries and the manual
+
+The source code for heimdal, links to binaries and the manual (this
+document) can be found on our web-page at
+@url{http://www.pdc.kth.se/heimdal/}.
diff --git a/src/kerberosV/src/doc/kerberos4.texi b/src/kerberosV/src/doc/kerberos4.texi
new file mode 100644 (file)
index 0000000..8539e32
--- /dev/null
@@ -0,0 +1,226 @@
+@c $KTH: kerberos4.texi,v 1.16 2001/07/19 17:17:46 assar Exp $
+
+@node Kerberos 4 issues, Windows 2000 compatability, Things in search for a better place, Top
+@comment  node-name,  next,  previous,  up
+@chapter Kerberos 4 issues
+
+If compiled with version 4 support, the KDC can serve requests from a
+Kerberos 4 client. There are a few things you must do for this to work.
+
+The KDC will also have kaserver emulation and be able to handle
+AFS-clients that use @code{klog}.
+
+@menu
+* Principal conversion issues::  
+* Converting a version 4 database::  
+* kaserver::
+@end menu
+
+@node Principal conversion issues, Converting a version 4 database, Kerberos 4 issues, Kerberos 4 issues
+@section Principal conversion issues
+
+First, Kerberos 4 and Kerberos 5 principals are different. A version 4
+principal consists of a name, an instance, and a realm. A version 5
+principal has one or more components, and a realm (the terms ``name''
+and ``instance'' are still used, for the first and second component,
+respectively).    Also, in some cases the name of a version 4 principal
+differs from the first component of the corresponding version 5
+principal. One notable example is the ``host'' type principals, where
+the version 4 name is @samp{rcmd} (for ``remote command''), and the
+version 5 name is @samp{host}. For the class of principals that has a
+hostname as instance, there is an other major difference, Kerberos 4
+uses only the first component of the hostname, whereas Kerberos 5 uses
+the fully qualified hostname.
+
+Because of this it can be hard or impossible to correctly convert a
+version 4 principal to a version 5 principal @footnote{the other way is
+not always trivial either, but usually easier}. The biggest problem is
+to know if the conversion resulted in a valid principal. To give an
+example, suppose you want to convert the principal @samp{rcmd.foo}.
+
+The @samp{rcmd} name suggests that the instance is a hostname (even if
+there are exceptions to this rule). To correctly convert the instance
+@samp{foo} to a hostname, you have to know which host it is referring
+to. You can to this by either guessing (from the realm) which domain
+name to append, or you have to have a list of possible hostnames. In the
+simplest cases you can cover most principals with the first rule. If you
+have several domains sharing a single realm this will not usually
+work. If the exceptions are few you can probably come by with a lookup
+table for the exceptions.
+
+In a complex scenario you will need some kind of host lookup mechanism.
+Using DNS for this is tempting, but DNS is error prone, slow and unsafe
+@footnote{at least until secure DNS is commonly available}.
+
+Fortunately, the KDC has a trump on hand: it can easily tell if a
+principal exists in the database. The KDC will use
+@code{krb5_425_conv_principal_ext} to convert principals when handling
+to version 4 requests.
+
+@node Converting a version 4 database, kaserver , Principal conversion issues, Kerberos 4 issues
+@section Converting a version 4 database
+
+If you want to convert an existing version 4 database, the principal
+conversion issue arises too.
+
+If you decide to convert your database once and for all, you will only
+have to do this conversion once. It is also possible to run a version 5
+KDC as a slave to a version 4 KDC. In this case this conversion will
+happen every time the database is propagated.  When doing this
+conversion, there are a few things to look out for. If you have stale
+entries in the database, these entries will not be converted. This might
+be because these principals are not used anymore, or it might be just
+because the principal couldn't be converted.
+
+You might also see problems with a many-to-one mapping of
+principals. For instance, if you are using DNS lookups and you have two
+principals @samp{rcmd.foo} and @samp{rcmd.bar}, where `foo' is a CNAME
+for `bar', the resulting principals will be the same. Since the
+conversion function can't tell which is correct, these conflicts will
+have to be resolved manually.
+
+@subsection Conversion example
+
+Given the following set of hosts and services:
+
+@example
+foo.se          rcmd
+mail.foo.se     rcmd, pop
+ftp.bar.se      rcmd, ftp
+@end example
+
+you have a database that consists of the following principals:
+
+@samp{rcmd.foo}, @samp{rcmd.mail}, @samp{pop.mail}, @samp{rcmd.ftp}, and
+@samp{ftp.ftp}.
+
+lets say you also got these extra principals: @samp{rcmd.gone},
+@samp{rcmd.old-mail}, where @samp{gone.foo.se} was a machine that has
+now passed away, and @samp{old-mail.foo.se} was an old mail machine that
+is now a CNAME for @samp{mail.foo.se}.
+
+When you convert this database you want the following conversions to be
+done:
+@example
+rcmd.foo         host/foo.se
+rcmd.mail        host/mail.foo.se
+pop.mail         pop/mail.foo.se
+rcmd.ftp         host/ftp.bar.se
+ftp.ftp          ftp/ftp.bar.se
+rcmd.gone        @i{removed}
+rcmd.old-mail    @i{removed}
+@end example
+
+A @file{krb5.conf} that does this looks like:
+
+@example
+[realms]
+        FOO.SE = @{
+                v4_name_convert = @{
+                        host = @{
+                                ftp = ftp
+                                pop = pop
+                                rcmd = host
+                        @}
+                @}
+                v4_instance_convert = @{
+                        foo = foo.se
+                        ftp = ftp.bar.se
+                @}
+                default_domain = foo.se
+        @}
+@end example
+
+The @samp{v4_name_convert} section says which names should be considered
+having an instance consisting of a hostname, and it also says how the
+names should be converted (for instance @samp{rcmd} should be converted
+to @samp{host}). The @samp{v4_instance_convert} section says how a
+hostname should be qualified (this is just a hosts-file in
+disguise). Host-instances that aren't covered by
+@samp{v4_instance_convert} are qualified by appending the contents of
+the @samp{default_domain}.
+
+Actually, this example doesn't work. Or rather, it works to well. Since
+it has no way of knowing which hostnames are valid and which are not, it
+will happily convert @samp{rcmd.gone} to @samp{host/gone.foo.se}. This
+isn't a big problem, but if you have run your kerberos realm for a few
+years, chances are big that you have quite a few `junk' principals.
+
+If you don't want this you can remove the @samp{default_domain}
+statement, but then you will have to add entries for @emph{all} your hosts
+in the @samp{v4_instance_convert} section.
+
+Instead of doing this you can use DNS to convert instances. This is not
+a solution without problems, but it is probably easier than adding lots
+of static host entries. 
+
+To enable DNS lookup you should turn on @samp{v4_instance_resolve} in
+the @samp{[libdefaults]} section.
+
+@subsection Converting a database
+
+The database conversion is done with @samp{hprop}. You can run this
+command to propagate the database to the machine called
+@samp{slave-server} (which should be running a @samp{hpropd}).
+
+@example
+hprop --source=krb4-db --master-key=/.m slave-server
+@end example
+
+This command can also be to use for converting the v4 database on the
+server:
+
+@example
+hprop -n --source=krb4-db -d /var/kerberos/principal --master-key=/.m | hpropd -n
+@end example
+
+@section Version 4 Kadmin
+
+@samp{kadmind} can act as a version 4 kadmind, and you can do most
+operations, but with some restrictions (since the version 4 kadmin
+protocol is, lets say, very ad hoc.) One example is that it only passes
+des keys when creating principals and changing passwords (modern kpasswd
+clients do send the password, so it's possible to to password quality
+checks). Because of this you can only create principals with des keys,
+and you can't set any flags or do any other fancy stuff.
+
+To get this to work, you have to add another entry to inetd (since
+version 4 uses port 751, not 749).
+
+@emph{And then there are a many more things you can do; more on this in
+a later version of this manual. Until then, UTSL.}
+
+@node kaserver, , Converting a version 4 database, Kerberos 4 issues
+@section kaserver
+
+@subsection kaserver emulation
+
+The Heimdal kdc can emulate a kaserver. The kaserver is a Kerberos 4
+server with pre-authentication using Rx as the on-wire protocol. The kdc
+contains a minimalistic Rx implementation.
+
+There are three parts of the kaserver; KAA (Authentication), KAT (Ticket
+Granting), and KAM (Maintenance). The KAA interface and KAT interface
+both passes over DES encrypted data-blobs (just like the
+Kerberos-protocol) and thus do not need any other protection.  The KAM
+interface uses @code{rxkad} (Kerberos authentication layer for Rx) for
+security and data protection, and is used for example for changing
+passwords.  This part is not implemented in the kdc.
+
+Another difference between the ka-protocol and the Kerberos 4 protocol
+is that the pass-phrase is salted with the cellname in the @code{string to
+key} function in the ka-protocol, while in the Kerberos 4 protocol there
+is no salting of the password at all. To make sure AFS-compatible keys
+are added to each principals when they are created or their password are
+changed, @samp{afs3-salt} should be added to
+@samp{[kadmin]default_keys}.
+
+@subsection Transarc AFS Windows client
+
+The Transarc Windows client uses Kerberos 4 to obtain tokens, and thus
+does not need a kaserver. The Windows client assumes that the Kerberos
+server is on the same machine as the AFS-database server. If you do not
+like to do that you can add a small program that runs on the database
+servers that forward all kerberos requests to the real kerberos
+server. A program that does this is @code{krb-forward}
+(@url{ftp://ftp.stacken.kth.se/pub/projekts/krb-forward}).
diff --git a/src/kerberosV/src/doc/latin1.tex b/src/kerberosV/src/doc/latin1.tex
new file mode 100644 (file)
index 0000000..e683dd2
--- /dev/null
@@ -0,0 +1,95 @@
+% ISO Latin 1 (ISO 8859/1) encoding for Computer Modern fonts.
+% Jan Michael Rynning <jmr@nada.kth.se> 1990-10-12
+\def\inmathmode#1{\relax\ifmmode#1\else$#1$\fi}
+\global\catcode`\^^a0=\active \global\let^^a0=~                % no-break space
+\global\catcode`\^^a1=\active \global\def^^a1{!`}              % inverted exclamation mark
+\global\catcode`\^^a2=\active \global\def^^a2{{\rm\rlap/c}}    % cent sign
+\global\catcode`\^^a3=\active \global\def^^a3{{\it\$}} % pound sign
+% currency sign, yen sign, broken bar
+\global\catcode`\^^a7=\active \global\let^^a7=\S               % section sign
+\global\catcode`\^^a8=\active \global\def^^a8{\"{}}            % diaeresis
+\global\catcode`\^^a9=\active \global\let^^a9=\copyright       % copyright sign
+% feminine ordinal indicator, left angle quotation mark
+\global\catcode`\^^ac=\active \global\def^^ac{\inmathmode\neg}% not sign
+\global\catcode`\^^ad=\active \global\let^^ad=\-               % soft hyphen
+% registered trade mark sign
+\global\catcode`\^^af=\active \global\def^^af{\={}}            % macron
+% ...
+\global\catcode`\^^b1=\active \global\def^^b1{\inmathmode\pm}  % plus minus
+\global\catcode`\^^b2=\active \global\def^^b2{\inmathmode{{^2}}}
+\global\catcode`\^^b3=\active \global\def^^b3{\inmathmode{{^3}}}
+\global\catcode`\^^b4=\active \global\def^^b4{\'{}}            % acute accent
+\global\catcode`\^^b5=\active \global\def^^b5{\inmathmode\mu}  % mu
+\global\catcode`\^^b6=\active \global\let^^b6=\P               % pilcroy
+\global\catcode`\^^b7=\active \global\def^^b7{\inmathmode{{\cdot}}}
+\global\catcode`\^^b8=\active \global\def^^b8{\c{}}            % cedilla
+\global\catcode`\^^b9=\active \global\def^^b9{\inmathmode{{^1}}}
+% ...
+\global\catcode`\^^bc=\active \global\def^^bc{\inmathmode{{1\over4}}}
+\global\catcode`\^^bd=\active \global\def^^bd{\inmathmode{{1\over2}}}
+\global\catcode`\^^be=\active \global\def^^be{\inmathmode{{3\over4}}}
+\global\catcode`\^^bf=\active \global\def^^bf{?`}              % inverted question mark
+\global\catcode`\^^c0=\active \global\def^^c0{\`A}
+\global\catcode`\^^c1=\active \global\def^^c1{\'A}
+\global\catcode`\^^c2=\active \global\def^^c2{\^A}
+\global\catcode`\^^c3=\active \global\def^^c3{\~A}
+\global\catcode`\^^c4=\active \global\def^^c4{\"A}             % capital a with diaeresis
+\global\catcode`\^^c5=\active \global\let^^c5=\AA              % capital a with ring above
+\global\catcode`\^^c6=\active \global\let^^c6=\AE
+\global\catcode`\^^c7=\active \global\def^^c7{\c C}
+\global\catcode`\^^c8=\active \global\def^^c8{\`E}
+\global\catcode`\^^c9=\active \global\def^^c9{\'E}
+\global\catcode`\^^ca=\active \global\def^^ca{\^E}
+\global\catcode`\^^cb=\active \global\def^^cb{\"E}
+\global\catcode`\^^cc=\active \global\def^^cc{\`I}
+\global\catcode`\^^cd=\active \global\def^^cd{\'I}
+\global\catcode`\^^ce=\active \global\def^^ce{\^I}
+\global\catcode`\^^cf=\active \global\def^^cf{\"I}
+% capital eth
+\global\catcode`\^^d1=\active \global\def^^d1{\~N}
+\global\catcode`\^^d2=\active \global\def^^d2{\`O}
+\global\catcode`\^^d3=\active \global\def^^d3{\'O}
+\global\catcode`\^^d4=\active \global\def^^d4{\^O}
+\global\catcode`\^^d5=\active \global\def^^d5{\~O}
+\global\catcode`\^^d6=\active \global\def^^d6{\"O}             % capital o with diaeresis
+\global\catcode`\^^d7=\active \global\def^^d7{\inmathmode\times}% multiplication sign
+\global\catcode`\^^d8=\active \global\let^^d8=\O
+\global\catcode`\^^d9=\active \global\def^^d9{\`U}
+\global\catcode`\^^da=\active \global\def^^da{\'U}
+\global\catcode`\^^db=\active \global\def^^db{\^U}
+\global\catcode`\^^dc=\active \global\def^^dc{\"U}
+\global\catcode`\^^dd=\active \global\def^^dd{\'Y}
+% capital thorn
+\global\catcode`\^^df=\active \global\def^^df{\ss}
+\global\catcode`\^^e0=\active \global\def^^e0{\`a}
+\global\catcode`\^^e1=\active \global\def^^e1{\'a}
+\global\catcode`\^^e2=\active \global\def^^e2{\^a}
+\global\catcode`\^^e3=\active \global\def^^e3{\~a}
+\global\catcode`\^^e4=\active \global\def^^e4{\"a}             % small a with diaeresis
+\global\catcode`\^^e5=\active \global\let^^e5=\aa              % small a with ring above
+\global\catcode`\^^e6=\active \global\let^^e6=\ae
+\global\catcode`\^^e7=\active \global\def^^e7{\c c}
+\global\catcode`\^^e8=\active \global\def^^e8{\`e}
+\global\catcode`\^^e9=\active \global\def^^e9{\'e}
+\global\catcode`\^^ea=\active \global\def^^ea{\^e}
+\global\catcode`\^^eb=\active \global\def^^eb{\"e}
+\global\catcode`\^^ec=\active \global\def^^ec{\`\i}
+\global\catcode`\^^ed=\active \global\def^^ed{\'\i}
+\global\catcode`\^^ee=\active \global\def^^ee{\^\i}
+\global\catcode`\^^ef=\active \global\def^^ef{\"\i}
+% small eth
+\global\catcode`\^^f1=\active \global\def^^f1{\~n}
+\global\catcode`\^^f2=\active \global\def^^f2{\`o}
+\global\catcode`\^^f3=\active \global\def^^f3{\'o}
+\global\catcode`\^^f4=\active \global\def^^f4{\^o}
+\global\catcode`\^^f5=\active \global\def^^f5{\~o}
+\global\catcode`\^^f6=\active \global\def^^f6{\"o}             % small o with diaeresis
+\global\catcode`\^^f7=\active \global\def^^f7{\inmathmode\div}% division sign
+\global\catcode`\^^f8=\active \global\let^^f8=\o
+\global\catcode`\^^f9=\active \global\def^^f9{\`u}
+\global\catcode`\^^fa=\active \global\def^^fa{\'u}
+\global\catcode`\^^fb=\active \global\def^^fb{\^u}
+\global\catcode`\^^fc=\active \global\def^^fc{\"u}
+\global\catcode`\^^fd=\active \global\def^^fd{\'y}
+% capital thorn
+\global\catcode`\^^ff=\active \global\def^^ff{\"y}
diff --git a/src/kerberosV/src/doc/layman.asc b/src/kerberosV/src/doc/layman.asc
new file mode 100644 (file)
index 0000000..d4fbe64
--- /dev/null
@@ -0,0 +1,1855 @@
+A Layman's Guide to a Subset of ASN.1, BER, and DER
+
+An RSA Laboratories Technical Note
+Burton S. Kaliski Jr.
+Revised November 1, 1993
+
+
+Supersedes June 3, 1991 version, which was also published as
+NIST/OSI Implementors' Workshop document SEC-SIG-91-17.
+PKCS documents are available by electronic mail to
+<pkcs@rsa.com>.
+
+Copyright (C) 1991-1993 RSA Laboratories, a division of RSA
+Data Security, Inc. License to copy this document is granted
+provided that it is identified as "RSA Data Security, Inc.
+Public-Key Cryptography Standards (PKCS)" in all material
+mentioning or referencing this document.
+003-903015-110-000-000
+
+
+Abstract. This note gives a layman's introduction to a
+subset of OSI's Abstract Syntax Notation One (ASN.1), Basic
+Encoding Rules (BER), and Distinguished Encoding Rules
+(DER). The particular purpose of this note is to provide
+background material sufficient for understanding and
+implementing the PKCS family of standards.
+
+
+1. Introduction
+
+It is a generally accepted design principle that abstraction
+is a key to managing software development. With abstraction,
+a designer can specify a part of a system without concern
+for how the part is actually implemented or represented.
+Such a practice leaves the implementation open; it
+simplifies the specification; and it makes it possible to
+state "axioms" about the part that can be proved when the
+part is implemented, and assumed when the part is employed
+in another, higher-level part. Abstraction is the hallmark
+of most modern software specifications.
+
+One of the most complex systems today, and one that also
+involves a great deal of abstraction, is Open Systems
+Interconnection (OSI, described in X.200). OSI is an
+internationally standardized architecture that governs the
+interconnection of computers from the physical layer up to
+the user application layer. Objects at higher layers are
+defined abstractly and intended to be implemented with
+objects at lower layers. For instance, a service at one
+layer may require transfer of certain abstract objects
+between computers; a lower layer may provide transfer
+services for strings of ones and zeroes, using encoding
+rules to transform the abstract objects into such strings.
+OSI is called an open system because it supports many
+different implementations of the services at each layer.
+
+OSI's method of specifying abstract objects is called ASN.1
+(Abstract Syntax Notation One, defined in X.208), and one
+set of rules for representing such objects as strings of
+ones and zeros is called the BER (Basic Encoding Rules,
+defined in X.209). ASN.1 is a flexible notation that allows
+one to define a variety data types, from simple types such
+as integers and bit strings to structured types such as sets
+and sequences, as well as complex types defined in terms of
+others. BER describes how to represent or encode values of
+each ASN.1 type as a string of eight-bit octets. There is
+generally more than one way to BER-encode a given value.
+Another set of rules, called the Distinguished Encoding
+Rules (DER), which is a subset of BER, gives a unique
+encoding to each ASN.1 value.
+
+The purpose of this note is to describe a subset of ASN.1,
+BER and DER sufficient to understand and implement one OSI-
+based application, RSA Data Security, Inc.'s Public-Key
+Cryptography Standards. The features described include an
+overview of ASN.1, BER, and DER and an abridged list of
+ASN.1 types and their BER and DER encodings. Sections 2-4
+give an overview of ASN.1, BER, and DER, in that order.
+Section 5 lists some ASN.1 types, giving their notation,
+specific encoding rules, examples, and comments about their
+application to PKCS. Section 6 concludes with an example,
+X.500 distinguished names.
+
+Advanced features of ASN.1, such as macros, are not
+described in this note, as they are not needed to implement
+PKCS. For information on the other features, and for more
+detail generally, the reader is referred to CCITT
+Recommendations X.208 and X.209, which define ASN.1 and BER.
+
+Terminology and notation. In this note, an octet is an eight-
+bit unsigned integer. Bit 8 of the octet is the most
+significant and bit 1 is the least significant.
+
+The following meta-syntax is used for in describing ASN.1
+notation:
+
+     BIT  monospace denotes literal characters in the type
+          and value notation; in examples, it generally
+          denotes an octet value in hexadecimal
+
+     n1   bold italics denotes a variable
+
+     []   bold square brackets indicate that a term is
+          optional
+
+     {}   bold braces group related terms
+
+     |    bold vertical bar delimits alternatives with a
+          group
+
+     ...  bold ellipsis indicates repeated occurrences
+
+     =    bold equals sign expresses terms as subterms
+
+
+2. Abstract Syntax Notation One
+
+Abstract Syntax Notation One, abbreviated ASN.1, is a
+notation for describing abstract types and values.
+
+In ASN.1, a type is a set of values. For some types, there
+are a finite number of values, and for other types there are
+an infinite number. A value of a given ASN.1 type is an
+element of the type's set. ASN.1 has four kinds of type:
+simple types, which are "atomic" and have no components;
+structured types, which have components; tagged types, which
+are derived from other types; and other types, which include
+the CHOICE type and the ANY type. Types and values can be
+given names with the ASN.1 assignment operator (::=) , and
+those names can be used in defining other types and values.
+
+Every ASN.1 type other than CHOICE and ANY has a tag, which
+consists of a class and a nonnegative tag number. ASN.1
+types are abstractly the same if and only if their tag
+numbers are the same. In other words, the name of an ASN.1
+type does not affect its abstract meaning, only the tag
+does. There are four classes of tag:
+
+     Universal, for types whose meaning is the same in all
+          applications; these types are only defined in
+          X.208.
+
+     Application, for types whose meaning is specific to an
+          application, such as X.500 directory services;
+          types in two different applications may have the
+          same application-specific tag and different
+          meanings.
+
+     Private, for types whose meaning is specific to a given
+          enterprise.
+
+     Context-specific, for types whose meaning is specific
+          to a given structured type; context-specific tags
+          are used to distinguish between component types
+          with the same underlying tag within the context of
+          a given structured type, and component types in
+          two different structured types may have the same
+          tag and different meanings.
+
+The types with universal tags are defined in X.208, which
+also gives the types' universal tag numbers. Types with
+other tags are defined in many places, and are always
+obtained by implicit or explicit tagging (see Section 2.3).
+Table 1 lists some ASN.1 types and their universal-class
+tags.
+
+    Type                     Tag number     Tag number
+                             (decimal)      (hexadecimal)
+    INTEGER                  2              02
+    BIT STRING               3              03
+    OCTET STRING             4              04
+    NULL                     5              05
+    OBJECT IDENTIFIER        6              06
+    SEQUENCE and SEQUENCE OF 16             10
+    SET and SET OF           17             11
+    PrintableString          19             13
+    T61String                20             14
+    IA5String                22             16
+    UTCTime                  23             17
+
+     Table 1. Some types and their universal-class tags.
+
+ASN.1 types and values are expressed in a flexible,
+programming-language-like notation, with the following
+special rules:
+
+     o    Layout is not significant; multiple spaces and
+          line breaks can be considered as a single space.
+
+     o    Comments are delimited by pairs of hyphens (--),
+          or a pair of hyphens and a line break.
+
+     o    Identifiers (names of values and fields) and type
+          references (names of types) consist of upper- and
+          lower-case letters, digits, hyphens, and spaces;
+          identifiers begin with lower-case letters; type
+          references begin with upper-case letters.
+
+The following four subsections give an overview of simple
+types, structured types, implicitly and explicitly tagged
+types, and other types. Section 5 describes specific types
+in more detail.
+
+
+2.1 Simple types
+
+Simple types are those not consisting of components; they
+are the "atomic" types. ASN.1 defines several; the types
+that are relevant to the PKCS standards are the following:
+
+     BIT STRING, an arbitrary string of bits (ones and
+          zeroes).
+
+     IA5String, an arbitrary string of IA5 (ASCII)
+          characters.
+
+     INTEGER, an arbitrary integer.
+
+     NULL, a null value.
+
+     OBJECT IDENTIFIER, an object identifier, which is a
+          sequence of integer components that identify an
+          object such as an algorithm or attribute type.
+
+     OCTET STRING, an arbitrary string of octets (eight-bit
+          values).
+
+     PrintableString, an arbitrary string of printable
+          characters.
+
+     T61String, an arbitrary string of T.61 (eight-bit)
+          characters.
+
+     UTCTime, a "coordinated universal time" or Greenwich
+          Mean Time (GMT) value.
+
+Simple types fall into two categories: string types and non-
+string types. BIT STRING, IA5String, OCTET STRING,
+PrintableString, T61String, and UTCTime are string types.
+
+String types can be viewed, for the purposes of encoding, as
+consisting of components, where the components are
+substrings. This view allows one to encode a value whose
+length is not known in advance (e.g., an octet string value
+input from a file stream) with a constructed, indefinite-
+length encoding (see Section 3).
+
+The string types can be given size constraints limiting the
+length of values.
+
+
+2.2 Structured types
+
+Structured types are those consisting of components. ASN.1
+defines four, all of which are relevant to the PKCS
+standards:
+
+     SEQUENCE, an ordered collection of one or more types.
+
+     SEQUENCE OF, an ordered collection of zero or more
+          occurrences of a given type.
+
+     SET, an unordered collection of one or more types.
+
+     SET OF, an unordered collection of zero or more
+          occurrences of a given type.
+
+The structured types can have optional components, possibly
+with default values.
+
+
+2.3 Implicitly and explicitly tagged types
+
+Tagging is useful to distinguish types within an
+application; it is also commonly used to distinguish
+component types within a structured type. For instance,
+optional components of a SET or SEQUENCE type are typically
+given distinct context-specific tags to avoid ambiguity.
+
+There are two ways to tag a type: implicitly and explicitly.
+
+Implicitly tagged types are derived from other types by
+changing the tag of the underlying type. Implicit tagging is
+denoted by the ASN.1 keywords [class number] IMPLICIT (see
+Section 5.1).
+
+Explicitly tagged types are derived from other types by
+adding an outer tag to the underlying type. In effect,
+explicitly tagged types are structured types consisting of
+one component, the underlying type. Explicit tagging is
+denoted by the ASN.1 keywords [class number] EXPLICIT (see
+Section 5.2).
+
+The keyword [class number] alone is the same as explicit
+tagging, except when the "module" in which the ASN.1 type is
+defined has implicit tagging by default. ("Modules" are
+among the advanced features not described in this note.)
+
+For purposes of encoding, an implicitly tagged type is
+considered the same as the underlying type, except that the
+tag is different. An explicitly tagged type is considered
+like a structured type with one component, the underlying
+type. Implicit tags result in shorter encodings, but
+explicit tags may be necessary to avoid ambiguity if the tag
+of the underlying type is indeterminate (e.g., the
+underlying type is CHOICE or ANY).
+
+
+2.4 Other types
+
+Other types in ASN.1 include the CHOICE and ANY types. The
+CHOICE type denotes a union of one or more alternatives; the
+ANY type denotes an arbitrary value of an arbitrary type,
+where the arbitrary type is possibly defined in the
+registration of an object identifier or integer value.
+
+
+3. Basic Encoding Rules
+
+The Basic Encoding Rules for ASN.1, abbreviated BER, give
+one or more ways to represent any ASN.1 value as an octet
+string. (There are certainly other ways to represent ASN.1
+values, but BER is the standard for interchanging such
+values in OSI.)
+
+There are three methods to encode an ASN.1 value under BER,
+the choice of which depends on the type of value and whether
+the length of the value is known. The three methods are
+primitive, definite-length encoding; constructed, definite-
+length encoding; and constructed, indefinite-length
+encoding. Simple non-string types employ the primitive,
+definite-length method; structured types employ either of
+the constructed methods; and simple string types employ any
+of the methods, depending on whether the length of the value
+is known. Types derived by implicit tagging employ the
+method of the underlying type and types derived by explicit
+tagging employ the constructed methods.
+
+In each method, the BER encoding has three or four parts:
+
+     Identifier octets. These identify the class and tag
+          number of the ASN.1 value, and indicate whether
+          the method is primitive or constructed.
+
+     Length octets. For the definite-length methods, these
+          give the number of contents octets. For the
+          constructed, indefinite-length method, these
+          indicate that the length is indefinite.
+
+     Contents octets. For the primitive, definite-length
+          method, these give a concrete representation of
+          the  value. For the constructed methods, these
+          give the concatenation of the BER encodings of the
+          components of the value.
+
+     End-of-contents octets. For the constructed, indefinite-
+          length method, these denote the end of the
+          contents. For the other methods, these are absent.
+
+The three methods of encoding are described in the following
+sections.
+
+
+3.1 Primitive, definite-length method
+
+This method applies to simple types and types derived from
+simple types by implicit tagging. It requires that the
+length of the value be known in advance. The parts of the
+BER encoding are as follows:
+
+Identifier octets. There are two forms: low tag number (for
+tag numbers between 0 and 30) and high tag number (for tag
+numbers 31 and greater).
+
+     Low-tag-number form. One octet. Bits 8 and 7 specify
+          the class (see Table 2), bit 6 has value "0,"
+          indicating that the encoding is primitive, and
+          bits 5-1 give the tag number.
+
+                  Class            Bit  Bit
+                                   8    7
+                  universal        0    0
+                  application      0    1
+                  context-specific 1    0
+                  private          1    1
+
+        Table 2. Class encoding in identifier octets.
+
+     High-tag-number form. Two or more octets. First octet
+          is as in low-tag-number form, except that bits 5-1
+          all have value "1." Second and following octets
+          give the tag number, base 128, most significant
+          digit first, with as few digits as possible, and
+          with the bit 8 of each octet except the last set
+          to "1."
+
+Length octets. There are two forms: short (for lengths
+between 0 and 127), and long definite (for lengths between 0
+and 21008-1).
+
+     Short form. One octet. Bit 8 has value "0" and bits 7-1
+          give the length.
+
+     Long form. Two to 127 octets. Bit 8 of first octet has
+          value "1" and bits 7-1 give the number of
+          additional length octets. Second and following
+          octets give the length, base 256, most significant
+          digit first.
+
+Contents octets. These give a concrete representation of the
+value (or the value of the underlying type, if the type is
+derived by implicit tagging). Details for particular types
+are given in Section 5.
+
+
+3.2 Constructed, definite-length method
+
+This method applies to simple string types, structured
+types, types derived simple string types and structured
+types by implicit tagging, and types derived from anything
+by explicit tagging. It requires that the length of the
+value be known in advance. The parts of the BER encoding are
+as follows:
+
+Identifier octets. As described in Section 3.1, except that
+bit 6 has value "1," indicating that the encoding is
+constructed.
+
+Length octets. As described in Section 3.1.
+
+Contents octets. The concatenation of the BER encodings of
+the components of the value:
+
+     o    For simple string types and types derived from
+          them by implicit tagging, the concatenation of the
+          BER encodings of consecutive substrings of the
+          value (underlying value for implicit tagging).
+
+     o    For structured types and types derived from them
+          by implicit tagging, the concatenation of the BER
+          encodings of components of the value (underlying
+          value for implicit tagging).
+
+     o    For types derived from anything by explicit
+          tagging, the BER encoding of the underlying value.
+
+Details for particular types are given in Section 5.
+
+
+3.3 Constructed, indefinite-length method
+
+This method applies to simple string types, structured
+types, types derived simple string types and structured
+types by implicit tagging, and types derived from anything
+by explicit tagging. It does not require that the length of
+the value be known in advance. The parts of the BER encoding
+are as follows:
+
+Identifier octets. As described in Section 3.2.
+
+Length octets. One octet, 80.
+
+Contents octets. As described in Section 3.2.
+
+End-of-contents octets. Two octets, 00 00.
+
+Since the end-of-contents octets appear where an ordinary
+BER encoding might be expected (e.g., in the contents octets
+of a sequence value), the 00 and 00 appear as identifier and
+length octets, respectively. Thus the end-of-contents octets
+is really the primitive, definite-length encoding of a value
+with universal class, tag number 0, and length 0.
+
+
+4. Distinguished Encoding Rules
+
+The Distinguished Encoding Rules for ASN.1, abbreviated DER,
+are a subset of BER, and give exactly one way to represent
+any ASN.1 value as an octet string. DER is intended for
+applications in which a unique octet string encoding is
+needed, as is the case when a digital signature is computed
+on an ASN.1 value. DER is defined in Section 8.7 of X.509.
+
+DER adds the following restrictions to the rules given in
+Section 3:
+
+     1.   When the length is between 0 and 127, the short
+          form of length must be used
+
+     2.   When the length is 128 or greater, the long form
+          of length must be used, and the length must be
+          encoded in the minimum number of octets.
+
+     3.   For simple string types and implicitly tagged
+          types derived from simple string types, the
+          primitive, definite-length method must be
+          employed.
+
+     4.   For structured types, implicitly tagged types
+          derived from structured types, and explicitly
+          tagged types derived from anything, the
+          constructed, definite-length method must be
+          employed.
+
+Other restrictions are defined for particular types (such as
+BIT STRING, SEQUENCE, SET, and SET OF), and can be found in
+Section 5.
+
+
+5. Notation and encodings for some types
+
+This section gives the notation for some ASN.1 types and
+describes how to encode values of those types under both BER
+and DER.
+
+The types described are those presented in Section 2. They
+are listed alphabetically here.
+
+Each description includes ASN.1 notation, BER encoding, and
+DER encoding. The focus of the encodings is primarily on the
+contents octets; the tag and length octets follow Sections 3
+and 4. The descriptions also explain where each type is used
+in PKCS and related standards. ASN.1 notation is generally
+only for types, although for the type OBJECT IDENTIFIER,
+value notation is given as well.
+
+
+5.1 Implicitly tagged types
+
+An implicitly tagged type is a type derived from another
+type by changing the tag of the underlying type.
+
+Implicit tagging is used for optional SEQUENCE components
+with underlying type other than ANY throughout PKCS, and for
+the extendedCertificate alternative of PKCS #7's
+ExtendedCertificateOrCertificate type.
+
+ASN.1 notation:
+
+[[class] number] IMPLICIT Type
+
+class = UNIVERSAL  |  APPLICATION  |  PRIVATE
+
+where Type is a type, class is an optional class name, and
+number is the tag number within the class, a nonnegative
+integer.
+
+In ASN.1 "modules" whose default tagging method is implicit
+tagging, the notation [[class] number] Type is also
+acceptable, and the keyword IMPLICIT is implied. (See
+Section 2.3.) For definitions stated outside a module, the
+explicit inclusion of the keyword IMPLICIT is preferable to
+prevent ambiguity.
+
+If the class name is absent, then the tag is context-
+specific. Context-specific tags can only appear in a
+component of a structured or CHOICE type.
+
+Example: PKCS #8's PrivateKeyInfo type has an optional
+attributes component with an implicit, context-specific tag:
+
+PrivateKeyInfo ::= SEQUENCE {
+  version Version,
+  privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
+  privateKey PrivateKey,
+  attributes [0] IMPLICIT Attributes OPTIONAL }
+
+Here the underlying type is Attributes, the class is absent
+(i.e., context-specific), and the tag number within the
+class is 0.
+
+BER encoding. Primitive or constructed, depending on the
+underlying type. Contents octets are as for the BER encoding
+of the underlying value.
+
+Example: The BER encoding of the attributes component of a
+PrivateKeyInfo value is as follows:
+
+     o    the identifier octets are 80 if the underlying
+          Attributes value has a primitive BER encoding and
+          a0 if the underlying Attributes value has a
+          constructed BER encoding
+
+     o    the length and contents octets are the same as the
+          length and contents octets of the BER encoding of
+          the underlying Attributes value
+
+DER encoding. Primitive or constructed, depending on the
+underlying type. Contents octets are as for the DER encoding
+of the underlying value.
+
+
+5.2 Explicitly tagged types
+
+Explicit tagging denotes a type derived from another type by
+adding an outer tag to the underlying type.
+
+Explicit tagging is used for optional SEQUENCE components
+with underlying type ANY throughout PKCS, and for the
+version component of X.509's Certificate type.
+
+ASN.1 notation:
+
+[[class] number] EXPLICIT Type
+
+class = UNIVERSAL  |  APPLICATION  |  PRIVATE
+
+where Type is a type, class is an optional class name, and
+number is the tag number within the class, a nonnegative
+integer.
+
+If the class name is absent, then the tag is context-
+specific. Context-specific tags can only appear in a
+component of a SEQUENCE, SET or CHOICE type.
+
+In ASN.1 "modules" whose default tagging method is explicit
+tagging, the notation [[class] number] Type is also
+acceptable, and the keyword EXPLICIT is implied. (See
+Section 2.3.) For definitions stated outside a module, the
+explicit inclusion of the keyword EXPLICIT is preferable to
+prevent ambiguity.
+
+Example 1: PKCS #7's ContentInfo type has an optional
+content component with an explicit, context-specific tag:
+
+ContentInfo ::= SEQUENCE {
+  contentType ContentType,
+  content
+    [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+
+Here the underlying type is ANY DEFINED BY contentType, the
+class is absent (i.e., context-specific), and the tag number
+within the class is 0.
+
+Example 2: X.509's Certificate type has a version component
+with an explicit, context-specific tag, where the EXPLICIT
+keyword is omitted:
+
+Certificate ::= ...
+  version [0] Version DEFAULT v1988,
+...
+
+The tag is explicit because the default tagging method for
+the ASN.1 "module" in X.509 that defines the Certificate
+type is explicit tagging.
+
+BER encoding. Constructed. Contents octets are the BER
+encoding of the underlying value.
+
+Example: the BER encoding of the content component of a
+ContentInfo value is as follows:
+
+     o    identifier octets are a0
+
+     o    length octets represent the length of the BER
+          encoding of the underlying ANY DEFINED BY
+          contentType value
+
+     o    contents octets are the BER encoding of the
+          underlying ANY DEFINED BY contentType value
+
+DER encoding. Constructed. Contents octets are the DER
+encoding of the underlying value.
+
+
+5.3 ANY
+
+The ANY type denotes an arbitrary value of an arbitrary
+type, where the arbitrary type is possibly defined in the
+registration of an object identifier or associated with an
+integer index.
+
+The ANY type is used for content of a particular content
+type in PKCS #7's ContentInfo type, for parameters of a
+particular algorithm in X.509's AlgorithmIdentifier type,
+and for attribute values in X.501's Attribute and
+AttributeValueAssertion types. The Attribute type is used by
+PKCS #6, #7, #8, #9 and #10, and the AttributeValueAssertion
+type is used in X.501 distinguished names.
+
+ASN.1 notation:
+
+ANY [DEFINED BY identifier]
+
+where identifier is an optional identifier.
+
+In the ANY form, the actual type is indeterminate.
+
+The ANY DEFINED BY identifier form can only appear in a
+component of a SEQUENCE or SET type for which identifier
+identifies some other component, and that other component
+has type INTEGER or OBJECT IDENTIFIER (or a type derived
+from either of those by tagging). In that form, the actual
+type is determined by the value of the other component,
+either in the registration of the object identifier value,
+or in a table of integer values.
+
+Example: X.509's AlgorithmIdentifier type has a component of
+type ANY:
+
+AlgorithmIdentifier ::= SEQUENCE {
+  algorithm OBJECT IDENTIFIER,
+  parameters ANY DEFINED BY algorithm OPTIONAL }
+
+Here the actual type of the parameter component depends on
+the value of the algorithm component. The actual type would
+be defined in the registration of object identifier values
+for the algorithm component.
+
+BER encoding. Same as the BER encoding of the actual value.
+
+Example: The BER encoding of the value of the parameter
+component is the BER encoding of the value of the actual
+type as defined in the registration of object identifier
+values for the algorithm component.
+
+DER encoding. Same as the DER encoding of the actual value.
+
+
+5.4 BIT STRING
+
+The BIT STRING type denotes an arbitrary string of bits
+(ones and zeroes). A BIT STRING value can have any length,
+including zero. This type is a string type.
+
+The BIT STRING type is used for digital signatures on
+extended certificates in PKCS #6's ExtendedCertificate type,
+for digital signatures on certificates in X.509's
+Certificate type, and for public keys in certificates in
+X.509's SubjectPublicKeyInfo type.
+
+ASN.1 notation:
+
+BIT STRING
+
+Example: X.509's SubjectPublicKeyInfo type has a component
+of type BIT STRING:
+
+SubjectPublicKeyInfo ::= SEQUENCE {
+  algorithm AlgorithmIdentifier,
+  publicKey BIT STRING }
+
+BER encoding. Primitive or constructed. In a primitive
+encoding, the first contents octet gives the number of bits
+by which the length of the bit string is less than the next
+multiple of eight (this is called the "number of unused
+bits"). The second and following contents octets give the
+value of the bit string, converted to an octet string. The
+conversion process is as follows:
+
+     1.   The bit string is padded after the last bit with
+          zero to seven bits of any value to make the length
+          of the bit string a multiple of eight. If the
+          length of the bit string is a multiple of eight
+          already, no padding is done.
+
+     2.   The padded bit string is divided into octets. The
+          first eight bits of the padded bit string become
+          the first octet, bit 8 to bit 1, and so on through
+          the last eight bits of the padded bit string.
+
+In a constructed encoding, the contents octets give the
+concatenation of the BER encodings of consecutive substrings
+of the bit string, where each substring except the last has
+a length that is a multiple of eight bits.
+
+Example: The BER encoding of the BIT STRING value
+"011011100101110111" can be any of the following, among
+others, depending on the choice of padding bits, the form of
+length octets, and whether the encoding is primitive or
+constructed:
+
+03 04 06 6e 5d c0                               DER encoding
+
+03 04 06 6e 5d e0                       padded with "100000"
+
+03 81 04 06 6e 5d c0              long form of length octets
+
+23 09        constructed encoding: "0110111001011101" + "11"
+   03 03 00 6e 5d
+   03 02 06 c0
+
+DER encoding. Primitive. The contents octects are as for a
+primitive BER encoding, except that the bit string is padded
+with zero-valued bits.
+
+Example: The DER encoding of the BIT STRING value
+"011011100101110111" is
+
+03 04 06 6e 5d c0
+
+
+5.5 CHOICE
+
+The CHOICE type denotes a union of one or more alternatives.
+
+The CHOICE type is used to represent the union of an
+extended certificate and an X.509 certificate in PKCS #7's
+ExtendedCertificateOrCertificate type.
+
+ASN.1 notation:
+
+CHOICE {
+  [identifier1] Type1,
+  ...,
+  [identifiern] Typen }
+
+where identifier1 , ..., identifiern are optional, distinct
+identifiers for the alternatives, and Type1, ..., Typen are
+the types of the alternatives. The identifiers are primarily
+for documentation; they do not affect values of the type or
+their encodings in any way.
+
+The types must have distinct tags. This requirement is
+typically satisfied with explicit or implicit tagging on
+some of the alternatives.
+
+Example: PKCS #7's ExtendedCertificateOrCertificate type is
+a CHOICE type:
+
+ExtendedCertificateOrCertificate ::= CHOICE {
+  certificate Certificate, -- X.509
+  extendedCertificate [0] IMPLICIT ExtendedCertificate
+}
+
+Here the identifiers for the alternatives are certificate
+and extendedCertificate, and the types of the alternatives
+are Certificate and [0] IMPLICIT ExtendedCertificate.
+
+BER encoding. Same as the BER encoding of the chosen
+alternative. The fact that the alternatives have distinct
+tags makes it possible to distinguish between their BER
+encodings.
+
+Example: The identifier octets for the BER encoding are 30
+if the chosen alternative is certificate, and a0 if the
+chosen alternative is extendedCertificate.
+
+DER encoding. Same as the DER encoding of the chosen
+alternative.
+
+
+5.6 IA5String
+
+The IA5String type denotes an arbtrary string of IA5
+characters. IA5 stands for International Alphabet 5, which
+is the same as ASCII. The character set includes non-
+printing control characters. An IA5String value can have any
+length, including zero. This type is a string type.
+
+The IA5String type is used in PKCS #9's electronic-mail
+address, unstructured-name, and unstructured-address
+attributes.
+
+ASN.1 notation:
+
+IA5String
+
+BER encoding. Primitive or constructed. In a primitive
+encoding, the contents octets give the characters in the IA5
+string, encoded in ASCII. In a constructed encoding, the
+contents octets give the concatenation of the BER encodings
+of consecutive substrings of the IA5 string.
+
+Example: The BER encoding of the IA5String value
+"test1@rsa.com" can be any of the following, among others,
+depending on the form of length octets and whether the
+encoding is primitive or constructed:
+
+16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d DER encoding
+
+16 81 0d                       long form of length octets
+   74 65 73 74 31 40 72 73 61 2e 63 6f 6d
+
+36 13     constructed encoding: "test1" + "@" + "rsa.com"
+   16 05 74 65 73 74 31
+   16 01 40
+   16 07 72 73 61 2e 63 6f 6d
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+Example: The DER encoding of the IA5String value
+"test1@rsa.com" is
+
+16 0d 74 65 73 74 31 40 72 73 61 2e 63 6f 6d
+
+
+5.7 INTEGER
+
+The INTEGER type denotes an arbitrary integer. INTEGER
+values can be positive, negative, or zero, and can have any
+magnitude.
+
+The INTEGER type is used for version numbers throughout
+PKCS, cryptographic values such as modulus, exponent, and
+primes in PKCS #1's RSAPublicKey and RSAPrivateKey types and
+PKCS #3's DHParameter type, a message-digest iteration count
+in PKCS #5's PBEParameter type, and version numbers and
+serial numbers in X.509's Certificate type.
+
+ASN.1 notation:
+
+INTEGER [{ identifier1(value1) ... identifiern(valuen) }]
+
+where identifier1, ..., identifiern are optional distinct
+identifiers and value1, ..., valuen are optional integer
+values. The identifiers, when present, are associated with
+values of the type.
+
+Example: X.509's Version type is an INTEGER type with
+identified values:
+
+Version ::= INTEGER { v1988(0) }
+
+The identifier v1988 is associated with the value 0. X.509's
+Certificate type uses the identifier v1988 to give a default
+value of 0 for the version component:
+
+Certificate ::= ...
+  version Version DEFAULT v1988,
+...
+
+BER encoding. Primitive. Contents octets give the value of
+the integer, base 256, in two's complement form, most
+significant digit first, with the minimum number of octets.
+The value 0 is encoded as a single 00 octet.
+
+Some example BER encodings (which also happen to be DER
+encodings) are given in Table 3.
+
+                    Integer   BER encoding
+                    value
+                    0         02 01 00
+                    127       02 01 7F
+                    128       02 02 00 80
+                    256       02 02 01 00
+                    -128      02 01 80
+                    -129      02 02 FF 7F
+
+      Table 3. Example BER encodings of INTEGER values.
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+
+5.8 NULL
+
+The NULL type denotes a null value.
+
+The NULL type is used for algorithm parameters in several
+places in PKCS.
+
+ASN.1 notation:
+
+NULL
+
+BER encoding. Primitive. Contents octets are empty.
+
+Example: The BER encoding of a NULL value can be either of
+the following, as well as others, depending on the form of
+the length octets:
+
+05 00
+
+05 81 00
+
+DER encoding. Primitive. Contents octets are empty; the DER
+encoding of a NULL value is always 05 00.
+
+
+5.9 OBJECT IDENTIFIER
+
+The OBJECT IDENTIFIER type denotes an object identifier, a
+sequence of integer components that identifies an object
+such as an algorithm, an attribute type, or perhaps a
+registration authority that defines other object
+identifiers. An OBJECT IDENTIFIER value can have any number
+of components, and components can generally have any
+nonnegative value. This type is a non-string type.
+
+OBJECT IDENTIFIER values are given meanings by registration
+authorities. Each registration authority is responsible for
+all sequences of components beginning with a given sequence.
+A registration authority typically delegates responsibility
+for subsets of the sequences in its domain to other
+registration authorities, or for particular types of object.
+There are always at least two components.
+
+The OBJECT IDENTIFIER type is used to identify content in
+PKCS #7's ContentInfo type, to identify algorithms in
+X.509's AlgorithmIdentifier type, and to identify attributes
+in X.501's Attribute and AttributeValueAssertion types. The
+Attribute type is used by PKCS #6, #7, #8, #9, and #10, and
+the AttributeValueAssertion type is used in X.501
+distinguished names. OBJECT IDENTIFIER values are defined
+throughout PKCS.
+
+ASN.1 notation:
+
+OBJECT IDENTIFIER
+
+The ASN.1 notation for values of the OBJECT IDENTIFIER type
+is
+
+{ [identifier] component1 ... componentn }
+
+componenti = identifieri | identifieri (valuei) | valuei
+
+where identifier, identifier1, ..., identifiern are
+identifiers, and value1, ..., valuen are optional integer
+values.
+
+The form without identifier is the "complete" value with all
+its components; the form with identifier abbreviates the
+beginning components with another object identifier value.
+The identifiers identifier1, ..., identifiern are intended
+primarily for documentation, but they must correspond to the
+integer value when both are present. These identifiers can
+appear without integer values only if they are among a small
+set of identifiers defined in X.208.
+
+Example: The following values both refer to the object
+identifier assigned to RSA Data Security, Inc.:
+
+{ iso(1) member-body(2) 840 113549 }
+{ 1 2 840 113549 }
+
+(In this example, which gives ASN.1 value notation, the
+object identifier values are decimal, not hexadecimal.)
+Table 4 gives some other object identifier values and their
+meanings.
+
+ Object identifier value       Meaning
+ { 1 2 }                       ISO member bodies
+ { 1 2 840 }                   US (ANSI)
+ { 1 2 840 113549 }            RSA Data Security, Inc.
+ { 1 2 840 113549 1 }          RSA Data Security, Inc. PKCS
+ { 2 5 }                       directory services (X.500)
+ { 2 5 8 }                     directory services-algorithms
+
+ Table 4. Some object identifier values and their meanings.
+
+BER encoding. Primitive. Contents octets are as follows,
+where value1, ..., valuen denote the integer values of the
+components in the complete object identifier:
+
+     1.   The first octet has value 40 * value1 + value2.
+          (This is unambiguous, since value1 is limited to
+          values 0, 1, and 2; value2 is limited to the range
+          0 to 39 when value1 is 0 or 1; and, according to
+          X.208, n is always at least 2.)
+
+     2.   The following octets, if any, encode value3, ...,
+          valuen. Each value is encoded base 128, most
+          significant digit first, with as few digits as
+          possible, and the most significant bit of each
+          octet except the last in the value's encoding set
+          to "1."
+
+Example: The first octet of the BER encoding of RSA Data
+Security, Inc.'s object identifier is 40 * 1 + 2 = 42 =
+2a16. The encoding of 840 = 6 * 128 + 4816 is 86 48 and the
+encoding of 113549 = 6 * 1282 + 7716 * 128 + d16 is 86 f7
+0d. This leads to the following BER encoding:
+
+06 06 2a 86 48 86 f7 0d
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+
+5.10 OCTET STRING
+
+The OCTET STRING type denotes an arbitrary string of octets
+(eight-bit values). An OCTET STRING value can have any
+length, including zero. This type is a string type.
+
+The OCTET STRING type is used for salt values in PKCS #5's
+PBEParameter type, for message digests, encrypted message
+digests, and encrypted content in PKCS #7, and for private
+keys and encrypted private keys in PKCS #8.
+
+ASN.1 notation:
+
+OCTET STRING [SIZE ({size | size1..size2})]
+
+where size, size1, and size2 are optional size constraints.
+In the OCTET STRING SIZE (size) form, the octet string must
+have size octets. In the OCTET STRING SIZE (size1..size2)
+form, the octet string must have between size1 and size2
+octets. In the OCTET STRING form, the octet string can have
+any size.
+
+Example: PKCS #5's PBEParameter type has a component of type
+OCTET STRING:
+
+PBEParameter ::= SEQUENCE {
+  salt OCTET STRING SIZE(8),
+  iterationCount INTEGER }
+
+Here the size of the salt component is always eight octets.
+
+BER encoding. Primitive or constructed. In a primitive
+encoding, the contents octets give the value of the octet
+string, first octet to last octet. In a constructed
+encoding, the contents octets give the concatenation of the
+BER encodings of substrings of the OCTET STRING value.
+
+Example: The BER encoding of the OCTET STRING value 01 23 45
+67 89 ab cd ef can be any of the following, among others,
+depending on the form of length octets and whether the
+encoding is primitive or constructed:
+
+04 08 01 23 45 67 89 ab cd ef                   DER encoding
+
+04 81 08 01 23 45 67 89 ab cd ef  long form of length octets
+
+24 0c            constructed encoding: 01 ... 67 + 89 ... ef
+   04 04 01 23 45 67
+   04 04 89 ab cd ef
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+Example: The BER encoding of the OCTET STRING value 01 23 45
+67 89 ab cd ef is
+
+04 08 01 23 45 67 89 ab cd ef
+
+
+5.11 PrintableString
+
+The PrintableString type denotes an arbitrary string of
+printable characters from the following character set:
+
+                         A, B, ..., Z
+                         a, b, ..., z
+                         0, 1, ..., 9
+               (space) ' ( ) + , - . / : = ?
+
+This type is a string type.
+
+The PrintableString type is used in PKCS #9's challenge-
+password and unstructuerd-address attributes, and in several
+X.521 distinguished names attributes.
+
+ASN.1 notation:
+
+PrintableString
+
+BER encoding. Primitive or constructed. In a primitive
+encoding, the contents octets give the characters in the
+printable string, encoded in ASCII. In a constructed
+encoding, the contents octets give the concatenation of the
+BER encodings of consecutive substrings of the string.
+
+Example: The BER encoding of the PrintableString value "Test
+User 1" can be any of the following, among others, depending
+on the form of length octets and whether the encoding is
+primitive or constructed:
+
+13 0b 54 65 73 74 20 55 73 65 72 20 31          DER encoding
+
+13 81 0b                          long form of length octets
+   54 65 73 74 20 55 73 65 72 20 31
+
+33 0f               constructed encoding: "Test " + "User 1"
+   13 05 54 65 73 74 20
+   13 06 55 73 65 72 20 31
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+Example: The DER encoding of the PrintableString value "Test
+User 1" is
+
+13 0b 54 65 73 74 20 55 73 65 72 20 31
+
+
+5.12 SEQUENCE
+
+The SEQUENCE type denotes an ordered collection of one or
+more types.
+
+The SEQUENCE type is used throughout PKCS and related
+standards.
+
+ASN.1 notation:
+
+SEQUENCE {
+  [identifier1] Type1 [{OPTIONAL | DEFAULT value1}],
+  ...,
+  [identifiern] Typen [{OPTIONAL | DEFAULT valuen}]}
+
+where identifier1 , ..., identifiern are optional, distinct
+identifiers for the components, Type1, ..., Typen are the
+types of the components, and value1, ..., valuen are optional
+default values for the components. The identifiers are
+primarily for documentation; they do not affect values of
+the type or their encodings in any way.
+
+The OPTIONAL qualifier indicates that the value of a
+component is optional and need not be present in the
+sequence. The DEFAULT qualifier also indicates that the
+value of a component is optional, and assigns a default
+value to the component when the component is absent.
+
+The types of any consecutive series of components with the
+OPTIONAL or DEFAULT qualifier, as well as of any component
+immediately following that series, must have distinct tags.
+This requirement is typically satisfied with explicit or
+implicit tagging on some of the components.
+
+Example: X.509's Validity type is a SEQUENCE type with two
+components:
+
+Validity ::= SEQUENCE {
+  start UTCTime,
+  end UTCTime }
+
+Here the identifiers for the components are start and end,
+and the types of the components are both UTCTime.
+
+BER encoding. Constructed. Contents octets are the
+concatenation of the BER encodings of the values of the
+components of the sequence, in order of definition, with the
+following rules for components with the OPTIONAL and DEFAULT
+qualifiers:
+
+     o    if the value of a component with the OPTIONAL or
+          DEFAULT qualifier is absent from the sequence,
+          then the encoding of that component is not
+          included in the contents octets
+
+     o    if the value of a component with the DEFAULT
+          qualifier is the default value, then the encoding
+          of that component may or may not be included in
+          the contents octets
+
+DER encoding. Constructed. Contents octets are the same as
+the BER encoding, except that if the value of a component
+with the DEFAULT qualifier is the default value, the
+encoding of that component is not included in the contents
+octets.
+
+
+5.13 SEQUENCE OF
+
+The SEQUENCE OF type denotes an ordered collection of zero
+or more occurrences of a given type.
+
+The SEQUENCE OF type is used in X.501 distinguished names.
+
+ASN.1 notation:
+
+SEQUENCE OF Type
+
+where Type is a type.
+
+Example: X.501's RDNSequence type consists of zero or more
+occurences of the RelativeDistinguishedName type, most
+significant occurrence first:
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+BER encoding. Constructed. Contents octets are the
+concatenation of the BER encodings of the values of the
+occurrences in the collection, in order of occurence.
+
+DER encoding. Constructed. Contents octets are the
+concatenation of the DER encodings of the values of the
+occurrences in the collection, in order of occurence.
+
+
+5.14 SET
+
+The SET type denotes an unordered collection of one or more
+types.
+
+The SET type is not used in PKCS.
+
+ASN.1 notation:
+
+SET {
+  [identifier1] Type1 [{OPTIONAL | DEFAULT value1}],
+  ...,
+  [identifiern] Typen [{OPTIONAL | DEFAULT valuen}]}
+
+where identifier1, ..., identifiern are optional, distinct
+identifiers for the components, Type1, ..., Typen are the
+types of the components, and value1, ..., valuen are
+optional default values for the components. The identifiers
+are primarily for documentation; they do not affect values
+of the type or their encodings in any way.
+
+The OPTIONAL qualifier indicates that the value of a
+component is optional and need not be present in the set.
+The DEFAULT qualifier also indicates that the value of a
+component is optional, and assigns a default value to the
+component when the component is absent.
+
+The types must have distinct tags. This requirement is
+typically satisfied with explicit or implicit tagging on
+some of the components.
+
+BER encoding. Constructed. Contents octets are the
+concatenation of the BER encodings of the values of the
+components of the set, in any order, with the following
+rules for components with the OPTIONAL and DEFAULT
+qualifiers:
+
+     o    if the value of a component with the OPTIONAL or
+          DEFAULT qualifier is absent from the set, then the
+          encoding of that component is not included in the
+          contents octets
+
+     o    if the value of a component with the DEFAULT
+          qualifier is the default value, then the encoding
+          of that component may or may not be included in
+          the contents octets
+
+DER encoding. Constructed. Contents octets are the same as
+for the BER encoding, except that:
+
+     1.   If the value of a component with the DEFAULT
+          qualifier is the default value, the encoding of
+          that component is not included.
+
+     2.   There is an order to the components, namely
+          ascending order by tag.
+
+
+5.15 SET OF
+
+The SET OF type denotes an unordered collection of zero or
+more occurrences of a given type.
+
+The SET OF type is used for sets of attributes in PKCS #6,
+#7, #8, #9 and #10, for sets of message-digest algorithm
+identifiers, signer information, and recipient information
+in PKCS #7, and in X.501 distinguished names.
+
+ASN.1 notation:
+
+SET OF Type
+
+where Type is a type.
+
+Example: X.501's RelativeDistinguishedName type consists of
+zero or more occurrences of the AttributeValueAssertion
+type, where the order is unimportant:
+
+RelativeDistinguishedName ::=
+  SET OF AttributeValueAssertion
+
+BER encoding. Constructed. Contents octets are the
+concatenation of the BER encodings of the values of the
+occurrences in the collection, in any order.
+
+DER encoding. Constructed. Contents octets are the same as
+for the BER encoding, except that there is an order, namely
+ascending lexicographic order of BER encoding. Lexicographic
+comparison of two different BER encodings is done as
+follows: Logically pad the shorter BER encoding after the
+last octet with dummy octets that are smaller in value than
+any normal octet. Scan the BER encodings from left to right
+until a difference is found. The smaller-valued BER encoding
+is the one with the smaller-valued octet at the point of
+difference.
+
+
+5.16 T61String
+
+The T61String type denotes an arbtrary string of T.61
+characters. T.61 is an eight-bit extension to the ASCII
+character set. Special "escape" sequences specify the
+interpretation of subsequent character values as, for
+example, Japanese; the initial interpretation is Latin. The
+character set includes non-printing control characters. The
+T61String type allows only the Latin and Japanese character
+interepretations, and implementors' agreements for directory
+names exclude control characters [NIST92]. A T61String value
+can have any length, including zero. This type is a string
+type.
+
+The T61String type is used in PKCS #9's unstructured-address
+and challenge-password attributes, and in several X.521
+attributes.
+
+ASN.1 notation:
+
+T61String
+
+BER encoding. Primitive or constructed. In a primitive
+encoding, the contents octets give the characters in the
+T.61 string, encoded in ASCII. In a constructed encoding,
+the contents octets give the concatenation of the BER
+encodings of consecutive substrings of the T.61 string.
+
+Example: The BER encoding of the T61String value "cl'es
+publiques" (French for "public keys") can be any of the
+following, among others, depending on the form of length
+octets and whether the encoding is primitive or constructed:
+
+14 0f                                           DER encoding
+   63 6c c2 65 73 20 70 75 62 6c 69 71 75 65 73
+
+14 81 0f                          long form of length octets
+   63 6c c2 65 73 20 70 75 62 6c 69 71 75 65 73
+
+34 15      constructed encoding: "cl'es" + " " + "publiques"
+   14 05 63 6c c2 65 73
+   14 01 20
+   14 09 70 75 62 6c 69 71 75 65 73
+
+The eight-bit character c2 is a T.61 prefix that adds an
+acute accent (') to the next character.
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+Example: The DER encoding of the T61String value "cl'es
+publiques" is
+
+14 0f 63 6c c2 65 73 20 70 75 62 6c 69 71 75 65 73
+
+
+5.17 UTCTime
+
+The UTCTime type denotes a "coordinated universal time" or
+Greenwich Mean Time (GMT) value. A UTCTime value includes
+the local time precise to either minutes or seconds, and an
+offset from GMT in hours and minutes. It takes any of the
+following forms:
+
+YYMMDDhhmmZ
+YYMMDDhhmm+hh'mm'
+YYMMDDhhmm-hh'mm'
+YYMMDDhhmmssZ
+YYMMDDhhmmss+hh'mm'
+YYMMDDhhmmss-hh'mm'
+
+where:
+
+     YY is the least significant two digits of the year
+
+     MM is the month (01 to 12)
+
+     DD is the day (01 to 31)
+
+     hh is the hour (00 to 23)
+
+     mm are the minutes (00 to 59)
+
+     ss are the seconds (00 to 59)
+
+     Z indicates that local time is GMT, + indicates that
+          local time is later than GMT, and - indicates that
+          local time is earlier than GMT
+
+     hh' is the absolute value of the offset from GMT in
+          hours
+
+     mm' is the absolute value of the offset from GMT in
+          minutes
+
+This type is a string type.
+
+The UTCTime type is used for signing times in PKCS #9's
+signing-time attribute and for certificate validity periods
+in X.509's Validity type.
+
+ASN.1 notation:
+
+UTCTime
+
+BER encoding. Primitive or constructed. In a primitive
+encoding, the contents octets give the characters in the
+string, encoded in ASCII. In a constructed encoding, the
+contents octets give the concatenation of the BER encodings
+of consecutive substrings of the string. (The constructed
+encoding is not particularly interesting, since UTCTime
+values are so short, but the constructed encoding is
+permitted.)
+
+Example: The time this sentence was originally written was
+4:45:40 p.m. Pacific Daylight Time on May 6, 1991, which can
+be represented with either of the following UTCTime values,
+among others:
+
+"910506164540-0700"
+
+"910506234540Z"
+
+These values have the following BER encodings, among others:
+
+17 0d 39 31 30 35 30 36 32 33 34 35 34 30 5a
+
+17 11 39 31 30 35 30 36 31 36 34 35 34 30 2D 30 37 30
+      30
+
+DER encoding. Primitive. Contents octets are as for a
+primitive BER encoding.
+
+
+6. An example
+
+This section gives an example of ASN.1 notation and DER
+encoding: the X.501 type Name.
+
+
+6.1 Abstract notation
+
+This section gives the ASN.1 notation for the X.501 type
+Name.
+
+Name ::= CHOICE {
+  RDNSequence }
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+RelativeDistinguishedName ::=
+  SET OF AttributeValueAssertion
+
+AttributeValueAssertion ::= SEQUENCE {
+   AttributeType,
+   AttributeValue }
+
+AttributeType ::= OBJECT IDENTIFIER
+
+AttributeValue ::= ANY
+
+The Name type identifies an object in an X.500 directory.
+Name is a CHOICE type consisting of one alternative:
+RDNSequence. (Future revisions of X.500 may have other
+alternatives.)
+
+The RDNSequence type gives a path through an X.500 directory
+tree starting at the root. RDNSequence is a SEQUENCE OF type
+consisting of zero or more occurences of
+RelativeDistinguishedName.
+
+The RelativeDistinguishedName type gives a unique name to an
+object relative to the object superior to it in the
+directory tree. RelativeDistinguishedName is a SET OF type
+consisting of zero or more occurrences of
+AttributeValueAssertion.
+
+The AttributeValueAssertion type assigns a value to some
+attribute of a relative distinguished name, such as country
+name or common name. AttributeValueAssertion is a SEQUENCE
+type consisting of two components, an AttributeType type and
+an AttributeValue type.
+
+The AttributeType type identifies an attribute by object
+identifier. The AttributeValue type gives an arbitrary
+attribute value. The actual type of the attribute value is
+determined by the attribute type.
+
+
+6.2 DER encoding
+
+This section gives an example of a DER encoding of a value
+of type Name, working from the bottom up.
+
+The name is that of the Test User 1 from the PKCS examples
+[Kal93]. The name is represented by the following path:
+
+                           (root)
+                              |
+                     countryName = "US"
+                              |
+          organizationName = "Example Organization"
+                              |
+                 commonName = "Test User 1"
+
+Each level corresponds to one RelativeDistinguishedName
+value, each of which happens for this name to consist of one
+AttributeValueAssertion value. The AttributeType value is
+before the equals sign, and the AttributeValue value (a
+printable string for the given attribute types) is after the
+equals sign.
+
+The countryName, organizationName, and commonUnitName are
+attribute types defined in X.520 as:
+
+attributeType OBJECT IDENTIFIER ::=
+  { joint-iso-ccitt(2) ds(5) 4 }
+
+countryName OBJECT IDENTIFIER ::= { attributeType 6 }
+organizationName OBJECT IDENTIFIER ::=
+  { attributeType 10 }
+commonUnitName OBJECT IDENTIFIER ::=
+  { attributeType 3 }
+
+
+6.2.1 AttributeType
+
+The three AttributeType values are OCTET STRING values, so
+their DER encoding follows the primitive, definite-length
+method:
+
+06 03 55 04 06                                   countryName
+
+06 03 55 04 0a                              organizationName
+
+06 03 55 04 03                                    commonName
+
+The identifier octets follow the low-tag form, since the tag
+is 6 for OBJECT IDENTIFIER. Bits 8 and 7 have value "0,"
+indicating universal class, and bit 6 has value "0,"
+indicating that the encoding is primitive. The length octets
+follow the short form. The contents octets are the
+concatenation of three octet strings derived from
+subidentifiers (in decimal): 40 * 2 + 5 = 85 = 5516; 4; and
+6, 10, or 3.
+
+
+6.2.2 AttributeValue
+
+The three AttributeValue values are PrintableString values,
+so their encodings follow the primitive, definite-length
+method:
+
+13 02 55 53                                             "US"
+
+13 14                                 "Example Organization"
+   45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61
+   74 69 6f 6e
+
+13 0b                                          "Test User 1"
+   54 65 73 74 20 55 73 65 72 20 31
+
+The identifier octets follow the low-tag-number form, since
+the tag for PrintableString, 19 (decimal), is between 0 and
+30. Bits 8 and 7 have value "0" since PrintableString is in
+the universal class. Bit 6 has value "0" since the encoding
+is primitive. The length octets follow the short form, and
+the contents octets are the ASCII representation of the
+attribute value.
+
+
+6.2.3 AttributeValueAssertion
+
+The three AttributeValueAssertion values are SEQUENCE
+values, so their DER encodings follow the constructed,
+definite-length method:
+
+30 09                                     countryName = "US"
+   06 03 55 04 06
+   13 02 55 53
+
+30 1b              organizationName = "Example Organizaiton"
+   06 03 55 04 0a
+   13 14 ... 6f 6e
+
+30 12                             commonName = "Test User 1"
+   06 03 55 04 0b
+   13 0b ... 20 31
+
+The identifier octets follow the low-tag-number form, since
+the tag for SEQUENCE, 16 (decimal), is between 0 and 30.
+Bits 8 and 7 have value "0" since SEQUENCE is in the
+universal class. Bit 6 has value "1" since the encoding is
+constructed. The length octets follow the short form, and
+the contents octets are the concatenation of the DER
+encodings of the attributeType and attributeValue
+components.
+
+
+6.2.4 RelativeDistinguishedName
+
+The three RelativeDistinguishedName values are SET OF
+values, so their DER encodings follow the constructed,
+definite-length method:
+
+31 0b
+   30 09 ... 55 53
+
+31 1d
+   30 1b ... 6f 6e
+
+31 14
+   30 12 ... 20 31
+
+The identifier octets follow the low-tag-number form, since
+the tag for SET OF, 17 (decimal), is between 0 and 30. Bits
+8 and 7 have value "0" since SET OF is in the universal
+class Bit 6 has value "1" since the encoding is constructed.
+The lengths octets follow the short form, and the contents
+octets are the DER encodings of the respective
+AttributeValueAssertion values, since there is only one
+value in each set.
+
+
+6.2.5 RDNSequence
+
+The RDNSequence value is a SEQUENCE OF value, so its DER
+encoding follows the constructed, definite-length method:
+
+30 42
+   31 0b ... 55 53
+   31 1d ... 6f 6e
+   31 14 ... 20 31
+
+The identifier octets follow the low-tag-number form, since
+the tag for SEQUENCE OF, 16 (decimal), is between 0 and 30.
+Bits 8 and 7 have value "0" since SEQUENCE OF is in the
+universal class. Bit 6 has value "1" since the encoding is
+constructed. The lengths octets follow the short form, and
+the contents octets are the concatenation of the DER
+encodings of the three RelativeDistinguishedName values, in
+order of occurrence.
+
+
+6.2.6 Name
+
+The Name value is a CHOICE value, so its DER encoding is the
+same as that of the RDNSequence value:
+
+30 42
+   31 0b
+      30 09
+         06 03 55 04 06          attributeType = countryName
+         13 02 55 53                   attributeValue = "US"
+   31 1d
+      30 1b
+         06 03 55 04 0a     attributeType = organizationName
+         13 14       attributeValue = "Example Organization"
+            45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61
+            74 69 6f 6e
+
+   31 14
+      30 12
+         06 03 55 04 03           attributeType = commonName
+         13 0b                attributeValue = "Test User 1"
+            54 65 73 74 20 55 73 65 72 20 31
+
+
+References
+
+PKCS #1   RSA Laboratories. PKCS #1: RSA Encryption
+          Standard. Version 1.5, November 1993.
+
+PKCS #3   RSA Laboratories. PKCS #3: Diffie-Hellman Key-
+          Agreement Standard. Version 1.4, November 1993.
+
+PKCS #5   RSA Laboratories. PKCS #5: Password-Based
+          Encryption Standard. Version 1.5, November 1993.
+
+PKCS #6   RSA Laboratories. PKCS #6: Extended-Certificate
+          Syntax Standard. Version 1.5, November 1993.
+
+PKCS #7   RSA Laboratories. PKCS #7: Cryptographic Message
+          Syntax Standard. Version 1.5, November 1993.
+
+PKCS #8   RSA Laboratories. PKCS #8: Private-Key Information
+          Syntax Standard. Version 1.2, November 1993.
+
+PKCS #9   RSA Laboratories. PKCS #9: Selected Attribute
+          Types. Version 1.1, November 1993.
+
+PKCS #10  RSA Laboratories. PKCS #10: Certification Request
+          Syntax Standard. Version 1.0, November 1993.
+
+X.200     CCITT. Recommendation X.200: Reference Model of
+          Open Systems Interconnection for CCITT
+          Applications. 1984.
+
+X.208     CCITT. Recommendation X.208: Specification of
+          Abstract Syntax Notation One (ASN.1). 1988.
+
+X.209     CCITT. Recommendation X.209: Specification of
+          Basic Encoding Rules for Abstract Syntax Notation
+          One (ASN.1). 1988.
+
+X.500     CCITT. Recommendation X.500: The
+          Directory--Overview of Concepts, Models and
+          Services. 1988.
+
+X.501     CCITT. Recommendation X.501: The Directory--
+          Models. 1988.
+
+X.509     CCITT. Recommendation X.509: The Directory--
+          Authentication Framework. 1988.
+
+X.520     CCITT. Recommendation X.520: The Directory--
+          Selected Attribute Types. 1988.
+
+[Kal93]   Burton S. Kaliski Jr. Some Examples of the PKCS
+          Standards. RSA Laboratories, November 1993.
+
+[NIST92]  NIST. Special Publication 500-202: Stable
+          Implementation Agreements for Open Systems
+          Interconnection Protocols. Part 11 (Directory
+          Services Protocols). December 1992.
+
+
+Revision history
+
+
+June 3, 1991 version
+
+The June 3, 1991 version is part of the initial public
+release of PKCS. It was published as NIST/OSI Implementors'
+Workshop document SEC-SIG-91-17.
+
+
+November 1, 1993 version
+
+The November 1, 1993 version incorporates several editorial
+changes, including the addition of a revision history. It is
+updated to be consistent with the following versions of the
+PKCS documents:
+
+     PKCS #1: RSA Encryption Standard. Version 1.5, November
+          1993.
+
+     PKCS #3: Diffie-Hellman Key-Agreement Standard. Version
+          1.4, November 1993.
+
+     PKCS #5: Password-Based Encryption Standard. Version
+          1.5, November 1993.
+
+     PKCS #6: Extended-Certificate Syntax Standard. Version
+          1.5, November 1993.
+
+     PKCS #7: Cryptographic Message Syntax Standard. Version
+          1.5, November 1993.
+
+     PKCS #8: Private-Key Information Syntax Standard.
+          Version 1.2, November 1993.
+
+     PKCS #9: Selected Attribute Types. Version 1.1,
+          November 1993.
+
+     PKCS #10: Certification Request Syntax Standard.
+          Version 1.0, November 1993.
+
+The following substantive changes were made:
+
+     Section 5: Description of T61String type is added.
+
+     Section 6: Names are changed, consistent with other
+          PKCS examples.
+
+
+Author's address
+
+Burton S. Kaliski Jr., Ph.D.
+Chief Scientist
+RSA Laboratories              (415) 595-7703
+100 Marine Parkway            (415) 595-4126 (fax)
+Redwood City, CA  94065  USA  burt@rsa.com
diff --git a/src/kerberosV/src/doc/mdate-sh b/src/kerberosV/src/doc/mdate-sh
new file mode 100644 (file)
index 0000000..37171f2
--- /dev/null
@@ -0,0 +1,92 @@
+#!/bin/sh
+# Get modification time of a file or directory and pretty-print it.
+# Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+# written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, June 1995
+#
+# 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.
+
+# Prevent date giving response in another language.
+LANG=C
+export LANG
+LC_ALL=C
+export LC_ALL
+LC_TIME=C
+export LC_TIME
+
+# Get the extended ls output of the file or directory.
+# On HPUX /bin/sh, "set" interprets "-rw-r--r--" as options, so the "x" below.
+if ls -L /dev/null 1>/dev/null 2>&1; then
+  set - x`ls -L -l -d $1`
+else
+  set - x`ls -l -d $1`
+fi
+# The month is at least the fourth argument
+# (3 shifts here, the next inside the loop).
+shift
+shift
+shift
+
+# Find the month.  Next argument is day, followed by the year or time.
+month=
+until test $month
+do
+  shift
+  case $1 in
+    Jan) month=January; nummonth=1;;
+    Feb) month=February; nummonth=2;;
+    Mar) month=March; nummonth=3;;
+    Apr) month=April; nummonth=4;;
+    May) month=May; nummonth=5;;
+    Jun) month=June; nummonth=6;;
+    Jul) month=July; nummonth=7;;
+    Aug) month=August; nummonth=8;;
+    Sep) month=September; nummonth=9;;
+    Oct) month=October; nummonth=10;;
+    Nov) month=November; nummonth=11;;
+    Dec) month=December; nummonth=12;;
+  esac
+done
+
+day=$2
+
+# Here we have to deal with the problem that the ls output gives either
+# the time of day or the year.
+case $3 in
+  *:*) set `date`; eval year=\$$#
+       case $2 in
+        Jan) nummonthtod=1;;
+        Feb) nummonthtod=2;;
+        Mar) nummonthtod=3;;
+        Apr) nummonthtod=4;;
+        May) nummonthtod=5;;
+        Jun) nummonthtod=6;;
+        Jul) nummonthtod=7;;
+        Aug) nummonthtod=8;;
+        Sep) nummonthtod=9;;
+        Oct) nummonthtod=10;;
+        Nov) nummonthtod=11;;
+        Dec) nummonthtod=12;;
+       esac
+       # For the first six month of the year the time notation can also
+       # be used for files modified in the last year.
+       if (expr $nummonth \> $nummonthtod) > /dev/null;
+       then
+        year=`expr $year - 1`
+       fi;;
+  *) year=$3;;
+esac
+
+# The result.
+echo $day $month $year
diff --git a/src/kerberosV/src/doc/migration.texi b/src/kerberosV/src/doc/migration.texi
new file mode 100644 (file)
index 0000000..e4ed01e
--- /dev/null
@@ -0,0 +1,43 @@
+@c $KTH: migration.texi,v 1.3 2001/02/24 05:09:24 assar Exp $
+
+@node Migration, Acknowledgments, Programming with Kerberos, Top
+@chapter Migration
+
+@section General issues
+
+When migrating from a Kerberos 4 KDC.
+
+@section Order in what to do things:
+
+@itemize @bullet
+
+@item Convert the database, check all principals that hprop complains
+about.
+
+@samp{hprop -n --source=<NNN>| hpropd -n}
+
+Replace <NNN> with whatever source you have, like krb4-db or krb4-dump.
+
+@item Run a Kerberos 5 slave for a while.
+
+@c XXX Add you slave first to your kdc list in you kdc.
+
+@item Figure out if it does everything you want it to.
+
+Make sure that all things that you use works for you.
+
+@item Let a small number of controlled users use Kerberos 5 tools.
+
+Find a sample population of your users and check what programs they use,
+you can also check the kdc-log to check what ticket are checked out.
+
+@item Burn the bridge and change the master.
+@item Let all users use the Kerberos 5 tools by default.
+@item Turn off services that do not need Kerberos 4 authentication.
+
+Things that might be hard to get away is old programs with support for
+Kerberos 4. Example applications are old Eudora installations using
+KPOP, and Zephyr. Eudora can use the Kerberos 4 kerberos in the Heimdal
+kdc.
+
+@end itemize
diff --git a/src/kerberosV/src/doc/misc.texi b/src/kerberosV/src/doc/misc.texi
new file mode 100644 (file)
index 0000000..ea2a1c4
--- /dev/null
@@ -0,0 +1,58 @@
+@c $KTH: misc.texi,v 1.14 2003/05/04 13:32:37 lha Exp $
+
+@node Things in search for a better place, Kerberos 4 issues, Applications, Top
+@chapter Things in search for a better place
+
+@section Making things work on Ciscos
+
+Modern versions of Cisco IOS has some support for authenticating via
+Kerberos 5. This can be used both by having the router get a ticket when
+you login (boring), and by using Kerberos authenticated telnet to access
+your router (less boring). The following has been tested on IOS
+11.2(12), things might be different with other versions. Old versions
+are known to have bugs.
+
+To make this work, you will first have to configure your router to use
+Kerberos (this is explained in the documentation). A sample
+configuration looks like the following:
+
+@example
+aaa new-model
+aaa authentication login default krb5-telnet krb5 enable
+aaa authorization exec krb5-instance
+kerberos local-realm FOO.SE
+kerberos srvtab entry host/router.foo.se 0 891725446 4 1 8 012345678901234567
+kerberos server FOO.SE 10.0.0.1
+kerberos instance map admin 15
+@end example
+
+This tells you (among other things) that when logging in, the router
+should try to authenticate with kerberised telnet, and if that fails try
+to verify a plain text password via a Kerberos ticket exchange (as
+opposed to a local database, RADIUS or something similar), and if that
+fails try the local enable password. If you're not careful when you
+specify the `login default' authentication mechanism, you might not be
+able to login at all. The `instance map' and `authorization exec' lines
+says that people with `admin' instances should be given `enabled' shells
+when logging in.
+
+The numbers after the principal on the `srvtab' line are principal type,
+time stamp (in seconds since 1970), key version number (4), keytype (1 ==
+des), key length (always 8 with des), and then the key.
+
+To make the Heimdal KDC produce tickets that the Cisco can decode you
+might have to turn on the @samp{encode_as_rep_as_tgs_rep} flag in the
+KDC. You will also have to specify that the router can't handle anything
+but @samp{des-cbc-crc}. This can be done with the @samp{del_enctype}
+command of @samp{kadmin}.
+
+This all fine and so, but unless you have an IOS version with encryption
+(available only in the U.S) it doesn't really solve any problems. Sure
+you don't have to send your password over the wire, but since the telnet
+connection isn't protected it's still possible for someone to steal your
+session. This won't be fixed until someone adds integrity to the telnet
+protocol.
+
+A working solution would be to hook up a machine with a real operating
+system to the console of the Cisco and then use it as a backwards
+terminal server.
diff --git a/src/kerberosV/src/doc/programming.texi b/src/kerberosV/src/doc/programming.texi
new file mode 100644 (file)
index 0000000..cfe6f0b
--- /dev/null
@@ -0,0 +1,330 @@
+@c $KTH: programming.texi,v 1.7 2005/06/07 00:50:09 lha Exp $
+
+@node Programming with Kerberos
+@chapter Programming with Kerberos
+
+First you need to know how the Kerberos model works, go read the
+introduction text (@pxref{What is Kerberos?}).
+
+@menu
+* Kerberos 5 API Overview::     
+* Walkthru a sample Kerberos 5 client::  
+* Validating a password in a server application::  
+* API diffrences to MIT Kerberos::
+@end menu
+
+@node Kerberos 5 API Overview, Walkthru a sample Kerberos 5 client, Programming with Kerberos, Programming with Kerberos
+@section Kerberos 5 API Overview
+
+Most functions are documenteded in manual pages.  This overview only
+tries to point to where to look for a specific function.
+
+@subsection Kerberos context
+
+A kerberos context (@code{krb5_context}) holds all per thread state. All global variables that
+are context specific are stored in this struture, including default
+encryption types, credential-cache (ticket file), and default realms.
+
+See the manual pages for @manpage{krb5_context,3} and
+@manpage{krb5_init_context,3}.
+
+@subsection Kerberos authenication context
+
+Kerberos authentication context (@code{krb5_auth_context}) holds all
+context related to an authenticated connection, in a similar way to the
+kerberos context that holds the context for the thread or process.
+
+The @code{krb5_auth_context} is used by various functions that are
+directly related to authentication between the server/client. Example of
+data that this structure contains are various flags, addresses of client
+and server, port numbers, keyblocks (and subkeys), sequence numbers,
+replay cache, and checksum types.
+
+See the manual page for @manpage{krb5_auth_context,3}.
+
+@subsection Keytab management
+
+A keytab is a storage for locally stored keys. Heimdal includes keytab
+support for Kerberos 5 keytabs, Kerberos 4 srvtab, AFS-KeyFile's,
+and for storing keys in memory.
+
+See also manual page for @manpage{krb5_keytab,3}
+
+@subsection Kerberos principal
+
+See also manual page for @manpage{krb5_principal,3}
+
+@subsection Kerberos crypto
+
+See also manual page for @manpage{krb5_crypto_init,3},
+@manpage{krb5_keyblock,3}, @manpage{krb5_create_checksum,3}, 
+and @manpage{krb5_encrypt,3}.
+
+@node Walkthru a sample Kerberos 5 client, Validating a password in a server application, Kerberos 5 API Overview, Programming with Kerberos
+@section Walkthru a sample Kerberos 5 client
+
+This example contains parts of a sample TCP Kerberos 5 clients, if you
+want a real working client, please look in @file{appl/test} directory in
+the Heimdal distribution.
+
+All Kerberos error-codes that are returned from kerberos functions in
+this program are passed to @code{krb5_err}, that will print a
+descriptive text of the error code and exit. Graphical programs can
+convert error-code to a humal readable error-string with the
+@manpage{krb5_get_err_text,3} function.
+
+Note that you should not use any Kerberos function before
+@code{krb5_init_context()} have completed successfully. That is the
+reson @code{err()} is used when @code{krb5_init_context()} fails.
+
+First the client needs to call @code{krb5_init_context} to initialise
+the Kerberos 5 library. This is only needed once per thread
+in the program. If the function returns a non-zero value it indicates
+that either the Kerberos implemtation is failing or its disabled on
+this host.
+
+@example
+#include <krb5.h>
+
+int
+main(int argc, char **argv)
+@{
+        krb5_context context;
+
+        if (krb5_context(&context))
+                errx (1, "krb5_context");
+@end example
+
+Now the client wants to connect to the host at the other end. The
+preferred way of doing this is using @manpage{getaddrinfo,3} (for
+operating system that have this function implemented), since getaddrinfo
+is neutral to the address type and can use any protocol that is available.
+
+@example
+        struct addrinfo *ai, *a;
+        struct addrinfo hints;
+        int error;
+
+        memset (&hints, 0, sizeof(hints));
+        hints.ai_socktype = SOCK_STREAM;
+        hints.ai_protocol = IPPROTO_TCP;
+
+        error = getaddrinfo (hostname, "pop3", &hints, &ai);
+        if (error)
+                errx (1, "%s: %s", hostname, gai_strerror(error));
+
+        for (a = ai; a != NULL; a = a->ai_next) @{
+                int s;
+
+                s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+                if (s < 0)
+                        continue;
+                if (connect (s, a->ai_addr, a->ai_addrlen) < 0) @{
+                        warn ("connect(%s)", hostname);
+                            close (s);
+                            continue;
+                @}
+                freeaddrinfo (ai);
+                ai = NULL;
+        @}
+        if (ai) @{
+                    freeaddrinfo (ai);
+                    errx ("failed to contact %s", hostname);
+        @}
+@end example
+
+Before authenticating, an authentication context needs to be
+created. This context keeps all information for one (to be) authenticated
+connection (see @manpage{krb5_auth_context,3}).
+
+@example
+        status = krb5_auth_con_init (context, &auth_context);
+        if (status)
+                krb5_err (context, 1, status, "krb5_auth_con_init");
+@end example
+
+For setting the address in the authentication there is a help function
+@code{krb5_auth_con_setaddrs_from_fd} that does everthing that is needed
+when given a connected file descriptor to the socket.
+
+@example
+        status = krb5_auth_con_setaddrs_from_fd (context,
+                                                 auth_context,
+                                                 &sock);
+        if (status)
+                krb5_err (context, 1, status, 
+                          "krb5_auth_con_setaddrs_from_fd");
+@end example
+
+The next step is to build a server principal for the service we want
+to connect to. (See also @manpage{krb5_sname_to_principal,3}.)
+
+@example
+        status = krb5_sname_to_principal (context,
+                                          hostname,
+                                          service,
+                                          KRB5_NT_SRV_HST,
+                                          &server);
+        if (status)
+                krb5_err (context, 1, status, "krb5_sname_to_principal");
+@end example
+
+The client principal is not passed to @manpage{krb5_sendauth,3}
+function, this causes the @code{krb5_sendauth} function to try to figure it
+out itself.
+
+The server program is using the function @manpage{krb5_recvauth,3} to
+receive the Kerberos 5 authenticator.
+
+In this case, mutual authenication will be tried. That means that the server
+will authenticate to the client. Using mutual authenication
+is good since it enables the user to verify that they are talking to the
+right server (a server that knows the key).
+
+If you are using a non-blocking socket you will need to do all work of
+@code{krb5_sendauth} yourself. Basically you need to send over the
+authenticator from @manpage{krb5_mk_req,3} and, in case of mutual
+authentication, verifying the result from the server with
+@manpage{krb5_rd_rep,3}.
+
+@example
+        status = krb5_sendauth (context,
+                                &auth_context,
+                                &sock,
+                                VERSION,
+                                NULL,
+                                server,
+                                AP_OPTS_MUTUAL_REQUIRED,
+                                NULL,
+                                NULL,
+                                NULL,
+                                NULL,
+                                NULL,
+                                NULL);
+        if (status)
+                krb5_err (context, 1, status, "krb5_sendauth");
+@end example
+
+Once authentication has been performed, it is time to send some
+data. First we create a krb5_data structure, then we sign it with
+@manpage{krb5_mk_safe,3} using the @code{auth_context} that contains the
+session-key that was exchanged in the
+@manpage{krb5_sendauth,3}/@manpage{krb5_recvauth,3} authentication
+sequence.
+
+@example
+        data.data   = "hej";
+        data.length = 3;
+
+        krb5_data_zero (&packet);
+
+        status = krb5_mk_safe (context,
+                               auth_context,
+                               &data,
+                               &packet,
+                               NULL);
+        if (status)
+                krb5_err (context, 1, status, "krb5_mk_safe");
+@end example
+
+And send it over the network.
+
+@example
+        len = packet.length;
+        net_len = htonl(len);
+
+        if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+                err (1, "krb5_net_write");
+        if (krb5_net_write (context, &sock, packet.data, len) != len)
+                err (1, "krb5_net_write");
+@end example
+
+To send encrypted (and signed) data @manpage{krb5_mk_priv,3} should be
+used instead. @manpage{krb5_mk_priv,3} works the same way as
+@manpage{krb5_mk_safe,3}, with the exception that it encrypts the data
+in addition to signing it.
+
+@example
+        data.data   = "hemligt";
+        data.length = 7;
+
+        krb5_data_free (&packet);
+
+        status = krb5_mk_priv (context,
+                               auth_context,
+                               &data,
+                               &packet,
+                               NULL);
+        if (status)
+                krb5_err (context, 1, status, "krb5_mk_priv");
+@end example
+
+And send it over the network.
+
+@example
+        len = packet.length;
+        net_len = htonl(len);
+
+        if (krb5_net_write (context, &sock, &net_len, 4) != 4)
+                err (1, "krb5_net_write");
+        if (krb5_net_write (context, &sock, packet.data, len) != len)
+                err (1, "krb5_net_write");
+
+@end example
+
+The server is using @manpage{krb5_rd_safe,3} and
+@manpage{krb5_rd_priv,3} to verify the signature and decrypt the packet.
+
+@node Validating a password in a server application, API diffrences to MIT Kerberos, Walkthru a sample Kerberos 5 client, Programming with Kerberos
+@section Validating a password in an application
+
+See the manual page for @manpage{krb5_verify_user,3}.
+
+@node API diffrences to MIT Kerberos, , Validating a password in a server application, Programming with Kerberos
+@section API diffrences to MIT Kerberos
+
+This section is somewhat disorganised, but so far there is no overall
+structure to the differences, though some of the have their root in
+that Heimdal uses an ASN.1 compiler and MIT doesn't.
+
+@subsection Principal and realms
+
+Heimdal stores the realm as a @code{krb5_realm}, that is a @code{char *}.
+MIT Kerberos uses a @code{krb5_data} to store a realm.
+
+In Heimdal @code{krb5_principal} doesn't contain the component
+@code{name_type}; it's instead stored in component
+@code{name.name_type}. To get and set the nametype in Heimdal, use
+@manpage{krb5_principal_get_type,3} and
+@manpage{krb5_principal_set_type,3}.
+
+For more information about principal and realms, see
+@manpage{krb5_principal,3}.
+
+@subsection Error messages
+
+To get the error string, Heimdal uses
+@manpage{krb5_get_error_string,3} or, if @code{NULL} is returned,
+@manpage{krb5_get_err_text,3}. This is to return custom error messages
+(like ``Can't find host/datan.example.com@@EXAMPLE.COM in
+/etc/krb5.conf.'' instead of a ``Key table entry not found'' that
+@manpage{error_message,3} returns.
+
+Heimdal uses a threadsafe(r) version of the com_err interface; the
+global @code{com_err} table isn't initialised.  Then
+@manpage{error_message,3} returns quite a boring error string (just
+the error code itself).
+
+
+@c @node Why you should use GSS-API for new applications, Walkthru a sample GSS-API client, Validating a password in a server application, Programming with Kerberos
+@c @section Why you should use GSS-API for new applications
+@c 
+@c SSPI, bah, bah, microsoft, bah, bah, almost GSS-API.
+@c 
+@c It would also be possible for other mechanisms then Kerberos, but that
+@c doesn't exist any other GSS-API implementations today.
+@c 
+@c @node Walkthru a sample GSS-API client, , Why you should use GSS-API for new applications, Programming with Kerberos
+@c @section Walkthru a sample GSS-API client
+@c 
+@c Write about how gssapi_clent.c works.
diff --git a/src/kerberosV/src/doc/setup.texi b/src/kerberosV/src/doc/setup.texi
new file mode 100644 (file)
index 0000000..0543e57
--- /dev/null
@@ -0,0 +1,989 @@
+@c $KTH: setup.texi,v 1.55 2005/06/07 00:54:51 lha Exp $
+
+@node Setting up a realm, Applications, Building and Installing, Top
+
+@chapter Setting up a realm
+
+@menu
+* Configuration file::
+* Creating the database::
+* Modifying the database::
+* keytabs::
+* Serving Kerberos 4/524/kaserver::
+* Remote administration::
+* Password changing::
+* Testing clients and servers::
+* Slave Servers::
+* Incremental propagation::
+* Salting::
+* Cross realm::
+* Transit policy::
+* Setting up DNS::
+* Using LDAP to store the database::
+* Providing Kerberos credentials to servers and programs::
+@end menu
+
+A
+@cindex realm
+realm is an administrative domain.  The name of a Kerberos realm is
+usually the Internet domain name in uppercase.  Call your realm the same
+as your Internet domain name if you do not have strong reasons for not
+doing so.  It will make life easier for you and everyone else.
+
+@node  Configuration file, Creating the database, Setting up a realm, Setting up a realm
+@section Configuration file
+
+To setup a realm you will first have to create a configuration file:
+@file{/etc/kerberosV/krb5.conf}. The @file{krb5.conf} file can contain many
+configuration options, some of which are described here.
+
+There is a sample @file{krb5.conf} supplied in
+@file{/etc/kerberosV/krb5.conf.sample}.
+
+The configuration file is a hierarchical structure consisting of
+sections, each containing a list of bindings (either variable
+assignments or subsections). A section starts with
+@samp{[@samp{section-name}]}.  A binding consists of a left hand side, an equal
+(@samp{=}) and a right hand side (the left hand side tag must be
+separated from the equal with some whitespace). Subsections has a
+@samp{@{} as the first non-whitespace character after the equal. All
+other bindings are treated as variable assignments. The value of a
+variable extends to the end of the line.
+
+@example
+[section1]
+        a-subsection = @{
+                var = value1
+                other-var = value with @{@}
+                sub-sub-section = @{ 
+                        var = 123
+                @}
+        @}
+        var = some other value
+[section2]
+        var = yet another value
+@end example
+
+In this manual, names of sections and bindings will be given as strings
+separated by slashes (@samp{/}). The @samp{other-var} variable will thus
+be @samp{section1/a-subsection/other-var}.
+
+For in-depth information about the contents of the configuration file, refer to
+the @file{krb5.conf} manual page. Some of the more important sections
+are briefly described here.
+
+The @samp{libdefaults} section contains a list of library configuration
+parameters, such as the default realm and the timeout for KDC
+responses. The @samp{realms} section contains information about specific
+realms, such as where they hide their KDC@. This section serves the same
+purpose as the Kerberos 4 @file{krb.conf} file, but can contain more
+information. Finally the @samp{domain_realm} section contains a list of
+mappings from domains to realms, equivalent to the Kerberos 4
+@file{krb.realms} file.
+
+To continue with the realm setup, you will have to create a configuration file,
+with contents similar to the following.
+
+@example
+[libdefaults]
+        default_realm = MY.REALM
+[realms]
+        MY.REALM = @{
+                kdc = my.kdc my.slave.kdc
+                kdc = my.third.kdc
+        @}
+[domain_realm]
+        .my.domain = MY.REALM
+
+@end example
+
+If you use a realm name equal to your domain name, you can omit the
+@samp{libdefaults}, and @samp{domain_realm}, sections. If you have a DNS
+SRV-record for your realm, or your Kerberos server has DNS CNAME
+@samp{kerberos.my.realm}, you can omit the @samp{realms} section too.
+
+@node Creating the database, Modifying the database, Configuration file, Setting up a realm
+@section Creating the database
+
+The database library will look for the database in the directory
+@file{/var/heimdal}, so you should probably create that directory.
+Make sure the directory has restrictive permissions.
+
+@example
+# mkdir /var/heimdal
+@end example
+
+The keys of all the principals are stored in the database.  If you
+choose to, these can be encrypted with a master key.  You do not have to
+remember this key (or password), but just to enter it once and it will
+be stored in a file (@file{/var/heimdal/m-key}).  If you want to have a
+master key, run @samp{kstash} to create this master key:
+
+@example
+# kstash
+Master key: 
+Verifying password - Master key: 
+@end example
+
+If you want to generate a random master key you can use the
+@kbd{--random-key} flag to kstash. This will make sure you have a good
+key on which attackers can't do a dictionary attack.
+
+If you have a master key, make sure you make a backup of your master
+key file; without it backups of the database are of no use.
+
+To initialise the database use the @command{kadmin} program, with the
+@samp{-l} option (to enable local database mode). First issue a
+@kbd{init MY.REALM} command. This will create the database and insert
+default principals for that realm. You can have more than one realm in
+one database, so @samp{init} does not destroy any old database.
+
+Before creating the database, @samp{init} will ask you some questions
+about maximum ticket lifetimes.
+
+After creating the database you should probably add yourself to it. You
+do this with the @samp{add} command. It takes as argument the name of a
+principal. The principal should contain a realm, so if you haven't set up
+a default realm, you will need to explicitly include the realm.
+
+@example
+# kadmin -l
+kadmin> init MY.REALM
+Realm max ticket life [unlimited]:
+Realm max renewable ticket life [unlimited]:
+kadmin> add me  
+Max ticket life [unlimited]:
+Max renewable life [unlimited]:
+Attributes []:
+Password: 
+Verifying password - Password: 
+@end example
+
+Now start the KDC and try getting a ticket.
+
+@example
+# /usr/libexec/kdc &
+# kinit me
+me@@MY.REALMS's Password:
+# klist
+Credentials cache: /tmp/krb5cc_0
+        Principal: me@@MY.REALM
+
+  Issued           Expires          Principal
+Aug 25 07:25:55  Aug 25 17:25:55  krbtgt/MY.REALM@@MY.REALM
+@end example
+
+You can start the KDC automatically at boot by enabling it in
+@file{/etc/rc.conf}.
+
+If you are curious you can use the @samp{dump} command of kadmin to list all the
+entries in the database.  It should look something similar to the
+following example (note that the entries here are truncated for
+typographical reasons):
+
+@smallexample
+kadmin> dump
+me@@MY.REALM 1:0:1:0b01d3cb7c293b57:-:0:7:8aec316b9d1629e3baf8 ...
+kadmin/admin@@MY.REALM 1:0:1:e5c8a2675b37a443:-:0:7:cb913ebf85 ...
+krbtgt/MY.REALM@@MY.REALM 1:0:1:52b53b61c875ce16:-:0:7:c8943be ...
+kadmin/changepw@@MY.REALM 1:0:1:f48c8af2b340e9fb:-:0:7:e3e6088 ...
+@end smallexample
+
+@node Modifying the database, keytabs, Creating the database, Setting up a realm
+@section Modifying the database
+
+All modifications of principals are done with with kadmin.
+
+A principal have several attributes and lifetimes associated with it.
+
+Principals are added, renamed, modified, and deleted with the kadmin
+commands @samp{add}, @samp{rename}, @samp{modify}, @samp{delete}.
+Both interactive editing and command switches can be used (use --help
+to list the available options).
+
+There are different kind of types for the fields in the database,
+attributes, absolute time times and relative times.
+
+@subsection Attributes
+
+When doing interactive editing, attributes are listed with @samp{?}.
+
+The attributes are given in a comma (@samp{,}) separated list.
+Attributes are removed from the list by prefixing them with @samp{-}.
+
+@smallexample
+kadmin> modify me
+Max ticket life [1 day]:
+Max renewable life [1 week]:
+Principal expiration time [never]:
+Password expiration time [never]:
+Attributes [disallow-renewable]: requires-pre-auth,-disallow-renewable
+kadmin> get me
+            Principal: me@@MY.REALM
+[...]
+           Attributes: requires-pre-auth
+@end smallexample
+
+@subsection Absolute times
+
+The format for absolute times are any of the following
+
+@smallexample
+never
+now
+YYYY-mm-dd
+YYYY-mm-dd HH:MM:SS
+@end smallexample
+
+
+@subsection Relative times
+
+The format for relative times are any of the following combined
+
+@smallexample
+N year
+M month
+O day
+P hour
+Q minute
+R second
+@end smallexample
+
+@c Describe more of kadmin commands here...
+
+@node keytabs, Serving Kerberos 4/524/kaserver, Modifying the database, Setting up a realm
+@section keytabs
+
+To extract a service ticket from the database and put it in a keytab, you
+need to first create the principal in the database with @samp{ank}
+(using the @kbd{--random-key} flag to get a random key) and then
+extract it with @samp{ext_keytab}.
+
+@example
+kadmin> add --random-key host/my.host.name
+Max ticket life [unlimited]:
+Max renewable life [unlimited]:
+Attributes []:
+kadmin> ext host/my.host.name
+kadmin> exit
+# ktutil list
+Version  Type             Principal
+     1   des-cbc-md5      host/my.host.name@@MY.REALM
+     1   des-cbc-md4      host/my.host.name@@MY.REALM
+     1   des-cbc-crc      host/my.host.name@@MY.REALM
+     1   des3-cbc-sha1    host/my.host.name@@MY.REALM
+@end example
+
+@node Serving Kerberos 4/524/kaserver, Remote administration, keytabs, Setting up a realm
+@section Serving Kerberos 4/524/kaserver
+
+Support for Kerberos 4 has been removed in OpenBSD.
+
+@node Remote administration, Password changing, Serving Kerberos 4/524/kaserver, Setting up a realm
+@section Remote administration
+
+The administration server, @command{kadmind}, can be started automatically
+at boot by enabling it in @file{/etc/rc.conf}.
+
+For testing purposes, you can start it manually by running:
+
+@smallexample
+# /usr/libexec/kadmind &
+@end smallexample
+
+Access to the administration server is controlled by an ACL file, (default
+@file{/var/heimdal/kadmind.acl}.) The lines in the access file, have the
+following syntax:
+@smallexample
+principal       [priv1,priv2,...]       [glob-pattern]
+@end smallexample
+
+The matching is from top to bottom for matching principals (and if given,
+glob-pattern).  When there is a match, the access rights of that line are
+used.
+
+The privileges you can assign to a principal are: @samp{add},
+@samp{change-password} (or @samp{cpw} for short), @samp{delete},
+@samp{get}, @samp{list}, and @samp{modify}, or the special privilege
+@samp{all}. All of these roughly corresponds to the different commands
+in @command{kadmin}.
+
+If a @var{glob-pattern} is given on a line, it restricts the access rights for
+the principal to only apply for the subjects that match the pattern.
+The patterns are of the same type as those used in shell globbing, see
+@url{none,,fnmatch(3)}.
+
+In the example below @samp{lha/admin} can change every principal in the
+database. @samp{jimmy/admin} can only modify principals that belong to
+the realm @samp{E.KTH.SE}. @samp{mille/admin} is working at the
+help desk, so he should only be able to change the passwords for single
+component principals (ordinary users). He will not be able to change any
+@samp{/admin} principal.
+
+@example
+lha/admin@@E.KTH.SE    all
+jimmy/admin@@E.KTH.SE  all             *@@E.KTH.SE
+jimmy/admin@@E.KTH.SE  all             */*@@E.KTH.SE
+mille/admin@@E.KTH.SE  change-password *@@E.KTH.SE
+@end example
+
+@node Password changing, Testing clients and servers, Remote administration, Setting up a realm
+@section Password changing
+
+To allow users to change their passwords, @samp{kpasswdd} is started
+automatically at boot if the master KDC is enabled in @file{/etc/rc.conf}.
+
+@subsection Password quality assurance
+
+It is important that users have good passwords, both to make it harder
+to guess them and to avoid off-line attacks (although
+pre-authentication provides some defense against off-line attacks).
+To ensure that the users choose good passwords, you can enable
+password quality controls in @command{kpasswdd} and @command{kadmind}.
+The controls themselves are done in a shared library or an external
+program that is used by @command{kpasswdd}.  To configure in these
+controls, add lines similar to the following to your
+@file{/etc/krb5.conf}:
+
+@example
+[password_quality]
+       policies = external-check builtin:minimum-length module:policyname
+       external_program = /bin/false
+       policy_libraries = @var{library1.so} @var{library2.so}
+@end example
+
+In @samp{[password_quality]policies} the module name is optional if
+the policy name is unique in all modules (members of
+@samp{policy_libraries}).
+
+The builtin polices are
+
+@itemize @bullet
+
+@item external-check
+
+Executes the program specified by @samp{[password_quality]external_program}. 
+
+A number of key/value pairs is passed as input to the program, one per
+line, ending with the string @samp{end}.  The key/value lines are of
+the form
+@example
+principal: @var{principal}
+new-password: @var{password}
+@end example
+where @var{password} is the password to check for the previous
+@var{principal}.
+
+If the external application approves the password, it should return
+@samp{APPROVED} on standard out and exit with exit code 0.  If it
+doesn't approve the password, a one line error message explaining the
+problem should be returned on standard error and the application
+should exit with exit code 0.  In case of a fatal error, the
+application should, if possible, print an error message on standard
+error and exit with a non-zero error code.
+
+@item minimum-length
+
+The minimum length password quality check reads the configuration file
+stanza @samp{[password_quality]min_length} and requires the password
+to be at least this length.
+
+@item character-class
+
+The character-class password quality check reads the configuration
+file stanza @samp{[password_quality]min_classes}. The policy requires
+the password to have characters from at least that many characters
+classes. Default value if not given is 3.
+
+The four diffrent characters classes are, uppercase, lowercase,
+number, special characters.
+
+@end itemize
+
+If you want to write you own shared object that checks password
+policies, see the manual page @manpage{kadm5_pwcheck,3}.
+
+Code for a password quality checking function that uses the cracklib
+library can be found in @file{lib/kadm5/sample_password_check.c} in the
+source code distribution.  It requires the cracklib library built with
+the patch available at
+@url{ftp://ftp.pdc.kth.se/pub/krb/src/cracklib.patch}.
+
+A sample policy external program is included in
+@file{lib/kadm5/check-cracklib.pl}.
+
+If no password quality checking function is configured, it is only
+verified that it is at least six characters long.
+
+The program @command{test_pw_quality}, which is built in
+@file{lib/kadm5}, but not installed, can be used to check password
+policy settings.  It may be convenient to set the environment variable
+@samp{KRB5_CONFIG} to point to a test version of @file{krb5.conf}
+while you're testing the @samp{[password_quality]} stanza that way.
+
+@node Testing clients and servers, Slave Servers, Password changing, Setting up a realm
+@section Testing clients and servers
+
+Now you should be able to run all the clients and servers.  Refer to the
+appropriate man pages for information on how to use them.
+
+@node Slave Servers, Incremental propagation, Testing clients and servers, Setting up a realm
+@section Slave servers, Incremental propagation, Testing clients and servers, Setting up a realm
+
+It is desirable to have at least one backup (slave) server in case the
+master server fails. It is possible to have any number of such slave
+servers but more than three usually doesn't buy much more redundancy.
+
+All Kerberos servers for a realm must have the same database so that
+they present the same service to all the users.  The
+@pindex hprop
+@command{hprop} program, running on the master, will propagate the database
+to the slaves, running
+@pindex hpropd
+@command{hpropd} processes.
+
+Every slave needs a database directory, the master key (if it was used
+for the database) and a keytab with the principal
+@samp{hprop/@var{hostname}}.  Add the principal with the
+@pindex ktutil
+@command{ktutil} command and start
+@pindex hpropd
+@command{hpropd}, as follows:
+
+@example
+slave# ktutil get -p foo/admin hprop/`hostname`
+slave# mkdir /var/heimdal
+slave# hpropd
+@end example
+
+The master will use the principal @samp{kadmin/hprop} to authenticate to
+the slaves.  This principal should be added when running @kbd{kadmin -l
+init} but if you do not have it in your database for whatever reason,
+please add it with @kbd{kadmin -l add}.
+
+Then run
+@pindex hprop
+@code{hprop} on the master:
+
+@example
+master# hprop slave
+@end example
+
+This was just an hands-on example to make sure that everything was
+working properly.  Doing it manually is of course the wrong way, and to
+automate this you will want to start
+@pindex hpropd
+@command{hpropd} from @command{inetd} on the slave(s) and regularly run
+@pindex hprop
+@command{hprop} on the master to regularly propagate the database.
+Starting the propagation once an hour from @command{cron} is probably a
+good idea.
+
+f@node Incremental propagation, Salting , Slave Servers, Setting up a realm
+@section Incremental propagation
+
+There is also a newer, and still somewhat experimental, mechanism for
+doing incremental propagation in Heimdal.  Instead of sending the whole
+database regularly, it sends the changes as they happen on the master to
+the slaves.  The master keeps track of all the changes by assigning a
+version number to every change to the database.  The slaves know which
+was the latest version they saw and in this way it can be determined if
+they are in sync or not.  A log of all the changes is kept on the master,
+and when a slave is at an older version than the oldest one in the
+log, the whole database has to be sent.
+
+Protocol-wise, all the slaves connect to the master and as a greeting
+tell it the latest version that they have (@samp{IHAVE} message).  The
+master then responds by sending all the changes between that version and
+the current version at the master (a series of @samp{FORYOU} messages)
+or the whole database in a @samp{TELLYOUEVERYTHING} message.  There is
+also a keep-alive protocol that makes sure all slaves are up and running.
+
+@subsection Configuring incremental propagation
+
+The program that runs on the master is @command{ipropd-master} and all
+clients run @command{ipropd-slave}.
+
+Create the file @file{/var/heimdal/slaves} on the master containing all
+the slaves that the database should be propagated to.  Each line contains
+the full name of the principal (for example
+@samp{iprop/hemligare.foo.se@@FOO.SE}).
+
+You should already have @samp{iprop/tcp} defined as 2121, in your
+@file{/etc/services}.  Otherwise, or if you need to use a different port
+for some peculiar reason, you can use the @kbd{--port} option.  This is
+useful when you have multiple realms to distribute from one server.
+
+Then you need to create those principals that you added in the
+configuration file.  Create one @samp{iprop/hostname} for the master and
+for every slave.
+
+
+@example
+master# /usr/heimdal/sbin/ktutil get iprop/`hostname`
+@end example
+
+The next step is to start the @command{ipropd-master} process on the master
+server.  The @command{ipropd-master} listens on the UNIX domain socket
+@file{/var/heimdal/signal} to know when changes have been made to the
+database so they can be propagated to the slaves.  There is also a
+safety feature of testing the version number regularly (every 30
+seconds) to see if it has been modified by some means that do not raise
+this signal.  Then, start @command{ipropd-slave} on all the slaves:
+
+@example
+master# /usr/heimdal/libexec/ipropd-master &
+slave#  /usr/heimdal/libexec/ipropd-slave master &
+@end example
+
+@node Salting, Cross realm, Incremental propagation, Setting up a realm
+@section Salting
+@cindex Salting
+
+Salting is used to make it harder to precalculate all possible
+keys. Using a salt increases the search space to make it almost
+impossible to precalculate all keys. Salting is the process of mixing a
+public string (the salt) with the password, then sending it through an
+encryption type specific string-to-key function that will output the
+fixed size encryption key.
+
+In Kerberos 5 the salt is determined by the encryption-type, except
+in some special cases.
+
+In @code{des} there is the Kerberos 4 salt
+(none at all) or the afs-salt (using the cell (realm in
+AFS lingo)).
+
+In @code{arcfour} (the encryption type that Microsoft Windows 2000 uses)
+there is no salt. This is to be compatible with NTLM keys in Windows
+NT 4.
+
+@code{[kadmin]default_keys} in @file{krb5.conf} controls
+what salting to use,
+
+The syntax of @code{[kadmin]default_keys} is
+@samp{[etype:]salt-type[:salt-string]}. @samp{etype} is the encryption
+type (des, des3, arcfour), @code{salt-type} is the type of salt (pw-salt
+or afs3-salt), and the salt-string is the string that will be used as
+salt (remember that if the salt is appended/prepended, the empty salt ""
+is the same thing as no salt at all).
+
+Common types of salting include
+
+@itemize @bullet
+@item @code{v4} (or @code{des:pw-salt:})
+
+The Kerberos 4 salting is using no salt at all. Reason there is colon
+at the end of the salt string is that it makes the salt the empty
+string (same as no salt).
+
+@item @code{v5} (or @code{pw-salt})
+
+@code{pw-salt} uses the default salt for each encryption type is
+specified for. If the encryption type @samp{etype} isn't given, all
+default encryption will be used.
+
+@item @code{afs3-salt}
+
+@code{afs3-salt} is the salt that is used with Transarc kaserver. Its
+the cell name appended to the password.
+
+@end itemize
+
+@node Cross realm, Transit policy , Salting, Setting up a realm
+@section Cross realm
+@cindex Cross realm
+
+Suppose you reside in the realm @samp{MY.REALM}, how do you
+authenticate to a server in @samp{OTHER.REALM}? Having valid tickets in
+@samp{MY.REALM} allows you to communicate with Kerberised services in that
+realm. However, the computer in the other realm does not have a secret
+key shared with the Kerberos server in your realm.
+
+It is possible to share keys between two realms that trust each
+other. When a client program, such as @command{telnet} or @command{ssh},
+finds that the other computer is in a different realm, it will try to
+get a ticket granting ticket for that other realm, but from the local
+Kerberos server. With that ticket granting ticket, it will then obtain
+service tickets from the Kerberos server in the other realm.
+
+For a two way trust between @samp{MY.REALM} and @samp{OTHER.REALM}
+add the following principals to each realm. The principals should be
+@samp{krbtgt/OTHER.REALM@@MY.REALM} and
+@samp{krbtgt/MY.REALM@@OTHER.REALM} in @samp{MY.REALM}, and
+@samp{krbtgt/MY.REALM@@OTHER.REALM} and
+@samp{krbtgt/OTHER.REALM@@MY.REALM}in @samp{OTHER.REALM}.
+
+In Kerberos 5 the trust can be configured to be one way. So that
+users from @samp{MY.REALM} can authenticate to services in
+@samp{OTHER.REALM}, but not the opposite. In the example above, the
+@samp{krbtgt/MY.REALM@@OTHER.REALM} then should be removed.
+
+The two principals must have the same key, key version number, and the
+same set of encryption types. Remember to transfer the two keys in a
+safe manner.
+
+@example
+@cartouche
+vr$ klist
+Credentials cache: FILE:/tmp/krb5cc_913.console
+        Principal: lha@@E.KTH.SE
+
+  Issued           Expires          Principal                   
+May  3 13:55:52  May  3 23:55:54  krbtgt/E.KTH.SE@@E.KTH.SE      
+
+vr$ telnet -l lha hummel.it.su.se
+Trying 2001:6b0:5:1095:250:fcff:fe24:dbf...
+Connected to hummel.it.su.se.
+Escape character is '^]'.
+Waiting for encryption to be negotiated...
+[ Trying mutual KERBEROS5 (host/hummel.it.su.se@@SU.SE)... ]
+[ Kerberos V5 accepts you as ``lha@@E.KTH.SE'' ]
+Encryption negotiated.
+Last login: Sat May  3 14:11:47 from vr.l.nxs.se
+hummel$ exit
+
+vr$ klist
+Credentials cache: FILE:/tmp/krb5cc_913.console
+        Principal: lha@@E.KTH.SE
+
+  Issued           Expires          Principal                   
+May  3 13:55:52  May  3 23:55:54  krbtgt/E.KTH.SE@@E.KTH.SE      
+May  3 13:55:56  May  3 23:55:54  krbtgt/SU.SE@@E.KTH.SE         
+May  3 14:10:54  May  3 23:55:54  host/hummel.it.su.se@@SU.SE    
+
+@end cartouche
+@end example
+
+@node Transit policy, Setting up DNS , Cross realm, Setting up a realm
+@section Transit policy
+@cindex Transit policy
+
+If you want to use cross realm authentication through an intermediate
+realm, it must be explicitly allowed by either the KDCs or the server
+receiving the request. This is done in @file{krb5.conf} in the
+@code{[capaths]} section.
+
+When the ticket transits through a realm to another realm, the
+destination realm adds its peer to the "transited-realms" field in the
+ticket. The field is unordered, since there is no way to know if
+know if one of the transited-realms changed the order of the list.
+
+The syntax for @code{[capaths]} section:
+
+@example
+@cartouche
+[capaths]
+        CLIENT-REALM = @{
+                SERVER-REALM = PERMITTED-CROSS-REALMS ...
+        @}
+@end cartouche
+@end example
+
+The realm @code{STACKEN.KTH.SE} allows clients from @code{SU.SE} and
+@code{DSV.SU.SE} to cross it. Since @code{STACKEN.KTH.SE} only have
+direct cross realm with @code{KTH.SE}, and @code{DSV.SU.SE} only have direct cross
+realm with @code{SU.SE} they need to use both @code{SU.SE} and
+@code{KTH.SE} as transit realms.
+
+@example
+@cartouche
+[capaths]
+       SU.SE = @{
+                    STACKEN.KTH.SE = KTH.SE
+       @}
+       DSV.SU.SE = @{
+                    STACKEN.KTH.SE = SU.SE KTH.SE
+       @}
+
+@end cartouche
+@end example
+
+The order of the @code{PERMITTED-CROSS-REALMS} is not important when
+doing transit cross realm verification.
+
+However the order is important when the @code{[capaths]} section is used
+to figure out the intermediate realm to go to when doing multi-realm
+transit. When figuring out the next realm, the first realm of the list
+of @code{PERMITTED-CROSS-REALMS} is chosen. This is done in both the
+client kerberos library and the KDC.
+
+@c To test the cross realm configuration, use:
+@c    kmumble transit-check client server transit-realms ...
+
+@node Setting up DNS, Using LDAP to store the database, Transit policy, Setting up a realm
+@section Setting up DNS
+@cindex Setting up DNS
+
+@subsection Using DNS to find KDC
+
+If there is information about where to find the KDC or kadmind for a
+realm in the @file{krb5.conf} for a realm, that information will be
+preferred, and DNS will not be queried.
+
+Heimdal will try to use DNS to find the KDCs for a realm. First it
+will try to find a @code{SRV} resource record (RR) for the realm. If no
+SRV RRs are found, it will fall back to looking for an @code{A} RR for
+a machine named kerberos.REALM, and then kerberos-1.REALM, etc
+
+Adding this information to DNS makes the client have less
+configuration (in the common case, no configuration) and allows the
+system administrator to change the number of KDCs and on what machines
+they are running without caring about clients.
+
+The down side of using DNS that the client might be fooled to use the
+wrong server if someone fakes DNS replies/data, but storing the IP
+addresses of the KDC on all the clients makes it very hard to change
+the infrastructure.
+
+An example of the configuration for the realm @code{EXAMPLE.COM},
+
+@example
+
+$ORIGIN example.com.
+_kerberos._tcp          SRV     10 1 88 kerberos.example.com.
+_kerberos._udp          SRV     10 1 88 kerberos.example.com.
+_kerberos._tcp          SRV     10 1 88 kerberos-1.example.com.
+_kerberos._udp          SRV     10 1 88 kerberos-1.example.com.
+_kpasswd._udp           SRV     10 1 464 kerberos.example.com.
+_kerberos-adm._tcp     SRV     10 1 749 kerberos.example.com.
+
+@end example
+
+More information about DNS SRV resource records can be found in
+RFC-2782 (A DNS RR for specifying the location of services (DNS SRV)).
+
+@subsection Using DNS to map hostname to Kerberos realm
+
+Heimdal also supports a way to lookup a realm from a hostname. This to
+minimize configuration needed on clients. Using this has the drawback
+that clients can be redirected by an attacker to realms within the
+same cross realm trust and made to believe they are talking to the
+right server (since Kerberos authentication will succeed).
+
+An example configuration that informs clients that for the realms
+it.example.com and srv.example.com, they should use the realm
+EXAMPLE.COM:
+
+@example
+
+$ORIGIN example.com.
+_kerberos.it           TXT     "EXAMPLE.COM"
+_kerberos.srv          TXT     "EXAMPLE.COM"
+
+@end example
+
+@node Using LDAP to store the database, Providing Kerberos credentials to servers and programs, Setting up DNS, Setting up a realm
+@section Using LDAP to store the database
+@cindex Using the LDAP backend
+
+This document describes how to install the LDAP backend for
+Heimdal. Note that before attempting to configure such an
+installation, you should be aware of the implications of storing
+private information (such as users' keys) in a directory service
+primarily designed for public information. Nonetheless, with a
+suitable authorization policy, it is possible to set this up in a
+secure fashion. A knowledge of LDAP, Kerberos, and C is necessary to
+install this backend. The HDB schema was devised by Leif Johansson.
+
+Requirements:
+
+@itemize @bullet
+
+@item
+A current release of Heimdal, configured with
+@code{--with-openldap=/usr/local} (adjust according to where you have
+installed OpenLDAP).
+
+You can verify that you manage to configure LDAP support by running
+@file{kdc --builtin-hdb}, and checking that @samp{ldap:} is one entry
+in the list.
+
+Its also possible to configure the ldap backend as a shared module,
+see option --hdb-openldap-module to configure.
+
+@item
+OpenLDAP 2.0.x. Configure OpenLDAP with @kbd{--enable-local} to enable the
+local transport. (A patch to support SASL EXTERNAL authentication is
+necessary in order to use OpenLDAP 2.1.x.)
+
+@item
+Add the hdb schema to the LDAP server, its included in the source-tree
+in @file{lib/hdb/hdb.schema}. Example from slapd.conf:
+
+@example
+include /usr/local/etc/openldap/schema/hdb.schema
+@end example
+
+@item
+Configure the LDAP server ACLs to accept writes from clients over the
+local transport. For example:
+
+@example
+access to *
+        by dn.exact="uid=heimdal,dc=services,dc=example,dc=com" write
+        ...
+
+sasl-regexp "uidNumber=0\\\+gidNumber=.*,cn=peercred,cn=external,cn=auth"
+       "uid=heimdal,dc=services,dc=example,dc=com"
+
+@end example
+
+The sasl-regexp is for mapping between the SASL/EXTERNAL and a user in
+a tree.  The user that the key is mapped to should be have a
+krb5Principal aux object with krb5PrincipalName set so that the
+``creator'' and ``modifier'' is right in @file{kadmin}.
+
+Another option is to create an admins group and add the dn to that
+group.
+
+Since Heimdal talkes to the LDAP server over a UNIX domain socket, and
+uses external sasl authentication, its not possible to require
+security layer quality (ssf in cyrus-sasl lingo). So that requirement
+has to be turned off in OpenLDAP @command{slapd} configuration file
+@file{slapd.conf}.
+
+@example
+sasl-secprops minssf=0
+@end example
+
+@item
+
+Start @command{slapd} with the local listener (as well as the default TCP/IP
+listener on port 389) as follows:
+
+@example
+    slapd -h "ldapi:/// ldap:///"
+@end example
+
+Note: These is a bug in @command{slapd} where it appears to corrupt the krb5Key
+binary attribute on shutdown. This may be related to our use of the V3
+schema definition syntax instead of the old UMich-style, V2 syntax.
+
+@item
+You should specify the distinguished name under which your
+principals will be stored in @file{krb5.conf}:
+
+@example
+[kdc]
+        database = @{
+                dbname = ldap:ou=KerberosPrincipals,dc=example,dc=com
+                mkey_file = /path/to/mkey
+        @}
+@end example
+
+@samp{mkey_file} can be excluded if you feel that you trust your ldap
+directory to have the raw keys inside it.
+
+
+@item
+Once you have built Heimdal and started the LDAP server, run kadmin
+(as usual) to initialize the database. Note that the instructions for
+stashing a master key are as per any Heimdal installation.
+
+@example
+kdc# kadmin -l
+kadmin> init EXAMPLE.COM
+Realm max ticket life [unlimited]:
+Realm max renewable ticket life [unlimited]:
+kadmin> ank lukeh
+Max ticket life [1 day]:
+Max renewable life [1 week]:
+Principal expiration time [never]:
+Password expiration time [never]:
+Attributes []:
+lukeh@@EXAMPLE.COM's Password:
+Verifying password - lukeh@@EXAMPLE.COM's Password:
+kadmin> exit
+@end example
+
+Verify that the principal database has indeed been stored in the
+directory with the following command:
+
+@example
+kdc# ldapsearch -L -h localhost -D cn=manager \
+ -w secret -b ou=KerberosPrincipals,dc=example,dc=com \
+ 'objectclass=krb5KDCEntry' 
+@end example
+
+@item
+Now consider adding indexes to the database to speed up the access, at
+least theses should be added to slapd.conf.
+
+@example
+index  objectClass             eq
+index  cn                      eq,sub,pres
+index  uid                     eq,sub,pres
+index  displayName             eq,sub,pres
+index  krb5PrincipalName       eq
+@end example
+
+@end itemize
+
+@subsection Troubleshooting guide
+
+@url{https://sec.miljovern.no/bin/view/Info/TroubleshootingGuide}
+
+
+@subsection Using Samba LDAP password database
+@cindex Samba
+
+@c @node Using Samba LDAP password database, Providing Kerberos credentials to servers and programs, Using LDAP to store the database, Setting up a realm
+@c @section Using Samba LDAP password database
+
+Samba domain and the Kerberos realm can have diffrent names since
+arcfour's string to key function principal/realm independent.  So now
+will be your first and only chance name your Kerberos without needing
+to deal with old configuration files.
+
+First you should set up Samba and get that working with LDAP backend.
+
+Now you can proceed as in @xref{Using LDAP to store the database},
+Heimdal will pick up the Samba LDAP entries if they are in the same
+search space as the Kerberos entries.
+
+@node Providing Kerberos credentials to servers and programs, , Using LDAP to store the database, Setting up a realm
+@section Providing Kerberos credentials to servers and programs
+
+Some service require Kerberos credentials when they start to make
+connections to other services or use them when they have started.
+
+The easiest way to get ticket for the a service is to store the key in
+a keytab. Both ktutil get and kadmin ext can be used to get a
+keytab. ktutil get is better in that way it changes the key/password
+for the user. This the problem with the ktutil. It ktutil is used for
+the same service principal on several hosts, they keytab will only
+useful on the last host. In that case, run the command on host and
+copy the keytab around to all other hosts that needs it.
+
+@example
+host# ktutil -k /etc/krb5-service.keytab \
+      get -p lha/admin@@EXAMPLE.ORG service-principal@@EXAMPLE.ORG
+lha/admin@@EXAMPLE.ORG's Password: 
+@end example
+
+To get a Kerberos credential file for the service, use kinit in the
+--keytab mode, this will not ask for a password but rather that the
+key from the keytab.
+
+@example
+service@@host$ kinit --cache=/var/run/service_krb5_cache \
+               --keytab=/etc/krb5-service.keytab \
+       service-principal@@EXAMPLE.ORG
+@end example
+
+Long running services might need credentials longer then the
+expiration time of the tickets. kinit can run in a mode that refreshes
+the tickets before they expire. This is useful for services that write
+into AFS and other distributed file systems using Kerberos. To run the
+long running script, just append the program and arguments (if any)
+after the principal. kinit will stop refreshing credentials and remove
+the credentials when the script-to-start-service exits.
+
+@example
+service@@host$ kinit --cache=/var/run/service_krb5_cache \
+       --keytab=/etc/krb5-service.keytab \
+       service-principal@@EXAMPLE.ORG \
+       script-to-start-service argument1 argument2
+@end example
+
diff --git a/src/kerberosV/src/doc/whatis.texi b/src/kerberosV/src/doc/whatis.texi
new file mode 100644 (file)
index 0000000..bfef184
--- /dev/null
@@ -0,0 +1,159 @@
+@c $KTH: whatis.texi,v 1.8 2005/04/24 21:48:45 lha Exp $
+
+@node What is Kerberos?, Building and Installing, Introduction, Top
+@chapter What is Kerberos?
+
+@quotation
+@flushleft
+        Now this Cerberus had three heads of dogs,
+        the tail of a dragon, and on his back the
+        heads of all sorts of snakes.
+        --- Pseudo-Apollodorus Library 2.5.12
+@end flushleft
+@end quotation
+
+Kerberos is a system for authenticating users and services on a network.
+It is built upon the assumption that the network is ``unsafe''.  For
+example, data sent over the network can be eavesdropped and altered, and
+addresses can also be faked.  Therefore they cannot be used for
+authentication purposes.
+@cindex authentication
+
+Kerberos is a trusted third-party service.  That means that there is a
+third party (the kerberos server) that is trusted by all the entities on
+the network (users and services, usually called @dfn{principals}).  All
+principals share a secret password (or key) with the kerberos server and
+this enables principals to verify that the messages from the kerberos
+server are authentic.  Thus trusting the kerberos server, users and
+services can authenticate each other.
+
+@section Basic mechanism
+
+@ifinfo
+@macro sub{arg}
+<\arg\>
+@end macro
+@end ifinfo
+
+@tex
+@def@xsub#1{$_{#1}$}
+@global@let@sub=@xsub
+@end tex
+
+@ifhtml
+@macro sub{arg}
+<\arg\>
+@end macro
+@end ifhtml
+
+@c ifdocbook
+@c macro sub{arg}
+@c docbook
+@c <subscript>\arg\</subscript>
+@c end docbook
+@c end macro
+@c end ifdocbook
+
+@quotation
+@strong{Note} This discussion is about Kerberos version 4, but version
+5 works similarly.
+@end quotation
+
+In Kerberos, principals use @dfn{tickets} to prove that they are who
+they claim to be. In the following example, @var{A} is the initiator of
+the authentication exchange, usually a user, and @var{B} is the service
+that @var{A} wishes to use.
+
+To obtain a ticket for a specific service, @var{A} sends a ticket
+request to the kerberos server. The request contains @var{A}'s and
+@var{B}'s names (along with some other fields). The kerberos server
+checks that both @var{A} and @var{B} are valid principals.
+
+Having verified the validity of the principals, it creates a packet
+containing @var{A}'s and @var{B}'s names, @var{A}'s network address
+(@var{A@sub{addr}}), the current time (@var{t@sub{issue}}), the lifetime
+of the ticket (@var{life}), and a secret @dfn{session key}
+@cindex session key
+(@var{K@sub{AB}}). This packet is encrypted with @var{B}'s secret key
+(@var{K@sub{B}}).  The actual ticket (@var{T@sub{AB}}) looks like this:
+(@{@var{A}, @var{B}, @var{A@sub{addr}}, @var{t@sub{issue}}, @var{life},
+@var{K@sub{AB}}@}@var{K@sub{B}}).
+
+The reply to @var{A} consists of the ticket (@var{T@sub{AB}}), @var{B}'s
+name, the current time, the lifetime of the ticket, and the session key, all
+encrypted in @var{A}'s secret key (@{@var{B}, @var{t@sub{issue}},
+@var{life}, @var{K@sub{AB}}, @var{T@sub{AB}}@}@var{K@sub{A}}). @var{A}
+decrypts the reply and retains it for later use.
+
+@sp 1
+
+Before sending a message to @var{B}, @var{A} creates an authenticator
+consisting of @var{A}'s name, @var{A}'s address, the current time, and a
+``checksum'' chosen by @var{A}, all encrypted with the secret session
+key (@{@var{A}, @var{A@sub{addr}}, @var{t@sub{current}},
+@var{checksum}@}@var{K@sub{AB}}). This is sent together with the ticket
+received from the kerberos server to @var{B}.  Upon reception, @var{B}
+decrypts the ticket using @var{B}'s secret key.  Since the ticket
+contains the session key that the authenticator was encrypted with,
+@var{B} can now also decrypt the authenticator. To verify that @var{A}
+really is @var{A}, @var{B} now has to compare the contents of the ticket
+with that of the authenticator. If everything matches, @var{B} now
+considers @var{A} as properly authenticated.
+
+@c (here we should have some more explanations)
+
+@section Different attacks
+
+@subheading Impersonating A
+
+An impostor, @var{C} could steal the authenticator and the ticket as it
+is transmitted across the network, and use them to impersonate
+@var{A}. The address in the ticket and the authenticator was added to
+make it more difficult to perform this attack.  To succeed @var{C} will
+have to either use the same machine as @var{A} or fake the source
+addresses of the packets. By including the time stamp in the
+authenticator, @var{C} does not have much time in which to mount the
+attack.
+
+@subheading Impersonating B
+
+@var{C} can hijack @var{B}'s network address, and when @var{A} sends
+her credentials, @var{C} just pretend to verify them. @var{C} can't
+be sure that she is talking to @var{A}.
+
+@section Defense strategies
+
+It would be possible to add a @dfn{replay cache}
+@cindex replay cache
+to the server side.  The idea is to save the authenticators sent during
+the last few minutes, so that @var{B} can detect when someone is trying
+to retransmit an already used message. This is somewhat impractical
+(mostly regarding efficiency), and is not part of Kerberos 4; MIT
+Kerberos 5 contains it.
+
+To authenticate @var{B}, @var{A} might request that @var{B} sends
+something back that proves that @var{B} has access to the session
+key. An example of this is the checksum that @var{A} sent as part of the
+authenticator. One typical procedure is to add one to the checksum,
+encrypt it with the session key and send it back to @var{A}.  This is
+called @dfn{mutual authentication}.
+
+The session key can also be used to add cryptographic checksums to the
+messages sent between @var{A} and @var{B} (known as @dfn{message
+integrity}).  Encryption can also be added (@dfn{message
+confidentiality}). This is probably the best approach in all cases.
+@cindex integrity
+@cindex confidentiality
+
+@section Further reading
+
+The original paper on Kerberos from 1988 is @cite{Kerberos: An
+Authentication Service for Open Network Systems}, by Jennifer Steiner,
+Clifford Neuman and Jeffrey I. Schiller.
+
+A less technical description can be found in @cite{Designing an
+Authentication System: a Dialogue in Four Scenes} by Bill Bryant, also
+from 1988.
+
+These documents can be found on our web-page at
+@url{http://www.pdc.kth.se/kth-krb/}.
diff --git a/src/kerberosV/src/doc/win2k.texi b/src/kerberosV/src/doc/win2k.texi
new file mode 100644 (file)
index 0000000..d4dde4c
--- /dev/null
@@ -0,0 +1,315 @@
+@c $KTH: win2k.texi,v 1.19 2004/12/27 14:56:30 lha Exp $
+
+@node Windows 2000 compatability, Programming with Kerberos, Kerberos 4 issues, Top
+@comment  node-name,  next,  previous,  up
+@chapter Windows 2000 compatability
+
+Windows 2000 (formerly known as Windows NT 5) from Microsoft implements
+Kerberos 5.  Their implementation, however, has some quirks,
+peculiarities, and bugs.  This chapter is a short summary of the things
+that we have found out while trying to test Heimdal against Windows
+2000.  Another big problem with the Kerberos implementation in Windows
+2000 is that the available documentation is more focused on getting
+things to work rather than how they work, and not that useful in figuring
+out how things really work.
+
+This information should apply to Heimdal @value{VERSION} and Windows
+2000 Professional.  It's of course subject to change all the time and
+mostly consists of our not so inspired guesses.  Hopefully it's still
+somewhat useful.
+
+@menu
+* Configuring Windows 2000 to use a Heimdal KDC::  
+* Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC::  
+* Create account mappings::     
+* Encryption types::            
+* Authorization data::          
+* Quirks of Windows 2000 KDC::  
+* Useful links when reading about the Windows 2000::  
+@end menu
+
+@node Configuring Windows 2000 to use a Heimdal KDC, Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC, Windows 2000 compatability, Windows 2000 compatability
+@comment node-name, next, precious, up
+@section Configuring Windows 2000 to use a Heimdal KDC
+
+You need the command line program called @command{ksetup.exe} which is available
+in the file @file{SUPPORT/TOOLS/SUPPORT.CAB} on the Windows 2000 Professional
+CD-ROM. This program is used to configure the Kerberos settings on a
+Workstation.
+
+@command{Ksetup} store the domain information under the registry key:
+@code{HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\LSA\Kerberos\Domains}.
+
+Use the @command{kadmin} program in Heimdal to create a host principal in the
+Kerberos realm.
+
+@example
+unix% kadmin
+kadmin> ank --password=password host/datan.example.com
+@end example
+
+The name @samp{datan.example.com} should be replaced with DNS name of
+the workstation.
+
+You must configure the workstation as a member of a workgroup, as opposed
+to a member in an NT domain, and specify the KDC server of the realm
+as follows:
+@example
+C:> ksetup /setdomain EXAMPLE.COM
+C:> ksetup /addkdc EXAMPLE.COM kdc.example.com
+@end example
+
+Set the machine password, i.e.@: create the local keytab:
+@example
+C:> ksetup /setmachpassword password
+@end example
+
+The password used in @kbd{ksetup /setmachpassword} must be the same
+as the password used in the @kbd{kadmin ank} command.
+
+The workstation must now be rebooted.
+
+A mapping between local NT users and Kerberos principals must be specified.
+You have two choices. First:
+
+@example
+C:> ksetup /mapuser user@@MY.REALM nt_user
+@end example
+
+This will map a user to a specific principal; this allows you to have
+other usernames in the realm than in your NT user database. (Don't ask
+me why on earth you would want that@enddots{})
+
+You can also say:
+@example
+C:> ksetup /mapuser * *
+@end example
+The Windows machine will now map any user to the corresponding principal,
+for example @samp{nisse} to the principal @samp{nisse@@MY.REALM}.
+(This is most likely what you want.)
+
+@node Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC, Create account mappings, Configuring Windows 2000 to use a Heimdal KDC, Windows 2000 compatability
+@comment node-name, next, precious, up
+@section Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC
+
+See also the Step-by-Step guide from Microsoft, referenced below.
+
+Install Windows 2000, and create a new controller (Active Directory
+Server) for the domain.
+
+By default the trust will be non-transitive. This means that only users
+directly from the trusted domain may authenticate. This can be changed
+to transitive by using the @command{netdom.exe} tool. @command{netdom.exe} 
+can also be used to add the trust between two realms.
+
+You need to tell Windows 2000 on what hosts to find the KDCs for the
+non-Windows realm with @command{ksetup}, see @xref{Configuring Windows 2000
+to use a Heimdal KDC}.
+
+This needs to be done on all computers that want enable cross-realm
+login with @code{Mapped Names}. @c XXX probably shouldn't be @code
+
+Then you need to add the inter-realm keys on the Windows KDC@. Start the
+Domain Tree Management tool (found in Programs, Administrative tools,
+Active Directory Domains and Trusts).
+
+Right click on Properties of your domain, select the Trust tab.  Press
+Add on the appropriate trust windows and enter domain name and
+password. When prompted if this is a non-Windows Kerberos realm, press
+OK.
+
+Do not forget to add trusts in both directions (if that's what you want).
+
+If you want to use @command{netdom.exe} instead of the Domain Tree
+Management tool, you do it like this:
+
+@example
+netdom trust NT.REALM.EXAMPLE.COM /Domain:EXAMPLE.COM /add /realm /passwordt:TrustPassword
+@end example
+
+You also need to add the inter-realm keys to the Heimdal KDC. There are
+some tweaks that you need to do to @file{krb5.conf} beforehand.
+
+@example
+[libdefaults]
+        default_etypes = des-cbc-crc
+        default_etypes_des = des-cbc-crc
+@end example
+
+since otherwise checksum types that are not understood by Windows 2000
+will be generated (@pxref{Quirks of Windows 2000 KDC}).
+
+Another issue is salting.  Since Windows 2000 does not seem to
+understand Kerberos 4 salted hashes you might need to turn off anything
+similar to the following if you have it, at least while adding the
+principals that are going to share keys with Windows 2000.
+
+@example
+[kadmin]
+        default_keys = v5 v4
+@end example
+
+So remove v4 from default keys.
+
+What you probably want to use is this:
+
+@example
+[kadmin]
+        default_keys = des-cbc-crc:pw-salt arcfour-hmac-md5:pw-salt
+@end example
+
+@c XXX check this
+Note that before Windows 2003, arcfour-hmac-md5 wasn't supported
+beteen Windows realms and Non Windows realms.
+
+Once that is also done, you can add the required inter-realm keys:
+
+@example
+kadmin add krbtgt/NT.REALM.EXAMPLE.COM@@EXAMPLE.COM
+kadmin add krbtgt/REALM.EXAMPLE.COM@@NT.EXAMPLE.COM
+@end example
+
+Use the same passwords for both keys.
+
+Do not forget to reboot before trying the new realm-trust (after
+running @command{ksetup}). It looks like it might work, but packets are
+never sent to the non-Windows KDC.
+
+@node Create account mappings, Encryption types, Inter-Realm keys (trust) between Windows 2000 and a Heimdal KDC, Windows 2000 compatability
+@comment node-name, next, precious, up
+@section Create account mappings
+
+Start the @code{Active Directory Users and Computers} tool. Select the
+View menu, that is in the left corner just below the real menu (or press
+Alt-V), and select Advanced Features. Right click on the user that you
+are going to do a name mapping for and choose Name mapping.
+
+Click on the Kerberos Names tab and add a new principal from the
+non-Windows domain.
+
+@c XXX check entry name then I have network again
+This adds @samp{authorizationNames} entry to the users LDAP entry to
+the Active Directory LDAP catalog. When you create users by script you
+can add this entry instead.
+
+@node Encryption types, Authorization data, Create account mappings, Windows 2000 compatability
+@comment  node-name,  next,  previous,  up
+@section Encryption types
+
+Windows 2000 supports both the standard DES encryptions (@samp{des-cbc-crc} and
+@samp{des-cbc-md5}) and its own proprietary encryption that is based on MD4 and
+RC4 that is documented in and is supposed to be described in
+@file{draft-brezak-win2k-krb-rc4-hmac-03.txt}.  New users will get both
+MD4 and DES keys.  Users that are converted from a NT4 database, will
+only have MD4 passwords and will need a password change to get a DES
+key.
+
+@node Authorization data, Quirks of Windows 2000 KDC, Encryption types, Windows 2000 compatability
+@comment  node-name,  next,  previous,  up
+@section Authorization data
+
+The Windows 2000 KDC also adds extra authorization data in tickets.
+It is at this point unclear what triggers it to do this.  The format of
+this data is only available under a ``secret'' license from Microsoft,
+which prohibits you implementing it.
+
+A simple way of getting hold of the data to be able to understand it
+better is described here.
+
+@enumerate
+@item Find the client example on using the SSPI in the SDK documentation.
+@item Change ``AuthSamp'' in the source code to lowercase.
+@item Build the program.
+@item Add the ``authsamp'' principal with a known password to the
+database.  Make sure it has a DES key.
+@item Run @kbd{ktutil add} to add the key for that principal to a
+keytab.
+@item Run @kbd{appl/test/nt_gss_server -p 2000 -s authsamp
+--dump-auth=@var{file}} where @var{file} is an appropriate file.
+@item It should authenticate and dump for you the authorization data in
+the file.
+@item The tool @kbd{lib/asn1/asn1_print} is somewhat useful for
+analyzing the data.
+@end enumerate
+
+@node Quirks of Windows 2000 KDC, Useful links when reading about the Windows 2000, Authorization data, Windows 2000 compatability
+@comment  node-name,  next,  previous,  up
+@section Quirks of Windows 2000 KDC
+
+There are some issues with salts and Windows 2000.  Using an empty salt---which is the only one that Kerberos 4 supported, and is therefore known
+as a Kerberos 4 compatible salt---does not work, as far as we can tell
+from out experiments and users' reports.  Therefore, you have to make
+sure you keep around keys with all the different types of salts that are
+required.  Microsoft have fixed this issue post Windows 2003.
+
+Microsoft seems also to have forgotten to implement the checksum
+algorithms @samp{rsa-md4-des} and @samp{rsa-md5-des}. This can make Name
+mapping (@pxref{Create account mappings}) fail if a @samp{des-cbc-md5} key
+is used. To make the KDC return only @samp{des-cbc-crc} you must delete
+the @samp{des-cbc-md5} key from the kdc using the @kbd{kadmin
+del_enctype} command.
+
+@example
+kadmin del_enctype lha des-cbc-md5
+@end example
+
+You should also add the following entries to the @file{krb5.conf} file:
+
+@example
+[libdefaults]
+       default_etypes = des-cbc-crc
+       default_etypes_des = des-cbc-crc
+@end example
+
+These configuration options will make sure that no checksums of the
+unsupported types are generated.
+
+@node Useful links when reading about the Windows 2000,  , Quirks of Windows 2000 KDC, Windows 2000 compatability
+@comment  node-name,  next,  previous,  up
+@section Useful links when reading about the Windows 2000
+
+See also our paper presented at the 2001 usenix Annual Technical
+Conference, available in the proceedings or at
+@uref{http://www.usenix.org/publications/library/proceedings/usenix01/freenix01/westerlund.html}.
+
+There are lots of texts about Kerberos on Microsoft's web site, here is a
+short list of the interesting documents that we have managed to find.
+
+@itemize @bullet
+
+@item Step-by-Step Guide to Kerberos 5 (krb5 1.0) Interoperability:
+@uref{http://www.microsoft.com/windows2000/library/planning/security/kerbsteps.asp}.
+Kerberos GSS-API (in Windows-eze SSPI), Windows as a client in a
+non-Windows KDC realm, adding unix clients to a Windows 2000 KDC, and
+adding cross-realm trust (@pxref{Inter-Realm keys (trust) between Windows 2000
+and a Heimdal KDC}).
+
+@item Windows 2000 Kerberos Authentication:
+@uref{http://www.microsoft.com/TechNet/win2000/win2ksrv/technote/kerberos.asp}.
+White paper that describes how Kerberos is used in Windows 2000.
+
+@item Overview of Kerberos:
+@uref{http://support.microsoft.com/support/kb/articles/Q248/7/58.ASP}.
+Links to useful other links.
+
+@c @item Klist for Windows:
+@c @uref{http://msdn.microsoft.com/library/periodic/period00/security0500.htm}.
+@c Describes where to get a klist for Windows 2000.
+
+@item Event logging for Kerberos:
+@uref{http://support.microsoft.com/support/kb/articles/Q262/1/77.ASP}.
+Basicly it say that you can add a registry key
+@code{HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters\LogLevel}
+with value DWORD equal to 1, and then you'll get logging in the Event
+Logger.
+
+@c @item Access to the Active Directory through LDAP:
+@c @uref{http://msdn.microsoft.com/library/techart/kerberossamp.htm}
+
+@end itemize
+
+Other useful programs include these:
+
+@itemize @bullet
+@item pwdump2
+@uref{http://www.bindview.com/Support/RAZOR/Utilities/Windows/pwdump2_readme.cfm}@end itemize
diff --git a/src/kerberosV/src/etc/CVS/Entries b/src/kerberosV/src/etc/CVS/Entries
new file mode 100644 (file)
index 0000000..8d3549a
--- /dev/null
@@ -0,0 +1,2 @@
+/services.append/1.1.1.2/Wed Feb  6 08:54:42 2002//
+D
diff --git a/src/kerberosV/src/etc/CVS/Repository b/src/kerberosV/src/etc/CVS/Repository
new file mode 100644 (file)
index 0000000..8018aa5
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/etc
diff --git a/src/kerberosV/src/etc/CVS/Root b/src/kerberosV/src/etc/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/etc/services.append b/src/kerberosV/src/etc/services.append
new file mode 100644 (file)
index 0000000..6deaf27
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# $KTH: services.append,v 1.6 2001/08/08 15:48:37 assar Exp $
+#
+# Kerberos services
+#
+kerberos       88/udp          kerberos-sec    # Kerberos v5 UDP
+kerberos       88/tcp          kerberos-sec    # Kerberos v5 TCP
+kpasswd                464/udp                         # password changing
+kpasswd                464/tcp                         # password changing
+klogin         543/tcp                         # Kerberos authenticated rlogin
+kshell         544/tcp         krcmd           # and remote shell
+ekshell                545/tcp               # Kerberos encrypted remote shell -kfall
+ekshell2       2106/tcp              # What U of Colorado @ Boulder uses?
+kerberos-adm   749/udp                         # v5 kadmin
+kerberos-adm   749/tcp                         # v5 kadmin
+kerberos-iv    750/udp         kdc             # Kerberos authentication--udp
+kerberos-iv    750/tcp         kdc             # Kerberos authentication--tcp
+kerberos_master 751/udp                                # v4 kadmin
+kerberos_master 751/tcp                                # v4 kadmin
+krb_prop       754/tcp         hprop           # Kerberos slave propagation
+kpop           1109/tcp                        # Pop with Kerberos
+eklogin                2105/tcp                        # Kerberos encrypted rlogin
+rkinit         2108/tcp                        # Kerberos remote kinit
+kf             2110/tcp                        # forward credentials
+kx             2111/tcp                        # X over kerberos
+kip            2112/tcp                        # IP over kerberos
+kauth          2120/tcp                        # Remote kauth
+iprop          2121/tcp                        # incremental propagation
+krb524         4444/udp                        # MIT 5->4
diff --git a/src/kerberosV/src/include/CVS/Entries b/src/kerberosV/src/include/CVS/Entries
new file mode 100644 (file)
index 0000000..56c68e6
--- /dev/null
@@ -0,0 +1,5 @@
+/bits.c/1.4/Fri Apr 14 08:15:03 2006//
+/config.h.in/1.1.1.6/Fri Apr 14 07:32:35 2006//
+/make_crypto.c/1.1.1.3/Fri Apr 14 07:32:35 2006//
+/stamp-h.in/1.2/Wed Jun 27 15:22:43 2001//
+D
diff --git a/src/kerberosV/src/include/CVS/Repository b/src/kerberosV/src/include/CVS/Repository
new file mode 100644 (file)
index 0000000..f36f1fe
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/include
diff --git a/src/kerberosV/src/include/CVS/Root b/src/kerberosV/src/include/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/include/bits.c b/src/kerberosV/src/include/bits.c
new file mode 100644 (file)
index 0000000..7a631c9
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: bits.c,v 1.23 2005/01/05 15:22:02 lha Exp $");
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#define BITSIZE(TYPE)                                          \
+{                                                              \
+    int b = 0; TYPE x = 1, zero = 0; const char *pre = "u";    \
+    char tmp[128], tmp2[128];                                  \
+    while(x){ x <<= 1; b++; if(x < zero) pre=""; }             \
+    if(b >= len){                                              \
+        int tabs;                                              \
+       snprintf(tmp, sizeof tmp, "%sint%d_t" , pre, len);      \
+       snprintf(tmp2, sizeof tmp2, "typedef %s %s;", #TYPE, tmp);      \
+       tabs = 5 - strlen(tmp2) / 8;                            \
+        fprintf(f, "%s", tmp2);                                        \
+       while(tabs-- > 0) fprintf(f, "\t");                     \
+       fprintf(f, "/* %2d bits */\n", b);                      \
+        return;                                                 \
+    }                                                          \
+}
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+static void
+try_signed(FILE *f, int len)  __attribute__ ((unused));
+
+static void
+try_unsigned(FILE *f, int len) __attribute__ ((unused));
+
+static int
+print_bt(FILE *f, int flag) __attribute__ ((unused));
+
+static void
+try_signed(FILE *f, int len)
+{
+    BITSIZE(signed char);
+    BITSIZE(short);
+    BITSIZE(int);
+    BITSIZE(long);
+#ifdef HAVE_LONG_LONG
+    BITSIZE(long long);
+#endif
+    fprintf(f, "/* There is no %d bit type */\n", len);
+}
+
+static void
+try_unsigned(FILE *f, int len)
+{
+    BITSIZE(unsigned char);
+    BITSIZE(unsigned short);
+    BITSIZE(unsigned int);
+    BITSIZE(unsigned long);
+#ifdef HAVE_LONG_LONG
+    BITSIZE(unsigned long long);
+#endif
+    fprintf(f, "/* There is no %d bit type */\n", len);
+}
+
+static int
+print_bt(FILE *f, int flag)
+{
+    if(flag == 0){
+       fprintf(f, "/* For compatibility with various type definitions */\n");
+       fprintf(f, "#ifndef __BIT_TYPES_DEFINED__\n");
+       fprintf(f, "#define __BIT_TYPES_DEFINED__\n");
+       fprintf(f, "\n");
+    }
+    return 1;
+}
+
+int main(int argc, char **argv)
+{
+    FILE *f;
+    int flag;
+    const char *fn, *hb;
+    
+    if(argc < 2){
+       fn = "bits.h";
+       hb = "__BITS_H__";
+       f = stdout;
+    } else {
+       char *p;
+       fn = argv[1];
+       asprintf(&p, "__%s__", fn);
+       hb = p;
+       for(; *p; p++){
+           if(!isalnum((unsigned char)*p))
+               *p = '_';
+       }
+       f = fopen(argv[1], "w");
+    }
+    fprintf(f, "/* %s -- this file was generated for %s by\n", fn, HOST);
+    fprintf(f, "   %*s    %s */\n\n", (int)strlen(fn), "", 
+           "$KTH: bits.c,v 1.23 2005/01/05 15:22:02 lha Exp $");
+    fprintf(f, "#ifndef %s\n", hb);
+    fprintf(f, "#define %s\n", hb);
+    fprintf(f, "\n");
+#ifdef HAVE_INTTYPES_H
+    fprintf(f, "#include <inttypes.h>\n");
+#endif
+#ifdef HAVE_SYS_TYPES_H
+    fprintf(f, "#include <sys/types.h>\n");
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+    fprintf(f, "#include <sys/bitypes.h>\n");
+#endif
+#ifdef HAVE_BIND_BITYPES_H
+    fprintf(f, "#include <bind/bitypes.h>\n");
+#endif
+#ifdef HAVE_NETINET_IN6_MACHTYPES_H
+    fprintf(f, "#include <netinet/in6_machtypes.h>\n");
+#endif
+#ifdef HAVE_SOCKLEN_T
+    fprintf(f, "#include <sys/socket.h>\n");
+#endif
+    fprintf(f, "\n");
+
+    flag = 0;
+#ifndef HAVE_INT8_T
+    flag = print_bt(f, flag);
+    try_signed (f, 8);
+#endif /* HAVE_INT8_T */
+#ifndef HAVE_INT16_T
+    flag = print_bt(f, flag);
+    try_signed (f, 16);
+#endif /* HAVE_INT16_T */
+#ifndef HAVE_INT32_T
+    flag = print_bt(f, flag);
+    try_signed (f, 32);
+#endif /* HAVE_INT32_T */
+#if 0
+#ifndef HAVE_INT64_T
+    flag = print_bt(f, flag);
+    try_signed (f, 64);
+#endif /* HAVE_INT64_T */
+#endif
+
+#ifndef HAVE_UINT8_T
+    flag = print_bt(f, flag);
+    try_unsigned (f, 8);
+#endif /* HAVE_UINT8_T */
+#ifndef HAVE_UINT16_T
+    flag = print_bt(f, flag);
+    try_unsigned (f, 16);
+#endif /* HAVE_UINT16_T */
+#ifndef HAVE_UINT32_T
+    flag = print_bt(f, flag);
+    try_unsigned (f, 32);
+#endif /* HAVE_UINT32_T */
+#if 0
+#ifndef HAVE_UINT64_T
+    flag = print_bt(f, flag);
+    try_unsigned (f, 64);
+#endif /* HAVE_UINT64_T */
+#endif
+
+#define X(S) fprintf(f, "typedef uint" #S "_t u_int" #S "_t;\n")
+#ifndef HAVE_U_INT8_T
+    flag = print_bt(f, flag);
+    X(8);
+#endif /* HAVE_U_INT8_T */
+#ifndef HAVE_U_INT16_T
+    flag = print_bt(f, flag);
+    X(16);
+#endif /* HAVE_U_INT16_T */
+#ifndef HAVE_U_INT32_T
+    flag = print_bt(f, flag);
+    X(32);
+#endif /* HAVE_U_INT32_T */
+#if 0
+#ifndef HAVE_U_INT64_T
+    flag = print_bt(f, flag);
+    X(64);
+#endif /* HAVE_U_INT64_T */
+#endif
+
+    if(flag){
+       fprintf(f, "\n");
+       fprintf(f, "#endif /* __BIT_TYPES_DEFINED__ */\n\n");
+    }
+#ifdef KRB5
+    fprintf(f, "\n");
+#if defined(HAVE_SOCKLEN_T)
+    fprintf(f, "typedef socklen_t krb5_socklen_t;\n");
+#else
+    fprintf(f, "typedef int krb5_socklen_t;\n");
+#endif
+#if defined(HAVE_SSIZE_T)
+#ifdef HAVE_UNISTD_H
+    fprintf(f, "#include <unistd.h>\n");
+#endif
+    fprintf(f, "typedef ssize_t krb5_ssize_t;\n");
+#else
+    fprintf(f, "typedef int krb5_ssize_t;\n");
+#endif
+    fprintf(f, "\n");
+#endif /* KRB5 */
+    fprintf(f, "#endif /* %s */\n", hb);
+    return 0;
+}
diff --git a/src/kerberosV/src/include/config.h.in b/src/kerberosV/src/include/config.h.in
new file mode 100644 (file)
index 0000000..21bc006
--- /dev/null
@@ -0,0 +1,1496 @@
+/* include/config.h.in.  Generated from configure.in by autoheader.  */
+
+#ifdef BUILD_KRB5_LIB
+#ifndef KRB5_LIB_FUNCTION
+#ifdef _WIN32_
+#define KRB5_LIB_FUNCTION _export _stdcall
+#else
+#define KRB5_LIB_FUNCTION
+#endif
+#endif
+#endif
+
+
+#ifdef BUILD_ROKEN_LIB
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32_
+#define ROKEN_LIB_FUNCTION _export _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+#endif
+
+
+#ifndef RCSID
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (const char *)rcsid, "@(#)" msg }
+#endif
+
+/* Maximum values on all known systems */
+#define MaxHostNameLen (64+4)
+#define MaxPathLen (1024+4)
+
+
+
+/* Define if you want authentication support in telnet. */
+#undef AUTHENTICATION
+
+/* path to bin */
+#undef BINDIR
+
+/* Define if realloc(NULL) doesn't work. */
+#undef BROKEN_REALLOC
+
+/* Define if you want support for DCE/DFS PAG's. */
+#undef DCE
+
+/* Define if you want to use DES encryption in telnet. */
+#undef DES_ENCRYPTION
+
+/* Define this to enable diagnostics in telnet. */
+#undef DIAGNOSTICS
+
+/* Define if you want have a thread safe libraries */
+#undef ENABLE_PTHREAD_SUPPORT
+
+/* Define if you want encryption support in telnet. */
+#undef ENCRYPTION
+
+/* define if sys/param.h defines the endiness */
+#undef ENDIANESS_IN_SYS_PARAM_H
+
+/* Define this if you want support for broken ENV_{VAR,VAL} telnets. */
+#undef ENV_HACK
+
+/* define if prototype of gethostbyaddr is compatible with struct hostent
+   *gethostbyaddr(const void *, size_t, int) */
+#undef GETHOSTBYADDR_PROTO_COMPATIBLE
+
+/* define if prototype of gethostbyname is compatible with struct hostent
+   *gethostbyname(const char *) */
+#undef GETHOSTBYNAME_PROTO_COMPATIBLE
+
+/* define if prototype of getservbyname is compatible with struct servent
+   *getservbyname(const char *, const char *) */
+#undef GETSERVBYNAME_PROTO_COMPATIBLE
+
+/* define if prototype of getsockname is compatible with int getsockname(int,
+   struct sockaddr*, socklen_t*) */
+#undef GETSOCKNAME_PROTO_COMPATIBLE
+
+/* Define if you have the `altzone' variable. */
+#undef HAVE_ALTZONE
+
+/* Define to 1 if you have the <arpa/ftp.h> header file. */
+#undef HAVE_ARPA_FTP_H
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <arpa/nameser.h> header file. */
+#undef HAVE_ARPA_NAMESER_H
+
+/* Define to 1 if you have the <arpa/telnet.h> header file. */
+#undef HAVE_ARPA_TELNET_H
+
+/* Define to 1 if you have the `asnprintf' function. */
+#undef HAVE_ASNPRINTF
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the `atexit' function. */
+#undef HAVE_ATEXIT
+
+/* Define to 1 if you have the <bind/bitypes.h> header file. */
+#undef HAVE_BIND_BITYPES_H
+
+/* Define to 1 if you have the <bsdsetjmp.h> header file. */
+#undef HAVE_BSDSETJMP_H
+
+/* Define to 1 if you have the `bswap16' function. */
+#undef HAVE_BSWAP16
+
+/* Define to 1 if you have the `bswap32' function. */
+#undef HAVE_BSWAP32
+
+/* Define to 1 if you have the <capability.h> header file. */
+#undef HAVE_CAPABILITY_H
+
+/* Define to 1 if you have the `cap_set_proc' function. */
+#undef HAVE_CAP_SET_PROC
+
+/* Define to 1 if you have the `cgetent' function. */
+#undef HAVE_CGETENT
+
+/* Define if you have the function `chown'. */
+#undef HAVE_CHOWN
+
+/* Define if you have the function `closefrom'. */
+#undef HAVE_CLOSEFROM
+
+/* Define to 1 if you have the <config.h> header file. */
+#undef HAVE_CONFIG_H
+
+/* Define if you have the function `copyhostent'. */
+#undef HAVE_COPYHOSTENT
+
+/* Define to 1 if you have the `crypt' function. */
+#undef HAVE_CRYPT
+
+/* Define to 1 if you have the <crypt.h> header file. */
+#undef HAVE_CRYPT_H
+
+/* Define to 1 if you have the <curses.h> header file. */
+#undef HAVE_CURSES_H
+
+/* Define if you have the function `daemon'. */
+#undef HAVE_DAEMON
+
+/* define if you have a berkeley db1/2 library */
+#undef HAVE_DB1
+
+/* define if you have a berkeley db3/4 library */
+#undef HAVE_DB3
+
+/* Define to 1 if you have the <db3/db.h> header file. */
+#undef HAVE_DB3_DB_H
+
+/* Define to 1 if you have the <db4/db.h> header file. */
+#undef HAVE_DB4_DB_H
+
+/* Define to 1 if you have the `dbm_firstkey' function. */
+#undef HAVE_DBM_FIRSTKEY
+
+/* Define to 1 if you have the <dbm.h> header file. */
+#undef HAVE_DBM_H
+
+/* Define to 1 if you have the `dbopen' function. */
+#undef HAVE_DBOPEN
+
+/* Define to 1 if you have the <db_185.h> header file. */
+#undef HAVE_DB_185_H
+
+/* Define to 1 if you have the `db_create' function. */
+#undef HAVE_DB_CREATE
+
+/* Define to 1 if you have the <db.h> header file. */
+#undef HAVE_DB_H
+
+/* define if you have ndbm compat in db */
+#undef HAVE_DB_NDBM
+
+/* Define to 1 if you have the declaration of `altzone', and to 0 if you
+   don't. */
+#undef HAVE_DECL_ALTZONE
+
+/* Define to 1 if you have the declaration of `environ', and to 0 if you
+   don't. */
+#undef HAVE_DECL_ENVIRON
+
+/* Define to 1 if you have the declaration of `h_errlist', and to 0 if you
+   don't. */
+#undef HAVE_DECL_H_ERRLIST
+
+/* Define to 1 if you have the declaration of `h_errno', and to 0 if you
+   don't. */
+#undef HAVE_DECL_H_ERRNO
+
+/* Define to 1 if you have the declaration of `h_nerr', and to 0 if you don't.
+   */
+#undef HAVE_DECL_H_NERR
+
+/* Define to 1 if you have the declaration of `optarg', and to 0 if you don't.
+   */
+#undef HAVE_DECL_OPTARG
+
+/* Define to 1 if you have the declaration of `opterr', and to 0 if you don't.
+   */
+#undef HAVE_DECL_OPTERR
+
+/* Define to 1 if you have the declaration of `optind', and to 0 if you don't.
+   */
+#undef HAVE_DECL_OPTIND
+
+/* Define to 1 if you have the declaration of `optopt', and to 0 if you don't.
+   */
+#undef HAVE_DECL_OPTOPT
+
+/* Define to 1 if you have the declaration of `timezone', and to 0 if you
+   don't. */
+#undef HAVE_DECL_TIMEZONE
+
+/* Define to 1 if you have the declaration of `_res', and to 0 if you don't.
+   */
+#undef HAVE_DECL__RES
+
+/* Define to 1 if you have the declaration of `__progname', and to 0 if you
+   don't. */
+#undef HAVE_DECL___PROGNAME
+
+/* Define to 1 if you have the <dirent.h> header file. */
+#undef HAVE_DIRENT_H
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#undef HAVE_DLFCN_H
+
+/* Define to 1 if you have the `dlopen' function. */
+#undef HAVE_DLOPEN
+
+/* Define to 1 if you have the `dn_expand' function. */
+#undef HAVE_DN_EXPAND
+
+/* Define to 1 if you have the `door_create' function. */
+#undef HAVE_DOOR_CREATE
+
+/* Define if you have the function `ecalloc'. */
+#undef HAVE_ECALLOC
+
+/* Define to 1 if you have the `el_init' function. */
+#undef HAVE_EL_INIT
+
+/* Define if you have the function `emalloc'. */
+#undef HAVE_EMALLOC
+
+/* Define if you have the function `erealloc'. */
+#undef HAVE_EREALLOC
+
+/* Define if you have the function `err'. */
+#undef HAVE_ERR
+
+/* Define to 1 if you have the <errno.h> header file. */
+#undef HAVE_ERRNO_H
+
+/* Define if you have the function `errx'. */
+#undef HAVE_ERRX
+
+/* Define to 1 if you have the <err.h> header file. */
+#undef HAVE_ERR_H
+
+/* Define if you have the function `estrdup'. */
+#undef HAVE_ESTRDUP
+
+/* Define if you have the function `fchown'. */
+#undef HAVE_FCHOWN
+
+/* Define to 1 if you have the `fcntl' function. */
+#undef HAVE_FCNTL
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define if you have the function `flock'. */
+#undef HAVE_FLOCK
+
+/* Define if you have the function `fnmatch'. */
+#undef HAVE_FNMATCH
+
+/* Define to 1 if you have the <fnmatch.h> header file. */
+#undef HAVE_FNMATCH_H
+
+/* Define if el_init takes four arguments. */
+#undef HAVE_FOUR_VALUED_EL_INIT
+
+/* define if krb_put_int takes four arguments. */
+#undef HAVE_FOUR_VALUED_KRB_PUT_INT
+
+/* Define to 1 if you have the `freeaddrinfo' function. */
+#undef HAVE_FREEADDRINFO
+
+/* Define if you have the function `freehostent'. */
+#undef HAVE_FREEHOSTENT
+
+/* Define to 1 if you have the `gai_strerror' function. */
+#undef HAVE_GAI_STRERROR
+
+/* Define to 1 if you have the <gdbm/ndbm.h> header file. */
+#undef HAVE_GDBM_NDBM_H
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the `getconfattr' function. */
+#undef HAVE_GETCONFATTR
+
+/* Define if you have the function `getcwd'. */
+#undef HAVE_GETCWD
+
+/* Define if you have the function `getdtablesize'. */
+#undef HAVE_GETDTABLESIZE
+
+/* Define if you have the function `getegid'. */
+#undef HAVE_GETEGID
+
+/* Define if you have the function `geteuid'. */
+#undef HAVE_GETEUID
+
+/* Define if you have the function `getgid'. */
+#undef HAVE_GETGID
+
+/* Define to 1 if you have the `gethostbyname' function. */
+#undef HAVE_GETHOSTBYNAME
+
+/* Define to 1 if you have the `gethostbyname2' function. */
+#undef HAVE_GETHOSTBYNAME2
+
+/* Define if you have the function `gethostname'. */
+#undef HAVE_GETHOSTNAME
+
+/* Define if you have the function `getifaddrs'. */
+#undef HAVE_GETIFADDRS
+
+/* Define if you have the function `getipnodebyaddr'. */
+#undef HAVE_GETIPNODEBYADDR
+
+/* Define if you have the function `getipnodebyname'. */
+#undef HAVE_GETIPNODEBYNAME
+
+/* Define to 1 if you have the `getlogin' function. */
+#undef HAVE_GETLOGIN
+
+/* Define if you have a working getmsg. */
+#undef HAVE_GETMSG
+
+/* Define to 1 if you have the `getnameinfo' function. */
+#undef HAVE_GETNAMEINFO
+
+/* Define if you have the function `getopt'. */
+#undef HAVE_GETOPT
+
+/* Define to 1 if you have the `getpagesize' function. */
+#undef HAVE_GETPAGESIZE
+
+/* Define to 1 if you have the `getpeereid' function. */
+#undef HAVE_GETPEEREID
+
+/* Define to 1 if you have the `getpeerucred' function. */
+#undef HAVE_GETPEERUCRED
+
+/* Define to 1 if you have the `getprogname' function. */
+#undef HAVE_GETPROGNAME
+
+/* Define to 1 if you have the `getpwnam_r' function. */
+#undef HAVE_GETPWNAM_R
+
+/* Define to 1 if you have the `getrlimit' function. */
+#undef HAVE_GETRLIMIT
+
+/* Define to 1 if you have the `getsockopt' function. */
+#undef HAVE_GETSOCKOPT
+
+/* Define to 1 if you have the `getspnam' function. */
+#undef HAVE_GETSPNAM
+
+/* Define if you have the function `gettimeofday'. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define to 1 if you have the `getudbnam' function. */
+#undef HAVE_GETUDBNAM
+
+/* Define if you have the function `getuid'. */
+#undef HAVE_GETUID
+
+/* Define if you have the function `getusershell'. */
+#undef HAVE_GETUSERSHELL
+
+/* define if you have a glob() that groks GLOB_BRACE, GLOB_NOCHECK,
+   GLOB_QUOTE, GLOB_TILDE, and GLOB_LIMIT */
+#undef HAVE_GLOB
+
+/* Define to 1 if you have the `grantpt' function. */
+#undef HAVE_GRANTPT
+
+/* Define to 1 if you have the <grp.h> header file. */
+#undef HAVE_GRP_H
+
+/* Define to 1 if you have the `hstrerror' function. */
+#undef HAVE_HSTRERROR
+
+/* Define if you have the `h_errlist' variable. */
+#undef HAVE_H_ERRLIST
+
+/* Define if you have the `h_errno' variable. */
+#undef HAVE_H_ERRNO
+
+/* Define if you have the `h_nerr' variable. */
+#undef HAVE_H_NERR
+
+/* Define to 1 if you have the <ifaddrs.h> header file. */
+#undef HAVE_IFADDRS_H
+
+/* Define if you have the in6addr_loopback variable */
+#undef HAVE_IN6ADDR_LOOPBACK
+
+/* define */
+#undef HAVE_INET_ATON
+
+/* define */
+#undef HAVE_INET_NTOP
+
+/* define */
+#undef HAVE_INET_PTON
+
+/* Define if you have the function `initgroups'. */
+#undef HAVE_INITGROUPS
+
+/* Define to 1 if you have the `initstate' function. */
+#undef HAVE_INITSTATE
+
+/* Define if you have the function `innetgr'. */
+#undef HAVE_INNETGR
+
+/* Define to 1 if the system has the type `int16_t'. */
+#undef HAVE_INT16_T
+
+/* Define to 1 if the system has the type `int32_t'. */
+#undef HAVE_INT32_T
+
+/* Define to 1 if the system has the type `int64_t'. */
+#undef HAVE_INT64_T
+
+/* Define to 1 if the system has the type `int8_t'. */
+#undef HAVE_INT8_T
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the <io.h> header file. */
+#undef HAVE_IO_H
+
+/* Define if you have IPv6. */
+#undef HAVE_IPV6
+
+/* Define if you have the function `iruserok'. */
+#undef HAVE_IRUSEROK
+
+/* Define to 1 if you have the `issetugid' function. */
+#undef HAVE_ISSETUGID
+
+/* Define if you want to use the Kerberos Credentials Manager. */
+#undef HAVE_KCM
+
+/* Define to 1 if you have the `krb_disable_debug' function. */
+#undef HAVE_KRB_DISABLE_DEBUG
+
+/* Define to 1 if you have the `krb_enable_debug' function. */
+#undef HAVE_KRB_ENABLE_DEBUG
+
+/* Define to 1 if you have the `krb_get_kdc_time_diff' function. */
+#undef HAVE_KRB_GET_KDC_TIME_DIFF
+
+/* Define to 1 if you have the `krb_get_our_ip_for_realm' function. */
+#undef HAVE_KRB_GET_OUR_IP_FOR_REALM
+
+/* Define to 1 if you have the `krb_kdctimeofday' function. */
+#undef HAVE_KRB_KDCTIMEOFDAY
+
+/* Define to 1 if you have the <libutil.h> header file. */
+#undef HAVE_LIBUTIL_H
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the `loadquery' function. */
+#undef HAVE_LOADQUERY
+
+/* Define if you have the function `localtime_r'. */
+#undef HAVE_LOCALTIME_R
+
+/* Define to 1 if you have the `logout' function. */
+#undef HAVE_LOGOUT
+
+/* Define to 1 if you have the `logwtmp' function. */
+#undef HAVE_LOGWTMP
+
+/* Define to 1 if the system has the type `long long'. */
+#undef HAVE_LONG_LONG
+
+/* Define if you have the function `lstat'. */
+#undef HAVE_LSTAT
+
+/* Define to 1 if you have the <maillock.h> header file. */
+#undef HAVE_MAILLOCK_H
+
+/* Define if you have the function `memmove'. */
+#undef HAVE_MEMMOVE
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define if you have the function `mkstemp'. */
+#undef HAVE_MKSTEMP
+
+/* Define to 1 if you have the `mktime' function. */
+#undef HAVE_MKTIME
+
+/* Define to 1 if you have a working `mmap' system call. */
+#undef HAVE_MMAP
+
+/* define if you have a ndbm library */
+#undef HAVE_NDBM
+
+/* Define to 1 if you have the <ndbm.h> header file. */
+#undef HAVE_NDBM_H
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netgroup.h> header file. */
+#undef HAVE_NETGROUP_H
+
+/* Define to 1 if you have the <netinet6/in6.h> header file. */
+#undef HAVE_NETINET6_IN6_H
+
+/* Define to 1 if you have the <netinet6/in6_var.h> header file. */
+#undef HAVE_NETINET6_IN6_VAR_H
+
+/* Define to 1 if you have the <netinet/in6.h> header file. */
+#undef HAVE_NETINET_IN6_H
+
+/* Define to 1 if you have the <netinet/in6_machtypes.h> header file. */
+#undef HAVE_NETINET_IN6_MACHTYPES_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/in_systm.h> header file. */
+#undef HAVE_NETINET_IN_SYSTM_H
+
+/* Define to 1 if you have the <netinet/ip.h> header file. */
+#undef HAVE_NETINET_IP_H
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
+/* Define if you want to use Netinfo instead of krb5.conf. */
+#undef HAVE_NETINFO
+
+/* Define to 1 if you have the <netinfo/ni.h> header file. */
+#undef HAVE_NETINFO_NI_H
+
+/* Define to 1 if you have the <net/if.h> header file. */
+#undef HAVE_NET_IF_H
+
+/* Define if NDBM really is DB (creates files *.db) */
+#undef HAVE_NEW_DB
+
+/* define if you have hash functions like md4_finito() */
+#undef HAVE_OLD_HASH_NAMES
+
+/* Define to 1 if you have the `on_exit' function. */
+#undef HAVE_ON_EXIT
+
+/* Define to 1 if you have the `openpty' function. */
+#undef HAVE_OPENPTY
+
+/* define to use openssl's libcrypto */
+#undef HAVE_OPENSSL
+
+/* Define to enable basic OSF C2 support. */
+#undef HAVE_OSFC2
+
+/* Define to 1 if you have the <paths.h> header file. */
+#undef HAVE_PATHS_H
+
+/* Define to 1 if you have the `pidfile' function. */
+#undef HAVE_PIDFILE
+
+/* Define to 1 if you have the `poll' function. */
+#undef HAVE_POLL
+
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
+/* Define to 1 if you have the <pthread.h> header file. */
+#undef HAVE_PTHREAD_H
+
+/* Define to 1 if you have the `ptsname' function. */
+#undef HAVE_PTSNAME
+
+/* Define to 1 if you have the <pty.h> header file. */
+#undef HAVE_PTY_H
+
+/* Define if you have the function `putenv'. */
+#undef HAVE_PUTENV
+
+/* Define to 1 if you have the <pwd.h> header file. */
+#undef HAVE_PWD_H
+
+/* Define to 1 if you have the `rand' function. */
+#undef HAVE_RAND
+
+/* Define to 1 if you have the `random' function. */
+#undef HAVE_RANDOM
+
+/* Define if you have the function `rcmd'. */
+#undef HAVE_RCMD
+
+/* Define if you have a readline compatible library. */
+#undef HAVE_READLINE
+
+/* Define if you have the function `readv'. */
+#undef HAVE_READV
+
+/* Define if you have the function `recvmsg'. */
+#undef HAVE_RECVMSG
+
+/* Define to 1 if you have the <resolv.h> header file. */
+#undef HAVE_RESOLV_H
+
+/* Define to 1 if you have the `res_nsearch' function. */
+#undef HAVE_RES_NSEARCH
+
+/* Define to 1 if you have the `res_search' function. */
+#undef HAVE_RES_SEARCH
+
+/* Define to 1 if you have the `revoke' function. */
+#undef HAVE_REVOKE
+
+/* Define to 1 if you have the <rpcsvc/ypclnt.h> header file. */
+#undef HAVE_RPCSVC_YPCLNT_H
+
+/* Define to 1 if you have the <sac.h> header file. */
+#undef HAVE_SAC_H
+
+/* Define to 1 if the system has the type `sa_family_t'. */
+#undef HAVE_SA_FAMILY_T
+
+/* Define to 1 if you have the <security/pam_modules.h> header file. */
+#undef HAVE_SECURITY_PAM_MODULES_H
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define if you have the function `sendmsg'. */
+#undef HAVE_SENDMSG
+
+/* Define if you have the function `setegid'. */
+#undef HAVE_SETEGID
+
+/* Define if you have the function `setenv'. */
+#undef HAVE_SETENV
+
+/* Define if you have the function `seteuid'. */
+#undef HAVE_SETEUID
+
+/* Define to 1 if you have the `setitimer' function. */
+#undef HAVE_SETITIMER
+
+/* Define to 1 if you have the `setlim' function. */
+#undef HAVE_SETLIM
+
+/* Define to 1 if you have the `setlogin' function. */
+#undef HAVE_SETLOGIN
+
+/* Define to 1 if you have the `setpcred' function. */
+#undef HAVE_SETPCRED
+
+/* Define to 1 if you have the `setpgid' function. */
+#undef HAVE_SETPGID
+
+/* Define to 1 if you have the `setproctitle' function. */
+#undef HAVE_SETPROCTITLE
+
+/* Define to 1 if you have the `setprogname' function. */
+#undef HAVE_SETPROGNAME
+
+/* Define to 1 if you have the `setregid' function. */
+#undef HAVE_SETREGID
+
+/* Define to 1 if you have the `setresgid' function. */
+#undef HAVE_SETRESGID
+
+/* Define to 1 if you have the `setresuid' function. */
+#undef HAVE_SETRESUID
+
+/* Define to 1 if you have the `setreuid' function. */
+#undef HAVE_SETREUID
+
+/* Define to 1 if you have the `setsid' function. */
+#undef HAVE_SETSID
+
+/* Define to 1 if you have the `setsockopt' function. */
+#undef HAVE_SETSOCKOPT
+
+/* Define to 1 if you have the `setstate' function. */
+#undef HAVE_SETSTATE
+
+/* Define to 1 if you have the `setutent' function. */
+#undef HAVE_SETUTENT
+
+/* Define to 1 if you have the `sgi_getcapabilitybyname' function. */
+#undef HAVE_SGI_GETCAPABILITYBYNAME
+
+/* Define to 1 if you have the <sgtty.h> header file. */
+#undef HAVE_SGTTY_H
+
+/* Define to 1 if you have the <shadow.h> header file. */
+#undef HAVE_SHADOW_H
+
+/* Define to 1 if you have the <siad.h> header file. */
+#undef HAVE_SIAD_H
+
+/* Define to 1 if you have the `sigaction' function. */
+#undef HAVE_SIGACTION
+
+/* Define to 1 if you have the <signal.h> header file. */
+#undef HAVE_SIGNAL_H
+
+/* define if you have a working snprintf */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#undef HAVE_SOCKLEN_T
+
+/* Define to 1 if the system has the type `ssize_t'. */
+#undef HAVE_SSIZE_T
+
+/* Define to 1 if you have the <standards.h> header file. */
+#undef HAVE_STANDARDS_H
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define if you have the function `strcasecmp'. */
+#undef HAVE_STRCASECMP
+
+/* Define if you have the function `strdup'. */
+#undef HAVE_STRDUP
+
+/* Define if you have the function `strerror'. */
+#undef HAVE_STRERROR
+
+/* Define if you have the function `strftime'. */
+#undef HAVE_STRFTIME
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define if you have the function `strlcat'. */
+#undef HAVE_STRLCAT
+
+/* Define if you have the function `strlcpy'. */
+#undef HAVE_STRLCPY
+
+/* Define if you have the function `strlwr'. */
+#undef HAVE_STRLWR
+
+/* Define if you have the function `strncasecmp'. */
+#undef HAVE_STRNCASECMP
+
+/* Define if you have the function `strndup'. */
+#undef HAVE_STRNDUP
+
+/* Define if you have the function `strnlen'. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the <stropts.h> header file. */
+#undef HAVE_STROPTS_H
+
+/* Define if you have the function `strptime'. */
+#undef HAVE_STRPTIME
+
+/* Define if you have the function `strsep'. */
+#undef HAVE_STRSEP
+
+/* Define if you have the function `strsep_copy'. */
+#undef HAVE_STRSEP_COPY
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the `strsvis' function. */
+#undef HAVE_STRSVIS
+
+/* Define if you have the function `strtok_r'. */
+#undef HAVE_STRTOK_R
+
+/* Define to 1 if the system has the type `struct addrinfo'. */
+#undef HAVE_STRUCT_ADDRINFO
+
+/* Define to 1 if the system has the type `struct ifaddrs'. */
+#undef HAVE_STRUCT_IFADDRS
+
+/* Define to 1 if the system has the type `struct iovec'. */
+#undef HAVE_STRUCT_IOVEC
+
+/* Define to 1 if the system has the type `struct msghdr'. */
+#undef HAVE_STRUCT_MSGHDR
+
+/* Define to 1 if the system has the type `struct sockaddr'. */
+#undef HAVE_STRUCT_SOCKADDR
+
+/* Define if struct sockaddr has field sa_len. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* define if you have struct spwd */
+#undef HAVE_STRUCT_SPWD
+
+/* Define if struct tm has field tm_gmtoff. */
+#undef HAVE_STRUCT_TM_TM_GMTOFF
+
+/* Define if struct tm has field tm_zone. */
+#undef HAVE_STRUCT_TM_TM_ZONE
+
+/* Define if struct utmpx has field ut_exit. */
+#undef HAVE_STRUCT_UTMPX_UT_EXIT
+
+/* Define if struct utmpx has field ut_syslen. */
+#undef HAVE_STRUCT_UTMPX_UT_SYSLEN
+
+/* Define if struct utmp has field ut_addr. */
+#undef HAVE_STRUCT_UTMP_UT_ADDR
+
+/* Define if struct utmp has field ut_host. */
+#undef HAVE_STRUCT_UTMP_UT_HOST
+
+/* Define if struct utmp has field ut_id. */
+#undef HAVE_STRUCT_UTMP_UT_ID
+
+/* Define if struct utmp has field ut_pid. */
+#undef HAVE_STRUCT_UTMP_UT_PID
+
+/* Define if struct utmp has field ut_type. */
+#undef HAVE_STRUCT_UTMP_UT_TYPE
+
+/* Define if struct utmp has field ut_user. */
+#undef HAVE_STRUCT_UTMP_UT_USER
+
+/* define if struct winsize is declared in sys/termios.h */
+#undef HAVE_STRUCT_WINSIZE
+
+/* Define to 1 if you have the `strunvis' function. */
+#undef HAVE_STRUNVIS
+
+/* Define if you have the function `strupr'. */
+#undef HAVE_STRUPR
+
+/* Define to 1 if you have the `strvis' function. */
+#undef HAVE_STRVIS
+
+/* Define to 1 if you have the `strvisx' function. */
+#undef HAVE_STRVISX
+
+/* Define to 1 if you have the `svis' function. */
+#undef HAVE_SVIS
+
+/* Define if you have the function `swab'. */
+#undef HAVE_SWAB
+
+/* Define to 1 if you have the `sysconf' function. */
+#undef HAVE_SYSCONF
+
+/* Define to 1 if you have the `sysctl' function. */
+#undef HAVE_SYSCTL
+
+/* Define to 1 if you have the `syslog' function. */
+#undef HAVE_SYSLOG
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/bitypes.h> header file. */
+#undef HAVE_SYS_BITYPES_H
+
+/* Define to 1 if you have the <sys/bswap.h> header file. */
+#undef HAVE_SYS_BSWAP_H
+
+/* Define to 1 if you have the <sys/capability.h> header file. */
+#undef HAVE_SYS_CAPABILITY_H
+
+/* Define to 1 if you have the <sys/category.h> header file. */
+#undef HAVE_SYS_CATEGORY_H
+
+/* Define to 1 if you have the <sys/file.h> header file. */
+#undef HAVE_SYS_FILE_H
+
+/* Define to 1 if you have the <sys/filio.h> header file. */
+#undef HAVE_SYS_FILIO_H
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#undef HAVE_SYS_IOCCOM_H
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
+/* Define to 1 if you have the <sys/mman.h> header file. */
+#undef HAVE_SYS_MMAN_H
+
+/* Define to 1 if you have the <sys/param.h> header file. */
+#undef HAVE_SYS_PARAM_H
+
+/* Define to 1 if you have the <sys/proc.h> header file. */
+#undef HAVE_SYS_PROC_H
+
+/* Define to 1 if you have the <sys/ptyio.h> header file. */
+#undef HAVE_SYS_PTYIO_H
+
+/* Define to 1 if you have the <sys/ptyvar.h> header file. */
+#undef HAVE_SYS_PTYVAR_H
+
+/* Define to 1 if you have the <sys/pty.h> header file. */
+#undef HAVE_SYS_PTY_H
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
+/* Define to 1 if you have the <sys/select.h> header file. */
+#undef HAVE_SYS_SELECT_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/stream.h> header file. */
+#undef HAVE_SYS_STREAM_H
+
+/* Define to 1 if you have the <sys/stropts.h> header file. */
+#undef HAVE_SYS_STROPTS_H
+
+/* Define to 1 if you have the <sys/strtty.h> header file. */
+#undef HAVE_SYS_STRTTY_H
+
+/* Define to 1 if you have the <sys/str_tty.h> header file. */
+#undef HAVE_SYS_STR_TTY_H
+
+/* Define to 1 if you have the <sys/syscall.h> header file. */
+#undef HAVE_SYS_SYSCALL_H
+
+/* Define to 1 if you have the <sys/sysctl.h> header file. */
+#undef HAVE_SYS_SYSCTL_H
+
+/* Define to 1 if you have the <sys/termio.h> header file. */
+#undef HAVE_SYS_TERMIO_H
+
+/* Define to 1 if you have the <sys/timeb.h> header file. */
+#undef HAVE_SYS_TIMEB_H
+
+/* Define to 1 if you have the <sys/times.h> header file. */
+#undef HAVE_SYS_TIMES_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/tty.h> header file. */
+#undef HAVE_SYS_TTY_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/ucred.h> header file. */
+#undef HAVE_SYS_UCRED_H
+
+/* Define to 1 if you have the <sys/uio.h> header file. */
+#undef HAVE_SYS_UIO_H
+
+/* Define to 1 if you have the <sys/un.h> header file. */
+#undef HAVE_SYS_UN_H
+
+/* Define to 1 if you have the <sys/utsname.h> header file. */
+#undef HAVE_SYS_UTSNAME_H
+
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
+/* Define to 1 if you have the <termcap.h> header file. */
+#undef HAVE_TERMCAP_H
+
+/* Define to 1 if you have the <termios.h> header file. */
+#undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the <termio.h> header file. */
+#undef HAVE_TERMIO_H
+
+/* Define to 1 if you have the <term.h> header file. */
+#undef HAVE_TERM_H
+
+/* Define to 1 if you have the `tgetent' function. */
+#undef HAVE_TGETENT
+
+/* Define to 1 if you have the `timegm' function. */
+#undef HAVE_TIMEGM
+
+/* Define if you have the `timezone' variable. */
+#undef HAVE_TIMEZONE
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <tmpdir.h> header file. */
+#undef HAVE_TMPDIR_H
+
+/* Define to 1 if you have the `ttyname' function. */
+#undef HAVE_TTYNAME
+
+/* Define to 1 if you have the `ttyslot' function. */
+#undef HAVE_TTYSLOT
+
+/* Define to 1 if you have the <udb.h> header file. */
+#undef HAVE_UDB_H
+
+/* Define to 1 if the system has the type `uint16_t'. */
+#undef HAVE_UINT16_T
+
+/* Define to 1 if the system has the type `uint32_t'. */
+#undef HAVE_UINT32_T
+
+/* Define to 1 if the system has the type `uint64_t'. */
+#undef HAVE_UINT64_T
+
+/* Define to 1 if the system has the type `uint8_t'. */
+#undef HAVE_UINT8_T
+
+/* Define to 1 if you have the `umask' function. */
+#undef HAVE_UMASK
+
+/* Define to 1 if you have the `uname' function. */
+#undef HAVE_UNAME
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `unlockpt' function. */
+#undef HAVE_UNLOCKPT
+
+/* Define if you have the function `unsetenv'. */
+#undef HAVE_UNSETENV
+
+/* Define to 1 if you have the `unvis' function. */
+#undef HAVE_UNVIS
+
+/* Define to 1 if you have the <userconf.h> header file. */
+#undef HAVE_USERCONF_H
+
+/* Define to 1 if you have the <usersec.h> header file. */
+#undef HAVE_USERSEC_H
+
+/* Define to 1 if you have the <util.h> header file. */
+#undef HAVE_UTIL_H
+
+/* Define to 1 if you have the <utmpx.h> header file. */
+#undef HAVE_UTMPX_H
+
+/* Define to 1 if you have the <utmp.h> header file. */
+#undef HAVE_UTMP_H
+
+/* Define to 1 if the system has the type `u_int16_t'. */
+#undef HAVE_U_INT16_T
+
+/* Define to 1 if the system has the type `u_int32_t'. */
+#undef HAVE_U_INT32_T
+
+/* Define to 1 if the system has the type `u_int64_t'. */
+#undef HAVE_U_INT64_T
+
+/* Define to 1 if the system has the type `u_int8_t'. */
+#undef HAVE_U_INT8_T
+
+/* Define to 1 if you have the `vasnprintf' function. */
+#undef HAVE_VASNPRINTF
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define if you have the function `verr'. */
+#undef HAVE_VERR
+
+/* Define if you have the function `verrx'. */
+#undef HAVE_VERRX
+
+/* Define to 1 if you have the `vhangup' function. */
+#undef HAVE_VHANGUP
+
+/* Define to 1 if you have the `vis' function. */
+#undef HAVE_VIS
+
+/* Define to 1 if you have the <vis.h> header file. */
+#undef HAVE_VIS_H
+
+/* define if you have a working vsnprintf */
+#undef HAVE_VSNPRINTF
+
+/* Define if you have the function `vsyslog'. */
+#undef HAVE_VSYSLOG
+
+/* Define if you have the function `vwarn'. */
+#undef HAVE_VWARN
+
+/* Define if you have the function `vwarnx'. */
+#undef HAVE_VWARNX
+
+/* Define if you have the function `warn'. */
+#undef HAVE_WARN
+
+/* Define if you have the function `warnx'. */
+#undef HAVE_WARNX
+
+/* Define if you have the function `writev'. */
+#undef HAVE_WRITEV
+
+/* define if struct winsize has ws_xpixel */
+#undef HAVE_WS_XPIXEL
+
+/* define if struct winsize has ws_ypixel */
+#undef HAVE_WS_YPIXEL
+
+/* Define to 1 if you have the `XauFileName' function. */
+#undef HAVE_XAUFILENAME
+
+/* Define to 1 if you have the `XauReadAuth' function. */
+#undef HAVE_XAUREADAUTH
+
+/* Define to 1 if you have the `XauWriteAuth' function. */
+#undef HAVE_XAUWRITEAUTH
+
+/* Define to 1 if you have the `yp_get_default_domain' function. */
+#undef HAVE_YP_GET_DEFAULT_DOMAIN
+
+/* Define to 1 if you have the `_getpty' function. */
+#undef HAVE__GETPTY
+
+/* Define if you have the `_res' variable. */
+#undef HAVE__RES
+
+/* Define to 1 if you have the `_scrsize' function. */
+#undef HAVE__SCRSIZE
+
+/* define if your compiler has __attribute__ */
+#undef HAVE___ATTRIBUTE__
+
+/* Define if you have the `__progname' variable. */
+#undef HAVE___PROGNAME
+
+/* Define if you have the hesiod package. */
+#undef HESIOD
+
+/* Define if you are running IRIX 4. */
+#undef IRIX4
+
+/* Define if you have the krb4 package. */
+#undef KRB4
+
+/* Enable Kerberos 5 support in applications. */
+#undef KRB5
+
+/* Define if krb_mk_req takes const char * */
+#undef KRB_MK_REQ_CONST
+
+/* This is the krb4 sendauth version. */
+#undef KRB_SENDAUTH_VERS
+
+/* Define to zero if your krb.h doesn't */
+#undef KRB_VERIFY_NOT_SECURE
+
+/* Define to one if your krb.h doesn't */
+#undef KRB_VERIFY_SECURE
+
+/* Define to two if your krb.h doesn't */
+#undef KRB_VERIFY_SECURE_FAIL
+
+/* path to lib */
+#undef LIBDIR
+
+/* path to libexec */
+#undef LIBEXECDIR
+
+/* path to localstate */
+#undef LOCALSTATEDIR
+
+/* define if the system is missing a prototype for asnprintf() */
+#undef NEED_ASNPRINTF_PROTO
+
+/* define if the system is missing a prototype for asprintf() */
+#undef NEED_ASPRINTF_PROTO
+
+/* define if the system is missing a prototype for crypt() */
+#undef NEED_CRYPT_PROTO
+
+/* define if the system is missing a prototype for daemon() */
+#undef NEED_DAEMON_PROTO
+
+/* define if the system is missing a prototype for gethostname() */
+#undef NEED_GETHOSTNAME_PROTO
+
+/* define if the system is missing a prototype for getusershell() */
+#undef NEED_GETUSERSHELL_PROTO
+
+/* define if the system is missing a prototype for glob() */
+#undef NEED_GLOB_PROTO
+
+/* define if the system is missing a prototype for hstrerror() */
+#undef NEED_HSTRERROR_PROTO
+
+/* define if the system is missing a prototype for inet_aton() */
+#undef NEED_INET_ATON_PROTO
+
+/* define if the system is missing a prototype for mkstemp() */
+#undef NEED_MKSTEMP_PROTO
+
+/* define if the system is missing a prototype for setenv() */
+#undef NEED_SETENV_PROTO
+
+/* define if the system is missing a prototype for snprintf() */
+#undef NEED_SNPRINTF_PROTO
+
+/* define if the system is missing a prototype for strndup() */
+#undef NEED_STRNDUP_PROTO
+
+/* define if the system is missing a prototype for strsep() */
+#undef NEED_STRSEP_PROTO
+
+/* define if the system is missing a prototype for strsvis() */
+#undef NEED_STRSVIS_PROTO
+
+/* define if the system is missing a prototype for strtok_r() */
+#undef NEED_STRTOK_R_PROTO
+
+/* define if the system is missing a prototype for strunvis() */
+#undef NEED_STRUNVIS_PROTO
+
+/* define if the system is missing a prototype for strvisx() */
+#undef NEED_STRVISX_PROTO
+
+/* define if the system is missing a prototype for strvis() */
+#undef NEED_STRVIS_PROTO
+
+/* define if the system is missing a prototype for svis() */
+#undef NEED_SVIS_PROTO
+
+/* define if the system is missing a prototype for unsetenv() */
+#undef NEED_UNSETENV_PROTO
+
+/* define if the system is missing a prototype for unvis() */
+#undef NEED_UNVIS_PROTO
+
+/* define if the system is missing a prototype for vasnprintf() */
+#undef NEED_VASNPRINTF_PROTO
+
+/* define if the system is missing a prototype for vasprintf() */
+#undef NEED_VASPRINTF_PROTO
+
+/* define if the system is missing a prototype for vis() */
+#undef NEED_VIS_PROTO
+
+/* define if the system is missing a prototype for vsnprintf() */
+#undef NEED_VSNPRINTF_PROTO
+
+/* Define if you don't want to use mmap. */
+#undef NO_MMAP
+
+/* Define this to enable old environment option in telnet. */
+#undef OLD_ENVIRON
+
+/* Define if you have the openldap package. */
+#undef OPENLDAP
+
+/* Define if you want support for hdb ldap module */
+#undef OPENLDAP_MODULE
+
+/* define if prototype of openlog is compatible with void openlog(const char
+   *, int, int) */
+#undef OPENLOG_PROTO_COMPATIBLE
+
+/* Define if you want OTP support in applications. */
+#undef OTP
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to enable PKINIT. */
+#undef PKINIT
+
+/* Define if getlogin has POSIX flavour (and not BSD). */
+#undef POSIX_GETLOGIN
+
+/* Define if getpwnam_r has POSIX flavour. */
+#undef POSIX_GETPWNAM_R
+
+/* Define if you have the readline package. */
+#undef READLINE
+
+/* Define as the return type of signal handlers (`int' or `void'). */
+#undef RETSIGTYPE
+
+/* path to sbin */
+#undef SBINDIR
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define if you have streams ptys. */
+#undef STREAMSPTY
+
+/* path to sysconf */
+#undef SYSCONFDIR
+
+/* Define to what version of SunOS you are running. */
+#undef SunOS
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#undef TIME_WITH_SYS_TIME
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
+/* Version number of package */
+#undef VERSION
+
+/* Define if signal handlers return void. */
+#undef VOID_RETSIGTYPE
+
+/* define if target is big endian */
+#undef WORDS_BIGENDIAN
+
+/* Define to 1 if the X Window System is missing or not being used. */
+#undef X_DISPLAY_MISSING
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to enable extensions on glibc-based systems such as Linux. */
+#undef _GNU_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef gid_t
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define this to what the type mode_t should be. */
+#undef mode_t
+
+/* Define to `long' if <sys/types.h> does not define. */
+#undef off_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef pid_t
+
+/* Define this to what the type sig_atomic_t should be. */
+#undef sig_atomic_t
+
+/* Define to `unsigned' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> doesn't define. */
+#undef uid_t
+
+#if defined(HAVE_FOUR_VALUED_KRB_PUT_INT) || !defined(KRB4)
+#define KRB_PUT_INT(F, T, L, S) krb_put_int((F), (T), (L), (S))
+#else
+#define KRB_PUT_INT(F, T, L, S) krb_put_int((F), (T), (S))
+#endif
+
+
+
+#if defined(ENCRYPTION) && !defined(AUTHENTICATION)
+#define AUTHENTICATION 1
+#endif
+
+/* Set this to the default system lead string for telnetd 
+ * can contain %-escapes: %s=sysname, %m=machine, %r=os-release
+ * %v=os-version, %t=tty, %h=hostname, %d=date and time
+ */
+#undef USE_IM
+
+/* Used with login -p */
+#undef LOGIN_ARGS
+
+/* set this to a sensible login */
+#ifndef LOGIN_PATH
+#define LOGIN_PATH BINDIR "/login"
+#endif
+
+
+#ifdef ROKEN_RENAME
+#include "roken_rename.h"
+#endif
+
+#ifndef HAVE_KRB_KDCTIMEOFDAY
+#define krb_kdctimeofday(X) gettimeofday((X), NULL)
+#endif
+
+#ifndef HAVE_KRB_GET_KDC_TIME_DIFF
+#define krb_get_kdc_time_diff() (0)
+#endif
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#ifdef BROKEN_REALLOC
+#define realloc(X, Y) rk_realloc((X), (Y))
+#endif
+
+
+#if ENDIANESS_IN_SYS_PARAM_H
+#  include <sys/types.h>
+#  include <sys/param.h>
+#  if BYTE_ORDER == BIG_ENDIAN
+#  define WORDS_BIGENDIAN 1
+#  endif
+#endif
+
+
+#if _AIX
+#define _ALL_SOURCE
+/* XXX this is gross, but kills about a gazillion warnings */
+struct ether_addr;
+struct sockaddr;
+struct sockaddr_dl;
+struct sockaddr_in;
+#endif
+
+
+/* IRIX 4 braindamage */
+#if IRIX == 4 && !defined(__STDC__)
+#define __STDC__ 0
+#endif
+
diff --git a/src/kerberosV/src/include/make_crypto.c b/src/kerberosV/src/include/make_crypto.c
new file mode 100644 (file)
index 0000000..8917995
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2002 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: make_crypto.c,v 1.12 2005/04/18 07:56:41 lha Exp $");
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+int
+main(int argc, char **argv)
+{
+    char *p;
+    FILE *f;
+    if(argc != 2) {
+       fprintf(stderr, "Usage: make_crypto file\n");
+       exit(1);
+    }
+    f = fopen(argv[1], "w");
+    if(f == NULL) {
+       perror(argv[1]);
+       exit(1);
+    }
+    for(p = argv[1]; *p; p++)
+       if(!isalnum((unsigned char)*p))
+           *p = '_';
+    fprintf(f, "#ifndef __%s__\n", argv[1]);
+    fprintf(f, "#define __%s__\n", argv[1]);
+#ifdef HAVE_OPENSSL
+    fputs("#ifndef OPENSSL_DES_LIBDES_COMPATIBILITY\n", f);
+    fputs("#define OPENSSL_DES_LIBDES_COMPATIBILITY\n", f);
+    fputs("#endif\n", f);
+    fputs("#include <openssl/des.h>\n", f);
+    fputs("#include <openssl/rc4.h>\n", f);
+    fputs("#include <openssl/rc2.h>\n", f);
+    fputs("#include <openssl/md4.h>\n", f);
+    fputs("#include <openssl/md5.h>\n", f);
+    fputs("#include <openssl/sha.h>\n", f);
+    fputs("#include <openssl/aes.h>\n", f);
+    fputs("#include <openssl/ui.h>\n", f);
+#else
+    fputs("#ifdef KRB5\n", f);
+    fputs("#include <krb5-types.h>\n", f);
+    fputs("#elif defined(KRB4)\n", f);
+    fputs("#include <ktypes.h>\n", f);
+    fputs("#endif\n", f);
+    fputs("#include <des.h>\n", f);
+    fputs("#include <md4.h>\n", f);
+    fputs("#include <md5.h>\n", f);
+    fputs("#include <sha.h>\n", f);
+    fputs("#include <rc4.h>\n", f);
+    fputs("#include <rc2.h>\n", f);
+    fputs("#include <aes.h>\n", f);
+#ifdef HAVE_OLD_HASH_NAMES
+    fputs("\n", f);
+    fputs("    typedef struct md4 MD4_CTX;\n", f);
+    fputs("#define MD4_Init md4_init\n", f);
+    fputs("#define MD4_Update md4_update\n", f);
+    fputs("#define MD4_Final(D, C) md4_finito((C), (D))\n", f);
+    fputs("\n", f);
+    fputs("    typedef struct md5 MD5_CTX;\n", f);
+    fputs("#define MD5_Init md5_init\n", f);
+    fputs("#define MD5_Update md5_update\n", f);
+    fputs("#define MD5_Final(D, C) md5_finito((C), (D))\n", f);
+    fputs("\n", f);
+    fputs("    typedef struct sha SHA_CTX;\n", f);
+    fputs("#define SHA1_Init sha_init\n", f);
+    fputs("#define SHA1_Update sha_update\n", f);
+    fputs("#define SHA1_Final(D, C) sha_finito((C), (D))\n", f);
+#endif
+#endif
+    fprintf(f, "#endif /* __%s__ */\n", argv[1]);
+    fclose(f);
+    exit(0);
+}
diff --git a/src/kerberosV/src/include/stamp-h.in b/src/kerberosV/src/include/stamp-h.in
new file mode 100644 (file)
index 0000000..9788f70
--- /dev/null
@@ -0,0 +1 @@
+timestamp
diff --git a/src/kerberosV/src/kadmin/CVS/Entries b/src/kerberosV/src/kadmin/CVS/Entries
new file mode 100644 (file)
index 0000000..c1455a9
--- /dev/null
@@ -0,0 +1,28 @@
+/ChangeLog/1.1.1.6/Fri Apr 14 07:32:37 2006//
+/add-random-users.c/1.5/Mon Dec 18 21:08:28 2006//
+/ank.c/1.1.1.4/Fri Apr 14 07:32:37 2006//
+/cpw.c/1.1.1.4/Fri Apr 14 07:32:37 2006//
+/del.c/1.1.1.3/Fri Apr 14 07:32:37 2006//
+/del_enctype.c/1.1.1.3/Fri Apr 14 07:32:37 2006//
+/dump-format.txt/1.1.1.1/Fri Apr 14 07:32:37 2006//
+/dump.c/1.1.1.2/Fri Apr 14 07:32:37 2006//
+/ext.c/1.1.1.5/Fri Apr 14 07:32:37 2006//
+/get.c/1.1.1.3/Fri Apr 14 07:32:37 2006//
+/init.c/1.1.1.3/Fri Apr 14 07:32:38 2006//
+/kadm_conn.c/1.6/Fri Apr 14 08:15:03 2006//
+/kadmin-commands.in/1.1.1.1/Fri Apr 14 07:32:38 2006//
+/kadmin.c/1.4/Fri Apr 14 08:15:03 2006//
+/kadmin_locl.h/1.6/Fri Apr 14 08:15:03 2006//
+/kadmind.8/1.9/Fri Apr 14 08:15:03 2006//
+/kadmind.c/1.5/Fri Apr 14 08:15:03 2006//
+/load.c/1.3/Fri Apr 14 08:15:03 2006//
+/mod.c/1.1.1.3/Fri Apr 14 07:32:38 2006//
+/pw_quality.c/1.1.1.1/Fri Apr 14 07:32:38 2006//
+/random_password.c/1.2/Fri Oct  6 07:09:09 2006//
+/rename.c/1.1.1.3/Fri Apr 14 07:32:38 2006//
+/server.c/1.1.1.4/Fri Apr 14 07:32:39 2006//
+/stash.c/1.1.1.1/Fri Apr 14 07:32:39 2006//
+/util.c/1.6/Fri Apr 14 08:15:03 2006//
+/version4.c/1.4/Fri Oct 29 16:20:29 2004//
+/kadmin.8/1.5/Mon Apr  5 23:11:32 2010//
+D
diff --git a/src/kerberosV/src/kadmin/CVS/Repository b/src/kerberosV/src/kadmin/CVS/Repository
new file mode 100644 (file)
index 0000000..fbab1dd
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/kadmin
diff --git a/src/kerberosV/src/kadmin/CVS/Root b/src/kerberosV/src/kadmin/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/kadmin/ChangeLog b/src/kerberosV/src/kadmin/ChangeLog
new file mode 100644 (file)
index 0000000..b873583
--- /dev/null
@@ -0,0 +1,850 @@
+2005-06-07  David Love  <fx@gnu.org>
+
+       * dump-format.txt: Clarify, spelling and add examples.
+       
+2005-05-30  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * util.c (kdb_attrs): add ok-as-delegate
+
+       * get.c (getit): init data.mask to 0.  Problem found by Andrew
+       Bartlett <abartlet@samba.org>
+
+2005-05-09  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.c (main): catch -2 as EOF
+
+2005-05-03  Dave Love  <d.love@dl.ac.uk>
+
+       * init.c (init): Don't disable forwardable for kadmin/changepw.
+
+2005-05-02  Dave Love  <d.love@dl.ac.uk>
+
+       * kadmin.c (help): Don't use non-constant initializer for `fake'.
+
+2005-04-20  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * util.c (foreach_principal): initialize ret to make sure it have
+       a value
+
+2005-04-04  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmind.c: add verifier libraries with
+       kadm5_add_passwd_quality_verifier
+
+       * kadmin.c: add verifier libraries with
+       kadm5_add_passwd_quality_verifier
+
+       * load.c: max-life and max-renew is of unsigned int in asn1
+       compiler, use that for the parser too
+
+2005-03-26  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.8: List of attributes, from James F.  Hranicky
+       <jfh@cise.ufl.edu>
+
+2005-01-19  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * dump.c (dump): handle errors
+
+2005-01-08 Love Hörquist Ã…strand <lha@it.su.se>
+
+       * dump-format.txt: text dump format
+
+2004-12-08  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmind.8: use keeps around options, from OpenBSD
+       
+       * kadmin.8: use keeps around options, "improve" spelling, from
+       openbsd
+
+2004-11-01  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * get.c (getit): always free columns
+       
+       * ank.c (add_one_principal): catch error from
+       UI_UTIL_read_pw_string
+
+2004-10-31  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * del_enctype.c (del_enctype): fix off-by-one error in del_enctype
+       From: <ragge@ludd.luth.se>
+       
+2004-08-13  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * get.c: print keytypes on long format
+       
+2004-07-06  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * get.c (format_field): allow mod_name to be optional
+       
+       * ext.c (do_ext_keytab): if there isn't any keydata, try using
+       kadm5_randkey_principal
+
+2004-07-02  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * load.c: make merge/load work again
+       
+       * del.c: fix usage string
+       
+       * ank.c: fix slc lossage
+       
+2004-06-28  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.c: use kadm5_ad_init_with_password_ctx
+       
+2004-06-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmin.8: document get -o and stash
+       
+       * get.c: implement output column selection, similar to ps -o
+       
+       * kadmin-commands.in: make get -l the default again, and add
+       column selection flag; sync list with get
+       
+2004-06-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmin-commands.in: mod needs default kvno of -1
+       
+2004-06-21  Johan Danielsson  <joda@pdc.kth.se>
+       
+       * kadmin: convert to use slc; also add stash subcommand
+
+2004-06-15  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.c (main): keytab mode requires principal name
+       
+2004-06-12  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmind.c: drop keyfile, not used, found by
+       Elrond <elrond@samba-tng.org>
+       
+       * kadmin.c: if keyfile is set, pass in to libkadm5 bug pointed out
+       by Elrond <elrond@samba-tng.org>
+       
+2004-05-31  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.c: add --ad flag, XXX rewrite the init kadm5 interface
+       
+2004-05-13  Johan Danielsson  <joda@pdc.kth.se>
+
+       * nuke kerberos 4 kadmin goo
+
+2004-05-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * util.c (str2time_t): fix end-of-day logic, from Duncan
+       McEwan/Mark Davies.
+
+2004-04-29  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * version4.c (handle_v4): make sure length is longer then 2,
+       Pointed out by Evgeny Demidov <demidov@gleg.net>
+       
+       * kadmind.c: make kerberos4 support default turned off
+       
+2004-03-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmin.8: update manpage
+       
+       * mod.c: allow wildcarding principals, and make parameters a work
+       same as if prompted
+       
+2004-03-08  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.8: document password-quality
+       
+       * kadmin_locl.h: add prototype for password_quality
+       
+       * kadmin.c: add password-quality/pwq command
+       
+       * Makefile.am: kadmin_SOURCES += pw_quality.c
+       
+       * pw_quality.c: test run the password quality function
+       
+2004-03-07  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * ank.c (add_one_principal): even though the principal is disabled
+       (creation of random key/keydata), create it with a random password
+       
+2003-12-07  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * init.c (create_random_entry): print error message on failure
+       
+       * ank.c (add_one_principal): pass right argument to
+       kadm5_free_principal_ent From Panasas, Inc
+       
+2003-11-18  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmind.c (main): move opening the logfile to after reading
+       kdc.conf move the loading of hdb keytab ops closer to where its
+       used From: Jeffrey Hutzelman <jhutz@cmu.edu>
+       
+2003-10-04  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * util.c (str2time_t): allow whitespace between date and time
+       From: Bob Beck <beck@cvs.openbsd.org> and adharw@yahoo.com
+       
+2003-09-03  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * ank.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+       
+       * cpw.c: s/des_read_pw_string/UI_UTIL_read_pw_string/
+       
+2003-08-21  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * get.c (print_entry_terse): handle error when unparsing name
+       
+2003-08-18  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmind.c (main): use krb5_prepend_config_files_default, now all
+       options in kdc.conf is parsed, not just [kdc]key-file=
+       
+       * kadmin.c (main): use krb5_prepend_config_files_default, now all
+       options in kdc.conf is parsed, not just [kdc]key-file=
+       
+2003-04-14  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * util.c: cast argument to tolower to unsigned char, from
+       Christian Biere <christianbiere@gmx.de> via NetBSD
+       
+2003-04-06  Love Hörquist Ã…strand <lha@it.su.se>
+
+       * kadmind.8: s/kerberos/Kerberos/
+       
+2003-03-31  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmin.8: initialises -> initializes, from Perry E. Metzger"
+       <perry@piermont.com>
+
+       * kadmin.c: principal, not pricipal. From Thomas Klausner
+       <wiz@netbsd.org>
+
+2003-02-04  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * kadmind.8: spelling, from jmc <jmc@prioris.mini.pw.edu.pl>
+       
+       * kadmin.8: spelling, from jmc <jmc@prioris.mini.pw.edu.pl>
+       
+2003-01-29  Love Hörquist Ã…strand  <lha@it.su.se>
+
+       * server.c (kadmind_dispatch): kadm_chpass: require the password
+       to pass the password quality check in case the user changes the
+       user's own password kadm_chpass_with_key: disallow the user to
+       change it own password to a key, since that password might violate
+       the password quality check.
+
+2002-12-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * util.c (get_response): print a newline if interrupted
+
+       * mod.c (mod_entry): check return value from edit_entry
+
+       * ank.c (add_one_principal): check return value from edit_entry
+
+       * ank.c (add_one_principal): don't continue if create_principal
+       fails
+
+       * init.c: check return value from edit_deltat
+
+       * init.c: add --help
+
+2002-10-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * version4.c: speling (from Tomas Olsson)
+
+2002-10-23  Assar Westerlund  <assar@kth.se>
+
+       * version4.c (decode_packet): check the length of the version
+       string and that rlen has a reasonable value
+
+2002-10-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * version4.c: check size of rlen
+
+2002-09-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * server.c: constify match_appl_version()
+
+       * version4.c: change some lingering krb_err_base
+
+2002-09-09  Jacques Vidrine  <nectar@kth.se>
+
+       * server.c (kadmind_dispatch): while decoding arguments for
+       kadm_chpass_with_key, sanity check the number of keys given.
+       Potential problem pointed out by
+       Sebastian Krahmer <krahmer@suse.de>.
+
+2002-09-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * load.c (parse_generation): return if there is no generation
+       (spotted by Daniel Kouril)
+
+2002-06-07  Jacques Vidrine <n@nectar.com>
+
+       * ank.c: do not attempt to free uninitialized pointer when
+       kadm5_randkey_principal fails.
+
+2002-06-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * util.c: remove unused variable; reported by Hans Insulander
+
+2002-03-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmind.8: clarify some acl wording, and add an example file
+
+2002-02-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ext.c: no need to use the "modify" keytab anymore
+
+2001-09-20  Assar Westerlund  <assar@sics.se>
+
+       * add-random-users.c: allocate several buffers for the list of
+       words, instead of one strdup per word (running under efence does
+       not work very well otherwise)
+
+2001-09-13  Assar Westerlund  <assar@sics.se>
+
+       * add-random-users.c: allow specifying the number of users to
+       create
+
+2001-08-24  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: rename variable name to avoid error from current
+       automake
+
+2001-08-22  Assar Westerlund  <assar@sics.se>
+
+       * kadmin_locl.h: include libutil.h if it exists
+
+2001-08-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * util.c: do something to handle C-c in prompts
+
+       * load.c: remove unused etypes code, and add parsing of the
+       generation field
+
+       * ank.c: add a --use-defaults option to just use default values
+       without questions
+
+       * kadmin.c: add "del" alias for delete
+
+       * cpw.c: call this operation "passwd" in usage
+
+       * kadmin_locl.h: prototype for set_defaults
+
+       * util.c (edit_entry): move setting of default values to a
+       separate function, set_defaults
+
+2001-08-01  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmin.c: print help message on bad options
+
+2001-07-31  Assar Westerlund  <assar@sics.se>
+
+       * add-random-users.c (main): handle --version
+
+2001-07-30  Johan Danielsson  <joda@pdc.kth.se>
+
+       * load.c: increase line buffer to 8k
+
+2001-06-12  Assar Westerlund  <assar@sics.se>
+
+       * ext.c (ext_keytab): use the default modify keytab per default
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * kadm_conn.c (start_server): fix krb5_eai_to_heim_errno call
+
+2001-05-15  Assar Westerlund  <assar@sics.se>
+
+       * kadmin.c (main): some error cleaning required
+
+2001-05-14  Assar Westerlund  <assar@sics.se>
+
+       * kadmind.c: new krb5_config_parse_file
+       * kadmin.c: new krb5_config_parse_file
+       * kadm_conn.c: update to new krb5_sockaddr2address
+
+2001-05-07  Assar Westerlund  <assar@sics.se>
+
+       * kadmin_locl.h (foreach_principal): update prototype
+       * get.c (getit): new foreach_principal
+       * ext.c (ext_keytab): new foreach_principal
+       * del.c (del_entry): new foreach_principal
+       * cpw.c (cpw_entry): new foreach_principal
+       * util.c (foreach_principal): add `funcname' and try printing the
+       error string
+
+2001-05-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * rename.c: fix argument number test
+       
+2001-04-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * del_enctype.c: fix argument count check after getarg change;
+       spotted by mark@MCS.VUW.AC.NZ
+
+2001-02-15  Assar Westerlund  <assar@sics.se>
+
+       * kadmind.c (main): use a `struct sockaddr_storage' to be able to
+       store all types of addresses
+
+2001-02-07  Assar Westerlund  <assar@sics.se>
+
+       * kadmin.c: add --keytab / _K, from Leif Johansson
+       <leifj@it.su.se>
+
+2001-01-29  Assar Westerlund  <assar@sics.se>
+
+       * kadm_conn.c (spawn_child): close the newly created socket in the
+       packet, it's not used.  from <shadow@dementia.org>
+       * version4.c (decode_packet): check success of
+       krb5_425_conv_principal.  from <shadow@dementia.org>
+
+2001-01-12  Assar Westerlund  <assar@sics.se>
+
+       * util.c (parse_attributes): make empty string mean no attributes,
+       specifying the empty string at the command line should give you no
+       attributes, but just pressing return at the prompt gives you
+       default attributes
+       (edit_entry): only pick up values from the default principal if they
+       aren't set in the principal being edited
+
+2001-01-04  Assar Westerlund  <assar@sics.se>
+
+       * load.c (doit): print an error and bail out if storing an entry
+       in the database fails.  The most likely reason for it failing is
+       out-of-space.
+
+2000-12-31  Assar Westerlund  <assar@sics.se>
+
+       * kadmind.c (main): handle krb5_init_context failure consistently
+       * kadmin.c (main): handle krb5_init_context failure consistently
+       * add-random-users.c (add_user): handle krb5_init_context failure
+       consistently
+
+       * kadm_conn.c (spawn_child): use a struct sockaddr_storage
+
+2000-12-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * get.c: avoid asprintf'ing NULL strings
+
+2000-12-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * load.c: fix option parsing
+
+2000-11-16  Assar Westerlund  <assar@sics.se>
+
+       * kadm_conn.c (wait_for_connection): check for fd's being too
+       large to select on
+
+2000-11-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * get.c: don't try to print modifier name if it isn't set (from
+       Jacques A. Vidrine" <n@nectar.com>)
+
+2000-09-19  Assar Westerlund  <assar@sics.se>
+
+       * server.c (kadmind_loop): send in keytab to v4 handling function
+       * version4.c: allow the specification of what keytab to use
+
+       * get.c (print_entry_long): actually print the actual saltvalue
+       used if it's not the default
+
+2000-09-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmin.c: add option parsing, and add `privs' as an alias for
+       `privileges'
+
+       * init.c: complain if there's no realm name specified
+
+       * rename.c: add option parsing
+
+       * load.c: add option parsing
+
+       * get.c: make `get' and `list' aliases to each other, but with
+       different defaults
+
+       * del_enctype.c: add option parsing
+
+       * del.c: add option parsing
+
+       * ank.c: calling the command `add' make more sense from an english
+       pov
+
+       * Makefile.am: add kadmin manpage
+
+       * kadmin.8: short manpage
+
+       * kadmin.c: `quit' should be a alias for `exit', not `help'
+
+2000-08-27  Assar Westerlund  <assar@sics.se>
+
+       * server.c (handle_v5): do not try to perform stupid stunts when
+       printing errors
+
+2000-08-19  Assar Westerlund  <assar@sics.se>
+
+       * util.c (str2time_t): add alias for `now'.
+
+2000-08-18  Assar Westerlund  <assar@sics.se>
+
+       * server.c (handle_v5): accept any kadmin/admin@* principal as the
+       server
+       * kadmind.c: remove extra prototype of kadmind_loop
+       * kadmin_locl.h (kadmind_loop): add prototype
+       
+       * init.c (usage): print init-usage and not add-dito
+       
+2000-08-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmind.c: use roken_getsockname
+
+2000-08-07  Assar Westerlund  <assar@sics.se>
+
+       * kadmind.c, kadm_conn.c: use socklen_t instead of int where
+       appropriate.  From <thorpej@netbsd.org>
+
+2000-08-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: link with pidfile library
+
+       * kadmind.c: write a pid file, and setup password quality
+       functions
+
+       * kadmin_locl.h: util.h
+
+2000-07-27  Assar Westerlund  <assar@sics.se>
+
+       * version4.c (decode_packet): be totally consistent with the
+       prototype of des_cbc_cksum
+       * kadmind.c: use sa_size instead of sa_len, some systems define
+       this to emulate anonymous unions
+       * kadm_conn.c: use sa_size instead of sa_len, some systems define
+       this to emulate anonymous unions
+
+2000-07-24  Assar Westerlund  <assar@sics.se>
+
+       * kadmin.c (commands): add quit
+       * load.c (doit): truncate the log since there's no way of knowing
+       what changes are going to be added
+
+2000-07-23  Assar Westerlund  <assar@sics.se>
+
+       * util.c (str2time_t): be more careful with strptime that might
+       zero out the `struct tm'
+
+2000-07-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadm_conn.c: make the parent process wait for children and
+       terminate after receiving a signal, also terminate on SIGINT
+
+2000-07-22  Assar Westerlund  <assar@sics.se>
+
+       * version4.c: map both princ_expire_time and pw_expiration to v4
+       principal expiration
+
+2000-07-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * version4.c (handle_v4): check for termination
+
+       * server.c (v5_loop): check for termination
+
+       * kadm_conn.c (wait_term): if we're doing something, set just set
+       a flag otherwise exit rightaway
+
+       * server.c: use krb5_read_priv_message; (v5_loop): check for EOF
+
+2000-07-21  Assar Westerlund  <assar@sics.se>
+
+       * kadm_conn.c: remove sys/select.h.  make signal handlers
+       type-correct and static
+
+       * kadmin_locl.h: add limits.h and sys/select.h
+
+2000-07-20  Assar Westerlund  <assar@sics.se>
+
+       * init.c (init): also create `kadmin/hprop'
+       * kadmind.c: ports is a string argument
+       * kadm_conn.c (start_server): fix printf format
+
+       * kadmin_locl.h: add <sys/select.h>
+       * kadm_conn.c: remove sys/select.h.  make signal handlers
+       type-correct and static
+
+       * kadmin_locl.h: add limits.h and sys/select.h
+
+2000-07-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadm_conn.c: put all processes in a new process group
+
+       * server.c (v5_loop): use krb5_{read,write}_priv_message
+
+2000-07-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * version4.c: change log strings to match the v5 counterparts
+
+       * mod.c: allow setting kvno
+
+       * kadmind.c: if stdin is not a socket create and listen to sockets
+
+       * kadm_conn.c: socket creation functions
+
+       * util.c (deltat2str): treat 0 and INT_MAX as never
+
+2000-07-08  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (INCLUDES): add ../lib/krb5
+       * kadmin_locl.h: add krb5_locl.h (since we just use some stuff
+       from there)
+
+2000-06-07  Assar Westerlund  <assar@sics.se>
+
+       * add-random-users.c: new testing program that adds a number of
+       randomly generated users
+
+2000-04-12  Assar Westerlund  <assar@sics.se>
+
+       * cpw.c (do_cpw_entry): call set_password if no argument is given,
+       it will prompt for the password.
+       * kadmin.c: make help only print the commands that are actually
+       available.
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * del_enctype.c (del_enctype): set ignore correctly
+
+2000-04-02  Assar Westerlund  <assar@sics.se>
+
+       * kadmin.c (main): make parse errors a fatal error
+       * init.c (init): create changepw/kerberos with disallow-tgt and
+       pwchange attributes
+
+2000-03-23  Assar Westerlund  <assar@sics.se>
+
+       * util.c (hex2n, parse_des_key): add
+       * server.c (kadmind_dispatch): add kadm_chpass_with_key
+       * cpw.c: add --key
+       * ank.c: add --key
+
+2000-02-16  Assar Westerlund  <assar@sics.se>
+
+       * load.c (doit): check return value from parse_hdbflags2int
+       correctly
+
+2000-01-25  Assar Westerlund  <assar@sics.se>
+
+       * load.c: checking all parsing for errors and all memory
+       allocations also
+
+2000-01-02  Assar Westerlund  <assar@sics.se>
+
+       * server.c: check initial flag in ticket and allow users to change
+       their own password if it's set
+       * ext.c (do_ext_keytab): set timestamp
+
+1999-12-14  Assar Westerlund  <assar@sics.se>
+
+       * del_enctype.c (usage): don't use arg_printusage
+
+1999-11-25  Assar Westerlund  <assar@sics.se>
+
+       * del_enctype.c (del_enctype): try not to leak memory
+
+       * version4.c (kadm_ser_mod): use kadm5_s_modify_principal (no
+       _with_key)
+
+       * kadmin.c: add `del_enctype'
+
+       * del_enctype.c (del_enctype): new function for deleting enctypes
+       from a principal
+
+       * Makefile.am (kadmin_SOURCES): add del_enctype.c
+
+1999-11-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * server.c: cope with old clients
+
+       * kadmin_locl.h: remove version string
+
+1999-10-17  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (kadmin_LDADD): add LIB_dlopen
+
+1999-10-01  Assar Westerlund  <assar@sics.se>
+
+       * ank.c (add_one_principal): `password' can cactually be NULL in
+       the overwrite code, check for it.
+
+1999-09-20  Assar Westerlund  <assar@sics.se>
+
+       * mod.c (mod_entry): print the correct principal name in error
+       messages.  From Love <lha@e.kth.se>
+
+1999-09-10  Assar Westerlund  <assar@sics.se>
+
+       * init.c (init): also create `changepw/kerberos'
+
+       * version4.c: only create you loose packets when we fail decoding
+       and not when an operation is not performed for some reason
+       (decode_packet): read the service key from the hdb
+       (dispatch, decode_packet): return proper error messages
+
+       * version4.c (kadm_ser_cpw): add password quality functions
+
+1999-08-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * server.c (handle_v5): give more informative message if
+       KRB5_KT_NOTFOUND
+
+1999-08-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kadmind.c: use HDB keytabs
+
+1999-08-25  Assar Westerlund  <assar@sics.se>
+
+       * cpw.c (set_password): use correct variable.  From Love
+       <lha@e.kth.se>
+
+       * server.c (v5_loop): use correct error code
+
+       * ank.c (add_one_principal): initialize `default_ent'
+
+1999-08-21  Assar Westerlund  <assar@sics.se>
+
+       * random_password.c: new file, stolen from krb4
+
+       * kadmin_locl.h: add prototype for random_password
+
+       * cpw.c: add support for --random-password
+
+       * ank.c: add support for --random-password
+
+       * Makefile.am (kadmin_SOURCES): add random_password.c
+
+1999-08-19  Assar Westerlund  <assar@sics.se>
+
+       * util.c (edit_timet): break when we manage to parse the time not
+       the inverse.
+
+       * mod.c: add parsing of lots of options.  From Love
+       <lha@stacken.kth.se>
+
+       * ank.c: add setting of expiration and password expiration
+
+       * kadmin_locl.h: update util.c prototypes
+
+       * util.c: move-around.  clean-up, rename, make consistent (and
+       some other weird stuff).  based on patches from Love
+       <lha@stacken.kth.se>
+
+       * version4.c (kadm_ser_cpw): initialize password
+       (handle_v4): remove unused variable `ret'
+
+1999-08-16  Assar Westerlund  <assar@sics.se>
+
+       * version4.c (handle_v4): more error checking and more correct
+       error messages
+
+       * server.c (v5_loop, kadmind_loop): more error checking and more
+       correct error messages
+
+1999-07-24  Assar Westerlund  <assar@sics.se>
+
+       * util.c (str2timeval, edit_time): functions for parsing and
+       editing times.  Based on patches from Love <lha@stacken.kth.se>.
+       (edit_entry): call new functions
+
+       * mod.c (mod_entry): allow modifying expiration times
+
+       * kadmin_locl.h (str2timeval): add prototype
+
+       * ank.c (add_one_principal): allow setting expiration times
+
+1999-07-03  Assar Westerlund  <assar@sics.se>
+
+       * server.c (v5_loop): handle data allocation with krb5_data_alloc
+       and check return value
+
+1999-06-23  Assar Westerlund  <assar@sics.se>
+
+       * version4.c (kadm_ser_cpw): read the key in the strange order
+       it's sent
+
+       * util.c (edit_entry): look at default
+       (edit_time): always set mask even if value == 0
+
+       * kadmin_locl.h (edit_entry): update
+
+       * ank.c: make ank use the values of the default principal for
+       prompting
+
+       * version4.c (values_to_ent): convert key data correctly
+
+1999-05-23  Assar Westerlund  <assar@sics.se>
+
+       * init.c (create_random_entry): more correct setting of mask
+
+1999-05-21  Assar Westerlund  <assar@sics.se>
+
+       * server.c (handle_v5): read sendauth version correctly.
+
+1999-05-14  Assar Westerlund  <assar@sics.se>
+
+       * version4.c (error_code): try to handle really old krb4
+       distributions
+
+1999-05-11  Assar Westerlund  <assar@sics.se>
+
+       * init.c (init): initialize realm_max_life and realm_max_rlife
+
+1999-05-07  Assar Westerlund  <assar@sics.se>
+
+       * ank.c (add_new_key): initialize more variables
+
+1999-05-04  Assar Westerlund  <assar@sics.se>
+
+       * version4.c (kadm_ser_cpw): always allow a user to change her
+       password
+       (kadm_ser_*): make logging work
+       clean-up and restructure
+       
+       * kadmin_locl.h (set_entry): add prototype
+
+       * kadmin.c (usage): update usage string
+
+       * init.c (init): new arguments realm-max-ticket-life and
+       realm-max-renewable-life
+
+       * util.c (edit_time, edit_attributes): don't do anything if it's
+       already set
+       (set_entry): new function
+
+       * ank.c (add_new_key): new options for setting max-ticket-life,
+       max-renewable-life, and attributes
+
+       * server.c (v5_loop): remove unused variable
+
+       * kadmin_locl.h: add prototypes
+
+       * version4.c: re-insert krb_err.h and other miss
+
+       * server.c (kadmind_loop): break-up and restructure
+
+       * version4.c: add ACL checks more error code checks restructure
+       
+1999-05-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * load.c: check for (un-)encrypted keys
+
+       * dump.c: use hdb_print_entry
+       
+       * version4.c: version 4 support
+
+       * Makefile.am: link with krb4
+
+       * kadmin_locl.h: include <sys/un.h>
+
+       * server.c: move from lib/kadm5, and add basic support for krb4
+       kadmin protocol
+
+       * kadmind.c: move recvauth to kadmind_loop()
diff --git a/src/kerberosV/src/kadmin/add-random-users.c b/src/kerberosV/src/kadmin/add-random-users.c
new file mode 100644 (file)
index 0000000..bbc035b
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2000 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+
+RCSID("$KTH: add-random-users.c,v 1.6 2001/09/20 09:17:33 assar Exp $");
+
+#define WORDS_FILENAME "/usr/share/dict/words"
+
+#define NUSERS 1000
+
+#define WORDBUF_SIZE 65535
+
+static unsigned
+read_words (const char *filename, char ***ret_w)
+{
+    unsigned n, alloc;
+    FILE *f;
+    char buf[256];
+    char **w = NULL;
+    char *wbuf = NULL, *wptr = NULL, *wend = NULL;
+
+    f = fopen (filename, "r");
+    if (f == NULL)
+       err (1, "cannot open %s", filename);
+    alloc = n = 0;
+    while (fgets (buf, sizeof(buf), f) != NULL) {
+       size_t len;
+
+       buf[strcspn(buf, "\r\n")] = '\0';
+       len = strlen(buf);
+       if (n >= alloc) {
+           alloc = max(alloc + 16, alloc * 2);
+           w = erealloc (w, alloc * sizeof(char **));
+       }
+       if (wptr + len + 1 >= wend) {
+           wptr = wbuf = emalloc (WORDBUF_SIZE);
+           wend = wbuf + WORDBUF_SIZE;
+       }
+       memmove (wptr, buf, len + 1);
+       w[n++] = wptr;
+       wptr += len + 1;
+    }
+    *ret_w = w;
+    return n;
+}
+
+static void
+add_user (krb5_context context, void *kadm_handle,
+         unsigned nwords, char **words)
+{
+    kadm5_principal_ent_rec princ;
+    char name[64];
+    int r1, r2;
+    krb5_error_code ret;
+    int mask;
+
+    r1 = rand();
+    r2 = rand();
+
+    snprintf (name, sizeof(name), "%s%d", words[r1 % nwords], r2 % 1000);
+
+    mask = KADM5_PRINCIPAL;
+
+    memset(&princ, 0, sizeof(princ));
+    ret = krb5_parse_name(context, name, &princ.principal);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+
+    ret = kadm5_create_principal (kadm_handle, &princ, mask, name);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_create_principal");
+    kadm5_free_principal_ent(kadm_handle, &princ);
+    printf ("%s\n", name);
+}
+
+static void
+add_users (const char *filename, unsigned n)
+{
+    krb5_error_code ret;
+    int i;
+    void *kadm_handle;
+    krb5_context context;
+    unsigned nwords;
+    char **words;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+    ret = kadm5_s_init_with_password_ctx(context, 
+                                        KADM5_ADMIN_SERVICE,
+                                        NULL,
+                                        KADM5_ADMIN_SERVICE,
+                                        NULL, 0, 0, 
+                                        &kadm_handle);
+    if(ret)
+       krb5_err(context, 1, ret, "kadm5_init_with_password");
+
+    nwords = read_words (filename, &words);
+    
+    for (i = 0; i < n; ++i)
+       add_user (context, kadm_handle, nwords, words);
+    kadm5_destroy(kadm_handle);
+    krb5_free_context(context);
+}
+
+static int version_flag        = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "[filename [n]]");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    int n = NUSERS;
+    const char *filename = WORDS_FILENAME;
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    if (help_flag)
+       usage (0);
+    if (version_flag) {
+       print_version(NULL);
+       return 0;
+    }
+    srand (0);
+    argc -= optind;
+    argv += optind;
+
+    if (argc > 0) {
+       if (argc > 1)
+           n = atoi(argv[1]);
+       filename = argv[0];
+    }
+
+    add_users (filename, n);
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/ank.c b/src/kerberosV/src/kadmin/ank.c
new file mode 100644 (file)
index 0000000..201b6e6
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: ank.c,v 1.34 2004/11/01 08:41:00 lha Exp $");
+
+/*
+ * fetch the default principal corresponding to `princ'
+ */
+
+static krb5_error_code
+get_default (kadm5_server_context *context,
+            krb5_principal princ,
+            kadm5_principal_ent_t default_ent)
+{
+    krb5_error_code ret;
+    krb5_principal def_principal;
+    krb5_realm *realm = krb5_princ_realm(context->context, princ);
+
+    ret = krb5_make_principal (context->context, &def_principal,
+                              *realm, "default", NULL);
+    if (ret)
+       return ret;
+    ret = kadm5_get_principal (context, def_principal, default_ent,
+                              KADM5_PRINCIPAL_NORMAL_MASK);
+    krb5_free_principal (context->context, def_principal);
+    return ret;
+}
+
+/*
+ * Add the principal `name' to the database.
+ * Prompt for all data not given by the input parameters.
+ */
+
+static krb5_error_code
+add_one_principal (const char *name,
+                  int rand_key,
+                  int rand_password,
+                  int use_defaults, 
+                  char *password,
+                  krb5_key_data *key_data,
+                  const char *max_ticket_life,
+                  const char *max_renewable_life,
+                  const char *attributes,
+                  const char *expiration,
+                  const char *pw_expiration)
+{
+    krb5_error_code ret;
+    kadm5_principal_ent_rec princ, defrec;
+    kadm5_principal_ent_rec *default_ent = NULL;
+    krb5_principal princ_ent = NULL;
+    int mask = 0;
+    int default_mask = 0;
+    char pwbuf[1024];
+
+    memset(&princ, 0, sizeof(princ));
+    ret = krb5_parse_name(context, name, &princ_ent);
+    if (ret) {
+       krb5_warn(context, ret, "krb5_parse_name");
+       return ret;
+    }
+    princ.principal = princ_ent;
+    mask |= KADM5_PRINCIPAL;
+
+    ret = set_entry(context, &princ, &mask,
+                   max_ticket_life, max_renewable_life, 
+                   expiration, pw_expiration, attributes);
+    if (ret)
+       goto out;
+
+    default_ent = &defrec;
+    ret = get_default (kadm_handle, princ_ent, default_ent);
+    if (ret) {
+       default_ent  = NULL;
+       default_mask = 0;
+    } else {
+       default_mask = KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
+           KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION;
+    }
+
+    if(use_defaults) 
+       set_defaults(&princ, &mask, default_ent, default_mask);
+    else
+       if(edit_entry(&princ, &mask, default_ent, default_mask))
+           goto out;
+    if(rand_key || key_data) {
+       princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+       mask |= KADM5_ATTRIBUTES;
+       random_password (pwbuf, sizeof(pwbuf));
+       password = pwbuf;
+    } else if (rand_password) {
+       random_password (pwbuf, sizeof(pwbuf));
+       password = pwbuf;
+    } else if(password == NULL) {
+       char *princ_name;
+       char *prompt;
+
+       krb5_unparse_name(context, princ_ent, &princ_name);
+       asprintf (&prompt, "%s's Password: ", princ_name);
+       free (princ_name);
+       ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), prompt, 1);
+       free (prompt);
+       if (ret) {
+           krb5_set_error_string(context, "failed to verify password");
+           ret = KRB5_LIBOS_BADPWDMATCH;
+           goto out;
+       }
+       password = pwbuf;
+    }
+    
+    ret = kadm5_create_principal(kadm_handle, &princ, mask, password);
+    if(ret) {
+       krb5_warn(context, ret, "kadm5_create_principal");
+       goto out;
+    }
+    if(rand_key) {
+       krb5_keyblock *new_keys;
+       int n_keys, i;
+       ret = kadm5_randkey_principal(kadm_handle, princ_ent, 
+                                     &new_keys, &n_keys);
+       if(ret){
+           krb5_warn(context, ret, "kadm5_randkey_principal");
+           n_keys = 0;
+       }
+       for(i = 0; i < n_keys; i++)
+           krb5_free_keyblock_contents(context, &new_keys[i]);
+       if (n_keys > 0)
+           free(new_keys);
+       kadm5_get_principal(kadm_handle, princ_ent, &princ, 
+                           KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
+       princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
+       princ.kvno = 1;
+       kadm5_modify_principal(kadm_handle, &princ, 
+                              KADM5_ATTRIBUTES | KADM5_KVNO);
+       kadm5_free_principal_ent(kadm_handle, &princ);
+    } else if (key_data) {
+       ret = kadm5_chpass_principal_with_key (kadm_handle, princ_ent,
+                                              3, key_data);
+       if (ret) {
+           krb5_warn(context, ret, "kadm5_chpass_principal_with_key");
+       }
+       kadm5_get_principal(kadm_handle, princ_ent, &princ, 
+                           KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
+       princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
+       kadm5_modify_principal(kadm_handle, &princ, KADM5_ATTRIBUTES);
+       kadm5_free_principal_ent(kadm_handle, &princ);
+    } else if (rand_password) {
+       char *princ_name;
+
+       krb5_unparse_name(context, princ_ent, &princ_name);
+       printf ("added %s with password \"%s\"\n", princ_name, password);
+       free (princ_name);
+    }
+out:
+    if (princ_ent)
+       krb5_free_principal (context, princ_ent);
+    if(default_ent)
+       kadm5_free_principal_ent (kadm_handle, default_ent);
+    if (password != NULL)
+       memset (password, 0, strlen(password));
+    return ret;
+}
+
+/*
+ * parse the string `key_string' into `key', returning 0 iff succesful.
+ */
+
+/*
+ * the ank command
+ */
+
+/*
+ * Parse arguments and add all the principals.
+ */
+
+int
+add_new_key(struct add_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    int i;
+    int num;
+    krb5_key_data key_data[3];
+    krb5_key_data *kdp = NULL;
+
+    num = 0;
+    if (opt->random_key_flag)
+       ++num;
+    if (opt->random_password_flag)
+       ++num;
+    if (opt->password_string)
+       ++num;
+    if (opt->key_string)
+       ++num;
+
+    if (num > 1) {
+       fprintf (stderr, "give only one of "
+               "--random-key, --random-password, --password, --key\n");
+       return 0;
+    }
+
+    if (opt->key_string) {
+       const char *error;
+
+       if (parse_des_key (opt->key_string, key_data, &error)) {
+           fprintf (stderr, "failed parsing key \"%s\": %s\n", 
+                    opt->key_string, error);
+           return 0;
+       }
+       kdp = key_data;
+    }
+
+    for(i = 0; i < argc; i++) {
+       ret = add_one_principal (argv[i], 
+                                opt->random_key_flag, 
+                                opt->random_password_flag,
+                                opt->use_defaults_flag, 
+                                opt->password_string,
+                                kdp,
+                                opt->max_ticket_life_string,
+                                opt->max_renewable_life_string,
+                                opt->attributes_string,
+                                opt->expiration_time_string,
+                                opt->pw_expiration_time_string);
+       if (ret) {
+           krb5_warn (context, ret, "adding %s", argv[i]);
+           break;
+       }
+    }
+    if (kdp) {
+       int16_t dummy = 3;
+       kadm5_free_key_data (kadm_handle, &dummy, key_data);
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/cpw.c b/src/kerberosV/src/kadmin/cpw.c
new file mode 100644 (file)
index 0000000..f007be5
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: cpw.c,v 1.17 2004/07/04 15:09:42 joda Exp $");
+
+struct cpw_entry_data {
+    int random_key;
+    int random_password;
+    char *password;
+    krb5_key_data *key_data;
+};
+
+static int
+set_random_key (krb5_principal principal)
+{
+    krb5_error_code ret;
+    int i;
+    krb5_keyblock *keys;
+    int num_keys;
+
+    ret = kadm5_randkey_principal(kadm_handle, principal, &keys, &num_keys);
+    if(ret)
+       return ret;
+    for(i = 0; i < num_keys; i++)
+       krb5_free_keyblock_contents(context, &keys[i]);
+    free(keys);
+    return 0;
+}
+
+static int
+set_random_password (krb5_principal principal)
+{
+    krb5_error_code ret;
+    char pw[128];
+
+    random_password (pw, sizeof(pw));
+    ret = kadm5_chpass_principal(kadm_handle, principal, pw);
+    if (ret == 0) {
+       char *princ_name;
+
+       krb5_unparse_name(context, principal, &princ_name);
+
+       printf ("%s's password set to \"%s\"\n", princ_name, pw);
+       free (princ_name);
+    }
+    memset (pw, 0, sizeof(pw));
+    return ret;
+}
+
+static int
+set_password (krb5_principal principal, char *password)
+{
+    krb5_error_code ret = 0;
+    char pwbuf[128];
+
+    if(password == NULL) {
+       char *princ_name;
+       char *prompt;
+
+       krb5_unparse_name(context, principal, &princ_name);
+       asprintf(&prompt, "%s's Password: ", princ_name);
+       free (princ_name);
+       ret = UI_UTIL_read_pw_string(pwbuf, sizeof(pwbuf), prompt, 1);
+       free (prompt);
+       if(ret){
+           return 0; /* XXX error code? */
+       }
+       password = pwbuf;
+    }
+    if(ret == 0)
+       ret = kadm5_chpass_principal(kadm_handle, principal, password);
+    memset(pwbuf, 0, sizeof(pwbuf));
+    return ret;
+}
+
+static int
+set_key_data (krb5_principal principal, krb5_key_data *key_data)
+{
+    krb5_error_code ret;
+
+    ret = kadm5_chpass_principal_with_key (kadm_handle, principal,
+                                          3, key_data);
+    return ret;
+}
+
+static int
+do_cpw_entry(krb5_principal principal, void *data)
+{
+    struct cpw_entry_data *e = data;
+    
+    if (e->random_key)
+       return set_random_key (principal);
+    else if (e->random_password)
+       return set_random_password (principal);
+    else if (e->key_data)
+       return set_key_data (principal, e->key_data);
+    else
+       return set_password (principal, e->password);
+}
+
+int
+cpw_entry(struct passwd_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    int i;
+    struct cpw_entry_data data;
+    int num;
+    krb5_key_data key_data[3];
+
+    data.random_key = opt->random_key_flag;
+    data.random_password = opt->random_password_flag;
+    data.password = opt->password_string;
+    data.key_data       = NULL;
+
+    num = 0;
+    if (data.random_key)
+       ++num;
+    if (data.random_password)
+       ++num;
+    if (data.password)
+       ++num;
+    if (opt->key_string)
+       ++num;
+
+    if (num > 1) {
+       fprintf (stderr, "give only one of "
+               "--random-key, --random-password, --password, --key\n");
+       return 0;
+    }
+       
+    if (opt->key_string) {
+       const char *error;
+
+       if (parse_des_key (opt->key_string, key_data, &error)) {
+           fprintf (stderr, "failed parsing key \"%s\": %s\n", 
+                    opt->key_string, error);
+           return 0;
+       }
+       data.key_data = key_data;
+    }
+
+    for(i = 0; i < argc; i++)
+       ret = foreach_principal(argv[i], do_cpw_entry, "cpw", &data);
+
+    if (data.key_data) {
+       int16_t dummy;
+       kadm5_free_key_data (kadm_handle, &dummy, key_data);
+    }
+
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/del.c b/src/kerberosV/src/kadmin/del.c
new file mode 100644 (file)
index 0000000..331af3d
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: del.c,v 1.11 2004/07/05 11:41:22 joda Exp $");
+
+static int
+do_del_entry(krb5_principal principal, void *data)
+{
+    return kadm5_delete_principal(kadm_handle, principal);
+}
+
+int
+del_entry(void *opt, int argc, char **argv)
+{
+    int i;
+    krb5_error_code ret;
+
+    for(i = 0; i < argc; i++)
+       ret = foreach_principal(argv[i], do_del_entry, "del", NULL);
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/del_enctype.c b/src/kerberosV/src/kadmin/del_enctype.c
new file mode 100644 (file)
index 0000000..1184fe7
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: del_enctype.c,v 1.12 2004/10/31 14:13:17 lha Exp $");
+
+/*
+ * del_enctype principal enctypes...
+ */
+
+int
+del_enctype(void *opt, int argc, char **argv)
+{
+    kadm5_principal_ent_rec princ;
+    krb5_principal princ_ent = NULL;
+    krb5_error_code ret;
+    const char *princ_name;
+    int i, j, k;
+    krb5_key_data *new_key_data;
+    int n_etypes;
+    krb5_enctype *etypes;
+
+    memset (&princ, 0, sizeof(princ));
+    princ_name = argv[0];
+    n_etypes   = argc - 1;
+    etypes     = malloc (n_etypes * sizeof(*etypes));
+    if (etypes == NULL) {
+       krb5_warnx (context, "out of memory");
+       return 0;
+    }
+    argv++;
+    for (i = 0; i < n_etypes; ++i) {
+       ret = krb5_string_to_enctype (context, argv[i], &etypes[i]);
+       if (ret) {
+           krb5_warnx (context, "bad enctype \"%s\"", argv[i]);
+           goto out2;
+       }
+    }
+
+    ret = krb5_parse_name(context, princ_name, &princ_ent);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_parse_name %s", princ_name);
+       goto out2;
+    }
+
+    ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
+                             KADM5_PRINCIPAL | KADM5_KEY_DATA);
+    if (ret) {
+       krb5_free_principal (context, princ_ent);
+       krb5_warnx (context, "no such principal: %s", princ_name);
+       goto out2;
+    }
+
+    new_key_data   = malloc(princ.n_key_data * sizeof(*new_key_data));
+    if (new_key_data == NULL) {
+       krb5_warnx (context, "out of memory");
+       goto out;
+    }
+
+    for (i = 0, j = 0; i < princ.n_key_data; ++i) {
+       krb5_key_data *key = &princ.key_data[i];
+       int docopy = 1;
+
+       for (k = 0; k < n_etypes; ++k)
+           if (etypes[k] == key->key_data_type[0]) {
+               docopy = 0;
+               break;
+           }
+       if (docopy) {
+           new_key_data[j++] = *key;
+       } else {
+           int16_t ignore = 1;
+
+           kadm5_free_key_data (kadm_handle, &ignore, key);
+       }
+    }
+
+    free (princ.key_data);
+    princ.n_key_data = j;
+    princ.key_data   = new_key_data;
+
+    ret = kadm5_modify_principal (kadm_handle, &princ, KADM5_KEY_DATA);
+    if (ret)
+       krb5_warn(context, ret, "kadm5_modify_principal");
+out:
+    krb5_free_principal (context, princ_ent);
+    kadm5_free_principal_ent(kadm_handle, &princ);
+out2:
+    free (etypes);
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/dump-format.txt b/src/kerberosV/src/kadmin/dump-format.txt
new file mode 100644 (file)
index 0000000..fd5ebb0
--- /dev/null
@@ -0,0 +1,106 @@
+Format of the Heimdal text dump file as of Heimdal 0.6.3:
+
+$KTH: dump-format.txt,v 1.2 2005/06/07 00:43:31 lha Exp $
+
+Each line in the dump file is one entry in the database.
+
+Each field of a line is separated by one or more spaces, with the
+exception of fields consisting of principals containing spaces, where
+space can be quoted with \ and \ is quoted by \.
+
+Fields and their types are:
+
+       Quoted princial (quote character is \) [string]
+       Keys [keys]
+       Modification [event]
+       Valid start time [event optional]
+       Valid end time [time optional]
+       Password end valid time [time optional]
+       Max lifetime of ticket [time optional]
+       Max renew of ticket [integer optional]
+       Flags [hdb flags]
+       Generation number [generation optional]
+
+       Fields following these silently are ignored.
+
+All optional fields will be skipped if they fail to parse (or comprise
+the optional field marker of "-", w/o quotes).
+
+Example:
+
+fred@EXAMPLE.COM 27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:- 20020415130120:admin@EXAMPLE.COM 20041221112428:fred@EXAMPLE.COM - - - 86400 604800 126 20020415130120:793707:28
+
+Encoding of types are as follows:
+
+keys:
+
+       kvno:[masterkvno:keytype:keydata:salt]{zero or more separated by :}
+
+       kvno is the key version number.
+
+       keydata is hex-encoded
+
+       masterkvno is the kvno of the database master key.  If this
+       field is empty, the kadmin load and merge operations will
+       encrypt the key data with the master key if there is one.
+       Otherwise the key data will be imported asis.
+
+       salt is encoded as "-" (no/default salt) or
+
+       salt-type /
+       salt-type / "string"
+       salt-type / hex-encoded-data
+
+       keytype is the protocol enctype number; see enum ENCTYPE in
+       include/krb5_asn1.h for values.
+
+       Example:
+               27:1:16:e8b4c8fc7e60b9e641dcf4cff3f08a701d982a2f89ba373733d26ca59ba6c789666f6b8bfcf169412bb1e5dceb9b33cda29f3412:-:1:3:4498a933881178c744f4232172dcd774c64e81fa6d05ecdf643a7e390624a0ebf3c7407a:-:1:2:b01934b13eb795d76f3a80717d469639b4da0cfb644161340ef44fdeb375e54d684dbb85:-:1:1:ea8e16d8078bf60c781da90f508d4deccba70595258b9d31888d33987cd31af0c9cced2e:-
+
+               kvno=27,{key: masterkvno=1,keytype=des3-cbc-sha1,keydata=...,
+                        default salt}...
+
+
+time:
+       
+       Format of the time is: YYYYmmddHHMMSS, corresponding to
+       strftime format "%Y%m%d%k%M%S".
+
+       Time is expressed in UTC.
+
+       Time can be optional (using -), when the time 0 is used.
+
+       Example:
+               20041221112428
+
+event:
+       time:principal
+
+       time is as given in format time
+
+       principal is a string.  Not quoting it may not work in earlier
+       versions of Heimdal.
+
+       Example:
+               20041221112428:bloggs@EXAMPLE.COM
+
+hdb flags:
+
+       Integer encoding of HDB flags, see HDBFlags in
+       lib/hdb/hdb.asn1. Each bit in the integer is the same as the bit
+       in the specification.
+
+       Example:
+               XXX
+
+generation:
+
+       time:usec:gen
+
+       usec is a the microsecond, integer.
+       gen is generation number, integer.
+
+       The generation can be defaulted (using '-') or the empty string
+
+       Example:
+               XXX
diff --git a/src/kerberosV/src/kadmin/dump.c b/src/kerberosV/src/kadmin/dump.c
new file mode 100644 (file)
index 0000000..edb7107
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+#include <kadm5/private.h>
+
+RCSID("$KTH: dump.c,v 1.31 2005/01/19 17:09:56 lha Exp $");
+
+extern int local_flag;
+
+int
+dump(struct dump_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    FILE *f;
+    HDB *db = NULL;
+    
+    if(!local_flag) {
+       krb5_warnx(context, "dump is only available in local (-l) mode");
+       return 0;
+    }
+
+    db = _kadm5_s_get_db(kadm_handle);
+
+    if(argc == 0)
+       f = stdout;
+    else
+       f = fopen(argv[0], "w");
+    
+    if(f == NULL) {
+       krb5_warn(context, errno, "open: %s", argv[0]);
+       goto out;
+    }
+    ret = db->hdb_open(context, db, O_RDONLY, 0600);
+    if(ret) {
+       krb5_warn(context, ret, "hdb_open");
+       goto out;
+    }
+
+    hdb_foreach(context, db, opt->decrypt_flag ? HDB_F_DECRYPT : 0, 
+               hdb_print_entry, f);
+
+    db->hdb_close(context, db);
+out:
+    if(f && f != stdout)
+       fclose(f);
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/ext.c b/src/kerberosV/src/kadmin/ext.c
new file mode 100644 (file)
index 0000000..beffaef
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: ext.c,v 1.11 2004/07/06 04:21:26 lha Exp $");
+
+struct ext_keytab_data {
+    krb5_keytab keytab;
+};
+
+static int
+do_ext_keytab(krb5_principal principal, void *data)
+{
+    krb5_error_code ret;
+    kadm5_principal_ent_rec princ;
+    struct ext_keytab_data *e = data;
+    krb5_keytab_entry *keys = NULL;
+    krb5_keyblock *k = NULL;
+    int i, n_k;
+    
+    ret = kadm5_get_principal(kadm_handle, principal, &princ, 
+                             KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA);
+    if(ret)
+       return ret;
+
+    if (princ.n_key_data) {
+       keys = malloc(sizeof(*keys) * princ.n_key_data);
+       if (keys == NULL) {
+           kadm5_free_principal_ent(kadm_handle, &princ);
+           krb5_clear_error_string(context);
+           return ENOMEM;
+       }
+       for (i = 0; i < princ.n_key_data; i++) {
+           krb5_key_data *k = &princ.key_data[i];
+
+           keys[i].principal = princ.principal;
+           keys[i].vno = k->key_data_kvno;
+           keys[i].keyblock.keytype = k->key_data_type[0];
+           keys[i].keyblock.keyvalue.length = k->key_data_length[0];
+           keys[i].keyblock.keyvalue.data = k->key_data_contents[0];
+           keys[i].timestamp = time(NULL);
+       }
+
+       n_k = princ.n_key_data;
+    } else {
+       ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
+       if (ret) {
+           kadm5_free_principal_ent(kadm_handle, &princ);
+           return ret;
+       }
+       keys = malloc(sizeof(*keys) * n_k);
+       if (keys == NULL) {
+           kadm5_free_principal_ent(kadm_handle, &princ);
+           krb5_clear_error_string(context);
+           return ENOMEM;
+       }
+       for (i = 0; i < n_k; i++) {
+           keys[i].principal = principal;
+           keys[i].vno = princ.kvno + 1; /* XXX get entry again */
+           keys[i].keyblock = k[i];
+           keys[i].timestamp = time(NULL);
+       }
+    }
+
+    for(i = 0; i < n_k; i++) {
+       ret = krb5_kt_add_entry(context, e->keytab, &keys[i]);
+       if(ret)
+           krb5_warn(context, ret, "krb5_kt_add_entry(%d)", i);
+    }
+
+    if (k) {
+       memset(k, 0, n_k * sizeof(*k));
+       free(k);
+    }
+    if (keys)
+       free(keys);
+    kadm5_free_principal_ent(kadm_handle, &princ);
+    return 0;
+}
+
+int
+ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    int i;
+    struct ext_keytab_data data;
+
+    if (opt->keytab_string == NULL)
+       ret = krb5_kt_default(context, &data.keytab);
+    else
+       ret = krb5_kt_resolve(context, opt->keytab_string, &data.keytab);
+
+    if(ret){
+       krb5_warn(context, ret, "krb5_kt_resolve");
+       return 0;
+    }
+
+    for(i = 0; i < argc; i++) 
+       foreach_principal(argv[i], do_ext_keytab, "ext", &data);
+
+    krb5_kt_close(context, data.keytab);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/get.c b/src/kerberosV/src/kadmin/get.c
new file mode 100644 (file)
index 0000000..b4f7ecd
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+#include <parse_units.h>
+#include <rtbl.h>
+
+RCSID("$KTH: get.c,v 1.23 2005/05/30 20:41:17 lha Exp $");
+
+static struct field_name {
+    const char *fieldname;
+    unsigned int fieldvalue;
+    const char *default_header;
+    const char *def_longheader;
+    unsigned int flags;
+} field_names[] = {
+    { "principal", KADM5_PRINCIPAL, "Principal", "Principal", 0 },
+    { "princ_expire_time", KADM5_PRINC_EXPIRE_TIME, "Expiration", "Principal expires", 0 },
+    { "pw_expiration", KADM5_PW_EXPIRATION, "PW-exp", "Password expires", 0 },
+    { "last_pwd_change", KADM5_LAST_PWD_CHANGE, "PW-change", "Last password change", 0 },
+    { "max_life", KADM5_MAX_LIFE, "Max life", "Max ticket life", 0 },
+    { "max_rlife", KADM5_MAX_RLIFE, "Max renew", "Max renewable life", 0 },
+    { "mod_time", KADM5_MOD_TIME, "Mod time", "Last modified", 0 },
+    { "mod_name", KADM5_MOD_NAME, "Modifier", "Modifier", 0 },
+    { "attributes", KADM5_ATTRIBUTES, "Attributes", "Attributes", 0 },
+    { "kvno", KADM5_KVNO, "Kvno", "Kvno", RTBL_ALIGN_RIGHT  },
+    { "mkvno", KADM5_MKVNO, "Mkvno", "Mkvno", RTBL_ALIGN_RIGHT },
+    { "last_success", KADM5_LAST_SUCCESS, "Last login", "Last successful login", 0 },
+    { "last_failed", KADM5_LAST_FAILED, "Last fail", "Last failed login", 0 },
+    { "fail_auth_count", KADM5_FAIL_AUTH_COUNT, "Fail count", "Failed login count", RTBL_ALIGN_RIGHT },
+    
+    { "policy", KADM5_POLICY, "Policy", "Policy", 0 },
+    { "keytypes", KADM5_KEY_DATA, "Keytypes", "Keytypes", 0 },
+    { NULL }
+};
+
+struct field_info {
+    struct field_name *ff;
+    char *header;
+    struct field_info *next;
+};
+
+struct get_entry_data {
+    void (*format)(struct get_entry_data*, kadm5_principal_ent_t);
+    rtbl_t table;
+    u_int32_t mask;
+    struct field_info *chead, **ctail;
+};
+
+static int
+add_column(struct get_entry_data *data, struct field_name *ff, const char *header)
+{
+    struct field_info *f = malloc(sizeof(*f));
+    f->ff = ff;
+    if(header)
+       f->header = strdup(header);
+    else
+       f->header = NULL;
+    f->next = NULL;
+    *data->ctail = f;
+    data->ctail = &f->next;
+    data->mask |= ff->fieldvalue;
+    if(data->table != NULL)
+       rtbl_add_column_by_id(data->table, ff->fieldvalue, 
+                             header ? header : ff->default_header, ff->flags);
+    return 0;
+}
+
+/*
+ * return 0 iff `salt' actually is the same as the current salt in `k'
+ */
+
+static int
+cmp_salt (const krb5_salt *salt, const krb5_key_data *k)
+{
+    if (salt->salttype != k->key_data_type[1])
+       return 1;
+    if (salt->saltvalue.length != k->key_data_length[1])
+       return 1;
+    return memcmp (salt->saltvalue.data, k->key_data_contents[1],
+                  salt->saltvalue.length);
+}
+
+static void
+format_keytype(krb5_key_data *k, krb5_salt *def_salt, char *buf, size_t buf_len)
+{
+    krb5_error_code ret;
+    char *s;
+
+    ret = krb5_enctype_to_string (context,
+                                 k->key_data_type[0],
+                                 &s);
+    if (ret)
+       asprintf (&s, "unknown(%d)", k->key_data_type[0]);
+    strlcpy(buf, s, buf_len);
+    free(s);
+
+    strlcat(buf, "(", buf_len);
+
+    ret = krb5_salttype_to_string (context,
+                                  k->key_data_type[0],
+                                  k->key_data_type[1],
+                                  &s);
+    if (ret)
+       asprintf (&s, "unknown(%d)", k->key_data_type[1]);
+    strlcat(buf, s, buf_len);
+    free(s);
+
+    if (cmp_salt(def_salt, k) == 0)
+       s = strdup("");
+    else if(k->key_data_length[1] == 0)
+       s = strdup("()");
+    else
+       asprintf (&s, "(%.*s)", k->key_data_length[1],
+                 (char *)k->key_data_contents[1]);
+    strlcat(buf, s, buf_len);
+    free(s);
+
+    strlcat(buf, ")", buf_len);
+}
+
+static void
+format_field(kadm5_principal_ent_t princ, unsigned int field, 
+            char *buf, size_t buf_len, int condensed)
+{
+    switch(field) {
+    case KADM5_PRINCIPAL:
+       if(condensed)
+           krb5_unparse_name_fixed_short(context, princ->principal, buf, buf_len);
+       else
+           krb5_unparse_name_fixed(context, princ->principal, buf, buf_len);
+       break;
+    
+    case KADM5_PRINC_EXPIRE_TIME:
+       time_t2str(princ->princ_expire_time, buf, buf_len, !condensed);
+       break;
+           
+    case KADM5_PW_EXPIRATION:
+       time_t2str(princ->pw_expiration, buf, buf_len, !condensed);
+       break;
+           
+    case KADM5_LAST_PWD_CHANGE:
+       time_t2str(princ->last_pwd_change, buf, buf_len, !condensed);
+       break;
+           
+    case KADM5_MAX_LIFE:
+       deltat2str(princ->max_life, buf, buf_len);
+       break;
+           
+    case KADM5_MAX_RLIFE:
+       deltat2str(princ->max_renewable_life, buf, buf_len);
+       break;
+           
+    case KADM5_MOD_TIME:
+       time_t2str(princ->mod_date, buf, buf_len, !condensed);
+       break;
+
+    case KADM5_MOD_NAME:
+       if (princ->mod_name == NULL)
+           strlcpy(buf, "unknown", buf_len);
+       else if(condensed)
+           krb5_unparse_name_fixed_short(context, princ->mod_name, buf, buf_len);
+       else
+           krb5_unparse_name_fixed(context, princ->mod_name, buf, buf_len);
+       break;
+    case KADM5_ATTRIBUTES:
+       attributes2str (princ->attributes, buf, buf_len);
+       break;
+    case KADM5_KVNO:
+       snprintf(buf, buf_len, "%d", princ->kvno);
+       break;
+    case KADM5_MKVNO:
+       snprintf(buf, buf_len, "%d", princ->mkvno);
+       break;
+    case KADM5_LAST_SUCCESS:
+       time_t2str(princ->last_success, buf, buf_len, !condensed);
+       break;
+    case KADM5_LAST_FAILED:
+       time_t2str(princ->last_failed, buf, buf_len, !condensed);
+       break;
+    case KADM5_FAIL_AUTH_COUNT:
+       snprintf(buf, buf_len, "%d", princ->fail_auth_count);
+       break;
+    case KADM5_POLICY:
+       if(princ->policy != NULL)
+           strlcpy(buf, princ->policy, buf_len);
+       else
+           strlcpy(buf, "none", buf_len);
+       break;
+    case KADM5_KEY_DATA:{
+       krb5_salt def_salt;
+       int i;
+       char buf2[1024];
+       krb5_get_pw_salt (context, princ->principal, &def_salt);
+
+       *buf = '\0';
+       for (i = 0; i < princ->n_key_data; ++i) {
+           format_keytype(&princ->key_data[i], &def_salt, buf2, sizeof(buf2));
+           if(i > 0)
+               strlcat(buf, ", ", buf_len);
+           strlcat(buf, buf2, buf_len);
+       }
+       krb5_free_salt (context, def_salt);
+       break;
+    }
+    default:
+       strlcpy(buf, "<unknown>", buf_len);
+       break;
+    }
+}
+
+static void
+print_entry_short(struct get_entry_data *data, kadm5_principal_ent_t princ)
+{
+    char buf[1024];
+    struct field_info *f;
+    
+    for(f = data->chead; f != NULL; f = f->next) {
+       format_field(princ, f->ff->fieldvalue, buf, sizeof(buf), 1);
+       rtbl_add_column_entry_by_id(data->table, f->ff->fieldvalue, buf);
+    }
+}
+
+static void
+print_entry_long(struct get_entry_data *data, kadm5_principal_ent_t princ)
+{
+    char buf[1024];
+    struct field_info *f;
+    int width = 0;
+    
+    for(f = data->chead; f != NULL; f = f->next) {
+       int w = strlen(f->header ? f->header : f->ff->def_longheader);
+       if(w > width)
+           width = w;
+    }
+    for(f = data->chead; f != NULL; f = f->next) {
+       format_field(princ, f->ff->fieldvalue, buf, sizeof(buf), 0);
+       printf("%*s: %s\n", width, f->header ? f->header : f->ff->def_longheader, buf);
+    }
+    printf("\n");
+}
+
+static int
+do_get_entry(krb5_principal principal, void *data)
+{
+    kadm5_principal_ent_rec princ;
+    krb5_error_code ret;
+    struct get_entry_data *e = data;
+    
+    memset(&princ, 0, sizeof(princ));
+    ret = kadm5_get_principal(kadm_handle, principal, 
+                             &princ,
+                             e->mask);
+    if(ret)
+       return ret;
+    else {
+       (e->format)(e, &princ);
+       kadm5_free_principal_ent(kadm_handle, &princ);
+    }
+    return 0;
+}
+
+static void
+free_columns(struct get_entry_data *data)
+{
+    struct field_info *f, *next;
+    for(f = data->chead; f != NULL; f = next) {
+       free(f->header);
+       next = f->next;
+       free(f);
+    }
+    data->chead = NULL;
+    data->ctail = &data->chead;
+}
+
+static int
+setup_columns(struct get_entry_data *data, const char *column_info)
+{
+    char buf[1024], *q;
+    char *field, *header;
+    struct field_name *f;
+
+    while(strsep_copy(&column_info, ",", buf, sizeof(buf)) != -1) {
+       q = buf;
+       field = strsep(&q, "=");
+       header = strsep(&q, "=");
+       for(f = field_names; f->fieldname != NULL; f++) {
+           if(strcasecmp(field, f->fieldname) == 0) {
+               add_column(data, f, header);
+               break;
+           }
+       }
+       if(f->fieldname == NULL) {
+           krb5_warnx(context, "unknown field name \"%s\"", field);
+           free_columns(data);
+           return -1;
+       }
+    }
+    return 0;
+}
+
+#define DEFAULT_COLUMNS_SHORT "principal,princ_expire_time,pw_expiration,last_pwd_change,max_life,max_rlife"
+#define DEFAULT_COLUMNS_LONG "principal,princ_expire_time,pw_expiration,last_pwd_change,max_life,max_rlife,kvno,mkvno,last_success,last_failed,fail_auth_count,mod_time,mod_name,attributes,keytypes"
+#define DEFAULT_COLUMNS_TERSE "principal="
+
+static int
+getit(struct get_options *opt, const char *name, int argc, char **argv)
+{
+    int i;
+    krb5_error_code ret;
+    struct get_entry_data data;
+    
+    if(opt->long_flag == -1 && (opt->short_flag == 1 || opt->terse_flag == 1))
+       opt->long_flag = 0;
+    if(opt->short_flag == -1 && (opt->long_flag == 1 || opt->terse_flag == 1))
+       opt->short_flag = 0;
+    if(opt->terse_flag == -1 && (opt->long_flag == 1 || opt->short_flag == 1))
+       opt->terse_flag = 0;
+    if(opt->long_flag == 0 && opt->short_flag == 0 && opt->terse_flag == 0)
+       opt->short_flag = 1;
+
+    data.table = NULL;
+    data.chead = NULL;
+    data.ctail = &data.chead;
+    data.mask = 0;
+
+    if(opt->short_flag || opt->terse_flag) {
+       data.table = rtbl_create();
+       rtbl_set_separator(data.table, "  ");
+       data.format = print_entry_short;
+    } else
+       data.format = print_entry_long;
+    if(opt->column_info_string == NULL) {
+       if(opt->long_flag)
+           ret = setup_columns(&data, DEFAULT_COLUMNS_LONG);
+       else if(opt->short_flag)
+           ret = setup_columns(&data, DEFAULT_COLUMNS_SHORT);
+       else {
+           ret = setup_columns(&data, DEFAULT_COLUMNS_TERSE);
+           rtbl_set_flags(data.table, RTBL_HEADER_STYLE_NONE);
+       }
+    } else
+       ret = setup_columns(&data, opt->column_info_string);
+       
+    if(ret != 0) {
+       if(data.table != NULL)
+           rtbl_destroy(data.table);
+       return 0;
+    }
+    
+    for(i = 0; i < argc; i++)
+       ret = foreach_principal(argv[i], do_get_entry, "get", &data);
+    
+    if(data.table != NULL) {
+       rtbl_format(data.table, stdout);
+       rtbl_destroy(data.table);
+    }
+    free_columns(&data);
+    return 0;
+}
+
+int
+get_entry(struct get_options *opt, int argc, char **argv)
+{
+    return getit(opt, "get", argc, argv);
+}
+
+int
+list_princs(struct list_options *opt, int argc, char **argv)
+{
+    if(sizeof(struct get_options) != sizeof(struct list_options)) {
+       krb5_warnx(context, "programmer error: sizeof(struct get_options) != sizeof(struct list_options)");
+       return 0;
+    }
+    return getit((struct get_options*)opt, "list", argc, argv);
+}
diff --git a/src/kerberosV/src/kadmin/init.c b/src/kerberosV/src/kadmin/init.c
new file mode 100644 (file)
index 0000000..ac98808
--- /dev/null
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+#include <kadm5/private.h>
+
+RCSID("$KTH: init.c,v 1.38 2005/05/03 11:11:54 lha Exp $");
+
+static kadm5_ret_t
+create_random_entry(krb5_principal princ,
+                   unsigned max_life,
+                   unsigned max_rlife,
+                   u_int32_t attributes)
+{
+    kadm5_principal_ent_rec ent;
+    kadm5_ret_t ret;
+    int mask = 0;
+    krb5_keyblock *keys;
+    int n_keys, i;
+    char *name;
+
+    ret = krb5_unparse_name(context, princ, &name);
+    if (ret) {
+       krb5_warn(context, ret, "failed to unparse principal name");
+       return ret;
+    }
+
+    memset(&ent, 0, sizeof(ent));
+    ent.principal = princ;
+    mask |= KADM5_PRINCIPAL;
+    if (max_life) {
+       ent.max_life = max_life;
+       mask |= KADM5_MAX_LIFE;
+    }
+    if (max_rlife) {
+       ent.max_renewable_life = max_rlife;
+       mask |= KADM5_MAX_RLIFE;
+    }
+    ent.attributes |= attributes | KRB5_KDB_DISALLOW_ALL_TIX;
+    mask |= KADM5_ATTRIBUTES;
+
+    ret = kadm5_create_principal(kadm_handle, &ent, mask, "hemlig");
+    if(ret) {
+       krb5_warn(context, ret, "create_random_entry(%s): randkey failed", 
+                 name);
+       goto out;
+    }
+    ret = kadm5_randkey_principal(kadm_handle, princ, &keys, &n_keys);
+    if(ret) {
+       krb5_warn(context, ret, "create_random_entry*%s): randkey failed",
+                 name);
+       goto out;
+    }
+    for(i = 0; i < n_keys; i++)
+       krb5_free_keyblock_contents(context, &keys[i]);
+    free(keys);
+    ret = kadm5_get_principal(kadm_handle, princ, &ent, 
+                             KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
+    if(ret) {
+       krb5_warn(context, ret, "create_random_entry(%s): "
+                 "unable to get principal", name);
+       goto out;
+    }
+    ent.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
+    ent.kvno = 1;
+    ret = kadm5_modify_principal(kadm_handle, &ent, 
+                                KADM5_ATTRIBUTES|KADM5_KVNO);
+    kadm5_free_principal_ent (kadm_handle, &ent);
+    if(ret) {
+       krb5_warn(context, ret, "create_random_entry(%s): "
+                 "unable to modify principal", name);
+       goto out;
+    }
+ out:
+    free(name);
+    return ret;
+}
+
+extern int local_flag;
+
+int
+init(struct init_options *opt, int argc, char **argv)
+{
+    kadm5_ret_t ret;
+    int i;
+    HDB *db;
+    krb5_deltat max_life, max_rlife;
+
+    if(!local_flag) {
+       krb5_warnx(context, "init is only available in local (-l) mode");
+       return 0;
+    }
+
+    if (opt->realm_max_ticket_life_string) {
+       if (str2deltat (opt->realm_max_ticket_life_string, &max_life) != 0) {
+           krb5_warnx (context, "unable to parse \"%s\"", 
+                       opt->realm_max_ticket_life_string);
+           return 0;
+       }
+    }
+    if (opt->realm_max_renewable_life_string) {
+       if (str2deltat (opt->realm_max_renewable_life_string, &max_rlife) != 0) {
+           krb5_warnx (context, "unable to parse \"%s\"", 
+                       opt->realm_max_renewable_life_string);
+           return 0;
+       }
+    }
+
+    db = _kadm5_s_get_db(kadm_handle);
+
+    ret = db->hdb_open(context, db, O_RDWR | O_CREAT, 0600);
+    if(ret){
+       krb5_warn(context, ret, "hdb_open");
+       return 0;
+    }
+    db->hdb_close(context, db);
+    for(i = 0; i < argc; i++){
+       krb5_principal princ;
+       const char *realm = argv[i];
+
+       /* Create `krbtgt/REALM' */
+       ret = krb5_make_principal(context, &princ, realm,
+                                 KRB5_TGS_NAME, realm, NULL);
+       if(ret)
+           return 0;
+       if (opt->realm_max_ticket_life_string == NULL) {
+           max_life = 0;
+           if(edit_deltat ("Realm max ticket life", &max_life, NULL, 0)) {
+               krb5_free_principal(context, princ);
+               return 0;
+           }
+       }
+       if (opt->realm_max_renewable_life_string == NULL) {
+           max_rlife = 0;
+           if(edit_deltat("Realm max renewable ticket life", &max_rlife,
+                          NULL, 0)) {
+               krb5_free_principal(context, princ);
+               return 0;
+           }
+       }
+       create_random_entry(princ, max_life, max_rlife, 0);
+       krb5_free_principal(context, princ);
+
+       /* Create `kadmin/changepw' */
+       krb5_make_principal(context, &princ, realm, 
+                           "kadmin", "changepw", NULL);
+       /*
+        * The Windows XP (at least) password changing protocol
+        * request the `kadmin/changepw' ticket with `renewable_ok,
+        * renewable, forwardable' and so fails if we disallow
+        * forwardable here.
+        */
+       create_random_entry(princ, 5*60, 5*60, 
+                           KRB5_KDB_DISALLOW_TGT_BASED|
+                           KRB5_KDB_PWCHANGE_SERVICE|
+                           KRB5_KDB_DISALLOW_POSTDATED|
+                           KRB5_KDB_DISALLOW_RENEWABLE|
+                           KRB5_KDB_DISALLOW_PROXIABLE|
+                           KRB5_KDB_REQUIRES_PRE_AUTH);
+       krb5_free_principal(context, princ);
+
+       /* Create `kadmin/admin' */
+       krb5_make_principal(context, &princ, realm, 
+                           "kadmin", "admin", NULL);
+       create_random_entry(princ, 60*60, 60*60, KRB5_KDB_REQUIRES_PRE_AUTH);
+       krb5_free_principal(context, princ);
+
+       /* Create `changepw/kerberos' (for v4 compat) */
+       krb5_make_principal(context, &princ, realm,
+                           "changepw", "kerberos", NULL);
+       create_random_entry(princ, 60*60, 60*60,
+                           KRB5_KDB_DISALLOW_TGT_BASED|
+                           KRB5_KDB_PWCHANGE_SERVICE);
+
+       krb5_free_principal(context, princ);
+
+       /* Create `kadmin/hprop' for database propagation */
+       krb5_make_principal(context, &princ, realm,
+                           "kadmin", "hprop", NULL);
+       create_random_entry(princ, 60*60, 60*60,
+                           KRB5_KDB_REQUIRES_PRE_AUTH|
+                           KRB5_KDB_DISALLOW_TGT_BASED);
+       krb5_free_principal(context, princ);
+
+       /* Create `default' */
+       {
+           kadm5_principal_ent_rec ent;
+           int mask = 0;
+
+           memset (&ent, 0, sizeof(ent));
+           mask |= KADM5_PRINCIPAL;
+           krb5_make_principal(context, &ent.principal, realm,
+                               "default", NULL);
+           mask |= KADM5_MAX_LIFE;
+           ent.max_life = 24 * 60 * 60;
+           mask |= KADM5_MAX_RLIFE;
+           ent.max_renewable_life = 7 * ent.max_life;
+           ent.attributes = KRB5_KDB_DISALLOW_ALL_TIX;
+           mask |= KADM5_ATTRIBUTES;
+
+           ret = kadm5_create_principal(kadm_handle, &ent, mask, "");
+           if (ret)
+               krb5_err (context, 1, ret, "kadm5_create_principal");
+
+           krb5_free_principal(context, ent.principal);
+       }
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/kadm_conn.c b/src/kerberosV/src/kadmin/kadm_conn.c
new file mode 100644 (file)
index 0000000..f68cddc
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+
+RCSID("$KTH: kadm_conn.c,v 1.15 2004/05/13 17:46:20 joda Exp $");
+
+struct kadm_port {
+    char *port;
+    unsigned short def_port;
+    struct kadm_port *next;
+} *kadm_ports;
+
+static void
+add_kadm_port(krb5_context context, const char *service, unsigned int port)
+{
+    struct kadm_port *p;
+    p = malloc(sizeof(*p));
+    if(p == NULL) {
+       krb5_warnx(context, "failed to allocate %lu bytes\n", 
+                  (unsigned long)sizeof(*p));
+       return;
+    }
+    
+    p->port = strdup(service);
+    p->def_port = port;
+
+    p->next = kadm_ports;
+    kadm_ports = p;
+}
+
+static void
+add_standard_ports (krb5_context context)
+{
+    add_kadm_port(context, "kerberos-adm", 749);
+}
+
+/*
+ * parse the set of space-delimited ports in `str' and add them.
+ * "+" => all the standard ones
+ * otherwise it's port|service[/protocol]
+ */
+
+void
+parse_ports(krb5_context context, const char *str)
+{
+    char p[128];
+
+    while(strsep_copy(&str, " \t", p, sizeof(p)) != -1) {
+       if(strcmp(p, "+") == 0)
+           add_standard_ports(context);
+       else
+           add_kadm_port(context, p, 0);
+    }
+}
+
+static pid_t pgrp;
+volatile sig_atomic_t term_flag, doing_useful_work;
+
+static RETSIGTYPE
+sigchld(int sig)
+{
+    int save_errno = errno;
+    int status;
+    waitpid(-1, &status, 0);
+    errno = save_errno;
+    SIGRETURN(0);
+}
+
+static RETSIGTYPE
+terminate(int sig)
+{
+    int save_errno = errno;
+    if(getpid() == pgrp) {
+       /* parent */
+       term_flag = 1;
+       signal(sig, SIG_IGN);
+       killpg(pgrp, sig);
+    } else {
+       /* child */
+       if(doing_useful_work)
+           term_flag = 1;
+       else
+           _exit(0);
+    }
+    errno = save_errno;
+    SIGRETURN(0);
+}
+
+static int
+spawn_child(krb5_context context, int *socks, int num_socks, int this_sock)
+{
+    int e, i;
+    struct sockaddr_storage __ss;
+    struct sockaddr *sa = (struct sockaddr *)&__ss;
+    socklen_t sa_size = sizeof(__ss);
+    int s;
+    pid_t pid;
+    krb5_address addr;
+    char buf[128];
+    size_t buf_len;
+
+    s = accept(socks[this_sock], sa, &sa_size);
+    if(s < 0) {
+       krb5_warn(context, errno, "accept");
+       return 1;
+    }
+    e = krb5_sockaddr2address(context, sa, &addr);
+    if(e)
+       krb5_warn(context, e, "krb5_sockaddr2address");
+    else {
+       e = krb5_print_address (&addr, buf, sizeof(buf), 
+                               &buf_len);
+       if(e) 
+           krb5_warn(context, e, "krb5_print_address");
+       else
+           krb5_warnx(context, "connection from %s", buf);
+       krb5_free_address(context, &addr);
+    }
+    
+    pid = fork();
+    if(pid == 0) {
+       for(i = 0; i < num_socks; i++)
+           close(socks[i]);
+       dup2(s, STDIN_FILENO);
+       dup2(s, STDOUT_FILENO);
+       if(s != STDIN_FILENO && s != STDOUT_FILENO)
+           close(s);
+       return 0;
+    } else {
+       close(s);
+    }
+    return 1;
+}
+
+static int
+wait_for_connection(krb5_context context,
+                   int *socks, int num_socks)
+{
+    int i, e;
+    fd_set orig_read_set, read_set;
+    int max_fd = -1;
+    
+    FD_ZERO(&orig_read_set);
+    
+    for(i = 0; i < num_socks; i++) {
+       if (socks[i] >= FD_SETSIZE)
+           errx (1, "fd too large");
+       FD_SET(socks[i], &orig_read_set);
+       max_fd = max(max_fd, socks[i]);
+    }
+    
+    pgrp = getpid();
+
+    if(setpgid(0, pgrp) < 0)
+       err(1, "setpgid");
+
+    signal(SIGTERM, terminate);
+    signal(SIGINT, terminate);
+    signal(SIGCHLD, sigchld);
+
+    while (term_flag == 0) {
+       read_set = orig_read_set;
+       e = select(max_fd + 1, &read_set, NULL, NULL, NULL);
+       if(e < 0) {
+           if(errno != EINTR)
+               krb5_warn(context, errno, "select");
+       } else if(e == 0)
+           krb5_warnx(context, "select returned 0");
+       else {
+           for(i = 0; i < num_socks; i++) {
+               if(FD_ISSET(socks[i], &read_set))
+                   if(spawn_child(context, socks, num_socks, i) == 0)
+                       return 0;
+           }
+       }
+    }
+    signal(SIGCHLD, SIG_DFL);
+    while(1) {
+       int status;
+       pid_t pid;
+       pid = waitpid(-1, &status, 0);
+       if(pid == -1 && errno == ECHILD)
+           break;
+    }
+    exit(0);
+}
+
+
+int
+start_server(krb5_context context)
+{
+    int e;
+    struct kadm_port *p;
+
+    int *socks = NULL, *tmp;
+    int num_socks = 0;
+    int i;
+
+    for(p = kadm_ports; p; p = p->next) {
+       struct addrinfo hints, *ai, *ap;
+       char portstr[32];
+       memset (&hints, 0, sizeof(hints));
+       hints.ai_flags    = AI_PASSIVE;
+       hints.ai_socktype = SOCK_STREAM;
+
+       e = getaddrinfo(NULL, p->port, &hints, &ai);
+       if(e) {
+           snprintf(portstr, sizeof(portstr), "%u", p->def_port);
+           e = getaddrinfo(NULL, portstr, &hints, &ai);
+       }
+
+       if(e) {
+           krb5_warn(context, krb5_eai_to_heim_errno(e, errno),
+                     "%s", portstr);
+           continue;
+       }
+       i = 0;
+       for(ap = ai; ap; ap = ap->ai_next) 
+           i++;
+       tmp = realloc(socks, (num_socks + i) * sizeof(*socks));
+       if(tmp == NULL) {
+           krb5_warnx(context, "failed to reallocate %lu bytes", 
+                      (unsigned long)(num_socks + i) * sizeof(*socks));
+           continue;
+       }
+       socks = tmp;
+       for(ap = ai; ap; ap = ap->ai_next) {
+           int one = 1;
+           int s = socket(ap->ai_family, ap->ai_socktype, ap->ai_protocol);
+           if(s < 0) {
+               krb5_warn(context, errno, "socket");
+               continue;
+           }
+#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
+           if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&one,
+                         sizeof(one)) < 0)
+               krb5_warn(context, errno, "setsockopt");
+#endif
+           if (bind (s, ap->ai_addr, ap->ai_addrlen) < 0) {
+               krb5_warn(context, errno, "bind");
+               close(s);
+               continue;
+           }
+           if (listen (s, SOMAXCONN) < 0) {
+               krb5_warn(context, errno, "listen");
+               close(s);
+               continue;
+           }
+           socks[num_socks++] = s;
+       }
+       freeaddrinfo (ai);
+    }
+    if(num_socks == 0)
+       krb5_errx(context, 1, "no sockets to listen to - exiting");
+    return wait_for_connection(context, socks, num_socks);
+}
diff --git a/src/kerberosV/src/kadmin/kadmin-commands.in b/src/kerberosV/src/kadmin/kadmin-commands.in
new file mode 100644 (file)
index 0000000..957897e
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+/* $KTH: kadmin-commands.in,v 1.5 2004/07/05 11:30:30 joda Exp $ */
+
+command = {
+       name = "stash"
+       name = "kstash"
+       option = {
+               long = "enctype"
+               short = "e"
+               type = "string"
+               help = "encryption type"
+               default = "des3-cbc-sha1"
+       }
+       option = {
+               long = "key-file"
+               short = "k"
+               type = "string"
+               argument = "file"
+               help = "master key file"
+       }
+       option = {
+               long = "convert-file"
+               type = "flag"
+               help = "just convert keyfile to new format"
+       }
+       option = {
+               long = "master-key-fd"
+               type = "integer"
+               argument = "fd"
+               help = "filedescriptor to read passphrase from"
+               default = "-1"
+       }
+       help = "Writes the Kerberos master key to a file used by the KDC. \nLocal (-l) mode only."
+}
+command = {
+       name = "dump"
+       option = {
+               long = "decrypt"
+               short = "d"
+               type = "flag"
+               help = "decrypt keys"
+       }
+       argument = "[dump-file]"
+       min_args = "0"
+       max_args = "1"
+       help = "Dumps the database in a human readable format to the specified file, \nor the standard out. Local (-l) mode only."
+}
+
+command = {
+       name = "init"
+       option = {
+               long = "realm-max-ticket-life"
+               type = "string"
+               help = "realm max ticket lifetime"
+       }
+       option = {
+               long = "realm-max-renewable-life"
+               type = "string"
+               help = "realm max renewable lifetime"
+       }
+       argument = "realm..."
+       min_args = "1"
+       help = "Initializes the default principals for a realm. Creates the database\nif necessary. Local (-l) mode only."
+}
+command = {
+       name = "load"
+       argument = "file"
+       min_args = "1"
+       max_args = "1"
+       help = "Loads a previously dumped file. Local (-l) mode only."
+}
+command = {
+       name = "merge"
+       argument = "file"
+       min_args = "1"
+       max_args = "1"
+       help = "Merges the contents of a dump file into the database. Local (-l) mode only."
+}
+command = {
+       name = "add"
+       name = "add_new_key"
+       function = "add_new_key"
+       option = {
+               long = "random-key"
+               short = "r"
+               type = "flag"
+               help = "set random key"
+       }
+       option = {
+               long = "random-password"
+               type = "flag"
+               help = "set random password"
+       }
+       option = {
+               long = "password"
+               short = "p"
+               type = "string"
+               help = "principal's password"
+       }
+       option = {
+               long = "key"
+               type = "string"
+               help = "DES-key in hex"
+       }
+       option = {
+               long = "max-ticket-life"
+               type = "string"
+               argument ="lifetime"
+               help = "max ticket lifetime"
+       }
+       option = {
+               long = "max-renewable-life"
+               type = "string"
+               argument = "lifetime"
+               help = "max renewable life"
+       }
+       option = {
+               long = "attributes"
+               type = "string"
+               argument = "attributes"
+               help = "principal attributes"
+       }
+       option = {
+               long = "expiration-time"
+               type = "string"
+               argument = "time"
+               help = "principal expiration time"
+       }
+       option = {
+               long = "pw-expiration-time"
+               type = "string"
+               argument = "time"
+               help = "password expiration time"
+       }
+       option = {
+               long = "use-defaults"
+               type = "flag"
+               help = "use default values"
+       }
+       argument = "principal..."
+       min_args = "1"
+       help = "Adds a principal to the database."
+}
+command = {
+       name = "passwd"
+       name = "cpw"
+       name = "change_password"
+       function = "cpw_entry"
+       option = {
+               long = "random-key"
+               short = "r"
+               type = "flag"
+               help = "set random key"
+       }
+       option = {
+               long = "random-password"
+               type = "flag"
+               help = "set random password"
+       }
+       option = {
+               long = "password"
+               short = "p"
+               type = "string"
+               help = "princial's password"
+       }
+       option = {
+               long = "key"
+               type = "string"
+               help = "DES key in hex"
+       }
+       argument = "principal..."
+       min_args = "1"
+       help = "Changes the password of one or more principals matching the expressions."
+}
+command = {
+       name = "delete"
+       name = "del"
+       name = "del_entry"
+       function = "del_entry"
+       argument = "principal..."
+       min_args = "1"
+       help = "Deletes all principals matching the expressions."
+}
+command = {
+       name = "del_enctype"
+       argument = "principal enctype..."
+       min_args = "2"
+       help = "Delete all the mentioned enctypes for principal."
+}
+command = {
+       name = "ext_keytab"
+       option = {
+               long = "keytab"
+               short = "k"
+               type = "string"
+               help = "keytab to use"
+       }
+       argument = "principal..."
+       min_args = "1"
+       help = "Extracts the keys of all principals matching the expressions, and stores them in a keytab." 
+}
+command = {
+       name = "get"
+       name = "get_entry"
+       function = "get_entry"
+       /* XXX sync options with "list" */
+       option = {
+               long = "long"
+               short = "l"
+               type = "flag"
+               help = "long format"
+               default = "-1"
+       }
+       option = {
+               long = "short"
+               short = "s"
+               type = "flag"
+               help = "short format"
+       }
+       option = {
+               long = "terse"
+               short = "t"
+               type = "flag"
+               help = "terse format"
+       }
+       option = {
+               long = "column-info"
+               short = "o"
+               type = "string"
+               help = "columns to print for short output"
+       }
+       argument = "principal..."
+       min_args = "1"
+       help = "Shows information about principals matching the expressions."
+}
+command = {
+       name = "rename"
+       function = "rename_entry"
+       argument = "from to"
+       min_args = "2"
+       max_args = "2"
+       help = "Renames a principal."
+}
+command = {
+       name = "modify"
+       function = "mod_entry"
+       option = {
+               long = "max-ticket-life"
+               type = "string"
+               argument ="lifetime"
+               help = "max ticket lifetime"
+       }
+       option = {
+               long = "max-renewable-life"
+               type = "string"
+               argument = "lifetime"
+               help = "max renewable life"
+       }
+       option = {
+               long = "attributes"
+               short = "a"
+               type = "string"
+               argument = "attributes"
+               help = "principal attributes"
+       }
+       option = {
+               long = "expiration-time"
+               type = "string"
+               argument = "time"
+               help = "principal expiration time"
+       }
+       option = {
+               long = "pw-expiration-time"
+               type = "string"
+               argument = "time"
+               help = "password expiration time"
+       }
+       option = {
+               long = "kvno"
+               type = "integer"
+               help = "key version number"
+               default = "-1"
+       }
+       argument = "principal"
+       min_args = "1"
+       max_args = "1"
+       help = "Modifies some attributes of the specified principal."
+}
+command = {
+       name = "privileges"
+       name = "privs"
+       function = "get_privs"
+       help = "Shows which operations you are allowed to perform."
+}
+command = {
+       name = "list"
+       function = "list_princs"
+       /* XXX sync options with "get" */
+       option = {
+               long = "long"
+               short = "l"
+               type = "flag"
+               help = "long format"
+       }
+       option = {
+               long = "short"
+               short = "s"
+               type = "flag"
+               help = "short format"
+       }
+       option = {
+               long = "terse"
+               short = "t"
+               type = "flag"
+               help = "terse format"
+               default = "-1"
+       }
+       option = {
+               long = "column-info"
+               short = "o"
+               type = "string"
+               help = "columns to print for short output"
+       }
+       argument = "principal..."
+       min_args = "1"
+       help = "Lists principals in a terse format. Equivalent to \"get -t\"." 
+}
+
+command = {
+       name = "password-quality"
+       name = "pwq"
+       function = "password_quality"
+       argument = "principal password"
+       min_args = "2"
+       max_args = "2"
+       help = "Try run the password quality function locally (not doing RPC out to server)."
+}
+
+command = {
+       name = "help"
+       name = "?"
+       argument = "[command]"
+       min_args = "0"
+       max_args = "1"
+       help = "Help! I need somebody."
+}
+
+command = {
+       name = "exit"
+       name = "quit"
+       function = "exit_kadmin"
+       help = "Quits."
+}
diff --git a/src/kerberosV/src/kadmin/kadmin.8 b/src/kerberosV/src/kadmin/kadmin.8
new file mode 100644 (file)
index 0000000..d943f21
--- /dev/null
@@ -0,0 +1,375 @@
+.\" Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: kadmin.8,v 1.15 2005/03/26 10:10:56 lha Exp $
+.\"
+.Dd June 27, 2004
+.Dt KADMIN 8
+.Os HEIMDAL
+.Sh NAME
+.Nm kadmin
+.Nd Kerberos administration utility
+.Sh SYNOPSIS
+.Nm kadmin
+.Bk -words
+.Oo Fl p Ar string \*(Ba Xo
+.Fl -principal= Ns Ar string
+.Xc
+.Oc
+.Oo Fl K Ar string \*(Ba Xo
+.Fl -keytab= Ns Ar string
+.Xc
+.Oc
+.Oo Fl c Ar file \*(Ba Xo
+.Fl -config-file= Ns Ar file
+.Xc
+.Oc
+.Oo Fl k Ar file \*(Ba Xo
+.Fl -key-file= Ns Ar file
+.Xc
+.Oc
+.Oo Fl r Ar realm \*(Ba Xo
+.Fl -realm= Ns Ar realm
+.Xc
+.Oc
+.Oo Fl a Ar host \*(Ba Xo
+.Fl -admin-server= Ns Ar host
+.Xc
+.Oc
+.Oo Fl s Ar port number \*(Ba Xo
+.Fl -server-port= Ns Ar port number
+.Xc
+.Oc
+.Op Fl l | Fl -local
+.Op Fl h | Fl -help
+.Op Fl v | Fl -version
+.Op Ar command
+.Ek
+.Sh DESCRIPTION
+The
+.Nm
+program is used to make modifications to the Kerberos database, either remotely via the
+.Xr kadmind 8
+daemon, or locally (with the
+.Fl l
+option).
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl p Ar string ,
+.Fl -principal= Ns Ar string
+.Xc
+principal to authenticate as
+.It Xo
+.Fl K Ar string ,
+.Fl -keytab= Ns Ar string
+.Xc
+keytab for authentication principal
+.It Xo
+.Fl c Ar file ,
+.Fl -config-file= Ns Ar file
+.Xc
+location of config file
+.It Xo
+.Fl k Ar file ,
+.Fl -key-file= Ns Ar file
+.Xc
+location of master key file
+.It Xo
+.Fl r Ar realm ,
+.Fl -realm= Ns Ar realm
+.Xc
+realm to use
+.It Xo
+.Fl a Ar host ,
+.Fl -admin-server= Ns Ar host
+.Xc
+server to contact
+.It Xo
+.Fl s Ar port number ,
+.Fl -server-port= Ns Ar port number
+.Xc
+port to use
+.It Xo
+.Fl l ,
+.Fl -local
+.Xc
+local admin mode
+.El
+.Pp
+If no
+.Ar command
+is given on the command line,
+.Nm
+will prompt for commands to process. Some of the commands that take
+one or more principals as argument
+.Ns ( Nm delete ,
+.Nm ext_keytab ,
+.Nm get ,
+.Nm modify ,
+and
+.Nm passwd )
+will accept a glob style wildcard, and perform the operation on all
+matching principals.
+.Pp
+Commands include:
+.\" not using a list here, since groff apparently gets confused
+.\" with nested Xo/Xc
+.Pp
+.Nm add
+.Op Fl r | Fl -random-key
+.Op Fl -random-password
+.Oo Fl p Ar string \*(Ba Xo
+.Fl -password= Ns Ar string
+.Xc
+.Oc
+.Op Fl -key= Ns Ar string
+.Op Fl -max-ticket-life= Ns Ar lifetime
+.Op Fl -max-renewable-life= Ns Ar lifetime
+.Op Fl -attributes= Ns Ar attributes
+.Op Fl -expiration-time= Ns Ar time
+.Op Fl -pw-expiration-time= Ns Ar time
+.Ar principal...
+.Bd -ragged -offset indent
+Adds a new principal to the database. The options not passed on the
+command line will be promped for.
+.Ed
+.Pp
+.Nm delete
+.Ar principal...
+.Bd -ragged -offset indent
+Removes a principal.
+.Ed
+.Pp
+.Nm del_enctype
+.Ar principal enctypes...
+.Bd -ragged -offset indent
+Removes some enctypes from a principal; this can be useful if the service
+belonging to the principal is known to not handle certain enctypes.
+.Ed
+.Pp
+.Nm ext_keytab
+.Oo Fl k Ar string \*(Ba Xo
+.Fl -keytab= Ns Ar string
+.Xc
+.Oc
+.Ar principal...
+.Bd -ragged -offset indent
+Creates a keytab with the keys of the specified principals.
+.Ed
+.Pp
+.Nm get
+.Op Fl l | Fl -long
+.Op Fl s | Fl -short
+.Op Fl t | Fl -terse
+.Op Fl o Ar string | Fl -column-info= Ns Ar string
+.Ar principal...
+.Bd -ragged -offset indent
+Lists the matching principals, short prints the result as a table,
+while long format produces a more verbose output. Which columns to
+print can be selected with the
+.Fl o
+option. The argument is a comma separated list of column names
+optionally appended with an equal sign
+.Pq Sq =
+and a column header. Which columns are printed by default differ
+slightly between short and long output.
+.Pp
+The default terse output format is similar to
+.Fl s o Ar principal= ,
+just printing the names of matched principals.
+.Pp
+Possible column names include:
+.Li principal ,
+.Li princ_expire_time ,
+.Li pw_expiration ,
+.Li last_pwd_change ,
+.Li max_life ,
+.Li max_rlife ,
+.Li mod_time ,
+.Li mod_name ,
+.Li attributes ,
+.Li kvno ,
+.Li mkvno ,
+.Li last_success ,
+.Li last_failed ,
+.Li fail_auth_count ,
+.Li policy ,
+and
+.Li keytypes .
+.Ed
+.Pp
+.Nm modify
+.Oo Fl a Ar attributes \*(Ba Xo
+.Fl -attributes= Ns Ar attributes
+.Xc
+.Oc
+.Op Fl -max-ticket-life= Ns Ar lifetime
+.Op Fl -max-renewable-life= Ns Ar lifetime
+.Op Fl -expiration-time= Ns Ar time
+.Op Fl -pw-expiration-time= Ns Ar time
+.Op Fl -kvno= Ns Ar number
+.Ar principal...
+.Bd -ragged -offset indent
+Modifies certain attributes of a principal. If run without command
+line options, you will be prompted. With command line options, it will
+only change the ones specified.
+.Pp
+Possible attributes are:
+.Li new-princ ,
+.Li support-desmd5 ,
+.Li pwchange-service ,
+.Li disallow-svr ,
+.Li requires-pw-change ,
+.Li requires-hw-auth ,
+.Li requires-pre-auth ,
+.Li disallow-all-tix ,
+.Li disallow-dup-skey ,
+.Li disallow-proxiable ,
+.Li disallow-renewable ,
+.Li disallow-tgt-based ,
+.Li disallow-forwardable ,
+.Li disallow-postdated
+.Pp
+Attributes may be negated with a "-", e.g., 
+.Pp 
+kadmin -l modify -a -disallow-proxiable user
+.Ed
+.Pp
+.Nm passwd
+.Op Fl r | Fl -random-key
+.Op Fl -random-password
+.Oo Fl p Ar string \*(Ba Xo
+.Fl -password= Ns Ar string
+.Xc
+.Oc
+.Op Fl -key= Ns Ar string
+.Ar principal...
+.Bd -ragged -offset indent
+Changes the password of an existing principal.
+.Ed
+.Pp
+.Nm password-quality
+.Ar principal
+.Ar password
+.Bd -ragged -offset indent
+Run the password quality check function locally.
+You can run this on the host that is configured to run the kadmind
+process to verify that your configuration file is correct.
+The verification is done locally, if kadmin is is run in remote mode,
+no rpc call is done to the server.
+.Ed
+.Pp
+.Nm privileges
+.Bd -ragged -offset indent
+Lists the operations you are allowed to perform. These include
+.Li add ,
+.Li change-password ,
+.Li delete ,
+.Li get ,
+.Li list ,
+and
+.Li modify .
+.Ed
+.Pp
+.Nm rename
+.Ar from to
+.Bd -ragged -offset indent
+Renames a principal. This is normally transparent, but since keys are
+salted with the principal name, they will have a non-standard salt,
+and clients which are unable to cope with this will fail. Kerberos 4
+suffers from this.
+.Ed
+.Pp
+When running in local mode, the following commands can also be used:
+.Pp
+.Nm dump
+.Op Fl d | Fl -decrypt
+.Op Ar dump-file
+.Bd -ragged -offset indent
+Writes the database in
+.Dq human readable
+form to the specified file, or standard out. If the database is
+encrypted, the dump will also have encrypted keys, unless
+.Fl -decrypt
+is used.
+.Ed
+.Pp
+.Nm init
+.Op Fl -realm-max-ticket-life= Ns Ar string
+.Op Fl -realm-max-renewable-life= Ns Ar string
+.Ar realm
+.Bd -ragged -offset indent
+Initializes the Kerberos database with entries for a new realm. It's
+possible to have more than one realm served by one server.
+.Ed
+.Pp
+.Nm load
+.Ar file
+.Bd -ragged -offset indent
+Reads a previously dumped database, and re-creates that database from
+scratch.
+.Ed
+.Pp
+.Nm merge
+.Ar file
+.Bd -ragged -offset indent
+Similar to
+.Nm load
+but just modifies the database with the entries in the dump file.
+.Ed
+.Pp
+.Nm stash
+.Oo Fl e Ar enctype \*(Ba Xo
+.Fl -enctype= Ns Ar enctype
+.Xc
+.Oc
+.Oo Fl k Ar keyfile \*(Ba Xo
+.Fl -key-file= Ns Ar keyfile
+.Xc
+.Oc
+.Op Fl -convert-file
+.Op Fl -master-key-fd= Ns Ar fd
+.Bd -ragged -offset indent
+Writes the Kerberos master key to a file used by the KDC.
+.Ed
+.\".Sh ENVIRONMENT
+.\".Sh FILES
+.\".Sh EXAMPLES
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr kadmind 8 ,
+.Xr kdc 8
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/src/kerberosV/src/kadmin/kadmin.c b/src/kerberosV/src/kadmin/kadmin.c
new file mode 100644 (file)
index 0000000..c56f95b
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+#include <sl.h>
+
+RCSID("$KTH: kadmin.c,v 1.56 2005/05/09 15:35:22 lha Exp $");
+
+static char *config_file;
+static char *keyfile;
+int local_flag;
+static int ad_flag;
+static int help_flag;
+static int version_flag;
+static char *realm;
+static char *admin_server;
+static int server_port = 0;
+static char *client_name;
+static char *keytab;
+static char *check_library  = NULL;
+static char *check_function = NULL;
+static getarg_strings policy_libraries = { 0, NULL };
+
+static struct getargs args[] = {
+    {  "principal",    'p',    arg_string,     &client_name,
+       "principal to authenticate as" },
+    {   "keytab",      'K',    arg_string,     &keytab,
+       "keytab for authentication principal" },
+    { 
+       "config-file",  'c',    arg_string,     &config_file, 
+       "location of config file",      "file" 
+    },
+    {
+       "key-file",     'k',    arg_string, &keyfile, 
+       "location of master key file", "file"
+    },
+    {  
+       "realm",        'r',    arg_string,   &realm, 
+       "realm to use", "realm" 
+    },
+    {  
+       "admin-server", 'a',    arg_string,   &admin_server, 
+       "server to contact", "host" 
+    },
+    {  
+       "server-port",  's',    arg_integer,   &server_port, 
+       "port to use", "port number" 
+    },
+    {  "ad",           0, arg_flag, &ad_flag, "active directory admin mode" },
+#ifdef HAVE_DLOPEN
+    { "check-library", 0, arg_string, &check_library, 
+      "library to load password check function from", "library" },
+    { "check-function", 0, arg_string, &check_function,
+      "password check function to load", "function" },
+    { "policy-libraries", 0, arg_strings, &policy_libraries,
+      "password check function to load", "function" },
+#endif
+    {  "local", 'l', arg_flag, &local_flag, "local admin mode" },
+    {  "help",         'h',    arg_flag,   &help_flag },
+    {  "version",      'v',    arg_flag,   &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+
+krb5_context context;
+void *kadm_handle;
+
+int
+help(void *opt, int argc, char **argv)
+{
+    if(argc == 0) {
+       sl_help(commands, 1, argv - 1 /* XXX */);
+    } else {
+       SL_cmd *c = sl_match (commands, argv[0], 0);
+       if(c == NULL) {
+           fprintf (stderr, "No such command: %s. "
+                    "Try \"help\" for a list of commands\n",
+                    argv[0]);
+       } else {
+           if(c->func) {
+               char *fake[] = { NULL, "--help", NULL };
+               fake[0] = argv[0];
+               (*c->func)(2, fake);
+               fprintf(stderr, "\n");
+           }
+           if(c->help && *c->help)
+               fprintf (stderr, "%s\n", c->help);
+           if((++c)->name && c->func == NULL) {
+               int f = 0;
+               fprintf (stderr, "Synonyms:");
+               while (c->name && c->func == NULL) {
+                   fprintf (stderr, "%s%s", f ? ", " : " ", (c++)->name);
+                   f = 1;
+               }
+               fprintf (stderr, "\n");
+           }
+       }
+    }
+    return 0;
+}
+
+static int exit_seen = 0;
+
+int
+exit_kadmin (void *opt, int argc, char **argv)
+{
+    exit_seen = 1;
+    return 0;
+}
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, num_args, NULL, "[command]");
+    exit (ret);
+}
+
+int
+get_privs(void *opt, int argc, char **argv)
+{
+    u_int32_t privs;
+    char str[128];
+    kadm5_ret_t ret;
+    
+    ret = kadm5_get_privs(kadm_handle, &privs);
+    if(ret)
+       krb5_warn(context, ret, "kadm5_get_privs");
+    else{
+       ret =_kadm5_privs_to_string(privs, str, sizeof(str));
+       printf("%s\n", str);
+    }
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    char **files;
+    kadm5_config_params conf;
+    int optind = 0;
+    int exit_status = 0;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+    
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+
+    if (help_flag)
+       usage (0);
+
+    if (version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+    
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if(ret) 
+       krb5_err(context, 1, ret, "reading configuration files");
+    
+    memset(&conf, 0, sizeof(conf));
+    if(realm) {
+       krb5_set_default_realm(context, realm); /* XXX should be fixed
+                                                  some other way */
+       conf.realm = realm;
+       conf.mask |= KADM5_CONFIG_REALM;
+    }
+
+    if (admin_server) {
+       conf.admin_server = admin_server;
+       conf.mask |= KADM5_CONFIG_ADMIN_SERVER;
+    }
+
+    if (server_port) {
+       conf.kadmind_port = htons(server_port);
+       conf.mask |= KADM5_CONFIG_KADMIND_PORT;
+    }
+
+    if (keyfile) {
+       conf.stash_file = keyfile;
+       conf.mask |= KADM5_CONFIG_STASH_FILE;
+    }
+
+    if(local_flag) {
+       int i;
+
+       kadm5_setup_passwd_quality_check (context, 
+                                         check_library, check_function);
+       
+       for (i = 0; i < policy_libraries.num_strings; i++) {
+           ret = kadm5_add_passwd_quality_verifier(context, 
+                                                   policy_libraries.strings[i]);
+           if (ret)
+               krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
+       }
+       ret = kadm5_add_passwd_quality_verifier(context, NULL);
+       if (ret)
+           krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
+       
+       ret = kadm5_s_init_with_password_ctx(context, 
+                                            KADM5_ADMIN_SERVICE,
+                                            NULL,
+                                            KADM5_ADMIN_SERVICE,
+                                            &conf, 0, 0, 
+                                            &kadm_handle);
+    } else if (ad_flag) {
+       if (client_name == NULL)
+           krb5_errx(context, 1, "keytab mode require principal name");
+       ret = kadm5_ad_init_with_password_ctx(context,
+                                             client_name,
+                                             NULL,
+                                             KADM5_ADMIN_SERVICE,
+                                             &conf, 0, 0,
+                                             &kadm_handle);
+    } else if (keytab) {
+       if (client_name == NULL)
+           krb5_errx(context, 1, "keytab mode require principal name");
+        ret = kadm5_c_init_with_skey_ctx(context,
+                                        client_name,
+                                        keytab,
+                                        KADM5_ADMIN_SERVICE,
+                                         &conf, 0, 0,
+                                         &kadm_handle);
+    } else
+       ret = kadm5_c_init_with_password_ctx(context, 
+                                            client_name,
+                                            NULL,
+                                            KADM5_ADMIN_SERVICE,
+                                            &conf, 0, 0, 
+                                            &kadm_handle);
+    
+    if(ret)
+       krb5_err(context, 1, ret, "kadm5_init_with_password");
+
+    signal(SIGINT, SIG_IGN); /* ignore signals for now, the sl command
+                                parser will handle SIGINT its own way;
+                                we should really take care of this in
+                                each function, f.i `get' might be
+                                interruptable, but not `create' */
+    if (argc != 0) {
+       ret = sl_command (commands, argc, argv);
+       if(ret == -1)
+           krb5_warnx (context, "unrecognized command: %s", argv[0]);
+       else if (ret == -2)
+           ret = 0;
+       if(ret != 0)
+           exit_status = 1;
+    } else {
+       while(!exit_seen) {
+           ret = sl_command_loop(commands, "kadmin> ", NULL);
+           if (ret == -2)
+               exit_seen = 1;
+           else if (ret != 0)
+               exit_status = 1;
+       }
+    }
+
+    kadm5_destroy(kadm_handle);
+    krb5_free_context(context);
+    return exit_status;
+}
diff --git a/src/kerberosV/src/kadmin/kadmin_locl.h b/src/kerberosV/src/kadmin/kadmin_locl.h
new file mode 100644 (file)
index 0000000..6c0d929
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* 
+ * $KTH: kadmin_locl.h,v 1.45 2004/06/27 15:04:07 joda Exp $
+ */
+
+#ifndef __ADMIN_LOCL_H__
+#define __ADMIN_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#include <err.h>
+#include <roken.h>
+#include <krb5.h>
+#include <krb5_locl.h>
+#include <hdb.h>
+#include <hdb_err.h>
+#include <kadm5/admin.h>
+#include <kadm5/private.h>
+#include <kadm5/kadm5_err.h>
+#include <parse_time.h>
+#include <getarg.h>
+
+extern krb5_context context;
+extern void * kadm_handle;
+
+#undef ALLOC
+#define ALLOC(X) ((X) = malloc(sizeof(*(X))))
+
+/* util.c */
+
+void attributes2str(krb5_flags attributes, char *str, size_t len);
+int  str2attributes(const char *str, krb5_flags *flags);
+int  parse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit);
+int  edit_attributes (const char *prompt, krb5_flags *attr, int *mask,
+                     int bit);
+
+void time_t2str(time_t t, char *str, size_t len, int include_time);
+int  str2time_t (const char *str, time_t *time);
+int  parse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit);
+int  edit_timet (const char *prompt, krb5_timestamp *value, int *mask,
+                int bit);
+
+void deltat2str(unsigned t, char *str, size_t len);
+int  str2deltat(const char *str, krb5_deltat *delta);
+int  parse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit);
+int  edit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit);
+
+int edit_entry(kadm5_principal_ent_t ent, int *mask,
+              kadm5_principal_ent_t default_ent, int default_mask);
+void set_defaults(kadm5_principal_ent_t ent, int *mask,
+                 kadm5_principal_ent_t default_ent, int default_mask);
+int set_entry(krb5_context context,
+             kadm5_principal_ent_t ent,
+             int *mask,
+             const char *max_ticket_life,
+             const char *max_renewable_life,
+             const char *expiration,
+             const char *pw_expiration,
+             const char *attributes);
+int
+foreach_principal(const char *exp, 
+                 int (*func)(krb5_principal, void*), 
+                 const char *funcname,
+                 void *data);
+
+int parse_des_key (const char *key_string,
+                  krb5_key_data *key_data, const char **err);
+
+/* server.c */
+
+krb5_error_code
+kadmind_loop (krb5_context, krb5_auth_context, krb5_keytab, int);
+
+/* random_password.c */
+
+void
+random_password(char *pw, size_t len);
+
+/* kadm_conn.c */
+
+extern volatile sig_atomic_t term_flag, doing_useful_work;
+
+void parse_ports(krb5_context, const char*);
+int start_server(krb5_context);
+
+/* server.c */
+
+krb5_error_code
+kadmind_loop (krb5_context, krb5_auth_context, krb5_keytab, int);
+
+#endif /* __ADMIN_LOCL_H__ */
diff --git a/src/kerberosV/src/kadmin/kadmind.8 b/src/kerberosV/src/kadmin/kadmind.8
new file mode 100644 (file)
index 0000000..724475b
--- /dev/null
@@ -0,0 +1,178 @@
+.\" Copyright (c) 2002 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: kadmind.8,v 1.17 2004/12/08 17:20:21 lha Exp $
+.\"
+.Dd December  8, 2004
+.Dt KADMIND 8
+.Os HEIMDAL
+.Sh NAME
+.Nm kadmind
+.Nd "server for administrative access to Kerberos database"
+.Sh SYNOPSIS
+.Nm kadmind
+.Bk -words
+.Oo Fl c Ar file \*(Ba Xo
+.Fl -config-file= Ns Ar file
+.Xc
+.Oc
+.Oo Fl k Ar file \*(Ba Xo
+.Fl -key-file= Ns Ar file
+.Xc
+.Oc
+.Op Fl -keytab= Ns Ar keytab
+.Oo Fl r Ar realm \*(Ba Xo
+.Fl -realm= Ns Ar realm
+.Xc
+.Oc
+.Op Fl d | Fl -debug
+.Oo Fl p Ar port \*(Ba Xo
+.Fl -ports= Ns Ar port
+.Xc
+.Oc
+.Ek
+.Sh DESCRIPTION
+.Nm
+listens for requests for changes to the Kerberos database and performs
+these, subject to permissions.  When starting, if stdin is a socket it
+assumes that it has been started by
+.Xr inetd 8 ,
+otherwise it behaves as a daemon, forking processes for each new
+connection. The
+.Fl -debug
+option causes
+.Nm
+to accept exactly one connection, which is useful for debugging.
+.Pp
+The
+.Xr kpasswdd 8
+daemon is responsible for the Kerberos 5 password changing protocol
+(used by
+.Xr passwd 1 )
+.
+.Pp
+This daemon should only be run on the master server, and not on any
+slaves.
+.Pp
+Principals are always allowed to change their own password and list
+their own principal.  Apart from that, doing any operation requires
+permission explicitly added in the ACL file
+.Pa /var/heimdal/kadmind.acl .
+The format of this file is:
+.Bd -ragged
+.Va principal
+.Va rights
+.Op Va principal-pattern
+.Ed
+.Pp
+Where rights is any (comma separated) combination of:
+.Bl -bullet -compact
+.It
+change-password or cpw
+.It
+list
+.It
+delete
+.It
+modify
+.It
+add
+.It
+get
+.It
+all
+.El
+.Pp
+And the optional
+.Ar principal-pattern
+restricts the rights to operations on principals that match the
+glob-style pattern.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar file ,
+.Fl -config-file= Ns Ar file
+.Xc
+location of config file
+.It Xo
+.Fl k Ar file ,
+.Fl -key-file= Ns Ar file
+.Xc
+location of master key file
+.It Xo
+.Fl -keytab= Ns Ar keytab
+.Xc
+what keytab to use
+.It Xo
+.Fl r Ar realm ,
+.Fl -realm= Ns Ar realm
+.Xc
+realm to use
+.It Xo
+.Fl d ,
+.Fl -debug
+.Xc
+enable debugging
+.It Xo
+.Fl p Ar port ,
+.Fl -ports= Ns Ar port
+.Xc
+ports to listen to. By default, if run as a daemon, it listens to port
+749, but you can add any number of ports with this option. The port
+string is a whitespace separated list of port specifications, with the
+special string
+.Dq +
+representing the default port.
+.El
+.\".Sh ENVIRONMENT
+.Sh FILES
+.Pa /var/heimdal/kadmind.acl
+.Sh EXAMPLES
+This will cause
+.Nm
+to listen to port 4711 in addition to any
+compiled in defaults:
+.Pp
+.D1 Nm Fl -ports Ns Li "=\*[q]+ 4711\*[q] &"
+.Pp
+This acl file will grant Joe all rights, and allow Mallory to view and
+add host principals.
+.Bd -literal -offset indent
+joe/admin@EXAMPLE.COM      all
+mallory/admin@EXAMPLE.COM  add,get  host/*@EXAMPLE.COM
+.Ed
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr passwd 1 ,
+.Xr kadmin 8 ,
+.Xr kdc 8 ,
+.Xr kpasswdd 8
diff --git a/src/kerberosV/src/kadmin/kadmind.c b/src/kerberosV/src/kadmin/kadmind.c
new file mode 100644 (file)
index 0000000..cd40d7b
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+
+RCSID("$KTH: kadmind.c,v 1.34 2005/04/15 11:16:32 lha Exp $");
+
+static char *check_library  = NULL;
+static char *check_function = NULL;
+static getarg_strings policy_libraries = { 0, NULL };
+static char *config_file;
+static char *keytab_str = "HDB:";
+static int help_flag;
+static int version_flag;
+static int debug_flag;
+static char *port_str;
+char *realm;
+
+static struct getargs args[] = {
+    { 
+       "config-file",  'c',    arg_string,     &config_file, 
+       "location of config file",      "file" 
+    },
+    {
+       "keytab",       0,      arg_string, &keytab_str,
+       "what keytab to use", "keytab"
+    },
+    {  "realm",        'r',    arg_string,   &realm, 
+       "realm to use", "realm" 
+    },
+#ifdef HAVE_DLOPEN
+    { "check-library", 0, arg_string, &check_library, 
+      "library to load password check function from", "library" },
+    { "check-function", 0, arg_string, &check_function,
+      "password check function to load", "function" },
+    { "policy-libraries", 0, arg_strings, &policy_libraries,
+      "password check function to load", "function" },
+#endif
+    {  "debug",        'd',    arg_flag,   &debug_flag, 
+       "enable debugging" 
+    },
+    {  "ports",        'p',    arg_string, &port_str, 
+       "ports to listen to", "port" },
+    {  "help",         'h',    arg_flag,   &help_flag },
+    {  "version",      'v',    arg_flag,   &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+krb5_context context;
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, num_args, NULL, "");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    char **files;
+    int optind = 0;
+    int e, i;
+    krb5_log_facility *logf;
+    krb5_keytab keytab;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    while((e = getarg(args, num_args, argc, argv, &optind)))
+       warnx("error at argument `%s'", argv[optind]);
+
+    if (help_flag)
+       usage (0);
+
+    if (version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+    
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if(ret) 
+       krb5_err(context, 1, ret, "reading configuration files");
+    
+    ret = krb5_openlog(context, "kadmind", &logf);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_openlog");
+    ret = krb5_set_warn_dest(context, logf);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_set_warn_dest");
+
+    ret = krb5_kt_register(context, &hdb_kt_ops);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_kt_register");
+
+    ret = krb5_kt_resolve(context, keytab_str, &keytab);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_kt_resolve");
+
+    kadm5_setup_passwd_quality_check (context, check_library, check_function);
+
+    for (i = 0; i < policy_libraries.num_strings; i++) {
+       ret = kadm5_add_passwd_quality_verifier(context, 
+                                               policy_libraries.strings[i]);
+       if (ret)
+           krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
+    }
+    ret = kadm5_add_passwd_quality_verifier(context, NULL);
+    if (ret)
+       krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
+
+    {
+       int fd = 0;
+       struct sockaddr_storage __ss;
+       struct sockaddr *sa = (struct sockaddr *)&__ss;
+       socklen_t sa_size = sizeof(__ss);
+       krb5_auth_context ac = NULL;
+       int debug_port;
+
+       if(debug_flag) {
+           if(port_str == NULL)
+               debug_port = krb5_getportbyname (context, "kerberos-adm", 
+                                                "tcp", 749);
+           else
+               debug_port = htons(atoi(port_str));
+           mini_inetd(debug_port);
+       } else if(roken_getsockname(STDIN_FILENO, sa, &sa_size) < 0 && 
+                  errno == ENOTSOCK) {
+           parse_ports(context, port_str ? port_str : "+");
+           pidfile(NULL);
+           start_server(context);
+       }
+       if(realm)
+           krb5_set_default_realm(context, realm); /* XXX */
+       kadmind_loop(context, ac, keytab, fd);
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/load.c b/src/kerberosV/src/kadmin/load.c
new file mode 100644 (file)
index 0000000..25b5df8
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+#include <kadm5/private.h>
+
+RCSID("$KTH: load.c,v 1.52 2005/04/04 18:01:35 lha Exp $");
+
+struct entry {
+    char *principal;
+    char *key;
+    char *max_life;
+    char *max_renew;
+    char *created;
+    char *modified;
+    char *valid_start;
+    char *valid_end;
+    char *pw_end;
+    char *flags;
+    char *generation;
+};
+
+static char *
+skip_next(char *p)
+{
+    while(*p && !isspace((unsigned char)*p)) 
+       p++;
+    *p++ = 0;
+    while(*p && isspace((unsigned char)*p))
+       p++;
+    return p;
+}
+
+/*
+ * Parse the time in `s', returning:
+ * -1 if error parsing
+ * 0  if none  present
+ * 1  if parsed ok
+ */
+
+static int
+parse_time_string(time_t *t, const char *s)
+{
+    int year, month, date, hour, minute, second;
+    struct tm tm;
+
+    if(strcmp(s, "-") == 0)
+       return 0;
+    if(sscanf(s, "%04d%02d%02d%02d%02d%02d", 
+             &year, &month, &date, &hour, &minute, &second) != 6)
+       return -1;
+    tm.tm_year  = year - 1900;
+    tm.tm_mon   = month - 1;
+    tm.tm_mday  = date;
+    tm.tm_hour  = hour;
+    tm.tm_min   = minute;
+    tm.tm_sec   = second;
+    tm.tm_isdst = 0;
+    *t = timegm(&tm);
+    return 1;
+}
+
+/*
+ * parse time, allocating space in *t if it's there
+ */
+
+static int
+parse_time_string_alloc (time_t **t, const char *s)
+{
+    time_t tmp;
+    int ret;
+
+    *t = NULL;
+    ret = parse_time_string (&tmp, s);
+    if (ret == 1) {
+       *t = malloc (sizeof (**t));
+       if (*t == NULL)
+           krb5_errx (context, 1, "malloc: out of memory");
+       **t = tmp;
+    }
+    return ret;
+}
+
+/*
+ * see parse_time_string for calling convention
+ */
+
+static int
+parse_integer(unsigned int *u, const char *s)
+{
+    if(strcmp(s, "-") == 0)
+       return 0;
+    if (sscanf(s, "%u", u) != 1)
+       return -1;
+    return 1;
+}
+
+static int
+parse_integer_alloc (unsigned int **u, const char *s)
+{
+    unsigned int tmp;
+    int ret;
+
+    *u = NULL;
+    ret = parse_integer (&tmp, s);
+    if (ret == 1) {
+       *u = malloc (sizeof (**u));
+       if (*u == NULL)
+           krb5_errx (context, 1, "malloc: out of memory");
+       **u = tmp;
+    }
+    return ret;
+}
+
+/*
+ * Parse dumped keys in `str' and store them in `ent'
+ * return -1 if parsing failed
+ */
+
+static int
+parse_keys(hdb_entry *ent, char *str)
+{
+    krb5_error_code ret;
+    int tmp;
+    char *p;
+    int i;
+    
+    p = strsep(&str, ":");
+    if (sscanf(p, "%d", &tmp) != 1)
+       return 1;
+    ent->kvno = tmp;
+    p = strsep(&str, ":");
+    while(p){
+       Key *key;
+       key = realloc(ent->keys.val, 
+                     (ent->keys.len + 1) * sizeof(*ent->keys.val));
+       if(key == NULL)
+           krb5_errx (context, 1, "realloc: out of memory");
+       ent->keys.val = key;
+       key = ent->keys.val + ent->keys.len;
+       ent->keys.len++;
+       memset(key, 0, sizeof(*key));
+       if(sscanf(p, "%d", &tmp) == 1) {
+           key->mkvno = malloc(sizeof(*key->mkvno));
+           if (key->mkvno == NULL)
+               krb5_errx (context, 1, "malloc: out of memory");
+           *key->mkvno = tmp;
+       } else
+           key->mkvno = NULL;
+       p = strsep(&str, ":");
+       if (sscanf(p, "%d", &tmp) != 1)
+           return 1;
+       key->key.keytype = tmp;
+       p = strsep(&str, ":");
+       ret = krb5_data_alloc(&key->key.keyvalue, (strlen(p) - 1) / 2 + 1);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_data_alloc");
+       for(i = 0; i < strlen(p); i += 2) {
+           if(sscanf(p + i, "%02x", &tmp) != 1)
+               return 1;
+           ((u_char*)key->key.keyvalue.data)[i / 2] = tmp;
+       }
+       p = strsep(&str, ":");
+       if(strcmp(p, "-") != 0){
+           unsigned type;
+           size_t p_len;
+
+           if(sscanf(p, "%u/", &type) != 1)
+               return 1;
+           p = strchr(p, '/');
+           if(p == NULL)
+               return 1;
+           p++;
+           p_len = strlen(p);
+
+           key->salt = malloc(sizeof(*key->salt));
+           if (key->salt == NULL)
+               krb5_errx (context, 1, "malloc: out of memory");
+           key->salt->type = type;
+               
+           if (p_len) {
+               if(*p == '\"') {
+                   ret = krb5_data_copy(&key->salt->salt, p + 1, p_len - 2);
+                   if (ret)
+                       krb5_err (context, 1, ret, "krb5_data_copy");
+               } else {
+                   ret = krb5_data_alloc(&key->salt->salt,
+                                         (p_len - 1) / 2 + 1);
+                   if (ret)
+                       krb5_err (context, 1, ret, "krb5_data_alloc");
+                   for(i = 0; i < p_len; i += 2){
+                       if (sscanf(p + i, "%02x", &tmp) != 1)
+                           return 1;
+                       ((u_char*)key->salt->salt.data)[i / 2] = tmp;
+                   }
+               }
+           } else
+               krb5_data_zero (&key->salt->salt);
+       }
+       p = strsep(&str, ":");
+    }
+    return 0;
+}
+
+/*
+ * see parse_time_string for calling convention
+ */
+
+static int
+parse_event(Event *ev, char *s)
+{
+    krb5_error_code ret;
+    char *p;
+
+    if(strcmp(s, "-") == 0)
+       return 0;
+    memset(ev, 0, sizeof(*ev));
+    p = strsep(&s, ":");
+    if(parse_time_string(&ev->time, p) != 1)
+       return -1;
+    p = strsep(&s, ":");
+    ret = krb5_parse_name(context, p, &ev->principal);
+    if (ret)
+       return -1;
+    return 1;
+}
+
+static int
+parse_event_alloc (Event **ev, char *s)
+{
+    Event tmp;
+    int ret;
+
+    *ev = NULL;
+    ret = parse_event (&tmp, s);
+    if (ret == 1) {
+       *ev = malloc (sizeof (**ev));
+       if (*ev == NULL)
+           krb5_errx (context, 1, "malloc: out of memory");
+       **ev = tmp;
+    }
+    return ret;
+}
+
+static int
+parse_hdbflags2int(HDBFlags *f, const char *s)
+{
+    int ret;
+    unsigned int tmp;
+
+    ret = parse_integer (&tmp, s);
+    if (ret == 1)
+       *f = int2HDBFlags (tmp);
+    return ret;
+}
+
+static int
+parse_generation(char *str, GENERATION **gen)
+{
+    char *p;
+    int v;
+
+    if(strcmp(str, "-") == 0 || *str == '\0') {
+       *gen = NULL;
+       return 0;
+    }
+    *gen = calloc(1, sizeof(**gen));
+       if (*gen == NULL)
+           krb5_errx (context, 1, "calloc: out of memory");
+
+    p = strsep(&str, ":");
+    if(parse_time_string(&(*gen)->time, p) != 1)
+       return -1;
+    p = strsep(&str, ":");
+    if(sscanf(p, "%d", &v) != 1)
+       return -1;
+    (*gen)->usec = v;
+    p = strsep(&str, ":");
+    if(sscanf(p, "%d", &v) != 1)
+       return -1;
+    (*gen)->gen = v - 1; /* XXX gets bumped in _hdb_store */
+    return 0;
+}
+
+
+/*
+ * Parse the dump file in `filename' and create the database (merging
+ * iff merge)
+ */
+
+static int
+doit(const char *filename, int merge)
+{
+    krb5_error_code ret;
+    FILE *f;
+    char s[8192]; /* XXX should fix this properly */
+    char *p;
+    int line;
+    int flags = O_RDWR;
+    struct entry e;
+    hdb_entry ent;
+    HDB *db = _kadm5_s_get_db(kadm_handle);
+
+    f = fopen(filename, "r");
+    if(f == NULL){
+       krb5_warn(context, errno, "fopen(%s)", filename);
+       return 1;
+    }
+    ret = kadm5_log_truncate (kadm_handle);
+    if (ret) {
+       fclose (f);
+       krb5_warn(context, ret, "kadm5_log_truncate");
+       return 1;
+    }
+
+    if(!merge)
+       flags |= O_CREAT | O_TRUNC;
+    ret = db->hdb_open(context, db, flags, 0600);
+    if(ret){
+       krb5_warn(context, ret, "hdb_open");
+       fclose(f);
+       return 1;
+    }
+    line = 0;
+    ret = 0;
+    while(fgets(s, sizeof(s), f) != NULL) {
+       ret = 0;
+       line++;
+       e.principal = s;
+       for(p = s; *p; p++){
+           if(*p == '\\')
+               p++;
+           else if(isspace((unsigned char)*p)) {
+               *p = 0;
+               break;
+           }
+       }
+       p = skip_next(p);
+       
+       e.key = p;
+       p = skip_next(p);
+
+       e.created = p;
+       p = skip_next(p);
+
+       e.modified = p;
+       p = skip_next(p);
+
+       e.valid_start = p;
+       p = skip_next(p);
+
+       e.valid_end = p;
+       p = skip_next(p);
+
+       e.pw_end = p;
+       p = skip_next(p);
+
+       e.max_life = p;
+       p = skip_next(p);
+
+       e.max_renew = p;
+       p = skip_next(p);
+
+       e.flags = p;
+       p = skip_next(p);
+
+       e.generation = p;
+       p = skip_next(p);
+
+       memset(&ent, 0, sizeof(ent));
+       ret = krb5_parse_name(context, e.principal, &ent.principal);
+       if(ret) {
+           fprintf(stderr, "%s:%d:%s (%s)\n", 
+                   filename, 
+                   line,
+                   krb5_get_err_text(context, ret),
+                   e.principal);
+           continue;
+       }
+       
+       if (parse_keys(&ent, e.key)) {
+           fprintf (stderr, "%s:%d:error parsing keys (%s)\n",
+                    filename, line, e.key);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+       
+       if (parse_event(&ent.created_by, e.created) == -1) {
+           fprintf (stderr, "%s:%d:error parsing created event (%s)\n",
+                    filename, line, e.created);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+       if (parse_event_alloc (&ent.modified_by, e.modified) == -1) {
+           fprintf (stderr, "%s:%d:error parsing event (%s)\n",
+                    filename, line, e.modified);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+       if (parse_time_string_alloc (&ent.valid_start, e.valid_start) == -1) {
+           fprintf (stderr, "%s:%d:error parsing time (%s)\n",
+                    filename, line, e.valid_start);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+       if (parse_time_string_alloc (&ent.valid_end,   e.valid_end) == -1) {
+           fprintf (stderr, "%s:%d:error parsing time (%s)\n",
+                    filename, line, e.valid_end);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+       if (parse_time_string_alloc (&ent.pw_end,      e.pw_end) == -1) {
+           fprintf (stderr, "%s:%d:error parsing time (%s)\n",
+                    filename, line, e.pw_end);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+
+       if (parse_integer_alloc (&ent.max_life,  e.max_life) == -1) {
+           fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n",
+                    filename, line, e.max_life);
+           hdb_free_entry (context, &ent);
+           continue;
+
+       }
+       if (parse_integer_alloc (&ent.max_renew, e.max_renew) == -1) {
+           fprintf (stderr, "%s:%d:error parsing lifetime (%s)\n",
+                    filename, line, e.max_renew);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+
+       if (parse_hdbflags2int (&ent.flags, e.flags) != 1) {
+           fprintf (stderr, "%s:%d:error parsing flags (%s)\n",
+                    filename, line, e.flags);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+
+       if(parse_generation(e.generation, &ent.generation) == -1) {
+           fprintf (stderr, "%s:%d:error parsing generation (%s)\n",
+                    filename, line, e.generation);
+           hdb_free_entry (context, &ent);
+           continue;
+       }
+
+       ret = db->hdb_store(context, db, HDB_F_REPLACE, &ent);
+       hdb_free_entry (context, &ent);
+       if (ret) {
+           krb5_warn(context, ret, "db_store");
+           break;
+       }
+    }
+    db->hdb_close(context, db);
+    fclose(f);
+    return ret != 0;
+}
+
+
+extern int local_flag;
+
+static int
+loadit(int merge, const char *name, int argc, char **argv)
+{
+    if(!local_flag) {
+       krb5_warnx(context, "%s is only available in local (-l) mode", name);
+       return 0;
+    }
+
+    doit(argv[0], merge);
+    return 0;
+}
+int
+load(void *opt, int argc, char **argv)
+{
+    return loadit(0, "load", argc, argv);
+}
+int
+merge(void *opt, int argc, char **argv)
+{
+    return loadit(1, "merge", argc, argv);
+}
diff --git a/src/kerberosV/src/kadmin/mod.c b/src/kerberosV/src/kadmin/mod.c
new file mode 100644 (file)
index 0000000..2ab1ab6
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: mod.c,v 1.16 2004/07/05 11:41:22 joda Exp $");
+
+static int
+do_mod_entry(krb5_principal principal, void *data)
+{
+    krb5_error_code ret;
+    kadm5_principal_ent_rec princ;
+    int mask = 0;
+    struct modify_options *e = data;
+    
+    memset (&princ, 0, sizeof(princ));
+    ret = kadm5_get_principal(kadm_handle, principal, &princ,
+                             KADM5_PRINCIPAL | KADM5_ATTRIBUTES | 
+                             KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
+                             KADM5_PRINC_EXPIRE_TIME |
+                             KADM5_PW_EXPIRATION);
+    if(ret) 
+       return ret;
+
+    if(e->max_ticket_life_string || 
+       e->max_renewable_life_string ||
+       e->expiration_time_string ||
+       e->pw_expiration_time_string ||
+       e->attributes_string ||
+       e->kvno_integer != -1) {
+       ret = set_entry(context, &princ, &mask, 
+                       e->max_ticket_life_string, 
+                       e->max_renewable_life_string, 
+                       e->expiration_time_string, 
+                       e->pw_expiration_time_string, 
+                       e->attributes_string);
+       if(e->kvno_integer != -1) {
+           princ.kvno = e->kvno_integer;
+           mask |= KADM5_KVNO;
+       }
+    } else
+       ret = edit_entry(&princ, &mask, NULL, 0);
+    if(ret == 0) {
+       ret = kadm5_modify_principal(kadm_handle, &princ, mask);
+       if(ret)
+           krb5_warn(context, ret, "kadm5_modify_principal");
+    }
+    
+    kadm5_free_principal_ent(kadm_handle, &princ);
+    return 0;
+}
+
+int
+mod_entry(struct modify_options *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    int i;
+
+    for(i = 0; i < argc; i++)
+       ret = foreach_principal(argv[i], do_mod_entry, "mod", opt);
+
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kadmin/pw_quality.c b/src/kerberosV/src/kadmin/pw_quality.c
new file mode 100644 (file)
index 0000000..d728299
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2003-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: pw_quality.c,v 1.5 2004/07/05 11:41:22 joda Exp $");
+
+int
+password_quality(void *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_principal principal;
+    krb5_data pw_data;
+    const char *s;
+
+    ret = krb5_parse_name(context, argv[0], &principal);
+    if(ret){
+       krb5_warn(context, ret, "krb5_parse_name(%s)", argv[0]);
+       return 0;
+    }
+    pw_data.data = argv[1];
+    pw_data.length = strlen(argv[1]);
+
+    s = kadm5_check_password_quality (context, principal, &pw_data);
+    if (s)
+       krb5_warnx(context, "kadm5_check_password_quality: %s", s);
+
+    krb5_free_principal(context, principal);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/random_password.c b/src/kerberosV/src/kadmin/random_password.c
new file mode 100644 (file)
index 0000000..3f9c603
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+
+RCSID("$KTH: random_password.c,v 1.4 2001/02/15 04:20:53 assar Exp $");
+
+/* This file defines some a function that generates a random password,
+   that can be used when creating a large amount of principals (such
+   as for a batch of students). Since this is a political matter, you
+   should think about how secure generated passwords has to be.
+   
+   Both methods defined here will give you at least 55 bits of
+   entropy.
+   */
+
+/* If you want OTP-style passwords, define OTP_STYLE */
+
+#ifdef OTP_STYLE
+#include <otp.h>
+#else
+static void generate_password(char **pw, int num_classes, ...);
+#endif
+
+void
+random_password(char *pw, size_t len)
+{
+#ifdef OTP_STYLE
+    {
+       OtpKey newkey;
+
+       krb5_generate_random_block(&newkey, sizeof(newkey));
+       otp_print_stddict (newkey, pw, len);
+       strlwr(pw);
+    }
+#else
+    char *pass;
+    generate_password(&pass, 3, 
+                     "abcdefghijklmnopqrstuvwxyz", 7, 
+                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 2, 
+                     "@$%&*()-+=:,/<>1234567890", 1);
+    strlcpy(pw, pass, len);
+    memset(pass, 0, strlen(pass));
+    free(pass);
+#endif
+}
+
+/* some helper functions */
+
+#ifndef OTP_STYLE
+/* return a random value in range 0-127 */
+static int
+RND(unsigned char *key, int keylen, int *left)
+{
+    if(*left == 0){
+       krb5_generate_random_block(key, keylen);
+       *left = keylen;
+    }
+    (*left)--;
+    return ((unsigned char*)key)[*left];
+}
+
+/* This a helper function that generates a random password with a
+   number of characters from a set of character classes.
+
+   If there are n classes, and the size of each class is Pi, and the
+   number of characters from each class is Ni, the number of possible
+   passwords are (given that the character classes are disjoint):
+
+     n             n
+   -----        /  ----  \
+   |   |  Ni    |  \     |
+   |   | Pi     |   \  Ni| !
+   |   | ---- * |   /    |
+   |   | Ni!    |  /___  |
+    i=1          \  i=1  /
+   
+    Since it uses the RND function above, neither the size of each
+    class, nor the total length of the generated password should be
+    larger than 127 (without fixing RND).
+   
+   */
+static void
+generate_password(char **pw, int num_classes, ...)
+{
+    struct {
+       const char *str;
+       int len;
+       int freq;
+    } *classes;
+    va_list ap;
+    int len, i;
+    unsigned char rbuf[8]; /* random buffer */
+    int rleft = 0;
+
+    classes = malloc(num_classes * sizeof(*classes));
+    va_start(ap, num_classes);
+    len = 0;
+    for(i = 0; i < num_classes; i++){
+       classes[i].str = va_arg(ap, const char*);
+       classes[i].len = strlen(classes[i].str);
+       classes[i].freq = va_arg(ap, int);
+       len += classes[i].freq;
+    }
+    va_end(ap);
+    *pw = malloc(len + 1);
+    if(*pw == NULL) {
+       free(classes);
+       return;
+    }
+    for(i = 0; i < len; i++) {
+       int j;
+       int x = RND(rbuf, sizeof(rbuf), &rleft) % (len - i);
+       int t = 0;
+       for(j = 0; j < num_classes; j++) {
+           if(x < t + classes[j].freq) {
+               (*pw)[i] = classes[j].str[RND(rbuf, sizeof(rbuf), &rleft)
+                                        % classes[j].len];
+               classes[j].freq--;
+               break;
+           }
+           t += classes[j].freq;
+       }
+    }
+    (*pw)[len] = '\0';
+    memset(rbuf, 0, sizeof(rbuf));
+    free(classes);
+}
+#endif
diff --git a/src/kerberosV/src/kadmin/rename.c b/src/kerberosV/src/kadmin/rename.c
new file mode 100644 (file)
index 0000000..f7f5f12
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: rename.c,v 1.8 2004/07/05 11:41:22 joda Exp $");
+
+int
+rename_entry(void *opt, int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_principal princ1, princ2;
+
+    ret = krb5_parse_name(context, argv[0], &princ1);
+    if(ret){
+       krb5_warn(context, ret, "krb5_parse_name(%s)", argv[0]);
+       return 0;
+    }
+    ret = krb5_parse_name(context, argv[1], &princ2);
+    if(ret){
+       krb5_free_principal(context, princ2);
+       krb5_warn(context, ret, "krb5_parse_name(%s)", argv[1]);
+       return 0;
+    }
+    ret = kadm5_rename_principal(kadm_handle, princ1, princ2);
+    if(ret)
+       krb5_warn(context, ret, "rename");
+    krb5_free_principal(context, princ1);
+    krb5_free_principal(context, princ2);
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kadmin/server.c b/src/kerberosV/src/kadmin/server.c
new file mode 100644 (file)
index 0000000..a10a8d8
--- /dev/null
@@ -0,0 +1,574 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include <krb5-private.h>
+
+RCSID("$KTH: server.c,v 1.39 2004/05/13 17:46:20 joda Exp $");
+
+static kadm5_ret_t
+kadmind_dispatch(void *kadm_handle, krb5_boolean initial,
+                krb5_data *in, krb5_data *out)
+{
+    kadm5_ret_t ret;
+    int32_t cmd, mask, tmp;
+    kadm5_server_context *context = kadm_handle;
+    char client[128], name[128], name2[128];
+    char *op = "";
+    krb5_principal princ, princ2;
+    kadm5_principal_ent_rec ent;
+    char *password, *exp;
+    krb5_keyblock *new_keys;
+    int n_keys;
+    char **princs;
+    int n_princs;
+    krb5_storage *sp;
+    
+    krb5_unparse_name_fixed(context->context, context->caller, 
+                           client, sizeof(client));
+    
+    sp = krb5_storage_from_data(in);
+
+    krb5_ret_int32(sp, &cmd);
+    switch(cmd){
+    case kadm_get:{
+       op = "GET";
+       ret = krb5_ret_principal(sp, &princ);
+       if(ret)
+           goto fail;
+       ret = krb5_ret_int32(sp, &mask);
+       if(ret){
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       krb5_unparse_name_fixed(context->context, princ, name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+       ret = _kadm5_acl_check_permission(context, KADM5_PRIV_GET, princ);
+       if(ret){
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       ret = kadm5_get_principal(kadm_handle, princ, &ent, mask);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       if(ret == 0){
+           kadm5_store_principal_ent(sp, &ent);
+           kadm5_free_principal_ent(kadm_handle, &ent);
+       }
+       krb5_free_principal(context->context, princ);
+       break;
+    }
+    case kadm_delete:{
+       op = "DELETE";
+       ret = krb5_ret_principal(sp, &princ);
+       if(ret)
+           goto fail;
+       krb5_unparse_name_fixed(context->context, princ, name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+       ret = _kadm5_acl_check_permission(context, KADM5_PRIV_DELETE, princ);
+       if(ret){
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       ret = kadm5_delete_principal(kadm_handle, princ);
+       krb5_free_principal(context->context, princ);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       break;
+    }
+    case kadm_create:{
+       op = "CREATE";
+       ret = kadm5_ret_principal_ent(sp, &ent);
+       if(ret)
+           goto fail;
+       ret = krb5_ret_int32(sp, &mask);
+       if(ret){
+           kadm5_free_principal_ent(context->context, &ent);
+           goto fail;
+       }
+       ret = krb5_ret_string(sp, &password);
+       if(ret){
+           kadm5_free_principal_ent(context->context, &ent);
+           goto fail;
+       }
+       krb5_unparse_name_fixed(context->context, ent.principal, 
+                               name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+       ret = _kadm5_acl_check_permission(context, KADM5_PRIV_ADD,
+                                         ent.principal);
+       if(ret){
+           kadm5_free_principal_ent(context->context, &ent);
+           memset(password, 0, strlen(password));
+           free(password);
+           goto fail;
+       }
+       ret = kadm5_create_principal(kadm_handle, &ent, 
+                                    mask, password);
+       kadm5_free_principal_ent(kadm_handle, &ent);
+       memset(password, 0, strlen(password));
+       free(password);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       break;
+    }
+    case kadm_modify:{
+       op = "MODIFY";
+       ret = kadm5_ret_principal_ent(sp, &ent);
+       if(ret)
+           goto fail;
+       ret = krb5_ret_int32(sp, &mask);
+       if(ret){
+           kadm5_free_principal_ent(context, &ent);
+           goto fail;
+       }
+       krb5_unparse_name_fixed(context->context, ent.principal, 
+                               name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+       ret = _kadm5_acl_check_permission(context, KADM5_PRIV_MODIFY,
+                                         ent.principal);
+       if(ret){
+           kadm5_free_principal_ent(context, &ent);
+           goto fail;
+       }
+       ret = kadm5_modify_principal(kadm_handle, &ent, mask);
+       kadm5_free_principal_ent(kadm_handle, &ent);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       break;
+    }
+    case kadm_rename:{
+       op = "RENAME";
+       ret = krb5_ret_principal(sp, &princ);
+       if(ret)
+           goto fail;
+       ret = krb5_ret_principal(sp, &princ2);
+       if(ret){
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       krb5_unparse_name_fixed(context->context, princ, name, sizeof(name));
+       krb5_unparse_name_fixed(context->context, princ2, name2, sizeof(name2));
+       krb5_warnx(context->context, "%s: %s %s -> %s", 
+                  client, op, name, name2);
+       ret = _kadm5_acl_check_permission(context, 
+                                         KADM5_PRIV_ADD,
+                                         princ2)
+           || _kadm5_acl_check_permission(context, 
+                                          KADM5_PRIV_DELETE,
+                                          princ);
+       if(ret){
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       ret = kadm5_rename_principal(kadm_handle, princ, princ2);
+       krb5_free_principal(context->context, princ);
+       krb5_free_principal(context->context, princ2);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       break;
+    }
+    case kadm_chpass:{
+       op = "CHPASS";
+       ret = krb5_ret_principal(sp, &princ);
+       if(ret)
+           goto fail;
+       ret = krb5_ret_string(sp, &password);
+       if(ret){
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       krb5_unparse_name_fixed(context->context, princ, name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+
+       /*
+        * The change is allowed if at least one of:
+
+        * a) it's for the principal him/herself and this was an
+        *    initial ticket, but then, check with the password quality
+        *    function.
+        * b) the user is on the CPW ACL.
+        */
+
+       if (initial
+           && krb5_principal_compare (context->context, context->caller,
+                                      princ))
+       {
+           krb5_data pwd_data;
+           const char *pwd_reason;
+
+           pwd_data.data = password;
+           pwd_data.length = strlen(password);
+
+           pwd_reason = kadm5_check_password_quality (context->context,
+                                                      princ, &pwd_data);
+           if (pwd_reason != NULL)
+               ret = KADM5_PASS_Q_DICT;
+           else
+               ret = 0;
+       } else
+           ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ);
+
+       if(ret) {
+           krb5_free_principal(context->context, princ);
+           memset(password, 0, strlen(password));
+           free(password);
+           goto fail;
+       }
+       ret = kadm5_chpass_principal(kadm_handle, princ, password);
+       krb5_free_principal(context->context, princ);
+       memset(password, 0, strlen(password));
+       free(password);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       break;
+    }
+    case kadm_chpass_with_key:{
+       int i;
+       krb5_key_data *key_data;
+       int n_key_data;
+
+       op = "CHPASS_WITH_KEY";
+       ret = krb5_ret_principal(sp, &princ);
+       if(ret)
+           goto fail;
+       ret = krb5_ret_int32(sp, &n_key_data);
+       if (ret) {
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       /* n_key_data will be squeezed into an int16_t below. */
+       if (n_key_data < 0 || n_key_data >= 1 << 16 ||
+           n_key_data > UINT_MAX/sizeof(*key_data)) {
+           ret = ERANGE;
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+
+       key_data = malloc (n_key_data * sizeof(*key_data));
+       if (key_data == NULL) {
+           ret = ENOMEM;
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+
+       for (i = 0; i < n_key_data; ++i) {
+           ret = kadm5_ret_key_data (sp, &key_data[i]);
+           if (ret) {
+               int16_t dummy = i;
+
+               kadm5_free_key_data (context, &dummy, key_data);
+               free (key_data);
+               krb5_free_principal(context->context, princ);
+               goto fail;
+           }
+       }
+
+       krb5_unparse_name_fixed(context->context, princ, name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+
+       /*
+        * The change is only allowed if the user is on the CPW ACL,
+        * this it to force password quality check on the user.
+        */
+
+       ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ);
+       if(ret) {
+           int16_t dummy = n_key_data;
+
+           kadm5_free_key_data (context, &dummy, key_data);
+           free (key_data);
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       ret = kadm5_chpass_principal_with_key(kadm_handle, princ,
+                                             n_key_data, key_data);
+       {
+           int16_t dummy = n_key_data;
+           kadm5_free_key_data (context, &dummy, key_data);
+       }
+       free (key_data);
+       krb5_free_principal(context->context, princ);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       break;
+    }
+    case kadm_randkey:{
+       op = "RANDKEY";
+       ret = krb5_ret_principal(sp, &princ);
+       if(ret)
+           goto fail;
+       krb5_unparse_name_fixed(context->context, princ, name, sizeof(name));
+       krb5_warnx(context->context, "%s: %s %s", client, op, name);
+       /*
+        * The change is allowed if at least one of:
+        * a) it's for the principal him/herself and this was an initial ticket
+        * b) the user is on the CPW ACL.
+        */
+
+       if (initial
+           && krb5_principal_compare (context->context, context->caller,
+                                      princ))
+           ret = 0;
+       else
+           ret = _kadm5_acl_check_permission(context, KADM5_PRIV_CPW, princ);
+
+       if(ret) {
+           krb5_free_principal(context->context, princ);
+           goto fail;
+       }
+       ret = kadm5_randkey_principal(kadm_handle, princ, 
+                                     &new_keys, &n_keys);
+       krb5_free_principal(context->context, princ);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       if(ret == 0){
+           int i;
+           krb5_store_int32(sp, n_keys);
+           for(i = 0; i < n_keys; i++){
+               krb5_store_keyblock(sp, new_keys[i]);
+               krb5_free_keyblock_contents(context->context, &new_keys[i]);
+           }
+       }
+       break;
+    }
+    case kadm_get_privs:{
+       ret = kadm5_get_privs(kadm_handle, &mask);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       if(ret == 0)
+           krb5_store_int32(sp, mask);
+       break;
+    }
+    case kadm_get_princs:{
+       op = "LIST";
+       ret = krb5_ret_int32(sp, &tmp);
+       if(ret)
+           goto fail;
+       if(tmp){
+           ret = krb5_ret_string(sp, &exp);
+           if(ret)
+               goto fail;
+       }else
+           exp = NULL;
+       krb5_warnx(context->context, "%s: %s %s", client, op, exp ? exp : "*");
+       ret = _kadm5_acl_check_permission(context, KADM5_PRIV_LIST, NULL);
+       if(ret){
+           free(exp);
+           goto fail;
+       }
+       ret = kadm5_get_principals(kadm_handle, exp, &princs, &n_princs);
+       free(exp);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, ret);
+       if(ret == 0){
+           int i;
+           krb5_store_int32(sp, n_princs);
+           for(i = 0; i < n_princs; i++)
+               krb5_store_string(sp, princs[i]);
+           kadm5_free_name_list(kadm_handle, princs, &n_princs);
+       }
+       break;
+    }
+    default:
+       krb5_warnx(context->context, "%s: UNKNOWN OP %d", client, cmd);
+       krb5_storage_free(sp);
+       sp = krb5_storage_emem();
+       krb5_store_int32(sp, KADM5_FAILURE);
+       break;
+    }
+    krb5_storage_to_data(sp, out);
+    krb5_storage_free(sp);
+    return 0;
+fail:
+    krb5_warn(context->context, ret, "%s", op);
+    krb5_storage_seek(sp, 0, SEEK_SET);
+    krb5_store_int32(sp, ret);
+    krb5_storage_to_data(sp, out);
+    krb5_storage_free(sp);
+    return 0;
+}
+
+static void
+v5_loop (krb5_context context,
+        krb5_auth_context ac,
+        krb5_boolean initial,
+        void *kadm_handle,
+        int fd)
+{
+    krb5_error_code ret;
+    krb5_data in, out;
+
+    for (;;) {
+       doing_useful_work = 0;
+       if(term_flag)
+           exit(0);
+       ret = krb5_read_priv_message(context, ac, &fd, &in);
+       if(ret == HEIM_ERR_EOF)
+           exit(0);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_read_priv_message");
+       doing_useful_work = 1;
+       kadmind_dispatch(kadm_handle, initial, &in, &out);
+       krb5_data_free(&in);
+       ret = krb5_write_priv_message(context, ac, &fd, &out);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_write_priv_message");
+    }
+}
+
+static krb5_boolean
+match_appl_version(const void *data, const char *appl_version)
+{
+    unsigned minor;
+    if(sscanf(appl_version, "KADM0.%u", &minor) != 1)
+       return 0;
+    *(unsigned*)data = minor;
+    return 1;
+}
+
+static void
+handle_v5(krb5_context context,
+         krb5_auth_context ac,
+         krb5_keytab keytab,
+         int len,
+         int fd)
+{
+    krb5_error_code ret;
+    u_char version[sizeof(KRB5_SENDAUTH_VERSION)];
+    krb5_ticket *ticket;
+    char *server_name;
+    char *client;
+    void *kadm_handle;
+    ssize_t n;
+    krb5_boolean initial;
+
+    unsigned kadm_version;
+    kadm5_config_params realm_params;
+
+    if (len != sizeof(KRB5_SENDAUTH_VERSION))
+       krb5_errx(context, 1, "bad sendauth len %d", len);
+    n = krb5_net_read(context, &fd, version, len);
+    if (n < 0)
+       krb5_err (context, 1, errno, "reading sendauth version");
+    if (n == 0)
+       krb5_errx (context, 1, "EOF reading sendauth version");
+    if(memcmp(version, KRB5_SENDAUTH_VERSION, len) != 0)
+       krb5_errx(context, 1, "bad sendauth version %.8s", version);
+       
+    ret = krb5_recvauth_match_version(context, &ac, &fd, 
+                                     match_appl_version, &kadm_version,
+                                     NULL, KRB5_RECVAUTH_IGNORE_VERSION, 
+                                     keytab, &ticket);
+    if(ret == KRB5_KT_NOTFOUND)
+       krb5_errx(context, 1, "krb5_recvauth: key not found");
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_recvauth");
+
+    ret = krb5_unparse_name (context, ticket->server, &server_name);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_unparse_name");
+
+    if (strncmp (server_name, KADM5_ADMIN_SERVICE,
+                strlen(KADM5_ADMIN_SERVICE)) != 0)
+       krb5_errx (context, 1, "ticket for strange principal (%s)",
+                  server_name);
+
+    free (server_name);
+
+    memset(&realm_params, 0, sizeof(realm_params));
+
+    if(kadm_version == 1) {
+       krb5_data params;
+       ret = krb5_read_priv_message(context, ac, &fd, &params);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_read_priv_message");
+       _kadm5_unmarshal_params(context, &params, &realm_params);
+    }
+
+    initial = ticket->ticket.flags.initial;
+    ret = krb5_unparse_name(context, ticket->client, &client);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_unparse_name");
+    krb5_free_ticket (context, ticket);
+    ret = kadm5_init_with_password_ctx(context, 
+                                      client, 
+                                      NULL,
+                                      KADM5_ADMIN_SERVICE,
+                                      &realm_params, 
+                                      0, 0, 
+                                      &kadm_handle);
+    if(ret)
+       krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
+    v5_loop (context, ac, initial, kadm_handle, fd);
+}
+
+krb5_error_code
+kadmind_loop(krb5_context context,
+            krb5_auth_context ac,
+            krb5_keytab keytab, 
+            int fd)
+{
+    unsigned char tmp[4];
+    ssize_t n;
+    unsigned long len;
+
+    n = krb5_net_read(context, &fd, tmp, 4);
+    if(n == 0)
+       exit(0);
+    if(n < 0)
+       krb5_err(context, 1, errno, "read");
+    _krb5_get_int(tmp, &len, 4);
+    /* this v4 test could probably also go away */
+    if(len > 0xffff && (len & 0xffff) == ('K' << 8) + 'A') {
+       unsigned char v4reply[] = { 
+           0x00, 0x0c, 
+           'K', 'Y', 'O', 'U', 'L', 'O', 'S', 'E', 
+           0x95, 0xb7, 0xa7, 0x08 /* KADM_BAD_VER */
+       };
+       krb5_net_write(context, &fd, v4reply, sizeof(v4reply));
+       krb5_errx(context, 1, "packet appears to be version 4");
+    } else {
+       handle_v5(context, ac, keytab, len, fd);
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/stash.c b/src/kerberosV/src/kadmin/stash.c
new file mode 100644 (file)
index 0000000..3e44297
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include "kadmin-commands.h"
+
+RCSID("$KTH: stash.c,v 1.5 2004/07/05 11:37:01 joda Exp $");
+
+extern int local_flag;
+
+int
+stash(struct stash_options *opt, int argc, char **argv)
+{
+    char buf[1024];
+    krb5_error_code ret;
+    krb5_enctype enctype;
+    hdb_master_key mkey;
+    
+    if(!local_flag) {
+       krb5_warnx(context, "stash is only available in local (-l) mode");
+       return 0;
+    }
+
+    ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
+    if(ret) {
+       krb5_warn(context, ret, "%s", opt->enctype_string);
+       return 0;
+    }
+
+    if(opt->key_file_string == NULL)
+       opt->key_file_string = HDB_DB_DIR "/m-key";
+
+    ret = hdb_read_master_key(context, opt->key_file_string, &mkey);
+    if(ret && ret != ENOENT) {
+       krb5_warn(context, ret, "reading master key from %s", 
+                 opt->key_file_string);
+       return 0;
+    }
+
+    if (opt->convert_file_flag) {
+       if (ret)
+           krb5_warn(context, ret, "reading master key from %s", 
+                     opt->key_file_string);
+       return 0;
+    } else {
+       krb5_keyblock key;
+       krb5_salt salt;
+       salt.salttype = KRB5_PW_SALT;
+       /* XXX better value? */
+       salt.saltvalue.data = NULL;
+       salt.saltvalue.length = 0;
+       if(opt->master_key_fd_integer != -1) {
+           ssize_t n;
+           n = read(opt->master_key_fd_integer, buf, sizeof(buf));
+           if(n == 0)
+               krb5_warnx(context, "end of file reading passphrase");
+           else if(n < 0)
+               krb5_warn(context, errno, "reading passphrase");
+           buf[n] = '\0';
+           buf[strcspn(buf, "\r\n")] = '\0';
+       } else {
+           if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1)) {
+               hdb_free_master_key(context, mkey);
+               return 0;
+           }
+       }
+       ret = krb5_string_to_key_salt(context, enctype, buf, salt, &key);
+       ret = hdb_add_master_key(context, &key, &mkey);
+       krb5_free_keyblock_contents(context, &key);
+    }
+    
+    {
+       char *new, *old;
+       asprintf(&old, "%s.old", opt->key_file_string);
+       asprintf(&new, "%s.new", opt->key_file_string);
+       if(old == NULL || new == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+           
+       if(unlink(new) < 0 && errno != ENOENT) {
+           ret = errno;
+           goto out;
+       }
+       krb5_warnx(context, "writing key to \"%s\"", opt->key_file_string);
+       ret = hdb_write_master_key(context, new, mkey);
+       if(ret)
+           unlink(new);
+       else {
+           unlink(old);
+           if(link(opt->key_file_string, old) < 0 && errno != ENOENT) {
+               ret = errno;
+               unlink(new);
+           } else if(rename(new, opt->key_file_string) < 0) {
+               ret = errno;
+           }
+       }
+    out:
+       free(old);
+       free(new);
+       if(ret)
+           krb5_warn(context, errno, "writing master key file");
+    }
+
+    hdb_free_master_key(context, mkey);
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/util.c b/src/kerberosV/src/kadmin/util.c
new file mode 100644 (file)
index 0000000..28767ed
--- /dev/null
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadmin_locl.h"
+#include <parse_units.h>
+
+RCSID("$KTH: util.c,v 1.44 2005/05/30 20:47:04 lha Exp $");
+
+/*
+ * util.c - functions for parsing, unparsing, and editing different
+ * types of data used in kadmin.
+ */
+
+static int
+get_response(const char *prompt, const char *def, char *buf, size_t len);
+
+/*
+ * attributes 
+ */
+
+struct units kdb_attrs[] = {
+    { "ok-as-delegate",                KRB5_KDB_OK_AS_DELEGATE },
+    { "new-princ",             KRB5_KDB_NEW_PRINC },
+    { "support-desmd5",                KRB5_KDB_SUPPORT_DESMD5 },
+    { "pwchange-service",      KRB5_KDB_PWCHANGE_SERVICE },
+    { "disallow-svr",          KRB5_KDB_DISALLOW_SVR },
+    { "requires-pw-change",    KRB5_KDB_REQUIRES_PWCHANGE },
+    { "requires-hw-auth",      KRB5_KDB_REQUIRES_HW_AUTH },
+    { "requires-pre-auth",     KRB5_KDB_REQUIRES_PRE_AUTH },
+    { "disallow-all-tix",      KRB5_KDB_DISALLOW_ALL_TIX },
+    { "disallow-dup-skey",     KRB5_KDB_DISALLOW_DUP_SKEY },
+    { "disallow-proxiable",    KRB5_KDB_DISALLOW_PROXIABLE },
+    { "disallow-renewable",    KRB5_KDB_DISALLOW_RENEWABLE },
+    { "disallow-tgt-based",    KRB5_KDB_DISALLOW_TGT_BASED },
+    { "disallow-forwardable",  KRB5_KDB_DISALLOW_FORWARDABLE },
+    { "disallow-postdated",    KRB5_KDB_DISALLOW_POSTDATED },
+    { NULL }
+};
+
+/*
+ * convert the attributes in `attributes' into a printable string
+ * in `str, len'
+ */
+
+void
+attributes2str(krb5_flags attributes, char *str, size_t len)
+{
+    unparse_flags (attributes, kdb_attrs, str, len);
+}
+
+/*
+ * convert the string in `str' into attributes in `flags'
+ * return 0 if parsed ok, else -1.
+ */
+
+int
+str2attributes(const char *str, krb5_flags *flags)
+{
+    int res;
+
+    res = parse_flags (str, kdb_attrs, *flags);
+    if (res < 0)
+       return res;
+    else {
+       *flags = res;
+       return 0;
+    }
+}
+
+/*
+ * try to parse the string `resp' into attributes in `attr', also
+ * setting the `bit' in `mask' if attributes are given and valid.
+ */
+
+int
+parse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit)
+{
+    krb5_flags tmp = *attr;
+
+    if (str2attributes(resp, &tmp) == 0) {
+       *attr = tmp;
+       if (mask)
+           *mask |= bit;
+       return 0;
+    } else if(*resp == '?') {
+       print_flags_table (kdb_attrs, stderr);
+    } else {
+       fprintf (stderr, "Unable to parse \"%s\"\n", resp);
+    }
+    return -1;
+}
+
+/*
+ * allow the user to edit the attributes in `attr', prompting with `prompt'
+ */
+
+int
+edit_attributes (const char *prompt, krb5_flags *attr, int *mask, int bit)
+{
+    char buf[1024], resp[1024];
+
+    if (mask && (*mask & bit))
+       return 0;
+
+    attributes2str(*attr, buf, sizeof(buf));
+    for (;;) {
+       if(get_response("Attributes", buf, resp, sizeof(resp)) != 0)
+           return 1;
+       if (resp[0] == '\0')
+           break;
+       if (parse_attributes (resp, attr, mask, bit) == 0)
+           break;
+    }
+    return 0;
+}
+
+/*
+ * time_t
+ * the special value 0 means ``never''
+ */
+
+/*
+ * Convert the time `t' to a string representation in `str' (of max
+ * size `len').  If include_time also include time, otherwise just
+ * date.  
+ */
+
+void
+time_t2str(time_t t, char *str, size_t len, int include_time)
+{
+    if(t) {
+       if(include_time)
+           strftime(str, len, "%Y-%m-%d %H:%M:%S UTC", gmtime(&t));
+       else
+           strftime(str, len, "%Y-%m-%d", gmtime(&t));
+    } else
+       snprintf(str, len, "never");
+}
+
+/*
+ * Convert the time representation in `str' to a time in `time'.
+ * Return 0 if succesful, else -1.
+ */
+
+int
+str2time_t (const char *str, time_t *t)
+{
+    const char *p;
+    struct tm tm, tm2;
+
+    memset (&tm, 0, sizeof (tm));
+
+    if(strcasecmp(str, "never") == 0) {
+       *t = 0;
+       return 0;
+    }
+
+    if(strcasecmp(str, "now") == 0) {
+       *t = time(NULL);
+       return 0;
+    }
+
+    p = strptime (str, "%Y-%m-%d", &tm);
+
+    if (p == NULL)
+       return -1;
+
+
+    /* XXX this is really a bit optimistic, we should really complain
+       if there was a problem parsing the time */
+    if(strptime (p, "%t%H:%M:%S", &tm2) != NULL) {
+       tm.tm_hour = tm2.tm_hour;
+       tm.tm_min  = tm2.tm_min;
+       tm.tm_sec  = tm2.tm_sec;
+    } else {
+       /* Do it on the end of the day */
+       tm.tm_hour = 23;
+       tm.tm_min  = 59;
+       tm.tm_sec  = 59;
+    }
+
+    *t = tm2time (tm, 0);
+    return 0;
+}
+
+/*
+ * try to parse the time in `resp' storing it in `value'
+ */
+
+int
+parse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit)
+{
+    time_t tmp;
+
+    if (str2time_t(resp, &tmp) == 0) {
+       *value = tmp;
+       if(mask)
+           *mask |= bit;
+       return 0;
+    } 
+    if(*resp != '?')
+       fprintf (stderr, "Unable to parse time \"%s\"\n", resp);
+    fprintf (stderr, "Print date on format YYYY-mm-dd [hh:mm:ss]\n");
+    return -1;
+}
+
+/*
+ * allow the user to edit the time in `value'
+ */
+
+int
+edit_timet (const char *prompt, krb5_timestamp *value, int *mask, int bit)
+{
+    char buf[1024], resp[1024];
+
+    if (mask && (*mask & bit))
+       return 0;
+
+    time_t2str (*value, buf, sizeof (buf), 0);
+
+    for (;;) {
+       if(get_response(prompt, buf, resp, sizeof(resp)) != 0)
+           return 1;
+       if (parse_timet (resp, value, mask, bit) == 0)
+           break;
+    }
+    return 0;
+}
+
+/*
+ * deltat
+ * the special value 0 means ``unlimited''
+ */
+
+/*
+ * convert the delta_t value in `t' into a printable form in `str, len'
+ */
+
+void
+deltat2str(unsigned t, char *str, size_t len)
+{
+    if(t == 0 || t == INT_MAX)
+       snprintf(str, len, "unlimited");
+    else
+       unparse_time(t, str, len);
+}
+
+/*
+ * parse the delta value in `str', storing result in `*delta'
+ * return 0 if ok, else -1
+ */
+
+int
+str2deltat(const char *str, krb5_deltat *delta)
+{
+    int res;
+
+    if(strcasecmp(str, "unlimited") == 0) {
+       *delta = 0;
+       return 0;
+    }
+    res = parse_time(str, "day");
+    if (res < 0)
+       return res;
+    else {
+       *delta = res;
+       return 0;
+    }
+}
+
+/*
+ * try to parse the string in `resp' into a deltad in `value'
+ * `mask' will get the bit `bit' set if a value was given.
+ */
+
+int
+parse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit)
+{
+    krb5_deltat tmp;
+
+    if (str2deltat(resp, &tmp) == 0) {
+       *value = tmp;
+       if (mask)
+           *mask |= bit;
+       return 0;
+    } else if(*resp == '?') {
+       print_time_table (stderr);
+    } else {
+       fprintf (stderr, "Unable to parse time \"%s\"\n", resp);
+    }
+    return -1;
+}
+
+/*
+ * allow the user to edit the deltat in `value'
+ */
+
+int
+edit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit)
+{
+    char buf[1024], resp[1024];
+
+    if (mask && (*mask & bit))
+       return 0;
+
+    deltat2str(*value, buf, sizeof(buf));
+    for (;;) {
+       if(get_response(prompt, buf, resp, sizeof(resp)) != 0)
+           return 1;
+       if (parse_deltat (resp, value, mask, bit) == 0)
+           break;
+    }
+    return 0;
+}
+
+/*
+ * allow the user to edit `ent'
+ */
+
+void
+set_defaults(kadm5_principal_ent_t ent, int *mask,
+            kadm5_principal_ent_t default_ent, int default_mask)
+{
+    if (default_ent
+       && (default_mask & KADM5_MAX_LIFE)
+       && !(*mask & KADM5_MAX_LIFE))
+       ent->max_life = default_ent->max_life;
+
+    if (default_ent
+       && (default_mask & KADM5_MAX_RLIFE)
+       && !(*mask & KADM5_MAX_RLIFE))
+       ent->max_renewable_life = default_ent->max_renewable_life;
+
+    if (default_ent
+       && (default_mask & KADM5_PRINC_EXPIRE_TIME)
+       && !(*mask & KADM5_PRINC_EXPIRE_TIME))
+       ent->princ_expire_time = default_ent->princ_expire_time;
+
+    if (default_ent
+       && (default_mask & KADM5_PW_EXPIRATION)
+       && !(*mask & KADM5_PW_EXPIRATION))
+       ent->pw_expiration = default_ent->pw_expiration;
+
+    if (default_ent
+       && (default_mask & KADM5_ATTRIBUTES)
+       && !(*mask & KADM5_ATTRIBUTES))
+       ent->attributes = default_ent->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX;
+}
+
+int
+edit_entry(kadm5_principal_ent_t ent, int *mask,
+          kadm5_principal_ent_t default_ent, int default_mask)
+{
+
+    set_defaults(ent, mask, default_ent, default_mask);
+
+    if(edit_deltat ("Max ticket life", &ent->max_life, mask,
+                   KADM5_MAX_LIFE) != 0)
+       return 1;
+    
+    if(edit_deltat ("Max renewable life", &ent->max_renewable_life, mask,
+                   KADM5_MAX_RLIFE) != 0)
+       return 1;
+
+    if(edit_timet ("Principal expiration time", &ent->princ_expire_time, mask,
+                  KADM5_PRINC_EXPIRE_TIME) != 0)
+       return 1;
+
+    if(edit_timet ("Password expiration time", &ent->pw_expiration, mask,
+                  KADM5_PW_EXPIRATION) != 0)
+       return 1;
+
+    if(edit_attributes ("Attributes", &ent->attributes, mask,
+                       KADM5_ATTRIBUTES) != 0)
+       return 1;
+
+    return 0;
+}
+
+/*
+ * Parse the arguments, set the fields in `ent' and the `mask' for the
+ * entries having been set.
+ * Return 1 on failure and 0 on success.
+ */
+
+int
+set_entry(krb5_context context,
+         kadm5_principal_ent_t ent,
+         int *mask,
+         const char *max_ticket_life,
+         const char *max_renewable_life,
+         const char *expiration,
+         const char *pw_expiration,
+         const char *attributes)
+{
+    if (max_ticket_life != NULL) {
+       if (parse_deltat (max_ticket_life, &ent->max_life, 
+                         mask, KADM5_MAX_LIFE)) {
+           krb5_warnx (context, "unable to parse `%s'", max_ticket_life);
+           return 1;
+       }
+    }
+    if (max_renewable_life != NULL) {
+       if (parse_deltat (max_renewable_life, &ent->max_renewable_life, 
+                         mask, KADM5_MAX_RLIFE)) {
+           krb5_warnx (context, "unable to parse `%s'", max_renewable_life);
+           return 1;
+       }
+    }
+
+    if (expiration) {
+       if (parse_timet (expiration, &ent->princ_expire_time, 
+                       mask, KADM5_PRINC_EXPIRE_TIME)) {
+           krb5_warnx (context, "unable to parse `%s'", expiration);
+           return 1;
+       }
+    }
+    if (pw_expiration) {
+       if (parse_timet (pw_expiration, &ent->pw_expiration, 
+                        mask, KADM5_PW_EXPIRATION)) {
+           krb5_warnx (context, "unable to parse `%s'", pw_expiration);
+           return 1;
+       }
+    }
+    if (attributes != NULL) {
+       if (parse_attributes (attributes, &ent->attributes, 
+                             mask, KADM5_ATTRIBUTES)) {
+           krb5_warnx (context, "unable to parse `%s'", attributes);
+           return 1;
+       }
+    }
+    return 0;
+}
+
+/*
+ * Does `string' contain any globing characters?
+ */
+
+static int
+is_expression(const char *string)
+{
+    const char *p;
+    int quote = 0;
+
+    for(p = string; *p; p++) {
+       if(quote) {
+           quote = 0;
+           continue;
+       }
+       if(*p == '\\')
+           quote++;
+       else if(strchr("[]*?", *p) != NULL) 
+           return 1;
+    }
+    return 0;
+}
+
+/* loop over all principals matching exp */
+int
+foreach_principal(const char *exp, 
+                 int (*func)(krb5_principal, void*), 
+                 const char *funcname,
+                 void *data)
+{
+    char **princs;
+    int num_princs;
+    int i;
+    krb5_error_code ret = 0;
+    krb5_principal princ_ent;
+    int is_expr;
+
+    /* if this isn't an expression, there is no point in wading
+       through the whole database looking for matches */
+    is_expr = is_expression(exp);
+    if(is_expr)
+       ret = kadm5_get_principals(kadm_handle, exp, &princs, &num_princs);
+    if(!is_expr || ret == KADM5_AUTH_LIST) {
+       /* we might be able to perform the requested opreration even
+           if we're not allowed to list principals */
+       num_princs = 1;
+       princs = malloc(sizeof(*princs));
+       if(princs == NULL)
+           return ENOMEM;
+       princs[0] = strdup(exp);
+       if(princs[0] == NULL){ 
+           free(princs);
+           return ENOMEM;
+       }
+    } else if(ret) {
+       krb5_warn(context, ret, "kadm5_get_principals");
+       return ret;
+    }
+    for(i = 0; i < num_princs; i++) {
+       ret = krb5_parse_name(context, princs[i], &princ_ent);
+       if(ret){
+           krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]);
+           continue;
+       }
+       ret = (*func)(princ_ent, data);
+       if(ret)
+           krb5_warn(context, ret, "%s %s", funcname, princs[i]);
+       krb5_free_principal(context, princ_ent);
+    }
+    kadm5_free_name_list(kadm_handle, princs, &num_princs);
+    return 0;
+}
+
+/*
+ * prompt with `prompt' and default value `def', and store the reply
+ * in `buf, len'
+ */
+
+#include <setjmp.h>
+
+static jmp_buf jmpbuf;
+
+static void
+interrupt(int sig)
+{
+    longjmp(jmpbuf, 1);
+}
+
+static int
+get_response(const char *prompt, const char *def, char *buf, size_t len)
+{
+    char *p;
+    void (*osig)(int);
+
+    osig = signal(SIGINT, interrupt);
+    if(setjmp(jmpbuf)) {
+       signal(SIGINT, osig);
+       fprintf(stderr, "\n");
+       return 1;
+    }
+
+    fprintf(stderr, "%s [%s]:", prompt, def);
+    if(fgets(buf, len, stdin) == NULL) {
+       int save_errno = errno;
+       if(ferror(stdin))
+           krb5_err(context, 1, save_errno, "<stdin>");
+       signal(SIGINT, osig);
+       return 1;
+    }
+    p = strchr(buf, '\n');
+    if(p)
+       *p = '\0';
+    if(strcmp(buf, "") == 0)
+       strlcpy(buf, def, len);
+    signal(SIGINT, osig);
+    return 0;
+}
+
+/*
+ * return [0, 16) or -1
+ */
+
+static int
+hex2n (char c)
+{
+    static char hexdigits[] = "0123456789abcdef";
+    const char *p;
+
+    p = strchr (hexdigits, tolower((unsigned char)c));
+    if (p == NULL)
+       return -1;
+    else
+       return p - hexdigits;
+}
+
+/*
+ * convert a key in a readable format into a keyblock.
+ * return 0 iff succesful, otherwise `err' should point to an error message
+ */
+
+int
+parse_des_key (const char *key_string, krb5_key_data *key_data,
+              const char **err)
+{
+    const char *p = key_string;
+    unsigned char bits[8];
+    int i;
+
+    if (strlen (key_string) != 16) {
+       *err = "bad length, should be 16 for DES key";
+       return 1;
+    }
+    for (i = 0; i < 8; ++i) {
+       int d1, d2;
+
+       d1 = hex2n(p[2 * i]);
+       d2 = hex2n(p[2 * i + 1]);
+       if (d1 < 0 || d2 < 0) {
+           *err = "non-hex character";
+           return 1;
+       }
+       bits[i] = (d1 << 4) | d2;
+    }
+    for (i = 0; i < 3; ++i) {
+       key_data[i].key_data_ver  = 2;
+       key_data[i].key_data_kvno = 0;
+       /* key */
+       key_data[i].key_data_type[0]     = ETYPE_DES_CBC_CRC;
+       key_data[i].key_data_length[0]   = 8;
+       key_data[i].key_data_contents[0] = malloc(8);
+       memcpy (key_data[i].key_data_contents[0], bits, 8);
+       /* salt */
+       key_data[i].key_data_type[1]     = KRB5_PW_SALT;
+       key_data[i].key_data_length[1]   = 0;
+       key_data[i].key_data_contents[1] = NULL;
+    }
+    key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5;
+    key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
+    return 0;
+}
diff --git a/src/kerberosV/src/kadmin/version4.c b/src/kerberosV/src/kadmin/version4.c
new file mode 100644 (file)
index 0000000..cc62a9c
--- /dev/null
@@ -0,0 +1,1016 @@
+/*
+ * Copyright (c) 1999 - 2002 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. */
+
+#include "kadmin_locl.h"
+#include <krb5-private.h>
+
+#define Principal krb4_Principal
+#define kadm_get krb4_kadm_get
+#undef ALLOC
+#include <krb.h>
+#include <kadm.h>
+#include <krb_err.h>
+#include <kadm_err.h>
+
+RCSID("$KTH: version4.c,v 1.29.2.1 2004/04/29 12:29:23 lha Exp $");
+
+#define KADM_NO_OPCODE -1
+#define KADM_NO_ENCRYPT -2
+
+/*
+ * make an error packet if we fail encrypting
+ */
+
+static void
+make_you_lose_packet(int code, krb5_data *reply)
+{
+    krb5_data_alloc(reply, KADM_VERSIZE + 4);
+    memcpy(reply->data, KADM_ULOSE, KADM_VERSIZE);
+    _krb5_put_int((char*)reply->data + KADM_VERSIZE, code, 4);
+}
+
+static int
+ret_fields(krb5_storage *sp, char *fields)
+{
+    return krb5_storage_read(sp, fields, FLDSZ);
+}
+
+static int
+store_fields(krb5_storage *sp, char *fields)
+{
+    return krb5_storage_write(sp, fields, FLDSZ);
+}
+
+static void
+ret_vals(krb5_storage *sp, Kadm_vals *vals)
+{
+    int field;
+    char *tmp_string;
+
+    memset(vals, 0, sizeof(*vals));
+    
+    ret_fields(sp, vals->fields);
+    
+    for(field = 31; field >= 0; field--) {
+       if(IS_FIELD(field, vals->fields)) {
+           switch(field) {
+           case KADM_NAME:
+               krb5_ret_stringz(sp, &tmp_string);
+               strlcpy(vals->name, tmp_string, sizeof(vals->name));
+               free(tmp_string);
+               break;
+           case KADM_INST:
+               krb5_ret_stringz(sp, &tmp_string);
+               strlcpy(vals->instance, tmp_string, 
+                               sizeof(vals->instance));
+               free(tmp_string);
+               break;
+           case KADM_EXPDATE:
+               krb5_ret_int32(sp, &vals->exp_date);
+               break;
+           case KADM_ATTR:
+               krb5_ret_int16(sp, &vals->attributes);
+               break;
+           case KADM_MAXLIFE:
+               krb5_ret_int8(sp, &vals->max_life);
+               break;
+           case KADM_DESKEY:
+               krb5_ret_int32(sp, &vals->key_high);
+               krb5_ret_int32(sp, &vals->key_low);
+               break;
+#ifdef EXTENDED_KADM
+           case KADM_MODDATE:
+               krb5_ret_int32(sp, &vals->mod_date);
+               break;
+           case KADM_MODNAME:
+               krb5_ret_stringz(sp, &tmp_string);
+               strlcpy(vals->mod_name, tmp_string, 
+                               sizeof(vals->mod_name));
+               free(tmp_string);
+               break;
+           case KADM_MODINST:
+               krb5_ret_stringz(sp, &tmp_string);
+               strlcpy(vals->mod_instance, tmp_string, 
+                               sizeof(vals->mod_instance));
+               free(tmp_string);
+               break;
+           case KADM_KVNO:
+               krb5_ret_int8(sp, &vals->key_version);
+               break;
+#endif
+           default:
+               break;
+           }
+       }
+    }
+}
+
+static void
+store_vals(krb5_storage *sp, Kadm_vals *vals)
+{
+    int field;
+    
+    store_fields(sp, vals->fields);
+
+    for(field = 31; field >= 0; field--) {
+       if(IS_FIELD(field, vals->fields)) {
+           switch(field) {
+           case KADM_NAME:
+               krb5_store_stringz(sp, vals->name);
+               break;
+           case KADM_INST:
+               krb5_store_stringz(sp, vals->instance);
+               break;
+           case KADM_EXPDATE:
+               krb5_store_int32(sp, vals->exp_date);
+               break;
+           case KADM_ATTR:
+               krb5_store_int16(sp, vals->attributes);
+               break;
+           case KADM_MAXLIFE:
+               krb5_store_int8(sp, vals->max_life);
+               break;
+           case KADM_DESKEY:
+               krb5_store_int32(sp, vals->key_high);
+               krb5_store_int32(sp, vals->key_low);
+               break;
+#ifdef EXTENDED_KADM
+           case KADM_MODDATE:
+               krb5_store_int32(sp, vals->mod_date);
+               break;
+           case KADM_MODNAME:
+               krb5_store_stringz(sp, vals->mod_name);
+               break;
+           case KADM_MODINST:
+               krb5_store_stringz(sp, vals->mod_instance);
+               break;
+           case KADM_KVNO:
+               krb5_store_int8(sp, vals->key_version);
+               break;
+#endif
+           default:
+               break;
+           }
+       }
+    }
+}
+
+static int
+flags_4_to_5(char *flags)
+{
+    int i;
+    int32_t mask = 0;
+    for(i = 31; i >= 0; i--) {
+       if(IS_FIELD(i, flags))
+           switch(i) {
+           case KADM_NAME:
+           case KADM_INST:
+               mask |= KADM5_PRINCIPAL;
+           case KADM_EXPDATE:
+               mask |= KADM5_PRINC_EXPIRE_TIME;
+           case KADM_MAXLIFE:
+               mask |= KADM5_MAX_LIFE;
+#ifdef EXTENDED_KADM
+           case KADM_KVNO:
+               mask |= KADM5_KEY_DATA;
+           case KADM_MODDATE:
+               mask |= KADM5_MOD_TIME;
+           case KADM_MODNAME:
+           case KADM_MODINST:
+               mask |= KADM5_MOD_NAME;
+#endif
+           }
+    }
+    return mask;
+}
+
+static void
+ent_to_values(krb5_context context,
+             kadm5_principal_ent_t ent,
+             int32_t mask,
+             Kadm_vals *vals)
+{
+    krb5_error_code ret;
+    char realm[REALM_SZ];
+    time_t exp = 0;
+
+    memset(vals, 0, sizeof(*vals));
+    if(mask & KADM5_PRINCIPAL) {
+       ret = krb5_524_conv_principal(context, ent->principal, 
+                                     vals->name, vals->instance, realm);
+       SET_FIELD(KADM_NAME, vals->fields);
+       SET_FIELD(KADM_INST, vals->fields);
+    }
+    if(mask & KADM5_PRINC_EXPIRE_TIME) {
+       if(ent->princ_expire_time != 0)
+           exp = ent->princ_expire_time;
+    }
+    if(mask & KADM5_PW_EXPIRATION) {
+       if(ent->pw_expiration != 0 && (exp == 0 || exp > ent->pw_expiration))
+           exp = ent->pw_expiration;
+    }
+    if(exp) {
+       vals->exp_date = exp;
+       SET_FIELD(KADM_EXPDATE, vals->fields);
+    }
+    if(mask & KADM5_MAX_LIFE) {
+       if(ent->max_life == 0)
+           vals->max_life = 255;
+       else
+           vals->max_life = krb_time_to_life(0, ent->max_life);
+       SET_FIELD(KADM_MAXLIFE, vals->fields);
+    }
+    if(mask & KADM5_KEY_DATA) {
+       if(ent->n_key_data > 0) {
+#ifdef EXTENDED_KADM
+       vals->key_version = ent->key_data[0].key_data_kvno;
+       SET_FIELD(KADM_KVNO, vals->fields);
+#endif
+       }
+       /* XXX the key itself? */
+    }
+#ifdef EXTENDED_KADM
+    if(mask & KADM5_MOD_TIME) {
+       vals->mod_date = ent->mod_date;
+       SET_FIELD(KADM_MODDATE, vals->fields);
+    }
+    if(mask & KADM5_MOD_NAME) {
+       krb5_524_conv_principal(context, ent->mod_name, 
+                               vals->mod_name, vals->mod_instance, realm);
+       SET_FIELD(KADM_MODNAME, vals->fields);
+       SET_FIELD(KADM_MODINST, vals->fields);
+    }
+#endif
+}
+
+/*
+ * convert the kadm4 values in `vals' to `ent' (and `mask')
+ */
+
+static krb5_error_code
+values_to_ent(krb5_context context,
+             Kadm_vals *vals, 
+             kadm5_principal_ent_t ent,
+             int32_t *mask)
+{
+    krb5_error_code ret;
+    *mask = 0;
+    memset(ent, 0, sizeof(*ent));
+    
+    if(IS_FIELD(KADM_NAME, vals->fields)) {
+       char *inst = NULL;
+       if(IS_FIELD(KADM_INST, vals->fields))
+           inst = vals->instance;
+       ret = krb5_425_conv_principal(context, 
+                                     vals->name,
+                                     inst,
+                                     NULL,
+                                     &ent->principal);
+       if(ret)
+           return ret;
+       *mask |= KADM5_PRINCIPAL;
+    }
+    if(IS_FIELD(KADM_EXPDATE, vals->fields)) {
+       ent->princ_expire_time = vals->exp_date;
+       *mask |= KADM5_PRINC_EXPIRE_TIME;
+    }
+    if(IS_FIELD(KADM_MAXLIFE, vals->fields)) {
+       ent->max_life = krb_life_to_time(0, vals->max_life);
+       *mask |= KADM5_MAX_LIFE;
+    }
+    
+    if(IS_FIELD(KADM_DESKEY, vals->fields)) {
+       int i;
+       ent->key_data = calloc(3, sizeof(*ent->key_data));
+       if(ent->key_data == NULL)
+           return ENOMEM;
+       for(i = 0; i < 3; i++) {
+           u_int32_t key_low, key_high;
+
+           ent->key_data[i].key_data_ver = 2;
+#ifdef EXTENDED_KADM
+           if(IS_FIELD(KADM_KVNO, vals->fields))
+               ent->key_data[i].key_data_kvno = vals->key_version;
+#endif
+           ent->key_data[i].key_data_type[0] = ETYPE_DES_CBC_MD5;
+           ent->key_data[i].key_data_length[0] = 8;
+           if((ent->key_data[i].key_data_contents[0] = malloc(8)) == NULL)
+               return ENOMEM;
+
+           key_low  = ntohl(vals->key_low);
+           key_high = ntohl(vals->key_high);
+           memcpy(ent->key_data[i].key_data_contents[0],
+                  &key_low, 4);
+           memcpy((char*)ent->key_data[i].key_data_contents[0] + 4,
+                  &key_high, 4);
+           ent->key_data[i].key_data_type[1] = KRB5_PW_SALT;
+           ent->key_data[i].key_data_length[1] = 0;
+           ent->key_data[i].key_data_contents[1] = NULL;
+       }
+       ent->key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
+       ent->key_data[2].key_data_type[0] = ETYPE_DES_CBC_CRC;
+       ent->n_key_data = 3;
+       *mask |= KADM5_KEY_DATA;
+    }
+    
+#ifdef EXTENDED_KADM
+    if(IS_FIELD(KADM_MODDATE, vals->fields)) {
+       ent->mod_date = vals->mod_date;
+       *mask |= KADM5_MOD_TIME;
+    }
+    if(IS_FIELD(KADM_MODNAME, vals->fields)) {
+       char *inst = NULL;
+       if(IS_FIELD(KADM_MODINST, vals->fields))
+           inst = vals->mod_instance;
+       ret = krb5_425_conv_principal(context, 
+                                     vals->mod_name,
+                                     inst,
+                                     NULL,
+                                     &ent->mod_name);
+       if(ret)
+           return ret;
+       *mask |= KADM5_MOD_NAME;
+    }
+#endif
+    return 0;
+}
+
+/*
+ * Try to translate a KADM5 error code into a v4 kadmin one.
+ */
+
+static int
+error_code(int ret)
+{
+    switch (ret) {
+    case 0:
+       return 0;
+    case KADM5_FAILURE :
+    case KADM5_AUTH_GET :
+    case KADM5_AUTH_ADD :
+    case KADM5_AUTH_MODIFY :
+    case KADM5_AUTH_DELETE :
+    case KADM5_AUTH_INSUFFICIENT :
+       return KADM_UNAUTH;
+    case KADM5_BAD_DB :
+       return KADM_UK_RERROR;
+    case KADM5_DUP :
+       return KADM_INUSE;
+    case KADM5_RPC_ERROR :
+    case KADM5_NO_SRV :
+       return KADM_NO_SERV;
+    case KADM5_NOT_INIT :
+       return KADM_NO_CONN;
+    case KADM5_UNK_PRINC :
+       return KADM_NOENTRY;
+    case KADM5_PASS_Q_TOOSHORT :
+#ifdef KADM_PASS_Q_TOOSHORT
+       return KADM_PASS_Q_TOOSHORT;
+#else
+       return KADM_INSECURE_PW;
+#endif
+    case KADM5_PASS_Q_CLASS :
+#ifdef KADM_PASS_Q_CLASS
+       return KADM_PASS_Q_CLASS;
+#else
+       return KADM_INSECURE_PW;
+#endif
+    case KADM5_PASS_Q_DICT :
+#ifdef KADM_PASS_Q_DICT
+       return KADM_PASS_Q_DICT;
+#else
+       return KADM_INSECURE_PW;
+#endif
+    case KADM5_PASS_REUSE :
+    case KADM5_PASS_TOOSOON :
+    case KADM5_BAD_PASSWORD :
+       return KADM_INSECURE_PW;
+    case KADM5_PROTECT_PRINCIPAL :
+       return KADM_IMMUTABLE;
+    case KADM5_POLICY_REF :
+    case KADM5_INIT :
+    case KADM5_BAD_HIST_KEY :
+    case KADM5_UNK_POLICY :
+    case KADM5_BAD_MASK :
+    case KADM5_BAD_CLASS :
+    case KADM5_BAD_LENGTH :
+    case KADM5_BAD_POLICY :
+    case KADM5_BAD_PRINCIPAL :
+    case KADM5_BAD_AUX_ATTR :
+    case KADM5_BAD_HISTORY :
+    case KADM5_BAD_MIN_PASS_LIFE :
+    case KADM5_BAD_SERVER_HANDLE :
+    case KADM5_BAD_STRUCT_VERSION :
+    case KADM5_OLD_STRUCT_VERSION :
+    case KADM5_NEW_STRUCT_VERSION :
+    case KADM5_BAD_API_VERSION :
+    case KADM5_OLD_LIB_API_VERSION :
+    case KADM5_OLD_SERVER_API_VERSION :
+    case KADM5_NEW_LIB_API_VERSION :
+    case KADM5_NEW_SERVER_API_VERSION :
+    case KADM5_SECURE_PRINC_MISSING :
+    case KADM5_NO_RENAME_SALT :
+    case KADM5_BAD_CLIENT_PARAMS :
+    case KADM5_BAD_SERVER_PARAMS :
+    case KADM5_AUTH_LIST :
+    case KADM5_AUTH_CHANGEPW :
+    case KADM5_BAD_TL_TYPE :
+    case KADM5_MISSING_CONF_PARAMS :
+    case KADM5_BAD_SERVER_NAME :
+    default :
+       return KADM_UNAUTH;     /* XXX */
+    }
+}
+
+/*
+ * server functions
+ */
+
+static int
+kadm_ser_cpw(krb5_context context,
+            void *kadm_handle, 
+            krb5_principal principal, 
+            const char *principal_string,
+            krb5_storage *message,
+            krb5_storage *reply)
+{
+    char key[8];
+    char *password = NULL;
+    krb5_error_code ret;
+    
+    krb5_warnx(context, "v4-compat %s: CHPASS %s",
+              principal_string, principal_string); 
+
+    ret = krb5_storage_read(message, key + 4, 4);
+    ret = krb5_storage_read(message, key, 4);
+    ret = krb5_ret_stringz(message, &password);
+    
+    if(password) {
+       krb5_data pwd_data;
+       const char *tmp;
+
+       pwd_data.data   = password;
+       pwd_data.length = strlen(password);
+
+       tmp = kadm5_check_password_quality (context, principal, &pwd_data);
+
+       if (tmp != NULL) {
+           krb5_store_stringz (reply, (char *)tmp);
+           ret = KADM5_PASS_Q_DICT;
+           goto fail;
+       }
+       ret = kadm5_chpass_principal(kadm_handle, principal, password);
+    } else {
+       krb5_key_data key_data[3];
+       int i;
+       for(i = 0; i < 3; i++) {
+           key_data[i].key_data_ver = 2;
+           key_data[i].key_data_kvno = 0;
+           /* key */
+           key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC;
+           key_data[i].key_data_length[0] = 8;
+           key_data[i].key_data_contents[0] = malloc(8);
+           memcpy(key_data[i].key_data_contents[0], &key, 8);
+           /* salt */
+           key_data[i].key_data_type[1] = KRB5_PW_SALT;
+           key_data[i].key_data_length[1] = 0;
+           key_data[i].key_data_contents[1] = NULL;
+       }
+       key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5;
+       key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4;
+       ret = kadm5_s_chpass_principal_with_key(kadm_handle, 
+                                               principal, 3, key_data);
+    }
+
+    if(ret != 0) {
+       krb5_store_stringz(reply, (char*)krb5_get_err_text(context, ret));
+       goto fail;
+    }
+    return 0;
+fail:
+    krb5_warn(context, ret, "v4-compat CHPASS");
+    return error_code(ret);
+}
+
+static int
+kadm_ser_add(krb5_context context,
+            void *kadm_handle, 
+            krb5_principal principal, 
+            const char *principal_string,
+            krb5_storage *message,
+            krb5_storage *reply)
+{
+    int32_t mask;
+    kadm5_principal_ent_rec ent, out;
+    Kadm_vals values;
+    krb5_error_code ret;
+    char name[128];
+
+    ret_vals(message, &values);
+
+    ret = values_to_ent(context, &values, &ent, &mask);
+    if(ret)
+       goto fail;
+
+    krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
+    krb5_warnx(context, "v4-compat %s: ADD %s",
+              principal_string, name);
+
+    ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_ADD,
+                                      ent.principal);
+    if (ret)
+       goto fail;
+
+    ret = kadm5_s_create_principal_with_key(kadm_handle, &ent, mask);
+    if(ret) {
+       kadm5_free_principal_ent(kadm_handle, &ent);
+       goto fail;
+    }
+
+    mask = KADM5_PRINCIPAL | KADM5_PRINC_EXPIRE_TIME | KADM5_MAX_LIFE |
+       KADM5_KEY_DATA | KADM5_MOD_TIME | KADM5_MOD_NAME;
+    
+    kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
+    ent_to_values(context, &out, mask, &values);
+    kadm5_free_principal_ent(kadm_handle, &ent);
+    kadm5_free_principal_ent(kadm_handle, &out);
+    store_vals(reply, &values);
+    return 0;
+fail:
+    krb5_warn(context, ret, "v4-compat ADD");
+    return error_code(ret);
+}
+
+static int
+kadm_ser_get(krb5_context context,
+            void *kadm_handle, 
+            krb5_principal principal, 
+            const char *principal_string,
+            krb5_storage *message,
+            krb5_storage *reply)
+{
+    krb5_error_code ret;
+    Kadm_vals values;
+    kadm5_principal_ent_rec ent, out;
+    int32_t mask;
+    char flags[FLDSZ];
+    char name[128];
+
+    ret_vals(message, &values);
+    /* XXX BRAIN DAMAGE! these flags are not stored in the same order
+       as in the header */
+    krb5_ret_int8(message, &flags[3]);
+    krb5_ret_int8(message, &flags[2]);
+    krb5_ret_int8(message, &flags[1]);
+    krb5_ret_int8(message, &flags[0]);
+    ret = values_to_ent(context, &values, &ent, &mask);
+    if(ret)
+       goto fail;
+
+    krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
+    krb5_warnx(context, "v4-compat %s: GET %s",
+              principal_string, name);
+
+    ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_GET,
+                                      ent.principal);
+    if (ret)
+       goto fail;
+
+    mask = flags_4_to_5(flags);
+
+    ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
+    kadm5_free_principal_ent(kadm_handle, &ent);
+
+    if (ret)
+       goto fail;
+    
+    ent_to_values(context, &out, mask, &values);
+
+    kadm5_free_principal_ent(kadm_handle, &out);
+
+    store_vals(reply, &values);
+    return 0;
+fail:
+    krb5_warn(context, ret, "v4-compat GET");
+    return error_code(ret);
+}
+
+static int
+kadm_ser_mod(krb5_context context,
+            void *kadm_handle, 
+            krb5_principal principal, 
+            const char *principal_string,
+            krb5_storage *message,
+            krb5_storage *reply)
+{
+    Kadm_vals values1, values2;
+    kadm5_principal_ent_rec ent, out;
+    int32_t mask;
+    krb5_error_code ret;
+    char name[128];
+    
+    ret_vals(message, &values1);
+    /* why are the old values sent? is the mask the same in the old and
+       the new entry? */
+    ret_vals(message, &values2);
+    
+    ret = values_to_ent(context, &values2, &ent, &mask);
+    if(ret)
+       goto fail;
+
+    krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
+    krb5_warnx(context, "v4-compat %s: MOD %s",
+              principal_string, name);
+
+    ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_MODIFY,
+                                      ent.principal);
+    if (ret)
+       goto fail;
+
+    ret = kadm5_s_modify_principal(kadm_handle, &ent, mask);
+    if(ret) {
+       kadm5_free_principal_ent(kadm_handle, &ent);
+       krb5_warn(context, ret, "kadm5_s_modify_principal");
+       goto fail;
+    }
+
+    ret = kadm5_get_principal(kadm_handle, ent.principal, &out, mask);
+    if(ret) {
+       kadm5_free_principal_ent(kadm_handle, &ent);
+       krb5_warn(context, ret, "kadm5_s_modify_principal");
+       goto fail;
+    }
+
+    ent_to_values(context, &out, mask, &values1);
+
+    kadm5_free_principal_ent(kadm_handle, &ent);
+    kadm5_free_principal_ent(kadm_handle, &out);
+    
+    store_vals(reply, &values1);
+    return 0;
+fail:
+    krb5_warn(context, ret, "v4-compat MOD");
+    return error_code(ret);
+}
+
+static int
+kadm_ser_del(krb5_context context,
+            void *kadm_handle, 
+            krb5_principal principal, 
+            const char *principal_string,
+            krb5_storage *message,
+            krb5_storage *reply)
+{
+    Kadm_vals values;
+    kadm5_principal_ent_rec ent;
+    int32_t mask;
+    krb5_error_code ret;
+    char name[128];
+
+    ret_vals(message, &values);
+
+    ret = values_to_ent(context, &values, &ent, &mask);
+    if(ret)
+       goto fail;
+    
+    krb5_unparse_name_fixed(context, ent.principal, name, sizeof(name));
+    krb5_warnx(context, "v4-compat %s: DEL %s",
+              principal_string, name);
+
+    ret = _kadm5_acl_check_permission (kadm_handle, KADM5_PRIV_DELETE,
+                                      ent.principal);
+    if (ret)
+       goto fail;
+
+    ret = kadm5_delete_principal(kadm_handle, ent.principal);
+
+    kadm5_free_principal_ent(kadm_handle, &ent);
+
+    if (ret)
+       goto fail;
+
+    return 0;
+fail:
+    krb5_warn(context, ret, "v4-compat ADD");
+    return error_code(ret);
+}
+
+static int
+dispatch(krb5_context context,
+        void *kadm_handle,
+        krb5_principal principal,
+        const char *principal_string,
+        krb5_data msg, 
+        krb5_data *reply)
+{
+    int retval;
+    int8_t command;
+    krb5_storage *sp_in, *sp_out;
+    
+    sp_in = krb5_storage_from_data(&msg);
+    krb5_ret_int8(sp_in, &command);
+    
+    sp_out = krb5_storage_emem();
+    krb5_storage_write(sp_out, KADM_VERSTR, KADM_VERSIZE);
+    krb5_store_int32(sp_out, 0);
+
+    switch(command) {
+    case CHANGE_PW:
+       retval = kadm_ser_cpw(context, kadm_handle, principal,
+                             principal_string,
+                             sp_in, sp_out);
+       break;
+    case ADD_ENT:
+       retval = kadm_ser_add(context, kadm_handle, principal,
+                             principal_string,
+                             sp_in, sp_out);
+       break;
+    case GET_ENT:
+       retval = kadm_ser_get(context, kadm_handle, principal,
+                             principal_string,
+                             sp_in, sp_out);
+       break;
+    case MOD_ENT:
+       retval = kadm_ser_mod(context, kadm_handle, principal,
+                             principal_string,
+                             sp_in, sp_out);
+       break;
+    case DEL_ENT:
+       retval = kadm_ser_del(context, kadm_handle, principal,
+                             principal_string,
+                             sp_in, sp_out);
+       break;
+    default:
+       krb5_warnx(context, "v4-compat %s: unknown opcode: %d",
+                  principal_string, command);
+       retval = KADM_NO_OPCODE;
+       break;
+    }
+    krb5_storage_free(sp_in);
+    if(retval) {
+       krb5_storage_seek(sp_out, KADM_VERSIZE, SEEK_SET);
+       krb5_store_int32(sp_out, retval);
+    }
+    krb5_storage_to_data(sp_out, reply);
+    krb5_storage_free(sp_out);
+    return retval;
+}
+
+/*
+ * Decode a v4 kadmin packet in `message' and create a reply in `reply'
+ */
+
+static void
+decode_packet(krb5_context context,
+             krb5_keytab keytab,
+             struct sockaddr_in *admin_addr,
+             struct sockaddr_in *client_addr,
+             krb5_data message,
+             krb5_data *reply)
+{
+    int ret;
+    KTEXT_ST authent;
+    AUTH_DAT ad;
+    MSG_DAT msg_dat;
+    off_t off = 0;
+    unsigned long rlen;
+    char sname[] = "changepw", sinst[] = "kerberos";
+    unsigned long checksum;
+    des_key_schedule schedule;
+    char *msg = message.data;
+    void *kadm_handle;
+    krb5_principal client;
+    char *client_str;
+    krb5_keytab_entry entry;
+    
+    if(message.length < KADM_VERSIZE + 4
+       || strncmp(msg, KADM_VERSTR, KADM_VERSIZE) != 0) {
+       make_you_lose_packet (KADM_BAD_VER, reply);
+       return;
+    }
+
+    off = KADM_VERSIZE;
+    off += _krb5_get_int(msg + off, &rlen, 4);
+    memset(&authent, 0, sizeof(authent));
+    authent.length = message.length - rlen - KADM_VERSIZE - 4;
+
+    if(rlen > message.length - KADM_VERSIZE - 4
+       || authent.length > MAX_KTXT_LEN) {
+       krb5_warnx(context, "received bad rlen (%lu)", (unsigned long)rlen);
+       make_you_lose_packet (KADM_LENGTH_ERROR, reply);
+       return;
+    }
+
+    memcpy(authent.dat, (char*)msg + off, authent.length);
+    off += authent.length;
+    
+    {
+       krb5_principal principal;
+       krb5_keyblock *key;
+
+       ret = krb5_make_principal(context, &principal, NULL, 
+                                 "changepw", "kerberos", NULL);
+       if (ret) {
+           krb5_warn (context, ret, "krb5_make_principal");
+           make_you_lose_packet (KADM_NOMEM, reply);
+           return;
+       }
+       ret = krb5_kt_get_entry (context, keytab, principal, 0,
+                                ETYPE_DES_CBC_MD5, &entry);
+       krb5_kt_close (context, keytab);
+       if (ret) {
+           krb5_free_principal(context, principal);
+           make_you_lose_packet (KADM_NO_AUTH, reply);
+           return;
+       }
+       ret = krb5_copy_keyblock (context, &entry.keyblock,& key);
+       krb5_kt_free_entry(context, &entry);
+       krb5_free_principal(context, principal);
+       if(ret) {
+           if(ret == KRB5_KT_NOTFOUND)
+               make_you_lose_packet(KADM_NO_AUTH, reply);
+           else
+               /* XXX */
+               make_you_lose_packet(KADM_NO_AUTH, reply);
+           krb5_warn(context, ret, "krb5_kt_read_service_key");
+           return;
+       }
+       
+       if(key->keyvalue.length != 8)
+           krb5_abortx(context, "key has wrong length (%lu)", 
+                       (unsigned long)key->keyvalue.length);
+       krb_set_key(key->keyvalue.data, 0);
+       krb5_free_keyblock(context, key);
+    }
+    
+    ret = krb_rd_req(&authent, sname, sinst, 
+                    client_addr->sin_addr.s_addr, &ad, NULL);
+
+    if(ret) {
+       make_you_lose_packet(ERROR_TABLE_BASE_krb + ret, reply);
+       krb5_warnx(context, "krb_rd_req: %d", ret);
+       return;
+    }
+
+    ret = krb5_425_conv_principal(context, ad.pname, ad.pinst, ad.prealm,
+                                 &client);
+    if (ret) {
+       krb5_warnx (context, "krb5_425_conv_principal: %d", ret);
+       make_you_lose_packet (KADM_NOMEM, reply);
+       return;
+    }
+
+    krb5_unparse_name(context, client, &client_str);
+
+    ret = kadm5_init_with_password_ctx(context, 
+                                      client_str, 
+                                      NULL,
+                                      KADM5_ADMIN_SERVICE,
+                                      NULL, 0, 0, 
+                                      &kadm_handle);
+    if (ret) {
+       krb5_warn (context, ret, "kadm5_init_with_password_ctx");
+       make_you_lose_packet (KADM_NOMEM, reply);
+       goto out;
+    }
+    
+    checksum = des_quad_cksum((void *)(msg + off), NULL, rlen, 0, &ad.session);
+    if(checksum != ad.checksum) {
+       krb5_warnx(context, "decode_packet: bad checksum");
+       make_you_lose_packet (KADM_BAD_CHK, reply);
+       goto out;
+    }
+    des_set_key(&ad.session, schedule);
+    ret = krb_rd_priv(msg + off, rlen, schedule, &ad.session, 
+                     client_addr, admin_addr, &msg_dat);
+    if (ret) {
+       make_you_lose_packet (ERROR_TABLE_BASE_krb + ret, reply);
+       krb5_warnx(context, "krb_rd_priv: %d", ret);
+       goto out;
+    }
+
+    {
+       krb5_data d, r;
+       int retval;
+
+       d.data   = msg_dat.app_data;
+       d.length = msg_dat.app_length;
+       
+       retval = dispatch(context, kadm_handle,
+                         client, client_str, d, &r);
+       krb5_data_alloc(reply, r.length + 26);
+       reply->length = krb_mk_priv(r.data, reply->data, r.length, 
+                                   schedule, &ad.session, 
+                                   admin_addr, client_addr);
+       if((ssize_t)reply->length < 0) {
+           make_you_lose_packet(KADM_NO_ENCRYPT, reply);
+           goto out;
+       }
+    }
+out:
+    krb5_free_principal(context, client);
+    free(client_str);
+}
+
+void
+handle_v4(krb5_context context,
+         krb5_keytab keytab,
+         int len,
+         int fd)
+{
+    int first = 1;
+    struct sockaddr_in admin_addr, client_addr;
+    socklen_t addr_len;
+    krb5_data message, reply;
+    ssize_t n;
+
+    addr_len = sizeof(client_addr);
+    if (getsockname(fd, (struct sockaddr*)&admin_addr, &addr_len) < 0)
+       krb5_errx (context, 1, "getsockname");
+    addr_len = sizeof(client_addr);
+    if (getpeername(fd, (struct sockaddr*)&client_addr, &addr_len) < 0)
+       krb5_errx (context, 1, "getpeername");
+
+    while(1) {
+       doing_useful_work = 0;
+       if(term_flag)
+           exit(0);
+       if(first) {
+           if (len < 2)
+               krb5_errx(context, 1, "received too short len (%d < 2)", len);
+           /* first time around, we have already read len, and two
+               bytes of the version string */
+           krb5_data_alloc(&message, len);
+           memcpy(message.data, "KA", 2);
+           n = krb5_net_read(context, &fd, (char*)message.data + 2,
+                             len - 2);
+           if (n == 0)
+               exit (0);
+           if (n < 0)
+               krb5_err (context, 1, errno, "krb5_net_read");
+           first = 0;
+       } else {
+           char buf[2];
+           unsigned long tmp;
+           ssize_t n;
+
+           n = krb5_net_read(context, &fd, buf, sizeof(2));
+           if (n == 0)
+               exit (0);
+           if (n < 0)
+               krb5_err (context, 1, errno, "krb5_net_read");
+           _krb5_get_int(buf, &tmp, 2);
+           krb5_data_alloc(&message, tmp);
+           n = krb5_net_read(context, &fd, message.data, message.length);
+           if (n == 0)
+               krb5_errx (context, 1, "EOF in krb5_net_read");
+           if (n < 0)
+               krb5_err (context, 1, errno, "krb5_net_read");
+       }
+       doing_useful_work = 1;
+       decode_packet(context, keytab, &admin_addr, &client_addr, 
+                     message, &reply);
+       krb5_data_free(&message);
+       {
+           char buf[2];
+
+           _krb5_put_int(buf, reply.length, sizeof(buf));
+           n = krb5_net_write(context, &fd, buf, sizeof(buf));
+           if (n < 0)
+               krb5_err (context, 1, errno, "krb5_net_write");
+           n = krb5_net_write(context, &fd, reply.data, reply.length);
+           if (n < 0)
+               krb5_err (context, 1, errno, "krb5_net_write");
+           krb5_data_free(&reply);
+       }
+    }
+}
diff --git a/src/kerberosV/src/kcm/CVS/Entries b/src/kerberosV/src/kcm/CVS/Entries
new file mode 100644 (file)
index 0000000..59cb346
--- /dev/null
@@ -0,0 +1,20 @@
+/Makefile.am/1.1.1.1/Fri Apr 14 07:32:39 2006//
+/Makefile.in/1.1.1.1/Fri Apr 14 07:32:39 2006//
+/acl.c/1.1.1.1/Fri Apr 14 07:32:39 2006//
+/acquire.c/1.1.1.1/Fri Apr 14 07:32:40 2006//
+/cache.c/1.1.1.1/Fri Apr 14 07:32:40 2006//
+/client.c/1.1.1.1/Fri Apr 14 07:32:40 2006//
+/config.c/1.1.1.1/Fri Apr 14 07:32:40 2006//
+/connect.c/1.4/Mon Mar 24 16:11:00 2008//
+/cursor.c/1.1.1.1/Fri Apr 14 07:32:40 2006//
+/events.c/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/glue.c/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/headers.h/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/kcm.8/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/kcm_locl.h/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/kcm_protos.h/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/log.c/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/main.c/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/protocol.c/1.1.1.1/Fri Apr 14 07:32:41 2006//
+/renew.c/1.1.1.1/Fri Apr 14 07:32:41 2006//
+D
diff --git a/src/kerberosV/src/kcm/CVS/Repository b/src/kerberosV/src/kcm/CVS/Repository
new file mode 100644 (file)
index 0000000..9514944
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/kcm
diff --git a/src/kerberosV/src/kcm/CVS/Root b/src/kerberosV/src/kcm/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/kcm/Makefile.am b/src/kerberosV/src/kcm/Makefile.am
new file mode 100644 (file)
index 0000000..7c21679
--- /dev/null
@@ -0,0 +1,44 @@
+# $KTH: Makefile.am,v 1.5 2005/05/29 14:51:50 lha Exp $
+
+include $(top_srcdir)/Makefile.am.common
+
+AM_CPPFLAGS += $(INCLUDE_krb4) $(INCLUDE_des) -I$(srcdir)/../lib/krb5
+
+libexec_PROGRAMS = kcm
+
+kcm_SOURCES =          \
+       acl.c           \
+       acquire.c       \
+       cache.c         \
+       client.c        \
+       config.c        \
+       connect.c       \
+       cursor.c        \
+       events.c        \
+       glue.c          \
+       headers.h       \
+       kcm_locl.h      \
+       kcm_protos.h    \
+       log.c           \
+       main.c          \
+       protocol.c      \
+       renew.c
+
+$(srcdir)/kcm_protos.h:
+       cd $(srcdir); perl ../cf/make-proto.pl -o kcm_protos.h -q -P comment $(kcm_SOURCES) || rm -f kcm_protos.h
+
+$(kcm_OBJECTS): $(srcdir)/kcm_protos.h
+
+man_MANS = kcm.8
+
+LDADD = $(top_builddir)/lib/hdb/libhdb.la \
+       $(LIB_openldap) \
+       $(top_builddir)/lib/krb5/libkrb5.la \
+       $(LIB_krb4) \
+       $(LIB_des) \
+       $(top_builddir)/lib/asn1/libasn1.la \
+       $(LIB_roken) \
+       $(LIB_door_create) \
+       $(LIB_pidfile)
+
+
diff --git a/src/kerberosV/src/kcm/Makefile.in b/src/kerberosV/src/kcm/Makefile.in
new file mode 100644 (file)
index 0000000..6a89957
--- /dev/null
@@ -0,0 +1,865 @@
+# Makefile.in generated by automake 1.8.3 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004  Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program 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.
+
+@SET_MAKE@
+
+# $KTH: Makefile.am,v 1.5 2005/05/29 14:51:50 lha Exp $
+
+# $KTH: Makefile.am.common,v 1.5 2002/05/19 18:35:37 joda Exp $
+
+# $KTH: Makefile.am.common,v 1.44 2005/05/29 14:43:42 lha Exp $
+
+SOURCES = $(kcm_SOURCES)
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
+       $(top_srcdir)/Makefile.am.common \
+       $(top_srcdir)/cf/Makefile.am.common
+libexec_PROGRAMS = kcm$(EXEEXT)
+subdir = kcm
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/cf/aix.m4 \
+       $(top_srcdir)/cf/auth-modules.m4 \
+       $(top_srcdir)/cf/broken-getaddrinfo.m4 \
+       $(top_srcdir)/cf/broken-getnameinfo.m4 \
+       $(top_srcdir)/cf/broken-glob.m4 \
+       $(top_srcdir)/cf/broken-realloc.m4 \
+       $(top_srcdir)/cf/broken-snprintf.m4 $(top_srcdir)/cf/broken.m4 \
+       $(top_srcdir)/cf/broken2.m4 $(top_srcdir)/cf/c-attribute.m4 \
+       $(top_srcdir)/cf/capabilities.m4 \
+       $(top_srcdir)/cf/check-compile-et.m4 \
+       $(top_srcdir)/cf/check-getpwnam_r-posix.m4 \
+       $(top_srcdir)/cf/check-man.m4 \
+       $(top_srcdir)/cf/check-netinet-ip-and-tcp.m4 \
+       $(top_srcdir)/cf/check-type-extra.m4 \
+       $(top_srcdir)/cf/check-var.m4 $(top_srcdir)/cf/check-x.m4 \
+       $(top_srcdir)/cf/check-xau.m4 $(top_srcdir)/cf/crypto.m4 \
+       $(top_srcdir)/cf/db.m4 $(top_srcdir)/cf/destdirs.m4 \
+       $(top_srcdir)/cf/dlopen.m4 \
+       $(top_srcdir)/cf/find-func-no-libs.m4 \
+       $(top_srcdir)/cf/find-func-no-libs2.m4 \
+       $(top_srcdir)/cf/find-func.m4 \
+       $(top_srcdir)/cf/find-if-not-broken.m4 \
+       $(top_srcdir)/cf/have-struct-field.m4 \
+       $(top_srcdir)/cf/have-type.m4 $(top_srcdir)/cf/irix.m4 \
+       $(top_srcdir)/cf/krb-bigendian.m4 \
+       $(top_srcdir)/cf/krb-func-getlogin.m4 \
+       $(top_srcdir)/cf/krb-ipv6.m4 $(top_srcdir)/cf/krb-prog-ln-s.m4 \
+       $(top_srcdir)/cf/krb-readline.m4 \
+       $(top_srcdir)/cf/krb-struct-spwd.m4 \
+       $(top_srcdir)/cf/krb-struct-winsize.m4 \
+       $(top_srcdir)/cf/largefile.m4 $(top_srcdir)/cf/mips-abi.m4 \
+       $(top_srcdir)/cf/misc.m4 $(top_srcdir)/cf/need-proto.m4 \
+       $(top_srcdir)/cf/osfc2.m4 $(top_srcdir)/cf/otp.m4 \
+       $(top_srcdir)/cf/proto-compat.m4 $(top_srcdir)/cf/pthreads.m4 \
+       $(top_srcdir)/cf/retsigtype.m4 $(top_srcdir)/cf/roken-frag.m4 \
+       $(top_srcdir)/cf/sunos.m4 $(top_srcdir)/cf/telnet.m4 \
+       $(top_srcdir)/cf/test-package.m4 $(top_srcdir)/cf/wflags.m4 \
+       $(top_srcdir)/cf/win32.m4 $(top_srcdir)/cf/with-all.m4 \
+       $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(mkdir_p)
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_FILES =
+am__installdirs = "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(man8dir)"
+libexecPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(libexec_PROGRAMS)
+am_kcm_OBJECTS = acl.$(OBJEXT) acquire.$(OBJEXT) cache.$(OBJEXT) \
+       client.$(OBJEXT) config.$(OBJEXT) connect.$(OBJEXT) \
+       cursor.$(OBJEXT) events.$(OBJEXT) glue.$(OBJEXT) log.$(OBJEXT) \
+       main.$(OBJEXT) protocol.$(OBJEXT) renew.$(OBJEXT)
+kcm_OBJECTS = $(am_kcm_OBJECTS)
+kcm_LDADD = $(LDADD)
+am__DEPENDENCIES_1 =
+kcm_DEPENDENCIES = $(top_builddir)/lib/hdb/libhdb.la \
+       $(am__DEPENDENCIES_1) $(top_builddir)/lib/krb5/libkrb5.la \
+       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
+       $(top_builddir)/lib/asn1/libasn1.la $(am__DEPENDENCIES_1) \
+       $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
+depcomp =
+am__depfiles_maybe =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) \
+       $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+       $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+       $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(kcm_SOURCES)
+DIST_SOURCES = $(kcm_SOURCES)
+man8dir = $(mandir)/man8
+MANS = $(man_MANS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AIX4_FALSE = @AIX4_FALSE@
+AIX4_TRUE = @AIX4_TRUE@
+AIX_DYNAMIC_AFS_FALSE = @AIX_DYNAMIC_AFS_FALSE@
+AIX_DYNAMIC_AFS_TRUE = @AIX_DYNAMIC_AFS_TRUE@
+AIX_EXTRA_KAFS = @AIX_EXTRA_KAFS@
+AIX_FALSE = @AIX_FALSE@
+AIX_TRUE = @AIX_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CANONICAL_HOST = @CANONICAL_HOST@
+CATMAN = @CATMAN@
+CATMANEXT = @CATMANEXT@
+CATMAN_FALSE = @CATMAN_FALSE@
+CATMAN_TRUE = @CATMAN_TRUE@
+CC = @CC@
+CFLAGS = @CFLAGS@
+COMPILE_ET = @COMPILE_ET@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DBLIB = @DBLIB@
+DCE_FALSE = @DCE_FALSE@
+DCE_TRUE = @DCE_TRUE@
+DEFS = @DEFS@
+DIR_com_err = @DIR_com_err@
+DIR_des = @DIR_des@
+DIR_roken = @DIR_roken@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_LIB45 = @EXTRA_LIB45@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GROFF = @GROFF@
+HAVE_DB1_FALSE = @HAVE_DB1_FALSE@
+HAVE_DB1_TRUE = @HAVE_DB1_TRUE@
+HAVE_DB3_FALSE = @HAVE_DB3_FALSE@
+HAVE_DB3_TRUE = @HAVE_DB3_TRUE@
+HAVE_DLOPEN_FALSE = @HAVE_DLOPEN_FALSE@
+HAVE_DLOPEN_TRUE = @HAVE_DLOPEN_TRUE@
+HAVE_NDBM_FALSE = @HAVE_NDBM_FALSE@
+HAVE_NDBM_TRUE = @HAVE_NDBM_TRUE@
+HAVE_OPENSSL_FALSE = @HAVE_OPENSSL_FALSE@
+HAVE_OPENSSL_TRUE = @HAVE_OPENSSL_TRUE@
+HAVE_X_FALSE = @HAVE_X_FALSE@
+HAVE_X_TRUE = @HAVE_X_TRUE@
+INCLUDES_roken = @INCLUDES_roken@
+INCLUDE_des = @INCLUDE_des@
+INCLUDE_hesiod = @INCLUDE_hesiod@
+INCLUDE_krb4 = @INCLUDE_krb4@
+INCLUDE_openldap = @INCLUDE_openldap@
+INCLUDE_readline = @INCLUDE_readline@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+IRIX_FALSE = @IRIX_FALSE@
+IRIX_TRUE = @IRIX_TRUE@
+KCM_FALSE = @KCM_FALSE@
+KCM_TRUE = @KCM_TRUE@
+KRB4_FALSE = @KRB4_FALSE@
+KRB4_TRUE = @KRB4_TRUE@
+KRB5_FALSE = @KRB5_FALSE@
+KRB5_TRUE = @KRB5_TRUE@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIB_AUTH_SUBDIRS = @LIB_AUTH_SUBDIRS@
+LIB_NDBM = @LIB_NDBM@
+LIB_XauFileName = @LIB_XauFileName@
+LIB_XauReadAuth = @LIB_XauReadAuth@
+LIB_XauWriteAuth = @LIB_XauWriteAuth@
+LIB_bswap16 = @LIB_bswap16@
+LIB_bswap32 = @LIB_bswap32@
+LIB_com_err = @LIB_com_err@
+LIB_com_err_a = @LIB_com_err_a@
+LIB_com_err_so = @LIB_com_err_so@
+LIB_crypt = @LIB_crypt@
+LIB_db_create = @LIB_db_create@
+LIB_dbm_firstkey = @LIB_dbm_firstkey@
+LIB_dbopen = @LIB_dbopen@
+LIB_des = @LIB_des@
+LIB_des_a = @LIB_des_a@
+LIB_des_appl = @LIB_des_appl@
+LIB_des_so = @LIB_des_so@
+LIB_dlopen = @LIB_dlopen@
+LIB_dn_expand = @LIB_dn_expand@
+LIB_door_create = @LIB_door_create@
+LIB_el_init = @LIB_el_init@
+LIB_freeaddrinfo = @LIB_freeaddrinfo@
+LIB_gai_strerror = @LIB_gai_strerror@
+LIB_getaddrinfo = @LIB_getaddrinfo@
+LIB_gethostbyname = @LIB_gethostbyname@
+LIB_gethostbyname2 = @LIB_gethostbyname2@
+LIB_getnameinfo = @LIB_getnameinfo@
+LIB_getpwnam_r = @LIB_getpwnam_r@
+LIB_getsockopt = @LIB_getsockopt@
+LIB_hesiod = @LIB_hesiod@
+LIB_hstrerror = @LIB_hstrerror@
+LIB_kdb = @LIB_kdb@
+LIB_krb4 = @LIB_krb4@
+LIB_krb_disable_debug = @LIB_krb_disable_debug@
+LIB_krb_enable_debug = @LIB_krb_enable_debug@
+LIB_krb_get_kdc_time_diff = @LIB_krb_get_kdc_time_diff@
+LIB_krb_get_our_ip_for_realm = @LIB_krb_get_our_ip_for_realm@
+LIB_krb_kdctimeofday = @LIB_krb_kdctimeofday@
+LIB_loadquery = @LIB_loadquery@
+LIB_logout = @LIB_logout@
+LIB_logwtmp = @LIB_logwtmp@
+LIB_openldap = @LIB_openldap@
+LIB_openpty = @LIB_openpty@
+LIB_otp = @LIB_otp@
+LIB_pidfile = @LIB_pidfile@
+LIB_readline = @LIB_readline@
+LIB_res_nsearch = @LIB_res_nsearch@
+LIB_res_search = @LIB_res_search@
+LIB_roken = @LIB_roken@
+LIB_security = @LIB_security@
+LIB_setsockopt = @LIB_setsockopt@
+LIB_socket = @LIB_socket@
+LIB_syslog = @LIB_syslog@
+LIB_tgetent = @LIB_tgetent@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+NEED_WRITEAUTH_FALSE = @NEED_WRITEAUTH_FALSE@
+NEED_WRITEAUTH_TRUE = @NEED_WRITEAUTH_TRUE@
+NROFF = @NROFF@
+OBJEXT = @OBJEXT@
+OPENLDAP_MODULE_FALSE = @OPENLDAP_MODULE_FALSE@
+OPENLDAP_MODULE_TRUE = @OPENLDAP_MODULE_TRUE@
+OTP_FALSE = @OTP_FALSE@
+OTP_TRUE = @OTP_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PTHREADS_CFLAGS = @PTHREADS_CFLAGS@
+PTHREADS_LIBS = @PTHREADS_LIBS@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+VOID_RETSIGTYPE = @VOID_RETSIGTYPE@
+WFLAGS = @WFLAGS@
+WFLAGS_NOIMPLICITINT = @WFLAGS_NOIMPLICITINT@
+WFLAGS_NOUNUSED = @WFLAGS_NOUNUSED@
+X_CFLAGS = @X_CFLAGS@
+X_EXTRA_LIBS = @X_EXTRA_LIBS@
+X_LIBS = @X_LIBS@
+X_PRE_LIBS = @X_PRE_LIBS@
+YACC = @YACC@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__leading_dot = @am__leading_dot@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+do_roken_rename_FALSE = @do_roken_rename_FALSE@
+do_roken_rename_TRUE = @do_roken_rename_TRUE@
+dpagaix_cflags = @dpagaix_cflags@
+dpagaix_ldadd = @dpagaix_ldadd@
+dpagaix_ldflags = @dpagaix_ldflags@
+el_compat_FALSE = @el_compat_FALSE@
+el_compat_TRUE = @el_compat_TRUE@
+exec_prefix = @exec_prefix@
+have_cgetent_FALSE = @have_cgetent_FALSE@
+have_cgetent_TRUE = @have_cgetent_TRUE@
+have_err_h_FALSE = @have_err_h_FALSE@
+have_err_h_TRUE = @have_err_h_TRUE@
+have_fnmatch_h_FALSE = @have_fnmatch_h_FALSE@
+have_fnmatch_h_TRUE = @have_fnmatch_h_TRUE@
+have_glob_h_FALSE = @have_glob_h_FALSE@
+have_glob_h_TRUE = @have_glob_h_TRUE@
+have_ifaddrs_h_FALSE = @have_ifaddrs_h_FALSE@
+have_ifaddrs_h_TRUE = @have_ifaddrs_h_TRUE@
+have_vis_h_FALSE = @have_vis_h_FALSE@
+have_vis_h_TRUE = @have_vis_h_TRUE@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+SUFFIXES = .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8
+AM_CPPFLAGS = -I$(top_builddir)/include $(INCLUDES_roken) $(INCLUDE_krb4) $(INCLUDE_des) -I$(srcdir)/../lib/krb5
+@do_roken_rename_TRUE@ROKEN_RENAME = -DROKEN_RENAME
+AM_CFLAGS = $(WFLAGS)
+CP = cp
+buildinclude = $(top_builddir)/include
+LIB_getattr = @LIB_getattr@
+LIB_getpwent_r = @LIB_getpwent_r@
+LIB_odm_initialize = @LIB_odm_initialize@
+LIB_setpcred = @LIB_setpcred@
+HESIODLIB = @HESIODLIB@
+HESIODINCLUDE = @HESIODINCLUDE@
+NROFF_MAN = groff -mandoc -Tascii
+LIB_kafs = $(top_builddir)/lib/kafs/libkafs.la $(AIX_EXTRA_KAFS)
+@KRB5_TRUE@LIB_krb5 = $(top_builddir)/lib/krb5/libkrb5.la \
+@KRB5_TRUE@    $(top_builddir)/lib/asn1/libasn1.la
+
+@KRB5_TRUE@LIB_gssapi = $(top_builddir)/lib/gssapi/libgssapi.la
+@KRB5_TRUE@LIB_tsasl = $(top_builddir)/lib/tsasl/libtsasl.la
+@DCE_TRUE@LIB_kdfs = $(top_builddir)/lib/kdfs/libkdfs.la
+kcm_SOURCES = \
+       acl.c           \
+       acquire.c       \
+       cache.c         \
+       client.c        \
+       config.c        \
+       connect.c       \
+       cursor.c        \
+       events.c        \
+       glue.c          \
+       headers.h       \
+       kcm_locl.h      \
+       kcm_protos.h    \
+       log.c           \
+       main.c          \
+       protocol.c      \
+       renew.c
+
+man_MANS = kcm.8
+LDADD = $(top_builddir)/lib/hdb/libhdb.la \
+       $(LIB_openldap) \
+       $(top_builddir)/lib/krb5/libkrb5.la \
+       $(LIB_krb4) \
+       $(LIB_des) \
+       $(top_builddir)/lib/asn1/libasn1.la \
+       $(LIB_roken) \
+       $(LIB_door_create) \
+       $(LIB_pidfile)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .et .h .x .1 .3 .5 .8 .cat1 .cat3 .cat5 .cat8 .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(top_srcdir)/Makefile.am.common $(top_srcdir)/cf/Makefile.am.common $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign  --ignore-deps kcm/Makefile'; \
+       cd $(top_srcdir) && \
+         $(AUTOMAKE) --foreign  --ignore-deps kcm/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-libexecPROGRAMS: $(libexec_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(libexecdir)" || $(mkdir_p) "$(DESTDIR)$(libexecdir)"
+       @list='$(libexec_PROGRAMS)'; for p in $$list; do \
+         p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         if test -f $$p \
+            || test -f $$p1 \
+         ; then \
+           f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+          echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(libexecPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(libexecdir)/$$f'"; \
+          $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(libexecPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(libexecdir)/$$f" || exit 1; \
+         else :; fi; \
+       done
+
+uninstall-libexecPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(libexec_PROGRAMS)'; for p in $$list; do \
+         f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+         echo " rm -f '$(DESTDIR)$(libexecdir)/$$f'"; \
+         rm -f "$(DESTDIR)$(libexecdir)/$$f"; \
+       done
+
+clean-libexecPROGRAMS:
+       @list='$(libexec_PROGRAMS)'; for p in $$list; do \
+         f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+         echo " rm -f $$p $$f"; \
+         rm -f $$p $$f ; \
+       done
+kcm$(EXEEXT): $(kcm_OBJECTS) $(kcm_DEPENDENCIES) 
+       @rm -f kcm$(EXEEXT)
+       $(LINK) $(kcm_LDFLAGS) $(kcm_OBJECTS) $(kcm_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+.c.o:
+       $(COMPILE) -c $<
+
+.c.obj:
+       $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+       $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+       -rm -f *.lo
+
+clean-libtool:
+       -rm -rf .libs _libs
+
+distclean-libtool:
+       -rm -f libtool
+uninstall-info-am:
+install-man8: $(man8_MANS) $(man_MANS)
+       @$(NORMAL_INSTALL)
+       test -z "$(man8dir)" || $(mkdir_p) "$(DESTDIR)$(man8dir)"
+       @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+       l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+       for i in $$l2; do \
+         case "$$i" in \
+           *.8*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \
+         else file=$$i; fi; \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         case "$$ext" in \
+           8*) ;; \
+           *) ext='8' ;; \
+         esac; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed -e 's/^.*\///'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \
+         $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst"; \
+       done
+uninstall-man8:
+       @$(NORMAL_UNINSTALL)
+       @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \
+       l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \
+       for i in $$l2; do \
+         case "$$i" in \
+           *.8*) list="$$list $$i" ;; \
+         esac; \
+       done; \
+       for i in $$list; do \
+         ext=`echo $$i | sed -e 's/^.*\\.//'`; \
+         case "$$ext" in \
+           8*) ;; \
+           *) ext='8' ;; \
+         esac; \
+         inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \
+         inst=`echo $$inst | sed -e 's/^.*\///'`; \
+         inst=`echo $$inst | sed '$(transform)'`.$$ext; \
+         echo " rm -f '$(DESTDIR)$(man8dir)/$$inst'"; \
+         rm -f "$(DESTDIR)$(man8dir)/$$inst"; \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(ETAGS_ARGS)$$tags$$unique" \
+         || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+            $$tags $$unique
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       tags=; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '    { files[$$0] = 1; } \
+              END { for (i in files) print i; }'`; \
+       test -z "$(CTAGS_ARGS)$$tags$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$tags $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && cd $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(mkdir_p) $(distdir)/.. $(distdir)/../cf
+       @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+       list='$(DISTFILES)'; for file in $$list; do \
+         case $$file in \
+           $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+           $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+         esac; \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+         if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+           dir="/$$dir"; \
+           $(mkdir_p) "$(distdir)$$dir"; \
+         else \
+           dir=''; \
+         fi; \
+         if test -d $$d/$$file; then \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+           fi; \
+           cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+         else \
+           test -f $(distdir)/$$file \
+           || cp -p $$d/$$file $(distdir)/$$file \
+           || exit 1; \
+         fi; \
+       done
+       $(MAKE) $(AM_MAKEFLAGS) \
+         top_distdir="$(top_distdir)" distdir="$(distdir)" \
+         dist-hook
+check-am: all-am
+       $(MAKE) $(AM_MAKEFLAGS) check-local
+check: check-am
+all-am: Makefile $(PROGRAMS) $(MANS) all-local
+installdirs:
+       for dir in "$(DESTDIR)$(libexecdir)" "$(DESTDIR)$(man8dir)"; do \
+         test -z "$$dir" || $(mkdir_p) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libexecPROGRAMS clean-libtool \
+       mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am: install-man
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+
+install-exec-am: install-libexecPROGRAMS
+       @$(NORMAL_INSTALL)
+       $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+
+install-info: install-info-am
+
+install-man: install-man8
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libexecPROGRAMS \
+       uninstall-man
+
+uninstall-man: uninstall-man8
+
+.PHONY: CTAGS GTAGS all all-am all-local check check-am check-local \
+       clean clean-generic clean-libexecPROGRAMS clean-libtool ctags \
+       distclean distclean-compile distclean-generic \
+       distclean-libtool distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-exec install-exec-am install-info \
+       install-info-am install-libexecPROGRAMS install-man \
+       install-man8 install-strip installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-compile mostlyclean-generic \
+       mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
+       uninstall-am uninstall-info-am uninstall-libexecPROGRAMS \
+       uninstall-man uninstall-man8
+
+
+install-suid-programs:
+       @foo='$(bin_SUIDS)'; \
+       for file in $$foo; do \
+       x=$(DESTDIR)$(bindir)/$$file; \
+       if chown 0:0 $$x && chmod u+s $$x; then :; else \
+       echo "*"; \
+       echo "* Failed to install $$x setuid root"; \
+       echo "*"; \
+       fi; done
+
+install-exec-hook: install-suid-programs
+
+install-build-headers:: $(include_HEADERS) $(build_HEADERZ)
+       @foo='$(include_HEADERS) $(nodist_include_HEADERS) $(build_HEADERZ)'; \
+       for f in $$foo; do \
+               f=`basename $$f`; \
+               if test -f "$(srcdir)/$$f"; then file="$(srcdir)/$$f"; \
+               else file="$$f"; fi; \
+               if cmp -s  $$file $(buildinclude)/$$f 2> /dev/null ; then \
+               : ; else \
+                       echo " $(CP) $$file $(buildinclude)/$$f"; \
+                       $(CP) $$file $(buildinclude)/$$f; \
+               fi ; \
+       done
+
+all-local: install-build-headers
+
+check-local::
+       @if test '$(CHECK_LOCAL)' = "no-check-local"; then \
+         foo=''; elif test '$(CHECK_LOCAL)'; then \
+         foo='$(CHECK_LOCAL)'; else \
+         foo='$(PROGRAMS)'; fi; \
+         if test "$$foo"; then \
+         failed=0; all=0; \
+         for i in $$foo; do \
+           all=`expr $$all + 1`; \
+           if ./$$i --version > /dev/null 2>&1; then \
+             echo "PASS: $$i"; \
+           else \
+             echo "FAIL: $$i"; \
+             failed=`expr $$failed + 1`; \
+           fi; \
+         done; \
+         if test "$$failed" -eq 0; then \
+           banner="All $$all tests passed"; \
+         else \
+           banner="$$failed of $$all tests failed"; \
+         fi; \
+         dashes=`echo "$$banner" | sed s/./=/g`; \
+         echo "$$dashes"; \
+         echo "$$banner"; \
+         echo "$$dashes"; \
+         test "$$failed" -eq 0; \
+       fi ; \
+       if test '$(CHECK_SYMBOLS)' != ""; then \
+         echo "$$dashes"; \
+         echo "Checking symbols"; \
+         sh $(top_srcdir)/cf/check-symbols.sh $(CHECK_SYMBOLS) || exit 1; \
+         echo "Passed"; \
+         echo "$$dashes"; \
+       fi
+
+.x.c:
+       @cmp -s $< $@ 2> /dev/null || cp $< $@
+#NROFF_MAN = nroff -man
+.1.cat1:
+       $(NROFF_MAN) $< > $@
+.3.cat3:
+       $(NROFF_MAN) $< > $@
+.5.cat5:
+       $(NROFF_MAN) $< > $@
+.8.cat8:
+       $(NROFF_MAN) $< > $@
+
+dist-cat1-mans:
+       @foo='$(man1_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.1) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat1/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-cat3-mans:
+       @foo='$(man3_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.3) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat3/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-cat5-mans:
+       @foo='$(man5_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.5) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat5/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-cat8-mans:
+       @foo='$(man8_MANS)'; \
+       bar='$(man_MANS)'; \
+       for i in $$bar; do \
+       case $$i in \
+       *.8) foo="$$foo $$i";; \
+       esac; done ;\
+       for i in $$foo; do \
+               x=`echo $$i | sed 's/\.[^.]*$$/.cat8/'`; \
+               echo "$(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x"; \
+               $(NROFF_MAN) $(srcdir)/$$i > $(distdir)/$$x; \
+       done
+
+dist-hook: dist-cat1-mans dist-cat3-mans dist-cat5-mans dist-cat8-mans
+
+install-cat-mans:
+       $(SHELL) $(top_srcdir)/cf/install-catman.sh "$(INSTALL_DATA)" "$(mkinstalldirs)" "$(srcdir)" "$(DESTDIR)$(mandir)" '$(CATMANEXT)' $(man_MANS) $(man1_MANS) $(man3_MANS) $(man5_MANS) $(man8_MANS)
+
+install-data-hook: install-cat-mans
+
+.et.h:
+       $(COMPILE_ET) $<
+.et.c:
+       $(COMPILE_ET) $<
+
+$(srcdir)/kcm_protos.h:
+       cd $(srcdir); perl ../cf/make-proto.pl -o kcm_protos.h -q -P comment $(kcm_SOURCES) || rm -f kcm_protos.h
+
+$(kcm_OBJECTS): $(srcdir)/kcm_protos.h
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/kerberosV/src/kcm/acl.c b/src/kerberosV/src/kcm/acl.c
new file mode 100644 (file)
index 0000000..70b1422
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: acl.c,v 1.4 2005/02/06 01:22:48 lukeh Exp $");
+
+krb5_error_code
+kcm_access(krb5_context context,
+          kcm_client *client,
+          kcm_operation opcode,
+          kcm_ccache ccache)
+{
+    int read_p = 0;
+    int write_p = 0;
+    u_int16_t mask;
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+
+    switch (opcode) {
+    case KCM_OP_INITIALIZE:
+    case KCM_OP_DESTROY:
+    case KCM_OP_STORE:
+    case KCM_OP_REMOVE_CRED:
+    case KCM_OP_SET_FLAGS:
+    case KCM_OP_CHOWN:
+    case KCM_OP_CHMOD:
+    case KCM_OP_GET_INITIAL_TICKET:
+    case KCM_OP_GET_TICKET:
+       write_p = 1;
+       read_p = 0;
+       break;
+    case KCM_OP_NOOP:
+    case KCM_OP_GET_NAME:
+    case KCM_OP_RESOLVE:
+    case KCM_OP_GEN_NEW:
+    case KCM_OP_RETRIEVE:
+    case KCM_OP_GET_PRINCIPAL:
+    case KCM_OP_GET_FIRST:
+    case KCM_OP_GET_NEXT:
+    case KCM_OP_END_GET:
+    case KCM_OP_MAX:
+       write_p = 0;
+       read_p = 1;
+       break;
+    }
+
+    if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) {
+       /* System caches cannot be reinitialized or destroyed by users */
+       if (opcode == KCM_OP_INITIALIZE ||
+           opcode == KCM_OP_DESTROY ||
+           opcode == KCM_OP_REMOVE_CRED) {
+           ret = KRB5_FCC_PERM;
+           goto out;
+       }
+
+       /* Let root always read system caches */
+       if (client->uid == 0) {
+           ret = 0;
+           goto out;
+       }
+    }
+
+    mask = 0;
+
+    if (client->uid == ccache->uid) {
+       if (read_p)
+           mask |= S_IRUSR;
+       if (write_p)
+           mask |= S_IWUSR;
+    } else if (client->gid == ccache->gid) {
+       if (read_p)
+           mask |= S_IRGRP;
+       if (write_p)
+           mask |= S_IWGRP;
+    } else {
+       if (read_p)
+           mask |= S_IROTH;
+       if (write_p)
+           mask |= S_IWOTH;
+    }
+
+    ret = ((ccache->mode & mask) == mask) ? 0 : KRB5_FCC_PERM;
+
+out:
+    if (ret) {
+       kcm_log(2, "Process %d is not permitted to call %s on cache %s",
+               client->pid, kcm_op2string(opcode), ccache->name);
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_chmod(krb5_context context,
+         kcm_client *client,
+         kcm_ccache ccache,
+         u_int16_t mode)
+{
+    KCM_ASSERT_VALID(ccache);
+
+    /* System cache mode can only be set at startup */
+    if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM)
+       return KRB5_FCC_PERM;
+
+    if (ccache->uid != client->uid)
+       return KRB5_FCC_PERM;
+
+    if (ccache->gid != client->gid)
+       return KRB5_FCC_PERM;
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    ccache->mode = mode;
+
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return 0;
+}
+
+krb5_error_code
+kcm_chown(krb5_context context,
+         kcm_client *client,
+         kcm_ccache ccache,
+         uid_t uid,
+         gid_t gid)
+{
+    KCM_ASSERT_VALID(ccache);
+
+    /* System cache owner can only be set at startup */
+    if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM)
+       return KRB5_FCC_PERM;
+
+    if (ccache->uid != client->uid)
+       return KRB5_FCC_PERM;
+
+    if (ccache->gid != client->gid)
+       return KRB5_FCC_PERM;
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    ccache->uid = uid;
+    ccache->gid = gid;
+
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kcm/acquire.c b/src/kerberosV/src/kcm/acquire.c
new file mode 100644 (file)
index 0000000..58f26a4
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: acquire.c,v 1.5 2005/05/29 16:29:58 lha Exp $");
+
+static krb5_error_code
+change_pw_and_update_keytab(krb5_context context, kcm_ccache ccache);
+
+/*
+ * Get a new ticket using a keytab/cached key and swap it into
+ * an existing redentials cache
+ */
+
+krb5_error_code
+kcm_ccache_acquire(krb5_context context,
+                  kcm_ccache ccache,
+                  krb5_creds **credp)
+{
+    krb5_error_code ret = 0;
+    krb5_creds cred;
+    krb5_const_realm realm;
+    krb5_get_init_creds_opt opt;
+    krb5_ccache_data ccdata;
+    char *in_tkt_service = NULL;
+    int done = 0;
+
+    memset(&cred, 0, sizeof(cred));
+
+    KCM_ASSERT_VALID(ccache);
+
+    /* We need a cached key or keytab to acquire credentials */
+    if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) {
+       if (ccache->key.keyblock.keyvalue.length == 0)
+           krb5_abortx(context,
+                       "kcm_ccache_acquire: KCM_FLAGS_USE_CACHED_KEY without key");
+    } else if (ccache->flags & KCM_FLAGS_USE_KEYTAB) {
+       if (ccache->key.keytab == NULL)
+           krb5_abortx(context,
+                       "kcm_ccache_acquire: KCM_FLAGS_USE_KEYTAB without keytab");
+    } else {
+       kcm_log(0, "Cannot acquire initial credentials for cache %s without key",
+               ccache->name);
+       return KRB5_FCC_INTERNAL;
+    }
+       
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    /* Fake up an internal ccache */
+    kcm_internal_ccache(context, ccache, &ccdata);
+
+    /* Now, actually acquire the creds */
+    if (ccache->server != NULL) {
+       ret = krb5_unparse_name(context, ccache->server, &in_tkt_service);
+       if (ret) {
+           kcm_log(0, "Failed to unparse service principal name for cache %s: %s",
+                   ccache->name, krb5_get_err_text(context, ret));
+           return ret;
+       }
+    }
+
+    realm = krb5_principal_get_realm(context, ccache->client);
+
+    krb5_get_init_creds_opt_init(&opt);
+    krb5_get_init_creds_opt_set_default_flags(context, "kcm", realm, &opt);
+    if (ccache->tkt_life != 0)
+       krb5_get_init_creds_opt_set_tkt_life(&opt, ccache->tkt_life);
+    if (ccache->renew_life != 0)
+       krb5_get_init_creds_opt_set_renew_life(&opt, ccache->renew_life);
+
+    if (ccache->flags & KCM_FLAGS_USE_CACHED_KEY) {
+       ret = krb5_get_init_creds_keyblock(context,
+                                          &cred,
+                                          ccache->client,
+                                          &ccache->key.keyblock,
+                                          0,
+                                          in_tkt_service,
+                                          &opt);
+    } else {
+       /* loosely based on lib/krb5/init_creds_pw.c */
+       while (!done) {
+           ret = krb5_get_init_creds_keytab(context,
+                                            &cred,
+                                            ccache->client,
+                                            ccache->key.keytab,
+                                            0,
+                                            in_tkt_service,
+                                            &opt);
+           switch (ret) {
+           case KRB5KDC_ERR_KEY_EXPIRED:
+               if (in_tkt_service != NULL &&
+                   strcmp(in_tkt_service, "kadmin/changepw") == 0) {
+                   goto out;
+               }
+
+               ret = change_pw_and_update_keytab(context, ccache);
+               if (ret)
+                   goto out;
+               break;
+           case 0:
+           default:
+               done = 1;
+               break;
+           }
+       }
+    }
+
+    if (ret) {
+       kcm_log(0, "Failed to acquire credentials for cache %s: %s",
+               ccache->name, krb5_get_err_text(context, ret));
+       if (in_tkt_service != NULL)
+           free(in_tkt_service);
+       goto out;
+    }
+
+    if (in_tkt_service != NULL)
+       free(in_tkt_service);
+
+    /* Swap them in */
+    kcm_ccache_remove_creds_internal(context, ccache);
+
+    ret = kcm_ccache_store_cred_internal(context, ccache, &cred, 0, credp);
+    if (ret) {
+       kcm_log(0, "Failed to store credentials for cache %s: %s",
+               ccache->name, krb5_get_err_text(context, ret));
+       krb5_free_creds_contents(context, &cred);
+       goto out;
+    }
+
+out:
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
+static krb5_error_code
+change_pw(krb5_context context,
+         kcm_ccache ccache,
+         char *cpn,
+         char *newpw)
+{
+    krb5_error_code ret;
+    krb5_creds cpw_cred;
+    int result_code;
+    krb5_data result_code_string;
+    krb5_data result_string;
+    krb5_get_init_creds_opt options;
+
+    memset(&cpw_cred, 0, sizeof(cpw_cred));
+
+    krb5_get_init_creds_opt_init(&options);
+    krb5_get_init_creds_opt_set_tkt_life(&options, 60);
+    krb5_get_init_creds_opt_set_forwardable(&options, FALSE);
+    krb5_get_init_creds_opt_set_proxiable(&options, FALSE);
+
+    krb5_data_zero(&result_code_string);
+    krb5_data_zero(&result_string);
+
+    ret = krb5_get_init_creds_keytab(context,
+                                    &cpw_cred,
+                                    ccache->client,
+                                    ccache->key.keytab,
+                                    0,
+                                    "kadmin/changepw",
+                                    &options);
+    if (ret) {
+       kcm_log(0, "Failed to acquire password change credentials "
+               "for principal %s: %s", 
+               cpn, krb5_get_err_text(context, ret));
+       goto out;
+    }
+
+    ret = krb5_change_password(context,
+                              &cpw_cred,
+                              newpw,
+                              &result_code,
+                              &result_code_string,
+                              &result_string);
+    if (ret) {
+       kcm_log(0, "Failed to change password for principal %s: %s",
+               cpn, krb5_get_err_text(context, ret));
+       goto out;
+    }
+
+    if (result_code) {
+       kcm_log(0, "Failed to change password for principal %s: %.*s",
+               cpn,
+               (int)result_string.length,
+               result_string.length > 0 ? (char *)result_string.data : "");
+       goto out;
+    }
+
+out:
+    krb5_data_free(&result_string);
+    krb5_data_free(&result_code_string);
+    krb5_free_cred_contents(context, &cpw_cred);
+
+    return ret;
+}
+
+struct kcm_keyseed_data {
+    krb5_salt salt;
+    const char *password;
+};
+
+static krb5_error_code
+kcm_password_key_proc(krb5_context context,
+                     krb5_enctype etype,
+                     krb5_salt salt,
+                     krb5_const_pointer keyseed,
+                     krb5_keyblock **key)
+{
+    krb5_error_code ret;
+    struct kcm_keyseed_data *s = (struct kcm_keyseed_data *)keyseed;
+
+    /* we may be called multiple times */
+    krb5_free_salt(context, s->salt);
+    krb5_data_zero(&s->salt.saltvalue);
+
+    /* stash the salt */
+    s->salt.salttype = salt.salttype;
+
+    ret = krb5_data_copy(&s->salt.saltvalue,
+                        salt.saltvalue.data,
+                        salt.saltvalue.length);
+    if (ret)
+       return ret;
+
+    *key = (krb5_keyblock *)malloc(sizeof(**key));
+    if (*key == NULL) {
+       return ENOMEM;
+    }
+
+    ret = krb5_string_to_key_salt(context, etype, s->password,
+                                 s->salt, *key);
+    if (ret) {
+       free(*key);
+       *key = NULL;
+    }
+
+    return ret;
+}
+
+static krb5_error_code
+get_salt_and_kvno(krb5_context context,
+                 kcm_ccache ccache,
+                 krb5_enctype *etypes,
+                 char *cpn,
+                 char *newpw,
+                 krb5_salt *salt,
+                 unsigned *kvno)
+{
+    krb5_error_code ret;
+    krb5_creds creds;
+    krb5_ccache_data ccdata;
+    krb5_flags options = 0;
+    krb5_kdc_rep reply;
+    struct kcm_keyseed_data s;
+
+    memset(&creds, 0, sizeof(creds));
+    memset(&reply, 0, sizeof(reply));
+
+    s.password = NULL;
+    s.salt.salttype = (int)ETYPE_NULL;
+    krb5_data_zero(&s.salt.saltvalue);
+
+    *kvno = 0;
+    kcm_internal_ccache(context, ccache, &ccdata);
+    s.password = newpw;
+
+    /* Do an AS-REQ to determine salt and key version number */
+    ret = krb5_copy_principal(context, ccache->client, &creds.client);
+    if (ret)
+       return ret;
+
+    /* Yes, get a ticket to ourselves */
+    ret = krb5_copy_principal(context, ccache->client, &creds.server);
+    if (ret) {
+       krb5_free_principal(context, creds.client);
+       return ret;
+    }
+       
+    ret = krb5_get_in_tkt(context,
+                         options,
+                         NULL,
+                         etypes,
+                         NULL,
+                         kcm_password_key_proc,
+                         &s,
+                         NULL,
+                         NULL,
+                         &creds,
+                         &ccdata,
+                         &reply);
+    if (ret) {
+       kcm_log(0, "Failed to get self ticket for principal %s: %s",
+               cpn, krb5_get_err_text(context, ret));
+       krb5_free_salt(context, s.salt);
+    } else {
+       *salt = s.salt; /* retrieve stashed salt */
+       if (reply.kdc_rep.enc_part.kvno != NULL)
+           *kvno = *(reply.kdc_rep.enc_part.kvno);
+    }
+    /* ccache may have been modified but it will get trashed anyway */
+
+    krb5_free_creds_contents(context, &creds);
+    krb5_free_kdc_rep(context, &reply);
+
+    return ret;
+}
+
+static krb5_error_code
+update_keytab_entry(krb5_context context,
+                   kcm_ccache ccache,
+                   krb5_enctype etype,
+                   char *cpn,
+                   char *spn,
+                   char *newpw,
+                   krb5_salt salt,
+                   unsigned kvno)
+{
+    krb5_error_code ret;
+    krb5_keytab_entry entry;
+    krb5_data pw;
+
+    memset(&entry, 0, sizeof(entry));
+
+    pw.data = (char *)newpw;
+    pw.length = strlen(newpw);
+
+    ret = krb5_string_to_key_data_salt(context, etype, pw,
+                                      salt, &entry.keyblock);
+    if (ret) {
+       kcm_log(0, "String to key conversion failed for principal %s "
+               "and etype %d: %s",
+               cpn, etype, krb5_get_err_text(context, ret)); 
+       return ret;
+    }
+
+    if (spn == NULL) {
+       ret = krb5_copy_principal(context, ccache->client,
+                                 &entry.principal);
+       if (ret) {
+           kcm_log(0, "Failed to copy principal name %s: %s",
+                   cpn, krb5_get_err_text(context, ret));
+           return ret;
+       }
+    } else {
+       ret = krb5_parse_name(context, spn, &entry.principal);
+       if (ret) {
+           kcm_log(0, "Failed to parse SPN alias %s: %s",
+                   spn, krb5_get_err_text(context, ret));
+           return ret;
+       }
+    }
+
+    entry.vno = kvno;
+    entry.timestamp = time(NULL);
+
+    ret = krb5_kt_add_entry(context, ccache->key.keytab, &entry);
+    if (ret) {
+       kcm_log(0, "Failed to update keytab for principal %s "
+               "and etype %d: %s",
+               cpn, etype, krb5_get_err_text(context, ret));
+    }
+
+    krb5_kt_free_entry(context, &entry);
+
+    return ret; 
+}
+
+static krb5_error_code
+update_keytab_entries(krb5_context context,
+                     kcm_ccache ccache,
+                     krb5_enctype *etypes,
+                     char *cpn,
+                     char *spn,
+                     char *newpw,
+                     krb5_salt salt,
+                     unsigned kvno)
+{
+    krb5_error_code ret = 0;
+    int i;
+
+    for (i = 0; etypes[i] != ETYPE_NULL; i++) {
+       ret = update_keytab_entry(context, ccache, etypes[i],
+                                 cpn, spn, newpw, salt, kvno);
+       if (ret)
+           break;
+    }
+
+    return ret;
+}
+
+static void
+generate_random_pw(krb5_context context,
+                  char *buf,
+                  size_t bufsiz)
+{
+    unsigned char x[512], *p;
+    size_t i;
+
+    memset(x, 0, sizeof(x));
+    krb5_generate_random_block(x, sizeof(x));
+    p = x;
+
+    for (i = 0; i < bufsiz; i++) {
+       while (isprint(*p) == 0)
+           p++;
+
+       if (p - x >= sizeof(x)) {
+           krb5_generate_random_block(x, sizeof(x));
+           p = x;
+       }
+       buf[i] = (char)*p++;
+    }
+    buf[bufsiz - 1] = '\0';
+    memset(x, 0, sizeof(x));
+}
+
+static krb5_error_code
+change_pw_and_update_keytab(krb5_context context,
+                           kcm_ccache ccache)
+{
+    char newpw[121];
+    krb5_error_code ret;
+    unsigned kvno;
+    krb5_salt salt;
+    krb5_enctype *etypes = NULL;
+    int i;
+    char *cpn = NULL;
+    char **spns = NULL;
+
+    krb5_data_zero(&salt.saltvalue);
+
+    ret = krb5_unparse_name(context, ccache->client, &cpn);
+    if (ret) {
+       kcm_log(0, "Failed to unparse name: %s",
+               krb5_get_err_text(context, ret));
+       goto out;
+    }
+
+    ret = krb5_get_default_in_tkt_etypes(context, &etypes);
+    if (ret) {
+       kcm_log(0, "Failed to determine default encryption types: %s",
+               krb5_get_err_text(context, ret));
+       goto out;
+    }
+
+    /* Generate a random password (there is no set keys protocol) */
+    generate_random_pw(context, newpw, sizeof(newpw));
+
+    /* Change it */
+    ret = change_pw(context, ccache, cpn, newpw);
+    if (ret)
+       goto out;
+
+    /* Do an AS-REQ to determine salt and key version number */
+    ret = get_salt_and_kvno(context, ccache, etypes, cpn, newpw,
+                           &salt, &kvno);
+    if (ret) {
+       kcm_log(0, "Failed to determine salting principal for principal %s: %s",
+               cpn, krb5_get_err_text(context, ret));
+       goto out;
+    }
+
+    /* Add canonical name */
+    ret = update_keytab_entries(context, ccache, etypes, cpn,
+                               NULL, newpw, salt, kvno);
+    if (ret)
+       goto out;
+
+    /* Add SPN aliases, if any */
+    spns = krb5_config_get_strings(context, NULL, "kcm",
+                                  "system_ccache", "spn_aliases", NULL);
+    if (spns != NULL) {
+       for (i = 0; spns[i] != NULL; i++) {
+           ret = update_keytab_entries(context, ccache, etypes, cpn,
+                                       spns[i], newpw, salt, kvno);
+           if (ret)
+               goto out;
+       }
+    }
+
+    kcm_log(0, "Changed expired password for principal %s in cache %s",
+           cpn, ccache->name);
+
+out:
+    if (cpn != NULL)
+       free(cpn);
+    if (spns != NULL)
+       krb5_config_free_strings(spns);
+    if (etypes != NULL)
+       free(etypes);
+    krb5_free_salt(context, salt);
+    memset(newpw, 0, sizeof(newpw));
+
+    return ret;
+}
+
diff --git a/src/kerberosV/src/kcm/cache.c b/src/kerberosV/src/kcm/cache.c
new file mode 100644 (file)
index 0000000..25bfd07
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: cache.c,v 1.3 2005/02/06 01:22:48 lukeh Exp $");
+
+static HEIMDAL_MUTEX ccache_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static kcm_ccache_data *ccache_head = NULL;
+static unsigned int ccache_nextid = 0; 
+
+char *kcm_ccache_nextid(pid_t pid, uid_t uid, gid_t gid)
+{
+    unsigned n;
+    char *name;
+
+    HEIMDAL_MUTEX_lock(&ccache_mutex);
+    n = ++ccache_nextid;
+    HEIMDAL_MUTEX_unlock(&ccache_mutex);
+
+    asprintf(&name, "%d:%u", uid, n);
+
+    return name;
+}
+
+static krb5_error_code
+kcm_ccache_resolve_internal(krb5_context context,
+                           const char *name,
+                           kcm_ccache *ccache)
+{
+    kcm_ccache p;
+    krb5_error_code ret;
+
+    *ccache = NULL;
+
+    ret = KRB5_FCC_NOFILE;
+
+    HEIMDAL_MUTEX_lock(&ccache_mutex);
+
+    for (p = ccache_head; p != NULL; p = p->next) {
+       if ((p->flags & KCM_FLAGS_VALID) == 0)
+           continue;
+       if (strcmp(p->name, name) == 0) {
+           ret = 0;
+           break;
+       }
+    }
+
+    if (ret == 0) {
+       kcm_retain_ccache(context, p);
+       *ccache = p;
+    }
+
+    HEIMDAL_MUTEX_unlock(&ccache_mutex);
+
+    return ret;
+}
+
+krb5_error_code kcm_debug_ccache(krb5_context context)
+{
+    kcm_ccache p;
+
+    for (p = ccache_head; p != NULL; p = p->next) {
+       char *cpn = NULL, *spn = NULL;
+       int ncreds = 0;
+       struct kcm_creds *k;
+
+       if ((p->flags & KCM_FLAGS_VALID) == 0) {
+           kcm_log(7, "cache %08x: empty slot");
+           continue;
+       }
+
+       KCM_ASSERT_VALID(p);
+
+       for (k = p->creds; k != NULL; k = k->next)
+           ncreds++;
+
+       if (p->client != NULL)
+           krb5_unparse_name(context, p->client, &cpn);
+       if (p->server != NULL)
+           krb5_unparse_name(context, p->server, &spn);
+       
+       kcm_log(7, "cache %08x: name %s refcnt %d flags %04x mode %04o "
+               "uid %d gid %d client %s server %s ncreds %d",
+               p, p->name, p->refcnt, p->flags, p->mode, p->uid, p->gid,
+               (cpn == NULL) ? "<none>" : cpn,
+               (spn == NULL) ? "<none>" : spn,
+               ncreds);
+
+       if (cpn != NULL)
+           free(cpn);
+       if (spn != NULL)
+           free(spn);
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+kcm_ccache_destroy_internal(krb5_context context, const char *name)
+{
+    kcm_ccache *p;
+    krb5_error_code ret;
+
+    ret = KRB5_FCC_NOFILE;
+
+    HEIMDAL_MUTEX_lock(&ccache_mutex);
+    for (p = &ccache_head; *p != NULL; p = &(*p)->next) {
+       if (((*p)->flags & KCM_FLAGS_VALID) == 0)
+           continue;
+       if (strcmp((*p)->name, name) == 0) {
+           ret = 0;
+           break;
+       }
+    }
+
+    if (ret)
+       goto out;
+
+    kcm_release_ccache(context, p);
+
+out:
+    HEIMDAL_MUTEX_unlock(&ccache_mutex);
+
+    return ret;
+}
+
+static krb5_error_code
+kcm_ccache_alloc(krb5_context context,
+                const char *name,
+                kcm_ccache *ccache)
+{
+    kcm_ccache slot = NULL, p;
+    krb5_error_code ret;
+    int new_slot = 0;
+
+    *ccache = NULL;
+
+    /* First, check for duplicates */
+    HEIMDAL_MUTEX_lock(&ccache_mutex);
+    ret = 0;
+    for (p = ccache_head; p != NULL; p = p->next) {
+       if (p->flags & KCM_FLAGS_VALID) {
+           if (strcmp(p->name, name) == 0) {
+               ret = KRB5_CC_WRITE;
+               break;
+           }
+       } else if (slot == NULL)
+           slot = p;
+    }
+
+    if (ret)
+       goto out;
+
+    /*
+     * Then try and find an empty slot
+     * XXX we need to recycle slots for this to actually do anything
+     */
+    if (slot == NULL) {
+       for (; p != NULL; p = p->next) {
+           if ((p->flags & KCM_FLAGS_VALID) == 0) {
+               slot = p;
+               break;
+           }
+       }
+
+       if (slot == NULL) {
+           slot = (kcm_ccache_data *)malloc(sizeof(*slot));
+           if (slot == NULL) {
+               ret = KRB5_CC_NOMEM;
+               goto out;
+           }
+           slot->next = ccache_head;
+           HEIMDAL_MUTEX_init(&slot->mutex);
+           new_slot = 1;
+       }
+    }
+
+    slot->name = strdup(name);
+    if (slot->name == NULL) {
+       ret = KRB5_CC_NOMEM;
+       goto out;
+    }
+
+    slot->refcnt = 1;
+    slot->flags = KCM_FLAGS_VALID;
+    slot->mode = S_IRUSR | S_IWUSR;
+    slot->uid = -1;
+    slot->gid = -1;
+    slot->client = NULL;
+    slot->server = NULL;
+    slot->creds = NULL;
+    slot->n_cursor = 0;
+    slot->cursors = NULL;
+    slot->key.keytab = NULL;
+    slot->tkt_life = 0;
+    slot->renew_life = 0;
+
+    if (new_slot)
+       ccache_head = slot;
+
+    *ccache = slot;
+
+    HEIMDAL_MUTEX_unlock(&ccache_mutex);
+    return 0;
+
+out:
+    HEIMDAL_MUTEX_unlock(&ccache_mutex);
+    if (new_slot && slot != NULL) {
+       HEIMDAL_MUTEX_destroy(&slot->mutex);
+       free(slot);
+    }
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_remove_creds_internal(krb5_context context,
+                                kcm_ccache ccache)
+{
+    struct kcm_creds *k;
+    struct kcm_cursor *c;
+
+    k = ccache->creds;
+    while (k != NULL) {
+       struct kcm_creds *old;
+
+       krb5_free_cred_contents(context, &k->cred);
+       old = k;
+       k = k->next;
+       free(old);
+    }
+    ccache->creds = NULL;
+
+    /* remove anything that would have pointed into the creds too */
+
+    ccache->n_cursor = 0;
+
+    c = ccache->cursors;
+    while (c != NULL) {
+       struct kcm_cursor *old;
+
+       old = c;
+       c = c->next;
+       free(old);
+    }
+    ccache->cursors = NULL;
+
+    return 0;
+}
+
+krb5_error_code
+kcm_ccache_remove_creds(krb5_context context,
+                       kcm_ccache ccache)
+{
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    ret = kcm_ccache_remove_creds_internal(context, ccache);
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_zero_ccache_data_internal(krb5_context context,
+                             kcm_ccache_data *cache)
+{
+    if (cache->client != NULL) {
+       krb5_free_principal(context, cache->client);
+       cache->client = NULL;
+    }
+
+    if (cache->server != NULL) {
+       krb5_free_principal(context, cache->server);
+       cache->server = NULL;
+    }
+
+    kcm_ccache_remove_creds_internal(context, cache);
+
+    return 0;
+}
+
+krb5_error_code
+kcm_zero_ccache_data(krb5_context context,
+                    kcm_ccache cache)
+{
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(cache);
+
+    HEIMDAL_MUTEX_lock(&cache->mutex);
+    ret = kcm_zero_ccache_data_internal(context, cache);
+    HEIMDAL_MUTEX_unlock(&cache->mutex);
+
+    return ret;
+}
+
+static krb5_error_code
+kcm_free_ccache_data_internal(krb5_context context,
+                             kcm_ccache_data *cache)
+{
+    KCM_ASSERT_VALID(cache);
+
+    if (cache->name != NULL) {
+       free(cache->name);
+       cache->name = NULL;
+    }
+
+    if (cache->flags & KCM_FLAGS_USE_KEYTAB) {
+       krb5_kt_close(context, cache->key.keytab);
+       cache->key.keytab = NULL;
+    } else if (cache->flags & KCM_FLAGS_USE_CACHED_KEY) {
+       krb5_free_keyblock_contents(context, &cache->key.keyblock);
+       krb5_keyblock_zero(&cache->key.keyblock);
+    }
+
+    cache->flags = 0;
+    cache->mode = 0;
+    cache->uid = -1;
+    cache->gid = -1;
+
+    kcm_zero_ccache_data_internal(context, cache);
+
+    cache->tkt_life = 0;
+    cache->renew_life = 0;
+
+    cache->next = NULL;
+    cache->refcnt = 0;
+
+    HEIMDAL_MUTEX_unlock(&cache->mutex);
+    HEIMDAL_MUTEX_destroy(&cache->mutex);
+
+    return 0;
+}
+
+krb5_error_code
+kcm_retain_ccache(krb5_context context,
+                 kcm_ccache ccache)
+{
+    KCM_ASSERT_VALID(ccache);
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    ccache->refcnt++;
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return 0;
+}
+
+krb5_error_code
+kcm_release_ccache(krb5_context context,
+                  kcm_ccache *ccache)
+{
+    kcm_ccache c = *ccache;
+    krb5_error_code ret = 0;
+
+    KCM_ASSERT_VALID(c);
+
+    HEIMDAL_MUTEX_lock(&c->mutex);
+    if (c->refcnt == 1) {
+       ret = kcm_free_ccache_data_internal(context, c);
+       if (ret == 0)
+           free(c);
+    } else {
+       c->refcnt--;
+       HEIMDAL_MUTEX_unlock(&c->mutex);
+    }
+
+    *ccache = NULL;
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_gen_new(krb5_context context,
+                  pid_t pid,
+                  uid_t uid,
+                  gid_t gid,
+                  kcm_ccache *ccache)
+{
+    krb5_error_code ret;
+    char *name;
+
+    name = kcm_ccache_nextid(pid, uid, gid);
+    if (name == NULL) {
+       return KRB5_CC_NOMEM;
+    }
+
+    ret = kcm_ccache_new(context, name, ccache);
+
+    free(name);
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_new(krb5_context context,
+              const char *name,
+              kcm_ccache *ccache)
+{
+    krb5_error_code ret;
+
+    ret = kcm_ccache_alloc(context, name, ccache);
+    if (ret == 0) {
+       /*
+        * one reference is held by the linked list,
+        * one by the caller
+        */
+       kcm_retain_ccache(context, *ccache);
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_resolve(krb5_context context,
+                  const char *name,
+                  kcm_ccache *ccache)
+{
+    krb5_error_code ret;
+
+    ret = kcm_ccache_resolve_internal(context, name, ccache);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_destroy(krb5_context context,
+                  const char *name)
+{
+    krb5_error_code ret;
+
+    ret = kcm_ccache_destroy_internal(context, name);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_destroy_if_empty(krb5_context context,
+                           kcm_ccache ccache)
+{
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+    
+    if (ccache->creds == NULL) {
+       ret = kcm_ccache_destroy_internal(context, ccache->name);
+    } else
+       ret = 0;
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_store_cred(krb5_context context,
+                     kcm_ccache ccache,
+                     krb5_creds *creds,
+                     int copy)
+{
+    krb5_error_code ret;
+    krb5_creds *tmp;
+
+    KCM_ASSERT_VALID(ccache);
+    
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    ret = kcm_ccache_store_cred_internal(context, ccache, creds, copy, &tmp);
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_store_cred_internal(krb5_context context,
+                              kcm_ccache ccache,
+                              krb5_creds *creds,
+                              int copy,
+                              krb5_creds **credp)
+{
+    struct kcm_creds **c;
+    krb5_error_code ret;
+
+    for (c = &ccache->creds; *c != NULL; c = &(*c)->next)
+       ;
+
+    *c = (struct kcm_creds *)malloc(sizeof(struct kcm_creds));
+    if (*c == NULL) {
+       return KRB5_CC_NOMEM;
+    }
+
+    *credp = &(*c)->cred;
+
+    if (copy) {
+       ret = krb5_copy_creds_contents(context, creds, *credp);
+       if (ret) {
+           free(*c);
+           *c = NULL;
+       }
+    } else {
+       **credp = *creds;
+       ret = 0;
+    }
+
+    (*c)->next = NULL;
+
+    return ret;
+}
+
+static void
+remove_cred(krb5_context context,
+           struct kcm_creds **c)
+{
+    struct kcm_creds *cred;
+
+    cred = *c;
+
+    *c = cred->next;
+
+    krb5_free_cred_contents(context, &cred->cred);
+    free(cred);
+}
+
+krb5_error_code
+kcm_ccache_remove_cred_internal(krb5_context context,
+                               kcm_ccache ccache,
+                               krb5_flags whichfields,
+                               const krb5_creds *mcreds)
+{
+    krb5_error_code ret;
+    struct kcm_creds **c;
+
+    ret = KRB5_CC_NOTFOUND;
+
+    for (c = &ccache->creds; *c != NULL; c = &(*c)->next) {
+       if (krb5_compare_creds(context, whichfields, mcreds, &(*c)->cred)) {
+           remove_cred(context, c);
+           ret = 0;
+       }
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_remove_cred(krb5_context context,
+                      kcm_ccache ccache,
+                      krb5_flags whichfields,
+                      const krb5_creds *mcreds)
+{
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    ret = kcm_ccache_remove_cred_internal(context, ccache, whichfields, mcreds);
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_retrieve_cred_internal(krb5_context context,
+                                 kcm_ccache ccache,
+                                 krb5_flags whichfields,
+                                 const krb5_creds *mcreds,
+                                 krb5_creds **creds)
+{
+    krb5_boolean match;
+    struct kcm_creds *c;
+    krb5_error_code ret;
+
+    memset(creds, 0, sizeof(*creds));
+
+    ret = KRB5_CC_END;
+
+    match = FALSE;
+    for (c = ccache->creds; c != NULL; c = c->next) {
+       match = krb5_compare_creds(context, whichfields, mcreds, &c->cred);
+       if (match)
+           break;
+    }
+
+    if (match) {
+       ret = 0;
+       *creds = &c->cred;
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_retrieve_cred(krb5_context context,
+                        kcm_ccache ccache,
+                        krb5_flags whichfields,
+                        const krb5_creds *mcreds,
+                        krb5_creds **credp)
+{
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+    
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    ret = kcm_ccache_retrieve_cred_internal(context, ccache,
+                                           whichfields, mcreds, credp);
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
diff --git a/src/kerberosV/src/kcm/client.c b/src/kerberosV/src/kcm/client.c
new file mode 100644 (file)
index 0000000..52e8d34
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: client.c,v 1.3 2005/02/06 01:22:48 lukeh Exp $");
+
+krb5_error_code
+kcm_ccache_resolve_client(krb5_context context,
+                         kcm_client *client,
+                         kcm_operation opcode,
+                         const char *name,
+                         kcm_ccache *ccache)
+{
+    krb5_error_code ret;
+
+    ret = kcm_ccache_resolve(context, name, ccache);
+    if (ret) {
+       kcm_log(1, "Failed to resolve cache %s: %s",
+               name, krb5_get_err_text(context, ret));
+       return ret;
+    }
+
+    ret = kcm_access(context, client, opcode, *ccache);
+    if (ret) {
+       ret = KRB5_FCC_NOFILE; /* don't disclose */
+       kcm_release_ccache(context, ccache);
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_destroy_client(krb5_context context,
+                         kcm_client *client,
+                         const char *name)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+
+    ret = kcm_ccache_resolve(context, name, &ccache);
+    if (ret) {
+       kcm_log(1, "Failed to resolve cache %s: %s",
+               name, krb5_get_err_text(context, ret));
+       return ret;
+    }
+
+    ret = kcm_access(context, client, KCM_OP_DESTROY, ccache);
+    if (ret) {
+       kcm_release_ccache(context, &ccache);
+       return ret;
+    }
+
+    ret = kcm_ccache_destroy(context, ccache->name);
+    if (ret == 0) {
+       /* don't leave any events dangling */
+       kcm_cleanup_events(context, ccache);
+    }
+
+    kcm_release_ccache(context, &ccache);
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_new_client(krb5_context context,
+                     kcm_client *client,
+                     const char *name,
+                     kcm_ccache *ccache_p)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+
+    /* We insist the ccache name starts with UID or UID: */
+    if (name_constraints != 0) {
+       char prefix[64];
+       size_t prefix_len;
+       int bad = 1;
+
+       snprintf(prefix, sizeof(prefix), "%d:", client->uid);
+       prefix_len = strlen(prefix);
+
+       if (strncmp(name, prefix, prefix_len) == 0)
+           bad = 0;
+       else {
+           prefix[prefix_len - 1] = '\0';
+           if (strcmp(name, prefix) == 0)
+               bad = 0;
+       }
+
+       if (bad)
+           return KRB5_CC_BADNAME;
+    }
+       
+    ret = kcm_ccache_resolve(context, name, &ccache);
+    if (ret == 0) {
+       if (ccache->uid != client->uid ||
+           ccache->gid != client->gid)
+           return KRB5_FCC_PERM;
+    } else if (ret != KRB5_FCC_NOFILE) {
+       return ret;
+    }
+
+    if (ret == KRB5_FCC_NOFILE) {
+       ret = kcm_ccache_new(context, name, &ccache);
+       if (ret) {
+           kcm_log(1, "Failed to initialize cache %s: %s",
+                   name, krb5_get_err_text(context, ret));
+           return ret;
+       }
+
+       /* bind to current client */
+       ccache->uid = client->uid;
+       ccache->gid = client->gid;
+    } else {
+       ret = kcm_zero_ccache_data(context, ccache);
+       if (ret) {
+           kcm_log(1, "Failed to empty cache %s: %s",
+                   name, krb5_get_err_text(context, ret));
+           kcm_release_ccache(context, &ccache);
+           return ret;
+       }
+       kcm_cleanup_events(context, ccache);
+    }
+
+    ret = kcm_access(context, client, KCM_OP_INITIALIZE, ccache);
+    if (ret) {
+       kcm_release_ccache(context, &ccache);
+       kcm_ccache_destroy(context, name);
+       return ret;
+    }
+
+    *ccache_p = ccache;
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kcm/config.c b/src/kerberosV/src/kcm/config.c
new file mode 100644 (file)
index 0000000..9f09726
--- /dev/null
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+#include <getarg.h>
+#include <parse_bytes.h>
+
+RCSID("$KTH: config.c,v 1.7 2005/05/30 10:17:14 lha Exp $");
+
+static const char *config_file;        /* location of kcm config file */
+
+size_t max_request = 0;                /* maximal size of a request */
+char *socket_path = NULL;
+char *door_path = NULL;
+
+static char *max_request_str;  /* `max_request' as a string */
+
+int detach_from_console = -1;
+#define DETACH_IS_DEFAULT FALSE
+
+static const char *system_cache_name = NULL;
+static const char *system_keytab = NULL;
+static const char *system_principal = NULL;
+static const char *system_server = NULL;
+static const char *system_perms = NULL;
+static const char *system_user = NULL;
+static const char *system_group = NULL;
+
+static const char *renew_life = NULL;
+static const char *ticket_life = NULL;
+
+int disallow_getting_krbtgt = -1;
+int name_constraints = -1;
+
+static int help_flag;
+static int version_flag;
+
+static struct getargs args[] = {
+    { 
+       "cache-name",   0,      arg_string,     &system_cache_name, 
+       "system cache name", "cachename" 
+    },
+    { 
+       "config-file",  'c',    arg_string,     &config_file, 
+       "location of config file",      "file" 
+    },
+    { 
+       "group",        'g',    arg_string,     &system_group, 
+       "system cache group",   "group" 
+    },
+    { 
+       "max-request",  0,      arg_string, &max_request, 
+       "max size for a kcm-request", "size"
+    },
+#if DETACH_IS_DEFAULT
+    {
+       "detach",       'D',      arg_negative_flag, &detach_from_console, 
+       "don't detach from console"
+    },
+#else
+    {
+       "detach",       0 ,      arg_flag, &detach_from_console, 
+       "detach from console"
+    },
+#endif
+    {  "help",         'h',    arg_flag,   &help_flag },
+    { 
+       "system-principal",     'k',    arg_string,     &system_principal, 
+       "system principal name",        "principal" 
+    },
+    {
+       "lifetime",     'l', arg_string, &ticket_life,
+       "lifetime of system tickets", "time"
+    },
+    {
+       "mode",         'm', arg_string, &system_perms,
+       "octal mode of system cache", "mode"
+    },
+    {
+       "name-constraints",     'n', arg_negative_flag, &name_constraints,
+       "disable credentials cache name constraints"
+    },
+    {
+       "disallow-getting-krbtgt", 0, arg_flag, &disallow_getting_krbtgt,
+       "disable fetching krbtgt from the cache"
+    },
+    {
+       "renewable-life",       'r', arg_string, &renew_life,
+       "renewable lifetime of system tickets", "time"
+    },
+    {
+       "socket-path",          's', arg_string, &socket_path,
+       "path to kcm domain socket", "path"
+    },
+#ifdef HAVE_DOOR_CREATE
+    {
+       "door-path",            's', arg_string, &door_path,
+       "path to kcm door", "path"
+    },
+#endif
+    {
+       "server",               'S', arg_string, &system_server,
+       "server to get system ticket for", "principal"
+    },
+    { 
+       "keytab",       't',    arg_string,     &system_keytab, 
+       "system keytab name",   "keytab" 
+    },
+    { 
+       "user",         'u',    arg_string,     &system_user, 
+       "system cache owner",   "user" 
+    },
+    {  "version",      'v',    arg_flag,   &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, num_args, NULL, "");
+    exit (ret);
+}
+
+static int parse_owners(kcm_ccache ccache)
+{
+    uid_t uid = 0;
+    gid_t gid = 0;
+    struct passwd *pw;
+    struct group *gr;
+    int uid_p = 0;
+    int gid_p = 0;
+
+    if (system_user != NULL) {
+       if (isdigit((unsigned char)system_user[0])) {
+           pw = getpwuid(atoi(system_user));
+       } else {
+           pw = getpwnam(system_user);
+       }
+       if (pw == NULL) {
+           return errno;
+       }
+
+       system_user = strdup(pw->pw_name);
+       if (system_user == NULL) {
+           return ENOMEM;
+       }
+
+       uid = pw->pw_uid; uid_p = 1;
+       gid = pw->pw_gid; gid_p = 1;
+    }
+
+    if (system_group != NULL) {
+       if (isdigit((unsigned char)system_group[0])) {
+           gr = getgrgid(atoi(system_group));
+       } else {
+           gr = getgrnam(system_group);
+       }
+       if (gr == NULL) {
+           return errno;
+       }
+
+       gid = gr->gr_gid; gid_p = 1;
+    }
+
+    if (uid_p)
+       ccache->uid = uid;
+    else
+       ccache->uid = 0; /* geteuid() XXX */
+
+    if (gid_p)
+       ccache->gid = gid;
+    else
+       ccache->gid = 0; /* getegid() XXX */
+
+    return 0;
+}
+
+static const char *
+kcm_system_config_get_string(const char *string)
+{
+    return krb5_config_get_string(kcm_context, NULL, "kcm",
+                                 "system_ccache", string, NULL);
+}
+
+static krb5_error_code
+ccache_init_system(void)
+{
+    kcm_ccache ccache;
+    krb5_error_code ret;
+
+    if (system_cache_name == NULL)
+       system_cache_name = kcm_system_config_get_string("cc_name");
+
+    ret = kcm_ccache_new(kcm_context,
+                        system_cache_name ? system_cache_name : "SYSTEM",
+                        &ccache);
+    if (ret)
+       return ret;
+
+    ccache->flags |= KCM_FLAGS_OWNER_IS_SYSTEM;
+    ccache->flags |= KCM_FLAGS_USE_KEYTAB;
+
+    ret = parse_owners(ccache);
+    if (ret)
+       return ret;
+
+    ret = krb5_parse_name(kcm_context, system_principal, &ccache->client);
+    if (ret) {
+       kcm_release_ccache(kcm_context, &ccache);
+       return ret;
+    }
+
+    if (system_server == NULL)
+       system_server = kcm_system_config_get_string("server");
+
+    if (system_server != NULL) {
+       ret = krb5_parse_name(kcm_context, system_server, &ccache->server);
+       if (ret) {
+           kcm_release_ccache(kcm_context, &ccache);
+           return ret;
+       }
+    }
+
+    if (system_keytab == NULL)
+       system_keytab = kcm_system_config_get_string("keytab_name");
+
+    if (system_keytab != NULL) {
+       ret = krb5_kt_resolve(kcm_context, system_keytab, &ccache->key.keytab);
+    } else {
+       ret = krb5_kt_default(kcm_context, &ccache->key.keytab);
+    }
+    if (ret) {
+       kcm_release_ccache(kcm_context, &ccache);
+       return ret;
+    }
+
+    if (renew_life == NULL)
+       renew_life = kcm_system_config_get_string("renew_life");
+
+    if (renew_life == NULL)
+       renew_life = "1 month";
+
+    if (renew_life != NULL) {
+       ccache->renew_life = parse_time(renew_life, "s");
+       if (ccache->renew_life < 0) {
+           kcm_release_ccache(kcm_context, &ccache);
+           return EINVAL;
+       }
+    }
+
+    if (ticket_life == NULL)
+       ticket_life = kcm_system_config_get_string("ticket_life");
+
+    if (ticket_life != NULL) {
+       ccache->tkt_life = parse_time(ticket_life, "s");
+       if (ccache->tkt_life < 0) {
+           kcm_release_ccache(kcm_context, &ccache);
+           return EINVAL;
+       }
+    }
+
+    if (system_perms == NULL)
+       system_perms = kcm_system_config_get_string("mode");
+
+    if (system_perms != NULL) {
+       int mode;
+
+       if (sscanf(system_perms, "%o", &mode) != 1)
+           return EINVAL;
+
+       ccache->mode = mode;
+    }
+
+    if (disallow_getting_krbtgt == -1) {
+       disallow_getting_krbtgt =
+           krb5_config_get_bool_default(kcm_context, NULL, FALSE, "kcm",
+                                        "disallow-getting-krbtgt", NULL);
+    }
+
+    /* enqueue default actions for credentials cache */
+    ret = kcm_ccache_enqueue_default(kcm_context, ccache, NULL);
+
+    kcm_release_ccache(kcm_context, &ccache); /* retained by event queue */
+
+    return ret;
+}
+
+void
+kcm_configure(int argc, char **argv)
+{
+    krb5_error_code ret;
+    int optind = 0;
+    const char *p;
+    
+    while(getarg(args, num_args, argc, argv, &optind))
+       warnx("error at argument `%s'", argv[optind]);
+
+    if(help_flag)
+       usage (0);
+
+    if (version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0)
+       usage(1);
+    
+    {
+       char **files;
+
+       if(config_file == NULL)
+           config_file = _PATH_KCM_CONF;
+
+       ret = krb5_prepend_config_files_default(config_file, &files);
+       if (ret)
+           krb5_err(kcm_context, 1, ret, "getting configuration files");
+           
+       ret = krb5_set_config_files(kcm_context, files);
+       krb5_free_config_files(files);
+       if(ret) 
+           krb5_err(kcm_context, 1, ret, "reading configuration files");
+    }
+
+    if(max_request_str)
+       max_request = parse_bytes(max_request_str, NULL);
+
+    if(max_request == 0){
+       p = krb5_config_get_string (kcm_context,
+                                   NULL,
+                                   "kcm",
+                                   "max-request",
+                                   NULL);
+       if(p)
+           max_request = parse_bytes(p, NULL);
+    }
+
+    if (system_principal == NULL) {
+       system_principal = kcm_system_config_get_string("principal");
+    }
+
+    if (system_principal != NULL) {
+       ret = ccache_init_system();
+       if (ret)
+           krb5_err(kcm_context, 1, ret, "initializing system ccache");
+    }
+
+    if(detach_from_console == -1) 
+       detach_from_console = krb5_config_get_bool_default(kcm_context, NULL,
+                                                          DETACH_IS_DEFAULT,
+                                                          "kcm",
+                                                          "detach", NULL);
+    kcm_openlog();
+    if(max_request == 0)
+       max_request = 64 * 1024;
+}
+
diff --git a/src/kerberosV/src/kcm/connect.c b/src/kerberosV/src/kcm/connect.c
new file mode 100644 (file)
index 0000000..739e2b1
--- /dev/null
@@ -0,0 +1,689 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: connect.c,v 1.15.2.2 2006/02/03 14:37:11 lha Exp $");
+
+struct descr {
+    int s;
+    int type;
+    char *path;
+    unsigned char *buf;
+    size_t size;
+    size_t len;
+    time_t timeout;
+    struct sockaddr_storage __ss;
+    struct sockaddr *sa;
+    socklen_t sock_len;
+    kcm_client peercred;
+};
+
+static void
+init_descr(struct descr *d)
+{
+    memset(d, 0, sizeof(*d));
+    d->sa = (struct sockaddr *)&d->__ss;
+    d->s = -1;
+}
+
+/*
+ * re-initialize all `n' ->sa in `d'.
+ */
+
+static void
+reinit_descrs (struct descr *d, int n)
+{
+    int i;
+
+    for (i = 0; i < n; ++i)
+       d[i].sa = (struct sockaddr *)&d[i].__ss;
+}
+
+/*
+ * Update peer credentials from socket.
+ *
+ * SCM_CREDS can only be updated the first time there is read data to
+ * read from the filedescriptor, so if we read do it before this
+ * point, the cred data might not be is not there yet.
+ */
+
+static int
+update_client_creds(int s, kcm_client *peer)
+{
+#ifdef GETPEERUCRED
+    /* Solaris 10 */
+    {
+       ucred_t *peercred;
+       
+       if (getpeerucred(s, &peercred) != 0) {
+           peer->uid = ucred_geteuid(peercred);
+           peer->gid = ucred_getegid(peercred);
+           peer->pid = 0;
+           ucred_free(peercred);
+           return 0;
+       }
+    } 
+#endif
+#ifdef GETPEEREID
+    /* FreeBSD, OpenBSD */
+    {
+       uid_t uid;
+       gid_t gid;
+
+       if (getpeereid(s, &uid, &gid) == 0) {
+           peer->uid = uid;
+           peer->gid = gid;
+           peer->pid = 0;
+           return 0;
+       }
+    }
+#endif
+#ifdef SO_PEERCRED
+    /* Linux */
+    {
+       struct ucred pc;
+       socklen_t pclen = sizeof(pc);
+
+       if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&pc, &pclen) == 0) {
+           peer->uid = pc.uid;
+           peer->gid = pc.gid;
+           peer->pid = pc.pid;
+           return 0;
+       }
+    }
+#endif
+#if defined(LOCAL_PEERCRED) && defined(XUCRED_VERSION)
+    {
+       struct xucred peercred;
+       socklen_t peercredlen = sizeof(peercred);
+
+       if (getsockopt(s, LOCAL_PEERCRED, 1,
+                      (void *)&peercred, &peercredlen) == 0
+           && peercred.cr_version == XUCRED_VERSION)
+       {
+           peer->uid = peercred.cr_uid;
+           peer->gid = peercred.cr_gid;
+           peer->pid = 0;
+           return 0;
+       }
+    }
+#endif
+#if defined(SOCKCREDSIZE) && defined(SCM_CREDS)
+    /* NetBSD */
+    if (peer->uid == -1) {
+       struct msghdr msg;
+       socklen_t crmsgsize;
+       void *crmsg;
+       struct cmsghdr *cmp;
+       struct sockcred *sc;
+       
+       memset(&msg, 0, sizeof(msg));
+       crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS));
+       if (crmsgsize == 0)
+           return 1 ;
+
+       crmsg = malloc(crmsgsize);
+       if (crmsg == NULL)
+           goto failed_scm_creds;
+
+       memset(crmsg, 0, crmsgsize);
+       
+       msg.msg_control = crmsg;
+       msg.msg_controllen = crmsgsize;
+       
+       if (recvmsg(s, &msg, 0) < 0) {
+           free(crmsg);
+           goto failed_scm_creds;
+       }       
+       
+       if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) {
+           free(crmsg);
+           goto failed_scm_creds;
+       }       
+       
+       cmp = CMSG_FIRSTHDR(&msg);
+       if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS ||
+           cmp->cmsg_len != CMSG_LEN(sizeof(struct sockcred))) {
+           free(crmsg);
+           goto failed_scm_creds;
+       }       
+       
+       sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
+       
+       peer->uid = sc->sc_euid;
+       peer->gid = sc->sc_egid;
+       peer->pid = 0;
+       
+       free(crmsg);
+       return 0;
+    } else {
+       /* we already got the cred, just return it */
+       return 0;
+    }
+ failed_scm_creds:
+#endif
+    krb5_warn(kcm_context, errno, "failed to determine peer identity");
+    return 1;
+}
+
+
+/*
+ * Create the socket (family, type, port) in `d'
+ */
+
+static void 
+init_socket(struct descr *d)
+{
+    struct sockaddr_un un;
+    struct sockaddr *sa = (struct sockaddr *)&un;
+    krb5_socklen_t sa_size = sizeof(un);
+
+    init_descr (d);
+
+    un.sun_family = AF_UNIX;
+
+    if (socket_path != NULL)
+       d->path = socket_path;
+    else
+       d->path = _PATH_KCM_SOCKET;
+
+    strlcpy(un.sun_path, d->path, sizeof(un.sun_path));
+
+    d->s = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (d->s < 0){
+       krb5_warn(kcm_context, errno, "socket(%d, %d, 0)", AF_UNIX, SOCK_STREAM);
+       d->s = -1;
+       return;
+    }
+#if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR)
+    {
+       int one = 1;
+       setsockopt(d->s, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
+    }
+#endif
+#ifdef LOCAL_CREDS
+    {
+       int one = 1;
+       setsockopt(d->s, 0, LOCAL_CREDS, (void *)&one, sizeof(one));
+    }
+#endif
+
+    d->type = SOCK_STREAM;
+
+    unlink(d->path);
+
+    if (bind(d->s, sa, sa_size) < 0) {
+       krb5_warn(kcm_context, errno, "bind %s", un.sun_path);
+       close(d->s);
+       d->s = -1;
+       return;
+    }
+
+    if (listen(d->s, SOMAXCONN) < 0) {
+       krb5_warn(kcm_context, errno, "listen %s", un.sun_path);
+       close(d->s);
+       d->s = -1;
+       return;
+    }
+
+    chmod(d->path, 0777);
+
+    return;
+}
+
+/*
+ * Allocate descriptors for all the sockets that we should listen on
+ * and return the number of them.
+ */
+
+static int
+init_sockets(struct descr **desc)
+{
+    struct descr *d;
+    size_t num = 0;
+
+    d = (struct descr *)malloc(sizeof(*d));
+    if (d == NULL) {
+       krb5_errx(kcm_context, 1, "malloc failed");
+    }
+
+    init_socket(d);
+    if (d->s != -1) {
+       kcm_log(5, "listening on domain socket %s", d->path);
+       num++;
+    }
+
+    reinit_descrs (d, num);
+    *desc = d;
+
+    return num;
+}
+
+/*
+ * handle the request in `buf, len', from `addr' (or `from' as a string),
+ * sending a reply in `reply'.
+ */
+
+static int
+process_request(unsigned char *buf, 
+               size_t len, 
+               krb5_data *reply,
+               kcm_client *client)
+{
+    krb5_data request;
+   
+    if (len < 4) {
+       kcm_log(1, "malformed request from process %d (too short)", 
+               client->pid);
+       return -1;
+    }
+
+    if (buf[0] != KCM_PROTOCOL_VERSION_MAJOR ||
+       buf[1] != KCM_PROTOCOL_VERSION_MINOR) {
+       kcm_log(1, "incorrect protocol version %d.%d from process %d",
+               buf[0], buf[1], client->pid);
+       return -1;
+    }
+
+    buf += 2;
+    len -= 2;
+
+    /* buf is now pointing at opcode */
+
+    request.data = buf;
+    request.length = len;
+
+    return kcm_dispatch(kcm_context, client, &request, reply);
+}
+
+/*
+ * Handle the request in `buf, len' to socket `d'
+ */
+
+static void
+do_request(void *buf, size_t len, struct descr *d)
+{
+    krb5_error_code ret;
+    krb5_data reply;
+
+    reply.length = 0;
+
+    ret = process_request(buf, len, &reply, &d->peercred);
+    if (reply.length != 0) {
+       unsigned char len[4];
+       struct msghdr msghdr;
+       struct iovec iov[2];
+
+       kcm_log(5, "sending %lu bytes to process %d", 
+               (unsigned long)reply.length,
+               (int)d->peercred.pid);
+
+       memset (&msghdr, 0, sizeof(msghdr));
+       msghdr.msg_name       = NULL;
+       msghdr.msg_namelen    = 0;
+       msghdr.msg_iov        = iov;
+       msghdr.msg_iovlen     = sizeof(iov)/sizeof(*iov);
+#if 0
+       msghdr.msg_control    = NULL;
+       msghdr.msg_controllen = 0;
+#endif
+
+       len[0] = (reply.length >> 24) & 0xff;
+       len[1] = (reply.length >> 16) & 0xff;
+       len[2] = (reply.length >> 8) & 0xff;
+       len[3] = reply.length & 0xff;
+
+       iov[0].iov_base       = (void*)len;
+       iov[0].iov_len        = 4;
+       iov[1].iov_base       = reply.data;
+       iov[1].iov_len        = reply.length;
+
+       if (sendmsg (d->s, &msghdr, 0) < 0) {
+           kcm_log (0, "sendmsg(%d): %d %s", (int)d->peercred.pid,
+                    errno, strerror(errno));
+           krb5_data_free(&reply);
+           return;
+       }
+
+       krb5_data_free(&reply);
+    }
+
+    if (ret) {
+       kcm_log(0, "Failed processing %lu byte request from process %d", 
+               (unsigned long)len, d->peercred.pid);
+    }
+}
+
+static void
+clear_descr(struct descr *d)
+{
+    if(d->buf)
+       memset(d->buf, 0, d->size);
+    d->len = 0;
+    if(d->s != -1)
+       close(d->s);
+    d->s = -1;
+}
+
+#define STREAM_TIMEOUT 4
+
+/*
+ * accept a new stream connection on `d[parent]' and store it in `d[child]'
+ */
+
+static void
+add_new_stream (struct descr *d, int parent, int child)
+{
+    int s;
+
+    if (child == -1)
+       return;
+
+    d[child].peercred.pid = -1;
+    d[child].peercred.uid = -1;
+    d[child].peercred.gid = -1;
+
+    d[child].sock_len = sizeof(d[child].__ss);
+    s = accept(d[parent].s, d[child].sa, &d[child].sock_len);
+    if(s < 0) {
+       krb5_warn(kcm_context, errno, "accept");
+       return;
+    }
+
+    if (s >= FD_SETSIZE) {
+       krb5_warnx(kcm_context, "socket FD too large");
+       close (s);
+       return;
+    }
+
+    d[child].s = s;
+    d[child].timeout = time(NULL) + STREAM_TIMEOUT;
+    d[child].type = SOCK_STREAM;
+}
+
+/*
+ * Grow `d' to handle at least `n'.
+ * Return != 0 if fails
+ */
+
+static int
+grow_descr (struct descr *d, size_t n)
+{
+    if (d->size - d->len < n) {
+       unsigned char *tmp;
+       size_t grow;
+
+       grow = max(1024, d->len + n);
+       if (d->size + grow > max_request) {
+           kcm_log(0, "Request exceeds max request size (%lu bytes).",
+                   (unsigned long)d->size + grow);
+           clear_descr(d);
+           return -1;
+       }
+       tmp = realloc (d->buf, d->size + grow);
+       if (tmp == NULL) {
+           kcm_log(0, "Failed to re-allocate %lu bytes.",
+                   (unsigned long)d->size + grow);
+           clear_descr(d);
+           return -1;
+       }
+       d->size += grow;
+       d->buf = tmp;
+    }
+    return 0;
+}
+
+/*
+ * Handle incoming data to the stream socket in `d[index]'
+ */
+
+static void
+handle_stream(struct descr *d, int index, int min_free)
+{
+    unsigned char buf[1024];
+    int n;
+    int ret = 0;
+
+    if (d[index].timeout == 0) {
+       add_new_stream (d, index, min_free);
+       return;
+    }
+
+    if (update_client_creds(d[index].s, &d[index].peercred)) {
+       krb5_warnx(kcm_context, "failed to update peer identity");
+       clear_descr(d + index);
+       return;
+    }
+
+    if (d[index].peercred.uid == -1) {
+       krb5_warnx(kcm_context, "failed to determine peer identity");
+       clear_descr (d + index);
+       return;
+    }
+
+    n = recvfrom(d[index].s, buf, sizeof(buf), 0, NULL, NULL);
+    if (n < 0) {
+       krb5_warn(kcm_context, errno, "recvfrom");
+       return;
+    } else if (n == 0) {
+       krb5_warnx(kcm_context, "connection closed before end of data "
+                  "after %lu bytes from process %ld",
+                  (unsigned long) d[index].len, (long) d[index].peercred.pid);
+       clear_descr (d + index);
+       return;
+    }
+    if (grow_descr (&d[index], n))
+       return;
+    memcpy(d[index].buf + d[index].len, buf, n);
+    d[index].len += n;
+    if (d[index].len > 4) {
+       krb5_storage *sp;
+       int32_t len;
+
+       sp = krb5_storage_from_mem(d[index].buf, d[index].len);
+       if (sp == NULL) {
+           kcm_log (0, "krb5_storage_from_mem failed");
+           ret = -1;
+       } else {
+           krb5_ret_int32(sp, &len);
+           krb5_storage_free(sp);
+           if (d[index].len - 4 >= len) {
+               memmove(d[index].buf, d[index].buf + 4, d[index].len - 4);
+               ret = 1;
+           } else
+               ret = 0;
+       }
+    }
+    if (ret < 0)
+       return;
+    else if (ret == 1) {
+       do_request(d[index].buf, d[index].len, &d[index]);
+       clear_descr(d + index);
+    }
+}
+
+#ifdef HAVE_DOOR_CREATE
+
+static void
+kcm_door_server(void  *cookie, char *argp, size_t arg_size,
+               door_desc_t *dp, uint_t n_desc)
+{
+    kcm_client peercred;
+    door_cred_t cred;
+    krb5_error_code ret;
+    krb5_data reply;
+    size_t length;
+    char *p;
+
+    reply.length = 0;
+
+    p = NULL;
+    length = 0;
+
+    if (door_cred(&cred) != 0) {
+       kcm_log(0, "door_cred failed with %s", strerror(errno));
+       goto out;
+    }
+
+    peercred.uid = cred.dc_euid;
+    peercred.gid = cred.dc_egid;
+    peercred.pid = cred.dc_pid;
+
+    ret = process_request((unsigned char*)argp, arg_size, &reply, &peercred);
+    if (reply.length != 0) {
+       p = alloca(reply.length); /* XXX don't use alloca */
+       if (p) {
+           memcpy(p, reply.data, reply.length);
+           length = reply.length;
+       }
+       krb5_data_free(&reply);
+    }
+
+ out:
+    door_return(p, length, NULL, 0);
+}
+
+static void
+kcm_setup_door(void)
+{
+    int fd, ret;
+    char *path;
+
+    fd = door_create(kcm_door_server, NULL, 0);
+    if (fd < 0)
+       krb5_err(kcm_context, 1, errno, "Failed to create door");
+
+    if (door_path != NULL)
+       path = door_path;
+    else
+       path = _PATH_KCM_DOOR;
+
+    unlink(path);
+    ret = open(path, O_RDWR | O_CREAT, 0666);
+    if (ret < 0)
+       krb5_err(kcm_context, 1, errno, "Failed to create/open door");
+    close(ret);
+
+    ret = fattach(fd, path);
+    if (ret < 0)
+       krb5_err(kcm_context, 1, errno, "Failed to attach door");
+
+}
+#endif /* HAVE_DOOR_CREATE */
+
+
+void
+kcm_loop(void)
+{
+    struct descr *d;
+    int ndescr;
+
+#ifdef HAVE_DOOR_CREATE
+    kcm_setup_door();
+#endif
+
+    ndescr = init_sockets(&d);
+    if (ndescr <= 0) {
+       krb5_warnx(kcm_context, "No sockets!");
+#ifndef HAVE_DOOR_CREATE
+       exit(1);
+#endif
+    }
+    while (exit_flag == 0){
+       struct timeval tmout;
+       fd_set fds;
+       int min_free = -1;
+       int max_fd = 0;
+       int i;
+
+       FD_ZERO(&fds);
+       for(i = 0; i < ndescr; i++) {
+           if (d[i].s >= 0){
+               if(d[i].type == SOCK_STREAM && 
+                  d[i].timeout && d[i].timeout < time(NULL)) {
+                   kcm_log(1, "Stream connection from %d expired after %lu bytes",
+                           d[i].peercred.pid, (unsigned long)d[i].len);
+                   clear_descr(&d[i]);
+                   continue;
+               }
+               if (max_fd < d[i].s)
+                   max_fd = d[i].s;
+               if (max_fd >= FD_SETSIZE)
+                   krb5_errx(kcm_context, 1, "fd too large");
+               FD_SET(d[i].s, &fds);
+           } else if (min_free < 0 || i < min_free)
+               min_free = i;
+       }
+       if (min_free == -1) {
+           struct descr *tmp;
+           tmp = realloc(d, (ndescr + 4) * sizeof(*d));
+           if(tmp == NULL)
+               krb5_warnx(kcm_context, "No memory");
+           else {
+               d = tmp;
+               reinit_descrs (d, ndescr);
+               memset(d + ndescr, 0, 4 * sizeof(*d));
+               for(i = ndescr; i < ndescr + 4; i++)
+                   init_descr (&d[i]);
+               min_free = ndescr;
+               ndescr += 4;
+           }
+       }
+
+       tmout.tv_sec = STREAM_TIMEOUT;
+       tmout.tv_usec = 0;
+       switch (select(max_fd + 1, &fds, 0, 0, &tmout)){
+       case 0:
+           kcm_run_events(kcm_context, time(NULL));
+           break;
+       case -1:
+           if (errno != EINTR)
+               krb5_warn(kcm_context, errno, "select");
+           break;
+       default:
+           for(i = 0; i < ndescr; i++) {
+               if(d[i].s >= 0 && FD_ISSET(d[i].s, &fds)) {
+                   if (d[i].type == SOCK_STREAM)
+                       handle_stream(d, i, min_free);
+               }
+           }
+           kcm_run_events(kcm_context, time(NULL));
+           break;
+       }
+    }
+    if (d->path != NULL)
+       unlink(d->path);
+    free(d);
+}
+
diff --git a/src/kerberosV/src/kcm/cursor.c b/src/kerberosV/src/kcm/cursor.c
new file mode 100644 (file)
index 0000000..a87f50b
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: cursor.c,v 1.3 2005/02/06 01:22:48 lukeh Exp $");
+
+krb5_error_code
+kcm_cursor_new(krb5_context context,
+              pid_t pid,
+              kcm_ccache ccache,
+              u_int32_t *cursor)
+{
+    kcm_cursor **p;
+    krb5_error_code ret;
+
+    *cursor = 0;
+
+    KCM_ASSERT_VALID(ccache);
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    for (p = &ccache->cursors; *p != NULL; p = &(*p)->next)
+       ;
+
+    *p = (kcm_cursor *)malloc(sizeof(kcm_cursor));
+    if (*p == NULL) {
+       ret = KRB5_CC_NOMEM;
+       goto out;
+    }
+
+    (*p)->pid = pid;
+    (*p)->key = ++ccache->n_cursor;
+    (*p)->credp = ccache->creds;
+    (*p)->next = NULL;
+
+    *cursor = (*p)->key;
+
+    ret = 0;
+
+out:
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_cursor_find(krb5_context context,
+               pid_t pid,
+               kcm_ccache ccache,
+               u_int32_t key,
+               kcm_cursor **cursor)
+{
+    kcm_cursor *p;
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+
+    if (key == 0)
+       return KRB5_CC_NOTFOUND;
+
+    ret = KRB5_CC_END;
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    for (p = ccache->cursors; p != NULL; p = p->next) {
+       if (p->key == key) {
+           if (p->pid != pid)
+               ret = KRB5_FCC_PERM;
+           else
+               ret = 0;
+           break;
+       }
+    }
+
+    if (ret == 0)
+       *cursor = p;
+
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_cursor_delete(krb5_context context,
+                 pid_t pid,
+                 kcm_ccache ccache,
+                 u_int32_t key)
+{
+    kcm_cursor **p;
+    krb5_error_code ret;
+
+    KCM_ASSERT_VALID(ccache);
+
+    if (key == 0)
+       return KRB5_CC_NOTFOUND;
+
+    ret = KRB5_CC_END;
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    for (p = &ccache->cursors; *p != NULL; p = &(*p)->next) {
+       if ((*p)->key == key) {
+           if ((*p)->pid != pid)
+               ret = KRB5_FCC_PERM;
+           else
+               ret = 0;
+           break;
+       }
+    }
+
+    if (ret == 0) {
+       kcm_cursor *x = *p;
+
+       *p = x->next;
+       free(x);
+    }
+
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
diff --git a/src/kerberosV/src/kcm/events.c b/src/kerberosV/src/kcm/events.c
new file mode 100644 (file)
index 0000000..56e3bb8
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: events.c,v 1.4 2005/05/30 01:43:23 lukeh Exp $");
+
+/* thread-safe in case we multi-thread later */
+static HEIMDAL_MUTEX events_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static kcm_event *events_head = NULL;
+static time_t last_run = 0;
+
+static char *action_strings[] = {
+       "NONE", "ACQUIRE_CREDS", "RENEW_CREDS",
+       "DESTROY_CREDS", "DESTROY_EMPTY_CACHE" };
+
+krb5_error_code
+kcm_enqueue_event(krb5_context context,
+                 kcm_event *event)
+{
+    krb5_error_code ret;
+
+    if (event->action == KCM_EVENT_NONE) {
+       return 0;
+    }
+
+    HEIMDAL_MUTEX_lock(&events_mutex);
+    ret = kcm_enqueue_event_internal(context, event);
+    HEIMDAL_MUTEX_unlock(&events_mutex);
+
+    return ret;
+}
+
+static void
+print_times(time_t time, char buf[64])
+{
+    if (time)
+       strftime(buf, 64, "%m-%dT%H:%M", gmtime(&time));
+    else
+       strlcpy(buf, "never", 64);
+}
+
+static void
+log_event(kcm_event *event, char *msg)
+{
+    char fire_time[64], expire_time[64];
+
+    print_times(event->fire_time, fire_time);
+    print_times(event->expire_time, expire_time);
+
+    kcm_log(7, "%s event %08x: fire_time %s fire_count %d expire_time %s "
+           "backoff_time %d action %s cache %s",
+           msg, event, fire_time, event->fire_count, expire_time,
+           event->backoff_time, action_strings[event->action],
+           event->ccache->name);
+}
+
+krb5_error_code
+kcm_enqueue_event_internal(krb5_context context,
+                          kcm_event *event)
+{
+    kcm_event **e;
+
+    if (event->action == KCM_EVENT_NONE)
+       return 0;
+
+    for (e = &events_head; *e != NULL; e = &(*e)->next)
+       ;
+
+    *e = (kcm_event *)malloc(sizeof(kcm_event));
+    if (*e == NULL) {
+       return KRB5_CC_NOMEM;
+    }
+
+    (*e)->valid = 1;
+    (*e)->fire_time = event->fire_time;
+    (*e)->fire_count = 0;
+    (*e)->expire_time = event->expire_time;
+    (*e)->backoff_time = event->backoff_time;
+
+    (*e)->action = event->action;
+
+    kcm_retain_ccache(context, event->ccache);
+    (*e)->ccache = event->ccache;
+    (*e)->next = NULL;
+
+    log_event(*e, "enqueuing");
+
+    return 0;
+}
+
+/*
+ * Dump events list on SIGUSR2
+ */
+krb5_error_code
+kcm_debug_events(krb5_context context)
+{
+    kcm_event *e;
+
+    for (e = events_head; e != NULL; e = e->next)
+       log_event(e, "debug");
+
+    return 0;
+}
+
+krb5_error_code
+kcm_enqueue_event_relative(krb5_context context,
+                          kcm_event *event)
+{
+    krb5_error_code ret;
+    kcm_event e;
+
+    e = *event;
+    e.backoff_time = e.fire_time;
+    e.fire_time += time(NULL);
+
+    ret = kcm_enqueue_event(context, &e);
+
+    return ret;
+}
+
+static krb5_error_code
+kcm_remove_event_internal(krb5_context context,
+                         kcm_event **e)
+{
+    kcm_event *next;
+
+    next = (*e)->next;
+
+    (*e)->valid = 0;
+    (*e)->fire_time = 0;
+    (*e)->fire_count = 0;
+    (*e)->expire_time = 0;
+    (*e)->backoff_time = 0;
+    kcm_release_ccache(context, &(*e)->ccache);
+    (*e)->next = NULL;
+    free(*e);
+
+    *e = next;
+
+    return 0;
+}
+
+static int
+is_primary_credential_p(krb5_context context,
+                       kcm_ccache ccache,
+                       krb5_creds *newcred)
+{
+    krb5_flags whichfields;
+
+    if (ccache->client == NULL)
+       return 0;
+
+    if (newcred->client == NULL ||
+       !krb5_principal_compare(context, ccache->client, newcred->client))
+       return 0;
+
+    /* XXX just checks whether it's the first credential in the cache */
+    if (ccache->creds == NULL)
+       return 0;
+
+    whichfields = KRB5_TC_MATCH_KEYTYPE | KRB5_TC_MATCH_FLAGS_EXACT |
+                 KRB5_TC_MATCH_TIMES_EXACT | KRB5_TC_MATCH_AUTHDATA |
+                 KRB5_TC_MATCH_2ND_TKT | KRB5_TC_MATCH_IS_SKEY;
+
+    return krb5_compare_creds(context, whichfields, newcred, &ccache->creds->cred);
+}
+
+/*
+ * Setup default events for a new credential
+ */
+static krb5_error_code
+kcm_ccache_make_default_event(krb5_context context,
+                             kcm_event *event,
+                             krb5_creds *newcred)
+{
+    krb5_error_code ret = 0;
+    kcm_ccache ccache = event->ccache;
+
+    event->fire_time = 0; 
+    event->expire_time = 0;
+    event->backoff_time = KCM_EVENT_DEFAULT_BACKOFF_TIME;
+
+    if (newcred == NULL) {
+       /* no creds, must be acquire creds request */
+       if ((ccache->flags & KCM_MASK_KEY_PRESENT) == 0) {
+           kcm_log(0, "Cannot acquire credentials without a key");
+           return KRB5_FCC_INTERNAL;
+       }
+
+       event->fire_time = time(NULL); /* right away */
+       event->action = KCM_EVENT_ACQUIRE_CREDS;
+    } else if (is_primary_credential_p(context, ccache, newcred)) {
+       if (newcred->flags.b.renewable) {
+           event->action = KCM_EVENT_RENEW_CREDS;
+           ccache->flags |= KCM_FLAGS_RENEWABLE;
+       } else {
+           if (ccache->flags & KCM_MASK_KEY_PRESENT)
+               event->action = KCM_EVENT_ACQUIRE_CREDS;
+           else
+               event->action = KCM_EVENT_NONE;
+           ccache->flags &= ~(KCM_FLAGS_RENEWABLE);
+       }
+       /* requeue with some slop factor */
+       event->fire_time = newcred->times.endtime - KCM_EVENT_QUEUE_INTERVAL;
+    } else {
+       event->action = KCM_EVENT_NONE;
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_ccache_enqueue_default(krb5_context context,
+                          kcm_ccache ccache,
+                          krb5_creds *newcred)
+{
+    kcm_event event;
+    krb5_error_code ret;
+
+    memset(&event, 0, sizeof(event));
+    event.ccache = ccache;
+
+    ret = kcm_ccache_make_default_event(context, &event, newcred);
+    if (ret)
+       return ret;
+
+    ret = kcm_enqueue_event_internal(context, &event);
+    if (ret)
+       return ret;
+
+    return 0;
+}
+
+krb5_error_code
+kcm_remove_event(krb5_context context,
+                kcm_event *event)
+{
+    krb5_error_code ret;
+    kcm_event **e;
+    int found = 0;
+
+    log_event(event, "removing");
+
+    HEIMDAL_MUTEX_lock(&events_mutex);
+    for (e = &events_head; *e != NULL; e = &(*e)->next) {
+       if (event == *e) {
+           *e = event->next;
+           found++;
+           break;
+       }
+    }
+
+    if (!found) {
+       ret = KRB5_CC_NOTFOUND;
+       goto out;
+    }
+
+    ret = kcm_remove_event_internal(context, &event);
+
+out:
+    HEIMDAL_MUTEX_unlock(&events_mutex);
+
+    return ret;
+}
+
+krb5_error_code
+kcm_cleanup_events(krb5_context context,
+                  kcm_ccache ccache)
+{
+    kcm_event **e;
+
+    KCM_ASSERT_VALID(ccache);
+
+    HEIMDAL_MUTEX_lock(&events_mutex);
+
+    for (e = &events_head; *e != NULL; e = &(*e)->next) {
+       if ((*e)->valid && (*e)->ccache == ccache) {
+           kcm_remove_event_internal(context, e);
+       }
+       if (*e == NULL)
+           break;
+    }
+
+    HEIMDAL_MUTEX_unlock(&events_mutex);
+
+    return 0;
+}
+
+static krb5_error_code
+kcm_fire_event(krb5_context context,
+              kcm_event **e)
+{
+    kcm_event *event;
+    krb5_error_code ret;
+    krb5_creds *credp = NULL;
+    int oneshot = 1;
+
+    event = *e;
+
+    switch (event->action) {
+    case KCM_EVENT_ACQUIRE_CREDS:
+       ret = kcm_ccache_acquire(context, event->ccache, &credp);
+       oneshot = 0;
+       break;
+    case KCM_EVENT_RENEW_CREDS:
+       ret = kcm_ccache_refresh(context, event->ccache, &credp);
+       if (ret == KRB5KRB_AP_ERR_TKT_EXPIRED) {
+           ret = kcm_ccache_acquire(context, event->ccache, &credp);
+       }
+       oneshot = 0;
+       break;
+    case KCM_EVENT_DESTROY_CREDS:
+       ret = kcm_ccache_destroy(context, event->ccache->name);
+       break;
+    case KCM_EVENT_DESTROY_EMPTY_CACHE:
+       ret = kcm_ccache_destroy_if_empty(context, event->ccache);
+       break;
+    default:
+       ret = KRB5_FCC_INTERNAL;
+       break;
+    }
+
+    event->fire_count++;
+
+    if (ret) {
+       /* Reschedule failed event for another time */ 
+       event->fire_time += event->backoff_time;
+       if (event->backoff_time < KCM_EVENT_MAX_BACKOFF_TIME)
+           event->backoff_time *= 2;
+
+       /* Remove it if it would never get executed */
+       if (event->expire_time &&
+           event->fire_time > event->expire_time)
+           kcm_remove_event_internal(context, e);
+    } else {
+       if (!oneshot) {
+           char *cpn;
+
+           if (krb5_unparse_name(context, event->ccache->client,
+                                 &cpn))
+               cpn = NULL;
+
+           kcm_log(0, "%s credentials in cache %s for principal %s",
+                   (event->action == KCM_EVENT_ACQUIRE_CREDS) ?
+                       "Acquired" : "Renewed",
+                   event->ccache->name,
+                   (cpn != NULL) ? cpn : "<none>");
+
+           if (cpn != NULL)
+               free(cpn);
+
+           /* Succeeded, but possibly replaced with another event */
+           ret = kcm_ccache_make_default_event(context, event, credp);
+           if (ret || event->action == KCM_EVENT_NONE)
+               oneshot = 1;
+           else
+               log_event(event, "requeuing");
+       }
+       if (oneshot)
+           kcm_remove_event_internal(context, e);
+    }
+
+    return ret;
+}
+
+krb5_error_code
+kcm_run_events(krb5_context context,
+              time_t now)
+{
+    krb5_error_code ret;
+    kcm_event **e;
+
+    HEIMDAL_MUTEX_lock(&events_mutex);
+
+    /* Only run event queue every N seconds */
+    if (now < last_run + KCM_EVENT_QUEUE_INTERVAL) {
+       HEIMDAL_MUTEX_unlock(&events_mutex);
+       return 0;
+    }
+
+    /* go through events list, fire and expire */
+    for (e = &events_head; *e != NULL; e = &(*e)->next) {
+       if ((*e)->valid == 0)
+           continue;
+
+       if (now >= (*e)->fire_time) {
+           ret = kcm_fire_event(context, e);
+           if (ret) {
+               kcm_log(1, "Could not fire event for cache %s: %s",
+                       (*e)->ccache->name, krb5_get_err_text(context, ret));
+           }
+       } else if ((*e)->expire_time && now >= (*e)->expire_time) {
+           ret = kcm_remove_event_internal(context, e);
+           if (ret) {
+               kcm_log(1, "Could not expire event for cache %s: %s",
+                       (*e)->ccache->name, krb5_get_err_text(context, ret));
+           }
+       }
+
+       if (*e == NULL)
+           break;
+    }
+
+    last_run = now;
+
+    HEIMDAL_MUTEX_unlock(&events_mutex);
+
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kcm/glue.c b/src/kerberosV/src/kcm/glue.c
new file mode 100644 (file)
index 0000000..727191f
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: glue.c,v 1.4 2005/02/06 01:22:48 lukeh Exp $");
+
+/*
+ * Server-side loopback glue for credentials cache operations; this
+ * must be initialized with kcm_internal_ccache(), it is not for real
+ * use. This entire file assumes the cache is locked, it does not do
+ * any concurrency checking for multithread applications.
+ */
+
+#define KCMCACHE(X)    ((kcm_ccache)(X)->data.data)
+#define CACHENAME(X)   (KCMCACHE(X)->name)
+
+static const char *
+kcmss_get_name(krb5_context context,
+              krb5_ccache id)
+{
+    return CACHENAME(id);
+}
+
+static krb5_error_code
+kcmss_resolve(krb5_context context, krb5_ccache *id, const char *res)
+{
+    return KRB5_FCC_INTERNAL;
+}
+
+static krb5_error_code
+kcmss_gen_new(krb5_context context, krb5_ccache *id)
+{
+    return KRB5_FCC_INTERNAL;
+}
+
+static krb5_error_code
+kcmss_initialize(krb5_context context,
+                krb5_ccache id,
+                krb5_principal primary_principal)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    ret = kcm_zero_ccache_data_internal(context, c);
+    if (ret)
+       return ret;
+
+    ret = krb5_copy_principal(context, primary_principal,
+                             &c->client);
+
+    return ret;
+}
+
+static krb5_error_code
+kcmss_close(krb5_context context,
+           krb5_ccache id)
+{
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    id->data.data = NULL;
+    id->data.length = 0;
+
+    return 0;
+}
+
+static krb5_error_code
+kcmss_destroy(krb5_context context,
+             krb5_ccache id)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    ret = kcm_ccache_destroy(context, CACHENAME(id));
+
+    return ret;
+}
+
+static krb5_error_code
+kcmss_store_cred(krb5_context context,
+                krb5_ccache id,
+                krb5_creds *creds)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+    krb5_creds *tmp;
+
+    KCM_ASSERT_VALID(c);
+
+    ret = kcm_ccache_store_cred_internal(context, c, creds, 1, &tmp);
+
+    return ret;
+}
+
+static krb5_error_code
+kcmss_retrieve(krb5_context context,
+              krb5_ccache id,
+              krb5_flags which,
+              const krb5_creds *mcred,
+              krb5_creds *creds)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+    krb5_creds *credp;
+
+    KCM_ASSERT_VALID(c);
+
+    ret = kcm_ccache_retrieve_cred_internal(context, c, which,
+                                           mcred, &credp);
+    if (ret)
+       return ret;
+
+    ret = krb5_copy_creds_contents(context, credp, creds);
+    if (ret)
+       return ret;
+
+    return 0;
+}
+
+static krb5_error_code
+kcmss_get_principal(krb5_context context,
+                   krb5_ccache id,
+                   krb5_principal *principal)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    ret = krb5_copy_principal(context, c->client,
+                             principal);
+
+    return ret;
+}
+
+static krb5_error_code
+kcmss_get_first (krb5_context context,
+                krb5_ccache id,
+                krb5_cc_cursor *cursor)
+{
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    *cursor = c->creds;
+
+    return (*cursor == NULL) ? KRB5_CC_END : 0;
+}
+
+static krb5_error_code
+kcmss_get_next (krb5_context context,
+               krb5_ccache id,
+               krb5_cc_cursor *cursor,
+               krb5_creds *creds)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    ret = krb5_copy_creds_contents(context,
+                                  &((struct kcm_creds *)cursor)->cred,
+                                  creds);
+    if (ret)
+       return ret;
+
+    *cursor = ((struct kcm_creds *)cursor)->next;
+    if (*cursor == 0)
+       ret = KRB5_CC_END;
+
+    return ret;
+}
+
+static krb5_error_code
+kcmss_end_get (krb5_context context,
+              krb5_ccache id,
+              krb5_cc_cursor *cursor)
+{
+    *cursor = NULL;
+    return 0;
+}
+
+static krb5_error_code
+kcmss_remove_cred(krb5_context context,
+                 krb5_ccache id,
+                 krb5_flags which,
+                 krb5_creds *cred)
+{
+    krb5_error_code ret;
+    kcm_ccache c = KCMCACHE(id);
+
+    KCM_ASSERT_VALID(c);
+
+    ret = kcm_ccache_remove_cred_internal(context, c, which, cred);
+
+    return ret;
+}
+
+static krb5_error_code
+kcmss_set_flags(krb5_context context,
+               krb5_ccache id,
+               krb5_flags flags)
+{
+    return 0;
+}
+
+static krb5_error_code
+kcmss_get_version(krb5_context context,
+                 krb5_ccache id)
+{
+    return 0;
+}
+
+static const krb5_cc_ops krb5_kcmss_ops = {
+    "KCM",
+    kcmss_get_name,
+    kcmss_resolve,
+    kcmss_gen_new,
+    kcmss_initialize,
+    kcmss_destroy,
+    kcmss_close,
+    kcmss_store_cred,
+    kcmss_retrieve,
+    kcmss_get_principal,
+    kcmss_get_first,
+    kcmss_get_next,
+    kcmss_end_get,
+    kcmss_remove_cred,
+    kcmss_set_flags,
+    kcmss_get_version
+};
+
+krb5_error_code
+kcm_internal_ccache(krb5_context context,
+                   kcm_ccache c,
+                   krb5_ccache id)
+{
+    id->ops = &krb5_kcmss_ops;
+    id->data.length = sizeof(*c);
+    id->data.data = c;
+
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kcm/headers.h b/src/kerberosV/src/kcm/headers.h
new file mode 100644 (file)
index 0000000..1042dd8
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 __HEADERS_H__
+#define __HEADERS_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_SYS_UCRED_H
+#include <sys/ucred.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#ifdef HAVE_GETPEERUCRED
+#include <ucred.h>
+#endif
+#ifdef HAVE_DOOR_CREATE
+#include <door.h>
+#include <alloca.h>
+#endif
+#include <err.h>
+#include <roken.h>
+#include <getarg.h>
+#include <base64.h>
+#include <parse_units.h>
+#include <krb5.h>
+#include <krb5_locl.h>
+
+#endif /* __HEADERS_H__ */
+
diff --git a/src/kerberosV/src/kcm/kcm.8 b/src/kerberosV/src/kcm/kcm.8
new file mode 100644 (file)
index 0000000..9d66f6c
--- /dev/null
@@ -0,0 +1,221 @@
+.\" Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\"
+.\" $KTH: kcm.8,v 1.5 2005/05/30 14:31:20 lha Exp $
+.\"
+.Dd May 29, 2005
+.Dt KCM 8
+.Os Heimdal
+.Sh NAME
+.Nm kcm
+.Nd
+is a process based credential cache for Kerberos tickets.
+.Sh SYNOPSIS
+.Nm
+.Op Fl -cache-name= Ns Ar cachename
+.Oo Fl c Ar file \*(Ba Xo
+.Fl -config-file= Ns Ar file
+.Xc
+.Oc
+.Oo Fl g Ar group \*(Ba Xo
+.Fl -group= Ns Ar group
+.Xc
+.Oc
+.Op Fl -max-request= Ns Ar size
+.Op Fl -disallow-getting-krbtgt
+.Op Fl -detach
+.Op Fl h | Fl -help
+.Oo Fl k Ar principal \*(Ba Xo
+.Fl -system-principal= Ns Ar principal
+.Xc
+.Oc
+.Oo Fl l Ar time \*(Ba Xo
+.Fl -lifetime= Ns Ar time
+.Xc
+.Oc
+.Oo Fl m Ar mode \*(Ba Xo
+.Fl -mode= Ns Ar mode
+.Xc
+.Oc
+.Op Fl n | Fl -no-name-constraints
+.Oo Fl r Ar time \*(Ba Xo
+.Fl -renewable-life= Ns Ar time
+.Xc
+.Oc
+.Oo Fl s Ar path \*(Ba Xo
+.Fl -socket-path= Ns Ar path
+.Xc
+.Oc
+.Oo Xo
+.Fl -door-path= Ns Ar path
+.Xc
+.Oc
+.Oo Fl S Ar principal \*(Ba Xo
+.Fl -server= Ns Ar principal
+.Xc
+.Oc
+.Oo Fl t Ar keytab \*(Ba Xo
+.Fl -keytab= Ns Ar keytab
+.Xc
+.Oc
+.Oo Fl u Ar user \*(Ba Xo
+.Fl -user= Ns Ar user
+.Xc
+.Oc
+.Op Fl v | Fl -version
+.Sh DESCRIPTION
+.Nm
+is a process based credential cache.
+To use it, set the
+.Ev KRB5CCNAME
+enviroment variable to
+.Ql KCM: Ns Ar uid
+or add the stanza
+.br
+[libdefaults]default_cc_name KCM:%{uid}
+.br
+to the
+.Pa /etc/krb5.conf
+configuration file and make sure
+.Nm kcm
+is started in the system startup files.
+.Pp
+The
+.Nm
+daemon can hold the credentials for all users in the system.  Access
+control is done with Unix-like permissions.  The daemon checks the
+access on all operations based on the uid and gid of the user.  The
+tickets are renewed as long as is permitted by the KDC's policy.
+.Pp
+The
+.Nm
+daemon can also keep a SYSTEM credential that server processes can
+use to access services.  One example of usage might be an nss_ldap
+module that quickly needs to get credentials and doesn't want to renew
+the ticket itself. 
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl -cache-name= Ns Ar cachename
+.Xc
+system cache name
+.It Xo
+.Fl c Ar file ,
+.Fl -config-file= Ns Ar file
+.Xc
+location of config file
+.It Xo
+.Fl g Ar group ,
+.Fl -group= Ns Ar group
+.Xc
+system cache group
+.It Xo
+.Fl -max-request= Ns Ar size
+.Xc
+max size for a kcm-request
+.It Xo
+.Fl -disallow-getting-krbtgt
+.Xc
+disallow extracting any krbtgt from the
+.Nm kcm
+daemon.
+.It Xo
+.Fl -detach
+.Xc
+detach from console
+.It Xo
+.Fl h ,
+.Fl -help
+.Xc
+.It Xo
+.Fl k Ar principal ,
+.Fl -system-principal= Ns Ar principal
+.Xc
+system principal name
+.It Xo
+.Fl l Ar time ,
+.Fl -lifetime= Ns Ar time
+.Xc
+lifetime of system tickets
+.It Xo
+.Fl m Ar mode ,
+.Fl -mode= Ns Ar mode
+.Xc
+octal mode of system cache
+.It Xo
+.Fl n ,
+.Fl -no-name-constraints
+.Xc
+disable credentials cache name constraints
+.It Xo
+.Fl r Ar time ,
+.Fl -renewable-life= Ns Ar time
+.Xc
+renewable lifetime of system tickets
+.It Xo
+.Fl s Ar path ,
+.Fl -socket-path= Ns Ar path
+.Xc
+path to kcm domain socket
+.It Xo
+.Fl -door-path= Ns Ar path
+.Xc
+path to kcm door socket
+.It Xo
+.Fl S Ar principal ,
+.Fl -server= Ns Ar principal
+.Xc
+server to get system ticket for
+.It Xo
+.Fl t Ar keytab ,
+.Fl -keytab= Ns Ar keytab
+.Xc
+system keytab name
+.It Xo
+.Fl u Ar user ,
+.Fl -user= Ns Ar user
+.Xc
+system cache owner
+.It Xo
+.Fl v ,
+.Fl -version
+.Xc
+.El
+.\".Sh ENVIRONMENT
+.\".Sh FILES
+.\".Sh EXAMPLES
+.\".Sh DIAGNOSTICS
+.\".Sh SEE ALSO
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/src/kerberosV/src/kcm/kcm_locl.h b/src/kerberosV/src/kcm/kcm_locl.h
new file mode 100644 (file)
index 0000000..51f070d
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* 
+ * $KTH: kcm_locl.h,v 1.8 2005/06/07 00:31:29 lha Exp $ 
+ */
+
+#ifndef __KCM_LOCL_H__
+#define __KCM_LOCL_H__
+
+#include "headers.h"
+
+#include <kcm.h>
+
+#define KCM_LOG_REQUEST(_context, _client, _opcode)    do { \
+    kcm_log(1, "%s request by process %d/uid %d", \
+           kcm_op2string(_opcode), (_client)->pid, (_client)->uid); \
+    } while (0)
+
+#define KCM_LOG_REQUEST_NAME(_context, _client, _opcode, _name)        do { \
+    kcm_log(1, "%s request for cache %s by process %d/uid %d", \
+           kcm_op2string(_opcode), (_name), (_client)->pid, (_client)->uid); \
+    } while (0)
+
+/* Cache management */
+
+#define KCM_FLAGS_VALID                        0x0001
+#define KCM_FLAGS_USE_KEYTAB           0x0002
+#define KCM_FLAGS_RENEWABLE            0x0004
+#define KCM_FLAGS_OWNER_IS_SYSTEM      0x0008
+#define KCM_FLAGS_USE_CACHED_KEY       0x0010
+
+#define KCM_MASK_KEY_PRESENT           ( KCM_FLAGS_USE_KEYTAB | \
+                                         KCM_FLAGS_USE_CACHED_KEY )
+
+struct kcm_ccache_data;
+struct kcm_creds;
+
+typedef struct kcm_cursor {
+    pid_t pid;
+    u_int32_t key;
+    struct kcm_creds *credp;           /* pointer to next credential */ 
+    struct kcm_cursor *next;
+} kcm_cursor;
+
+typedef struct kcm_ccache_data {
+    char *name;
+    unsigned refcnt;
+    u_int16_t flags;
+    u_int16_t mode;
+    uid_t uid;
+    gid_t gid;
+    krb5_principal client; /* primary client principal */
+    krb5_principal server; /* primary server principal (TGS if NULL) */
+    struct kcm_creds {
+       krb5_creds cred; /* XXX would be useful for have ACLs on creds */
+       struct kcm_creds *next;
+    } *creds;
+    u_int32_t n_cursor;
+    kcm_cursor *cursors;
+    krb5_deltat tkt_life;
+    krb5_deltat renew_life;
+    union {
+       krb5_keytab keytab;
+       krb5_keyblock keyblock;
+    } key;
+    HEIMDAL_MUTEX mutex;
+    struct kcm_ccache_data *next;
+} kcm_ccache_data;
+
+#define KCM_ASSERT_VALID(_ccache)              do { \
+    if (((_ccache)->flags & KCM_FLAGS_VALID) == 0) \
+       krb5_abortx(context, "kcm_free_ccache_data: ccache invalid"); \
+    else if ((_ccache)->refcnt == 0) \
+       krb5_abortx(context, "kcm_free_ccache_data: ccache refcnt == 0"); \
+    } while (0)
+
+typedef kcm_ccache_data *kcm_ccache;
+
+/* Event management */
+
+typedef struct kcm_event {
+    int valid;
+    time_t fire_time;
+    unsigned fire_count;
+    time_t expire_time;
+    time_t backoff_time;
+    enum {
+       KCM_EVENT_NONE = 0,
+       KCM_EVENT_ACQUIRE_CREDS,
+       KCM_EVENT_RENEW_CREDS,
+       KCM_EVENT_DESTROY_CREDS,
+       KCM_EVENT_DESTROY_EMPTY_CACHE
+    } action;
+    kcm_ccache ccache;
+    struct kcm_event *next;
+} kcm_event;
+
+/* wakeup interval for event queue */
+#define KCM_EVENT_QUEUE_INTERVAL               60
+#define KCM_EVENT_DEFAULT_BACKOFF_TIME         5
+#define KCM_EVENT_MAX_BACKOFF_TIME             (12 * 60 * 60)
+
+
+/* Request format is  LENGTH | MAJOR | MINOR | OPERATION | request */
+/* Response format is LENGTH | STATUS | response */
+
+typedef struct kcm_client {
+    pid_t pid;
+    uid_t uid;
+    gid_t gid;
+} kcm_client;
+
+/* Dispatch table */
+/* passed in OPERATION | ... ; returns STATUS | ... */
+typedef krb5_error_code (*kcm_method)(krb5_context, kcm_client *, kcm_operation, krb5_storage *, krb5_storage *);
+
+struct kcm_op {
+    const char *name;
+    kcm_method method;
+};
+
+#define DEFAULT_LOG_DEST    "0/FILE:" LOCALSTATEDIR "/log/kcmd.log"
+#define _PATH_KCM_CONF     SYSCONFDIR "/kcm.conf"
+
+extern krb5_context kcm_context;
+extern char *socket_path;
+extern char *door_path;
+extern size_t max_request;
+extern sig_atomic_t exit_flag;
+extern int name_constraints;
+extern int detach_from_console;
+extern int disallow_getting_krbtgt;
+
+#if 0
+extern const krb5_cc_ops krb5_kcmss_ops;
+#endif
+
+#include <kcm_protos.h>
+
+#endif /* __KCM_LOCL_H__ */
+
diff --git a/src/kerberosV/src/kcm/kcm_protos.h b/src/kerberosV/src/kcm/kcm_protos.h
new file mode 100644 (file)
index 0000000..d13a8eb
--- /dev/null
@@ -0,0 +1,288 @@
+/* This is a generated file */
+#ifndef __kcm_protos_h__
+#define __kcm_protos_h__
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+krb5_error_code
+kcm_access (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       kcm_operation /*opcode*/,
+       kcm_ccache /*ccache*/);
+
+krb5_error_code
+kcm_ccache_acquire (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_creds **/*credp*/);
+
+krb5_error_code
+kcm_ccache_destroy (
+       krb5_context /*context*/,
+       const char */*name*/);
+
+krb5_error_code
+kcm_ccache_destroy_client (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       const char */*name*/);
+
+krb5_error_code
+kcm_ccache_destroy_if_empty (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/);
+
+krb5_error_code
+kcm_ccache_enqueue_default (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_creds */*newcred*/);
+
+krb5_error_code
+kcm_ccache_gen_new (
+       krb5_context /*context*/,
+       pid_t /*pid*/,
+       uid_t /*uid*/,
+       gid_t /*gid*/,
+       kcm_ccache */*ccache*/);
+
+krb5_error_code
+kcm_ccache_new (
+       krb5_context /*context*/,
+       const char */*name*/,
+       kcm_ccache */*ccache*/);
+
+krb5_error_code
+kcm_ccache_new_client (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       const char */*name*/,
+       kcm_ccache */*ccache_p*/);
+
+char *kcm_ccache_nextid (
+       pid_t /*pid*/,
+       uid_t /*uid*/,
+       gid_t /*gid*/);
+
+krb5_error_code
+kcm_ccache_refresh (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_creds **/*credp*/);
+
+krb5_error_code
+kcm_ccache_remove_cred (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds */*mcreds*/);
+
+krb5_error_code
+kcm_ccache_remove_cred_internal (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds */*mcreds*/);
+
+krb5_error_code
+kcm_ccache_remove_creds (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/);
+
+krb5_error_code
+kcm_ccache_remove_creds_internal (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/);
+
+krb5_error_code
+kcm_ccache_resolve (
+       krb5_context /*context*/,
+       const char */*name*/,
+       kcm_ccache */*ccache*/);
+
+krb5_error_code
+kcm_ccache_resolve_client (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       kcm_operation /*opcode*/,
+       const char */*name*/,
+       kcm_ccache */*ccache*/);
+
+krb5_error_code
+kcm_ccache_retrieve_cred (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds */*mcreds*/,
+       krb5_creds **/*credp*/);
+
+krb5_error_code
+kcm_ccache_retrieve_cred_internal (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds */*mcreds*/,
+       krb5_creds **/*creds*/);
+
+krb5_error_code
+kcm_ccache_store_cred (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_creds */*creds*/,
+       int /*copy*/);
+
+krb5_error_code
+kcm_ccache_store_cred_internal (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/,
+       krb5_creds */*creds*/,
+       int /*copy*/,
+       krb5_creds **/*credp*/);
+
+krb5_error_code
+kcm_chmod (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       kcm_ccache /*ccache*/,
+       u_int16_t /*mode*/);
+
+krb5_error_code
+kcm_chown (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       kcm_ccache /*ccache*/,
+       uid_t /*uid*/,
+       gid_t /*gid*/);
+
+krb5_error_code
+kcm_cleanup_events (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/);
+
+void
+kcm_configure (
+       int /*argc*/,
+       char **/*argv*/);
+
+krb5_error_code
+kcm_cursor_delete (
+       krb5_context /*context*/,
+       pid_t /*pid*/,
+       kcm_ccache /*ccache*/,
+       u_int32_t /*key*/);
+
+krb5_error_code
+kcm_cursor_find (
+       krb5_context /*context*/,
+       pid_t /*pid*/,
+       kcm_ccache /*ccache*/,
+       u_int32_t /*key*/,
+       kcm_cursor **/*cursor*/);
+
+krb5_error_code
+kcm_cursor_new (
+       krb5_context /*context*/,
+       pid_t /*pid*/,
+       kcm_ccache /*ccache*/,
+       u_int32_t */*cursor*/);
+
+krb5_error_code
+kcm_debug_ccache (krb5_context /*context*/);
+
+krb5_error_code
+kcm_debug_events (krb5_context /*context*/);
+
+krb5_error_code
+kcm_dispatch (
+       krb5_context /*context*/,
+       kcm_client */*client*/,
+       krb5_data */*req_data*/,
+       krb5_data */*resp_data*/);
+
+krb5_error_code
+kcm_enqueue_event (
+       krb5_context /*context*/,
+       kcm_event */*event*/);
+
+krb5_error_code
+kcm_enqueue_event_internal (
+       krb5_context /*context*/,
+       kcm_event */*event*/);
+
+krb5_error_code
+kcm_enqueue_event_relative (
+       krb5_context /*context*/,
+       kcm_event */*event*/);
+
+krb5_error_code
+kcm_internal_ccache (
+       krb5_context /*context*/,
+       kcm_ccache /*c*/,
+       krb5_ccache /*id*/);
+
+void
+kcm_log (
+       int /*level*/,
+       const char */*fmt*/,
+       ...);
+
+char*
+kcm_log_msg (
+       int /*level*/,
+       const char */*fmt*/,
+       ...);
+
+char*
+kcm_log_msg_va (
+       int /*level*/,
+       const char */*fmt*/,
+       va_list /*ap*/);
+
+void
+kcm_loop (void);
+
+const char *kcm_op2string (kcm_operation /*opcode*/);
+
+void
+kcm_openlog (void);
+
+krb5_error_code
+kcm_release_ccache (
+       krb5_context /*context*/,
+       kcm_ccache */*ccache*/);
+
+krb5_error_code
+kcm_remove_event (
+       krb5_context /*context*/,
+       kcm_event */*event*/);
+
+krb5_error_code
+kcm_retain_ccache (
+       krb5_context /*context*/,
+       kcm_ccache /*ccache*/);
+
+krb5_error_code
+kcm_run_events (
+       krb5_context /*context*/,
+       time_t /*now*/);
+
+krb5_error_code
+kcm_zero_ccache_data (
+       krb5_context /*context*/,
+       kcm_ccache /*cache*/);
+
+krb5_error_code
+kcm_zero_ccache_data_internal (
+       krb5_context /*context*/,
+       kcm_ccache_data */*cache*/);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kcm_protos_h__ */
diff --git a/src/kerberosV/src/kcm/log.c b/src/kerberosV/src/kcm/log.c
new file mode 100644 (file)
index 0000000..823c084
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1997, 1998, 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: log.c,v 1.3 2005/02/06 01:22:48 lukeh Exp $");
+
+static krb5_log_facility *logf;
+
+void
+kcm_openlog(void)
+{
+    char **s = NULL, **p;
+    krb5_initlog(kcm_context, "kcm", &logf);
+    s = krb5_config_get_strings(kcm_context, NULL, "kcm", "logging", NULL);
+    if(s == NULL)
+       s = krb5_config_get_strings(kcm_context, NULL, "logging", "kcm", NULL);
+    if(s){
+       for(p = s; *p; p++)
+           krb5_addlog_dest(kcm_context, logf, *p);
+       krb5_config_free_strings(s);
+    }else
+       krb5_addlog_dest(kcm_context, logf, DEFAULT_LOG_DEST);
+    krb5_set_warn_dest(kcm_context, logf);
+}
+
+char*
+kcm_log_msg_va(int level, const char *fmt, va_list ap)
+{
+    char *msg;
+    krb5_vlog_msg(kcm_context, logf, &msg, level, fmt, ap);
+    return msg;
+}
+
+char*
+kcm_log_msg(int level, const char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    va_start(ap, fmt);
+    s = kcm_log_msg_va(level, fmt, ap);
+    va_end(ap);
+    return s;
+}
+
+void
+kcm_log(int level, const char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    va_start(ap, fmt);
+    s = kcm_log_msg_va(level, fmt, ap);
+    if(s) free(s);
+    va_end(ap);
+}
diff --git a/src/kerberosV/src/kcm/main.c b/src/kerberosV/src/kcm/main.c
new file mode 100644 (file)
index 0000000..f331bff
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: main.c,v 1.5 2005/05/30 10:58:14 lha Exp $");
+
+sig_atomic_t exit_flag = 0;
+
+krb5_context kcm_context = NULL;
+
+static RETSIGTYPE
+sigterm(int sig)
+{
+    exit_flag = 1;
+}
+
+static RETSIGTYPE
+sigusr1(int sig)
+{
+    kcm_debug_ccache(kcm_context);
+}
+
+static RETSIGTYPE
+sigusr2(int sig)
+{
+    kcm_debug_events(kcm_context);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    setprogname(argv[0]);
+
+    ret = krb5_init_context(&kcm_context);
+    if (ret) {
+       errx (1, "krb5_init_context failed: %d", ret);
+       return ret;
+    }
+
+    kcm_configure(argc, argv);
+    
+#ifdef HAVE_SIGACTION
+    {
+       struct sigaction sa;
+
+       sa.sa_flags = 0;
+       sa.sa_handler = sigterm;
+       sigemptyset(&sa.sa_mask);
+
+       sigaction(SIGINT, &sa, NULL);
+       sigaction(SIGTERM, &sa, NULL);
+
+       sa.sa_handler = sigusr1;
+       sigaction(SIGUSR1, &sa, NULL);
+
+       sa.sa_handler = sigusr2;
+       sigaction(SIGUSR2, &sa, NULL);
+
+       sa.sa_handler = SIG_IGN;
+       sigaction(SIGPIPE, &sa, NULL);
+    }
+#else
+    signal(SIGINT, sigterm);
+    signal(SIGTERM, sigterm);
+    signal(SIGUSR1, sigusr1);
+    signal(SIGUSR2, sigusr2);
+    signal(SIGPIPE, SIG_IGN);
+#endif
+    if (detach_from_console)
+       daemon(0, 0);
+    pidfile(NULL);
+    kcm_loop();
+    krb5_free_context(kcm_context);
+    return 0;
+}
diff --git a/src/kerberosV/src/kcm/protocol.c b/src/kerberosV/src/kcm/protocol.c
new file mode 100644 (file)
index 0000000..d62cd80
--- /dev/null
@@ -0,0 +1,1045 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: protocol.c,v 1.8 2005/05/30 10:59:00 lha Exp $");
+
+static krb5_error_code
+kcm_op_noop(krb5_context context,
+           kcm_client *client,
+           kcm_operation opcode,
+           krb5_storage *request,
+           krb5_storage *response)
+{
+    KCM_LOG_REQUEST(context, client, opcode);
+
+    return 0;  
+}
+
+/*
+ * Request:
+ *     NameZ
+ * Response:
+ *     NameZ
+ *
+ */
+static krb5_error_code
+kcm_op_get_name(krb5_context context,
+               kcm_client *client,
+               kcm_operation opcode,
+               krb5_storage *request,
+               krb5_storage *response)
+
+{
+    krb5_error_code ret;
+    char *name = NULL;
+    kcm_ccache ccache;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_store_stringz(response, ccache->name);
+    if (ret) {
+       kcm_release_ccache(context, &ccache);
+       free(name);
+       return ret;
+    }
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+    return 0;
+}
+
+/*
+ * Request:
+ *     
+ * Response:
+ *     NameZ
+ */
+static krb5_error_code
+kcm_op_gen_new(krb5_context context,
+              kcm_client *client,
+              kcm_operation opcode,
+              krb5_storage *request,
+              krb5_storage *response)
+{
+    krb5_error_code ret;
+    char *name;
+
+    KCM_LOG_REQUEST(context, client, opcode);
+
+    name = kcm_ccache_nextid(client->pid, client->uid, client->gid);
+    if (name == NULL) {
+       return KRB5_CC_NOMEM;
+    }
+
+    ret = krb5_store_stringz(response, name);
+    free(name);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     Principal
+ *     
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_initialize(krb5_context context,
+                 kcm_client *client,
+                 kcm_operation opcode,
+                 krb5_storage *request,
+                 krb5_storage *response)
+{
+    kcm_ccache ccache;
+    krb5_principal principal;
+    krb5_error_code ret;
+    char *name;
+#if 0
+    kcm_event event;
+#endif
+
+    KCM_LOG_REQUEST(context, client, opcode);
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    ret = krb5_ret_principal(request, &principal);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_new_client(context, client, name, &ccache);
+    if (ret) {
+       free(name);
+       krb5_free_principal(context, principal);
+       return ret;
+    }
+
+    ccache->client = principal;
+
+    free(name);
+
+#if 0
+    /*
+     * Create a new credentials cache. To mitigate DoS attacks we will
+     * expire it in 30 minutes unless it has some credentials added
+     * to it
+     */
+
+    event.fire_time = 30 * 60;
+    event.expire_time = 0;
+    event.backoff_time = 0;
+    event.action = KCM_EVENT_DESTROY_EMPTY_CACHE;
+    event.ccache = ccache;
+
+    ret = kcm_enqueue_event_relative(context, &event);
+#endif
+
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_destroy(krb5_context context,
+              kcm_client *client,
+              kcm_operation opcode,
+              krb5_storage *request,
+              krb5_storage *response)
+{
+    krb5_error_code ret;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = kcm_ccache_destroy_client(context, client, name);
+
+    free(name);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     Creds
+ *     
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_store(krb5_context context,
+            kcm_client *client,
+            kcm_operation opcode,
+            krb5_storage *request,
+            krb5_storage *response)
+{
+    krb5_creds creds;
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_creds(request, &creds);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       krb5_free_creds_contents(context, &creds);
+       return ret;
+    }
+
+    ret = kcm_ccache_store_cred(context, ccache, &creds, 0);
+    if (ret) {
+       free(name);
+       krb5_free_creds_contents(context, &creds);
+       kcm_release_ccache(context, &ccache);
+       return ret;
+    }
+
+    kcm_ccache_enqueue_default(context, ccache, &creds);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return 0;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     WhichFields
+ *     MatchCreds
+ *
+ * Response:
+ *     Creds
+ *     
+ */
+static krb5_error_code
+kcm_op_retrieve(krb5_context context,
+               kcm_client *client,
+               kcm_operation opcode,
+               krb5_storage *request,
+               krb5_storage *response)
+{
+    u_int32_t flags;
+    krb5_creds mcreds;
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+    krb5_creds *credp;
+    int free_creds = 0;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &flags);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_ret_creds_tag(request, &mcreds);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    if (disallow_getting_krbtgt &&
+       mcreds.server->name.name_string.len == 2 &&
+       strcmp(mcreds.server->name.name_string.val[0], KRB5_TGS_NAME) == 0)
+    {
+       free(name);
+       krb5_free_creds_contents(context, &mcreds);
+       return KRB5_FCC_PERM;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       krb5_free_creds_contents(context, &mcreds);
+       return ret;
+    }
+
+    ret = kcm_ccache_retrieve_cred(context, ccache, flags,
+                                  &mcreds, &credp);
+    if (ret && ((flags & KRB5_GC_CACHED) == 0)) {
+       krb5_ccache_data ccdata;
+       krb5_creds in;
+
+       memset(&in, 0, sizeof(in));
+
+       /* try and acquire */
+       HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+       /* Fake up an internal ccache */
+       kcm_internal_ccache(context, ccache, &ccdata);
+
+       /* glue cc layer will store creds */
+       ret = krb5_get_credentials(context, 0, &ccdata, &mcreds, &credp);
+       if (ret == 0)
+           free_creds = 1;
+
+       HEIMDAL_MUTEX_unlock(&ccache->mutex);
+    }
+
+    if (ret == 0) {
+       ret = krb5_store_creds(response, credp);
+    }
+
+    free(name);
+    krb5_free_creds_contents(context, &mcreds);
+    kcm_release_ccache(context, &ccache);
+
+    if (free_creds)
+       krb5_free_cred_contents(context, credp);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *
+ * Response:
+ *     Principal
+ */
+static krb5_error_code
+kcm_op_get_principal(krb5_context context,
+                    kcm_client *client,
+                    kcm_operation opcode,
+                    krb5_storage *request,
+                    krb5_storage *response)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    if (ccache->client == NULL)
+       ret = KRB5_CC_NOTFOUND;
+    else
+       ret = krb5_store_principal(response, ccache->client);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return 0;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *
+ * Response:
+ *     Cursor
+ *     
+ */
+static krb5_error_code
+kcm_op_get_first(krb5_context context,
+                kcm_client *client,
+                kcm_operation opcode,
+                krb5_storage *request,
+                krb5_storage *response)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    u_int32_t cursor;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_cursor_new(context, client->pid, ccache, &cursor);
+    if (ret) {
+       kcm_release_ccache(context, &ccache);
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_store_int32(response, cursor);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     Cursor
+ *
+ * Response:
+ *     Creds
+ */
+static krb5_error_code
+kcm_op_get_next(krb5_context context,
+               kcm_client *client,
+               kcm_operation opcode,
+               krb5_storage *request,
+               krb5_storage *response)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+    u_int32_t cursor;
+    kcm_cursor *c;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &cursor);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_cursor_find(context, client->pid, ccache, cursor, &c);
+    if (ret) {
+       kcm_release_ccache(context, &ccache);
+       free(name);
+       return ret;
+    }
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+    if (c->credp == NULL) {
+       ret = KRB5_CC_END;
+    } else {
+       ret = krb5_store_creds(response, &c->credp->cred);
+       c->credp = c->credp->next;
+    }
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     Cursor
+ *
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_end_get(krb5_context context,
+              kcm_client *client,
+              kcm_operation opcode,
+              krb5_storage *request,
+              krb5_storage *response)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    u_int32_t cursor;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &cursor);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_cursor_delete(context, client->pid, ccache, cursor);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     WhichFields
+ *     MatchCreds
+ *
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_remove_cred(krb5_context context,
+                  kcm_client *client,
+                  kcm_operation opcode,
+                  krb5_storage *request,
+                  krb5_storage *response)
+{
+    u_int32_t whichfields;
+    krb5_creds mcreds;
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &whichfields);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_ret_creds_tag(request, &mcreds);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       krb5_free_creds_contents(context, &mcreds);
+       return ret;
+    }
+
+    ret = kcm_ccache_remove_cred(context, ccache, whichfields, &mcreds);
+
+    /* XXX need to remove any events that match */
+
+    free(name);
+    krb5_free_creds_contents(context, &mcreds);
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     Flags
+ *
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_set_flags(krb5_context context,
+                kcm_client *client,
+                kcm_operation opcode,
+                krb5_storage *request,
+                krb5_storage *response)
+{
+    u_int32_t flags;
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &flags);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    /* we don't really support any flags yet */
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return 0;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     UID
+ *     GID
+ *
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_chown(krb5_context context,
+            kcm_client *client,
+            kcm_operation opcode,
+            krb5_storage *request,
+            krb5_storage *response)
+{
+    u_int32_t uid;
+    u_int32_t gid;
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &uid);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_ret_int32(request, &gid);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_chown(context, client, ccache, uid, gid);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     Mode
+ *
+ * Response:
+ *     
+ */
+static krb5_error_code
+kcm_op_chmod(krb5_context context,
+            kcm_client *client,
+            kcm_operation opcode,
+            krb5_storage *request,
+            krb5_storage *response)
+{
+    u_int16_t mode;
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int16(request, &mode);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_chmod(context, client, ccache, mode);
+
+    free(name);
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Protocol extensions for moving ticket acquisition responsibility
+ * from client to KCM follow.
+ */
+
+/*
+ * Request:
+ *     NameZ
+ *     ServerPrincipalPresent
+ *     ServerPrincipal OPTIONAL
+ *     Key
+ *
+ * Repsonse:
+ *
+ */
+static krb5_error_code
+kcm_op_get_initial_ticket(krb5_context context,
+                         kcm_client *client,
+                         kcm_operation opcode,
+                         krb5_storage *request,
+                         krb5_storage *response)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+    int8_t not_tgt = 0;
+    krb5_principal server = NULL;
+    krb5_keyblock key;
+
+    krb5_keyblock_zero(&key);
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int8(request, &not_tgt);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    if (not_tgt) {
+       ret = krb5_ret_principal(request, &server);
+       if (ret) {
+           free(name);
+           return ret;
+       }
+    }
+
+    ret = krb5_ret_keyblock(request, &key);
+    if (ret) {
+       free(name);
+       if (server != NULL)
+           krb5_free_principal(context, server);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret == 0) {
+       HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+       if (ccache->server != NULL) {
+           krb5_free_principal(context, ccache->server);
+           ccache->server = NULL;
+       }
+
+       krb5_free_keyblock(context, &ccache->key.keyblock);
+
+       ccache->server = server;
+       ccache->key.keyblock = key;
+       ccache->flags |= KCM_FLAGS_USE_CACHED_KEY;
+
+       ret = kcm_ccache_enqueue_default(context, ccache, NULL);
+       if (ret) {
+           ccache->server = NULL;
+           krb5_keyblock_zero(&ccache->key.keyblock);
+           ccache->flags &= ~(KCM_FLAGS_USE_CACHED_KEY);
+       }
+
+       HEIMDAL_MUTEX_unlock(&ccache->mutex);
+    }
+
+    free(name);
+
+    if (ret != 0) {
+       krb5_free_principal(context, server);
+       krb5_free_keyblock(context, &key);
+    }
+
+    kcm_release_ccache(context, &ccache);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *     NameZ
+ *     ServerPrincipal
+ *     KDCFlags
+ *     EncryptionType
+ *
+ * Repsonse:
+ *
+ */
+static krb5_error_code
+kcm_op_get_ticket(krb5_context context,
+                 kcm_client *client,
+                 kcm_operation opcode,
+                 krb5_storage *request,
+                 krb5_storage *response)
+{
+    krb5_error_code ret;
+    kcm_ccache ccache;
+    char *name;
+    krb5_principal server = NULL;
+    krb5_ccache_data ccdata;
+    krb5_creds in, *out;
+    krb5_kdc_flags flags;
+
+    memset(&in, 0, sizeof(in));
+
+    ret = krb5_ret_stringz(request, &name);
+    if (ret)
+       return ret;
+
+    KCM_LOG_REQUEST_NAME(context, client, opcode, name);
+
+    ret = krb5_ret_int32(request, &flags.i);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_ret_int32(request, &in.session.keytype);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = krb5_ret_principal(request, &server);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = kcm_ccache_resolve_client(context, client, opcode,
+                                   name, &ccache);
+    if (ret) {
+       krb5_free_principal(context, server);
+       free(name);
+       return ret;
+    }
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    /* Fake up an internal ccache */
+    kcm_internal_ccache(context, ccache, &ccdata);
+
+    in.client = ccache->client;
+    in.server = server;
+    in.times.endtime = 0;
+
+    /* glue cc layer will store creds */
+    ret = krb5_get_credentials_with_flags(context, 0, flags,
+                                         &ccdata, &in, &out);
+
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    if (ret == 0)
+       krb5_free_cred_contents(context, out);
+
+    free(name);
+
+    return ret;
+}
+
+static struct kcm_op kcm_ops[] = {
+    { "NOOP",                  kcm_op_noop },
+    { "GET_NAME",              kcm_op_get_name },
+    { "RESOLVE",               kcm_op_noop },
+    { "GEN_NEW",               kcm_op_gen_new },
+    { "INITIALIZE",            kcm_op_initialize },
+    { "DESTROY",               kcm_op_destroy },
+    { "STORE",                 kcm_op_store },
+    { "RETRIEVE",              kcm_op_retrieve },
+    { "GET_PRINCIPAL",         kcm_op_get_principal },
+    { "GET_FIRST",             kcm_op_get_first },
+    { "GET_NEXT",              kcm_op_get_next },
+    { "END_GET",               kcm_op_end_get },
+    { "REMOVE_CRED",           kcm_op_remove_cred },
+    { "SET_FLAGS",             kcm_op_set_flags },
+    { "CHOWN",                 kcm_op_chown },
+    { "CHMOD",                 kcm_op_chmod },
+    { "GET_INITIAL_TICKET",    kcm_op_get_initial_ticket },
+    { "GET_TICKET",            kcm_op_get_ticket }
+};
+
+
+const char *kcm_op2string(kcm_operation opcode)
+{
+    if (opcode >= sizeof(kcm_ops)/sizeof(kcm_ops[0]))
+       return "Unknown operation";
+
+    return kcm_ops[opcode].name;
+}
+
+krb5_error_code
+kcm_dispatch(krb5_context context,
+            kcm_client *client,
+            krb5_data *req_data,
+            krb5_data *resp_data)
+{
+    krb5_error_code ret;
+    kcm_method method;
+    krb5_storage *req_sp = NULL;
+    krb5_storage *resp_sp = NULL;
+    u_int16_t opcode;
+
+    resp_sp = krb5_storage_emem();
+    if (resp_sp == NULL) {
+       return ENOMEM;
+    }
+
+    if (client->pid == -1) {
+       kcm_log(0, "Client had invalid process number");
+       ret = KRB5_FCC_INTERNAL;
+       goto out;
+    }
+
+    req_sp = krb5_storage_from_data(req_data);
+    if (req_sp == NULL) {
+       kcm_log(0, "Process %d: failed to initialize storage from data",
+               client->pid);
+       ret = KRB5_CC_IO;
+       goto out;
+    }
+
+    krb5_ret_int16(req_sp, &opcode);
+
+    if (opcode >= sizeof(kcm_ops)/sizeof(kcm_ops[0])) {
+       kcm_log(0, "Process %d: invalid operation code %d",
+               client->pid, opcode);
+       ret = KRB5_FCC_INTERNAL;
+       goto out;
+    }
+    method = kcm_ops[opcode].method;
+
+    /* seek past place for status code */
+    krb5_storage_seek(resp_sp, 4, SEEK_SET);
+
+    ret = (*method)(context, client, opcode, req_sp, resp_sp);
+
+out:
+    if (req_sp != NULL) {
+       krb5_storage_free(req_sp);
+    }
+
+    krb5_storage_seek(resp_sp, 0, SEEK_SET);
+    krb5_store_int32(resp_sp, ret);
+
+    ret = krb5_storage_to_data(resp_sp, resp_data);
+    krb5_storage_free(resp_sp);
+
+    return ret;
+}
+
diff --git a/src/kerberosV/src/kcm/renew.c b/src/kerberosV/src/kcm/renew.c
new file mode 100644 (file)
index 0000000..f180900
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kcm_locl.h"
+
+RCSID("$KTH: renew.c,v 1.3 2005/02/06 01:22:49 lukeh Exp $");
+
+krb5_error_code
+kcm_ccache_refresh(krb5_context context,
+                  kcm_ccache ccache,
+                  krb5_creds **credp)
+{
+    krb5_error_code ret;
+    krb5_creds in, *out;
+    krb5_kdc_flags flags;
+    krb5_const_realm realm;
+    krb5_ccache_data ccdata;
+
+    memset(&in, 0, sizeof(in));
+
+    KCM_ASSERT_VALID(ccache);
+
+    if (ccache->client == NULL) {
+       /* no primary principal */
+       kcm_log(0, "Refresh credentials requested but no client principal");
+       return KRB5_CC_NOTFOUND;
+    }
+
+    HEIMDAL_MUTEX_lock(&ccache->mutex);
+
+    /* Fake up an internal ccache */
+    kcm_internal_ccache(context, ccache, &ccdata);
+
+    /* Find principal */
+    in.client = ccache->client;
+
+    if (ccache->server != NULL) {
+       ret = krb5_copy_principal(context, ccache->server, &in.server);
+       if (ret) {
+           kcm_log(0, "Failed to copy service principal: %s",
+                   krb5_get_err_text(context, ret));
+           goto out;
+       }
+    } else {
+       realm = krb5_principal_get_realm(context, in.client);
+       ret = krb5_make_principal(context, &in.server, realm,
+                                 KRB5_TGS_NAME, realm, NULL);
+       if (ret) {
+           kcm_log(0, "Failed to make TGS principal for realm %s: %s",
+                   realm, krb5_get_err_text(context, ret));
+           goto out;
+       }
+    }
+
+    if (ccache->tkt_life)
+       in.times.endtime = time(NULL) + ccache->tkt_life;
+    if (ccache->renew_life)
+       in.times.renew_till = time(NULL) + ccache->renew_life;
+
+    flags.i = 0;
+    flags.b.renewable = TRUE;
+    flags.b.renew = TRUE;
+
+    ret = krb5_get_kdc_cred(context,
+                           &ccdata,
+                           flags,
+                           NULL,
+                           NULL,
+                           &in,
+                           &out);
+    if (ret) {
+       kcm_log(0, "Failed to renew credentials for cache %s: %s",
+               ccache->name, krb5_get_err_text(context, ret));
+       goto out;
+    }
+
+    /* Swap them in */
+    kcm_ccache_remove_creds_internal(context, ccache);
+
+    ret = kcm_ccache_store_cred_internal(context, ccache, out, 0, credp);
+    if (ret) {
+       kcm_log(0, "Failed to store credentials for cache %s: %s",
+               ccache->name, krb5_get_err_text(context, ret));
+       krb5_free_creds(context, out);
+       goto out;
+    }
+
+    free(out); /* but not contents */
+
+out:
+    HEIMDAL_MUTEX_unlock(&ccache->mutex);
+
+    return ret;
+}
+
diff --git a/src/kerberosV/src/kdc/524.c b/src/kerberosV/src/kdc/524.c
new file mode 100644 (file)
index 0000000..d62f932
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+RCSID("$KTH: 524.c,v 1.31.2.1 2005/07/26 20:43:13 lha Exp $");
+
+#include <krb5-v4compat.h>
+
+/*
+ * fetch the server from `t', returning the name in malloced memory in
+ * `spn' and the entry itself in `server'
+ */
+
+static krb5_error_code
+fetch_server (const Ticket *t,
+             char **spn,
+             hdb_entry **server,
+             const char *from)
+{
+    krb5_error_code ret;
+    krb5_principal sprinc;
+
+    ret = _krb5_principalname2krb5_principal(&sprinc, t->sname, t->realm);
+    if (ret) {
+       kdc_log(0, "_krb5_principalname2krb5_principal: %s",
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    ret = krb5_unparse_name(context, sprinc, spn);
+    if (ret) {
+       krb5_free_principal(context, sprinc);
+       kdc_log(0, "krb5_unparse_name: %s", krb5_get_err_text(context, ret));
+       return ret;
+    }
+    ret = db_fetch(sprinc, server);
+    krb5_free_principal(context, sprinc);
+    if (ret) {
+       kdc_log(0,
+       "Request to convert ticket from %s for unknown principal %s: %s",
+               from, *spn, krb5_get_err_text(context, ret));
+       if (ret == HDB_ERR_NOENTRY)
+           ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+       return ret;
+    }
+    return 0;
+}
+
+static krb5_error_code
+log_524 (const EncTicketPart *et,
+        const char *from,
+        const char *spn)
+{
+    krb5_principal client;
+    char *cpn;
+    krb5_error_code ret;
+
+    ret = _krb5_principalname2krb5_principal(&client, et->cname, et->crealm);
+    if (ret) {
+       kdc_log(0, "_krb5_principalname2krb5_principal: %s",
+               krb5_get_err_text (context, ret));
+       return ret;
+    }
+    ret = krb5_unparse_name(context, client, &cpn);
+    if (ret) {
+       krb5_free_principal(context, client);
+       kdc_log(0, "krb5_unparse_name: %s",
+               krb5_get_err_text (context, ret));
+       return ret;
+    }
+    kdc_log(1, "524-REQ %s from %s for %s", cpn, from, spn);
+    free(cpn);
+    krb5_free_principal(context, client);
+    return 0;
+}
+
+static krb5_error_code
+verify_flags (const EncTicketPart *et,
+             const char *spn)
+{
+    if(et->endtime < kdc_time){
+       kdc_log(0, "Ticket expired (%s)", spn);
+       return KRB5KRB_AP_ERR_TKT_EXPIRED;
+    }
+    if(et->flags.invalid){
+       kdc_log(0, "Ticket not valid (%s)", spn);
+       return KRB5KRB_AP_ERR_TKT_NYV;
+    }
+    return 0;
+}
+
+/*
+ * set the `et->caddr' to the most appropriate address to use, where
+ * `addr' is the address the request was received from.
+ */
+
+static krb5_error_code
+set_address (EncTicketPart *et,
+            struct sockaddr *addr,
+            const char *from)
+{
+    krb5_error_code ret;
+    krb5_address *v4_addr;
+
+    v4_addr = malloc (sizeof(*v4_addr));
+    if (v4_addr == NULL)
+       return ENOMEM;
+
+    ret = krb5_sockaddr2address(context, addr, v4_addr);
+    if(ret) {
+       free (v4_addr);
+       kdc_log(0, "Failed to convert address (%s)", from);
+       return ret;
+    }
+           
+    if (et->caddr && !krb5_address_search (context, v4_addr, et->caddr)) {
+       kdc_log(0, "Incorrect network address (%s)", from);
+       krb5_free_address(context, v4_addr);
+       free (v4_addr);
+       return KRB5KRB_AP_ERR_BADADDR;
+    }
+    if(v4_addr->addr_type == KRB5_ADDRESS_INET) {
+       /* we need to collapse the addresses in the ticket to a
+          single address; best guess is to use the address the
+          connection came from */
+       
+       if (et->caddr != NULL) {
+           free_HostAddresses(et->caddr);
+       } else {
+           et->caddr = malloc (sizeof (*et->caddr));
+           if (et->caddr == NULL) {
+               krb5_free_address(context, v4_addr);
+               free(v4_addr);
+               return ENOMEM;
+           }
+       }
+       et->caddr->val = v4_addr;
+       et->caddr->len = 1;
+    } else {
+       krb5_free_address(context, v4_addr);
+       free(v4_addr);
+    }
+    return 0;
+}
+
+
+static krb5_error_code
+encrypt_v4_ticket(void *buf, 
+                 size_t len, 
+                 krb5_keyblock *skey, 
+                 EncryptedData *reply)
+{
+    krb5_crypto crypto;
+    krb5_error_code ret;
+    ret = krb5_crypto_init(context, skey, ETYPE_DES_PCBC_NONE, &crypto);
+    if (ret) {
+       free(buf);
+       kdc_log(0, "krb5_crypto_init failed: %s",
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+
+    ret = krb5_encrypt_EncryptedData(context, 
+                                    crypto,
+                                    KRB5_KU_TICKET,
+                                    buf,
+                                    len,
+                                    0,
+                                    reply);
+    krb5_crypto_destroy(context, crypto);
+    if(ret) {
+       kdc_log(0, "Failed to encrypt data: %s",
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    return 0;
+}
+
+static krb5_error_code
+encode_524_response(const char *spn, const EncTicketPart et, const Ticket *t,
+                   hdb_entry *server, EncryptedData *ticket, int *kvno)
+{
+    krb5_error_code ret;
+    int use_2b;
+    size_t len;
+
+    use_2b = krb5_config_get_bool(context, NULL, "kdc", "use_2b", spn, NULL);
+    if(use_2b) {
+       ASN1_MALLOC_ENCODE(EncryptedData, 
+                          ticket->cipher.data, ticket->cipher.length, 
+                          &t->enc_part, &len, ret);
+       
+       if (ret) {
+           kdc_log(0, "Failed to encode v4 (2b) ticket (%s)", spn);
+           return ret;
+       }
+       
+       ticket->etype = 0;
+       ticket->kvno = NULL;
+       *kvno = 213; /* 2b's use this magic kvno */
+    } else {
+       unsigned char buf[MAX_KTXT_LEN + 4 * 4];
+       Key *skey;
+       
+       if (!enable_v4_cross_realm && strcmp (et.crealm, t->realm) != 0) {
+           kdc_log(0, "524 cross-realm %s -> %s disabled", et.crealm,
+                   t->realm);
+           return KRB5KDC_ERR_POLICY;
+       }
+
+       ret = encode_v4_ticket(buf + sizeof(buf) - 1, sizeof(buf),
+                              &et, &t->sname, &len);
+       if(ret){
+           kdc_log(0, "Failed to encode v4 ticket (%s)", spn);
+           return ret;
+       }
+       ret = get_des_key(server, TRUE, FALSE, &skey);
+       if(ret){
+           kdc_log(0, "no suitable DES key for server (%s)", spn);
+           return ret;
+       }
+       ret = encrypt_v4_ticket(buf + sizeof(buf) - len, len, 
+                               &skey->key, ticket);
+       if(ret){
+           kdc_log(0, "Failed to encrypt v4 ticket (%s)", spn);
+           return ret;
+       }
+       *kvno = server->kvno;
+    }
+
+    return 0;
+}
+
+/*
+ * process a 5->4 request, based on `t', and received `from, addr',
+ * returning the reply in `reply'
+ */
+
+krb5_error_code
+do_524(const Ticket *t, krb5_data *reply,
+       const char *from, struct sockaddr *addr)
+{
+    krb5_error_code ret = 0;
+    krb5_crypto crypto;
+    hdb_entry *server = NULL;
+    Key *skey;
+    krb5_data et_data;
+    EncTicketPart et;
+    EncryptedData ticket;
+    krb5_storage *sp;
+    char *spn = NULL;
+    unsigned char buf[MAX_KTXT_LEN + 4 * 4];
+    size_t len;
+    int kvno = 0;
+    
+    if(!enable_524) {
+       ret = KRB5KDC_ERR_POLICY;
+       kdc_log(0, "Rejected ticket conversion request from %s", from);
+       goto out;
+    }
+
+    ret = fetch_server (t, &spn, &server, from);
+    if (ret) {
+       goto out;
+    }
+
+    ret = hdb_enctype2key(context, server, t->enc_part.etype, &skey);
+    if(ret){
+       kdc_log(0, "No suitable key found for server (%s) from %s", spn, from);
+       goto out;
+    }
+    ret = krb5_crypto_init(context, &skey->key, 0, &crypto);
+    if (ret) {
+       kdc_log(0, "krb5_crypto_init failed: %s",
+               krb5_get_err_text(context, ret));
+       goto out;
+    }
+    ret = krb5_decrypt_EncryptedData (context,
+                                     crypto,
+                                     KRB5_KU_TICKET,
+                                     &t->enc_part,
+                                     &et_data);
+    krb5_crypto_destroy(context, crypto);
+    if(ret){
+       kdc_log(0, "Failed to decrypt ticket from %s for %s", from, spn);
+       goto out;
+    }
+    ret = krb5_decode_EncTicketPart(context, et_data.data, et_data.length, 
+                                   &et, &len);
+    krb5_data_free(&et_data);
+    if(ret){
+       kdc_log(0, "Failed to decode ticket from %s for %s", from, spn);
+       goto out;
+    }
+
+    ret = log_524 (&et, from, spn);
+    if (ret) {
+       free_EncTicketPart(&et);
+       goto out;
+    }
+
+    ret = verify_flags (&et, spn);
+    if (ret) {
+       free_EncTicketPart(&et);
+       goto out;
+    }
+
+    ret = set_address (&et, addr, from);
+    if (ret) {
+       free_EncTicketPart(&et);
+       goto out;
+    }
+
+    ret = encode_524_response(spn, et, t, server, &ticket, &kvno);
+    free_EncTicketPart(&et);
+
+out:
+    /* make reply */
+    memset(buf, 0, sizeof(buf));
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp) {
+       krb5_store_int32(sp, ret);
+       if(ret == 0){
+           krb5_store_int32(sp, kvno);
+           krb5_store_data(sp, ticket.cipher);
+           /* Aargh! This is coded as a KTEXT_ST. */
+           krb5_storage_seek(sp, MAX_KTXT_LEN - ticket.cipher.length, SEEK_CUR);
+           krb5_store_int32(sp, 0); /* mbz */
+           free_EncryptedData(&ticket);
+       }
+       ret = krb5_storage_to_data(sp, reply);
+       reply->length = krb5_storage_seek(sp, 0, SEEK_CUR);
+       krb5_storage_free(sp);
+    } else
+       krb5_data_zero(reply);
+    if(spn)
+       free(spn);
+    if(server)
+       free_ent (server);
+    return ret;
+}
diff --git a/src/kerberosV/src/kdc/CVS/Entries b/src/kerberosV/src/kdc/CVS/Entries
new file mode 100644 (file)
index 0000000..7e69b04
--- /dev/null
@@ -0,0 +1,27 @@
+/524.c/1.5/Fri Oct  6 07:09:10 2006//
+/config.c/1.8/Fri Apr 14 08:15:03 2006//
+/headers.h/1.6/Fri Apr 14 08:15:03 2006//
+/hprop.8/1.4/Fri Apr 14 08:15:03 2006//
+/hprop.c/1.7/Thu Oct 16 21:23:21 2008//
+/hprop.h/1.1.1.2/Fri Apr 14 07:32:43 2006//
+/hpropd.8/1.5/Fri Apr 14 08:15:03 2006//
+/hpropd.c/1.5/Fri Apr 14 08:15:03 2006//
+/kadb.h/1.1.1.1/Fri May 25 07:49:32 2001//
+/kaserver.c/1.5/Fri Apr 14 08:15:03 2006//
+/kdc.8/1.9/Thu Jun 15 18:18:14 2006//
+/kdc_locl.h/1.8/Fri Apr 14 08:15:03 2006//
+/kerberos4.c/1.6/Fri Apr 14 08:15:03 2006//
+/kerberos5.c/1.4/Fri Apr 14 08:15:03 2006//
+/kstash.8/1.4/Thu Mar  1 13:14:22 2007//
+/kstash.c/1.1.1.3/Fri Apr 14 07:32:45 2006//
+/log.c/1.1.1.2/Sun May 11 02:15:33 2003//
+/main.c/1.5/Fri Apr 14 08:15:03 2006//
+/misc.c/1.1.1.2/Fri Apr 14 07:32:45 2006//
+/mit_dump.c/1.2/Fri Oct  6 07:09:10 2006//
+/pkinit.c/1.1.1.1/Fri Apr 14 07:32:46 2006//
+/rx.h/1.1.1.1/Fri May 25 07:49:37 2001//
+/string2key.8/1.2/Tue Aug  2 04:00:08 2005//
+/string2key.c/1.6/Mon Dec 18 21:08:28 2006//
+/v4_dump.c/1.5/Fri Apr 14 08:15:03 2006//
+/connect.c/1.2/Sat Jan  2 15:00:40 2010//
+D
diff --git a/src/kerberosV/src/kdc/CVS/Repository b/src/kerberosV/src/kdc/CVS/Repository
new file mode 100644 (file)
index 0000000..ed26942
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/kdc
diff --git a/src/kerberosV/src/kdc/CVS/Root b/src/kerberosV/src/kdc/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/kdc/config.c b/src/kerberosV/src/kdc/config.c
new file mode 100644 (file)
index 0000000..20cd465
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+#include <getarg.h>
+#include <parse_bytes.h>
+
+RCSID("$KTH: config.c,v 1.59 2005/05/23 17:34:12 lha Exp $");
+
+static const char *config_file;        /* location of kdc config file */
+
+int require_preauth = -1;      /* 1 == require preauth for all principals */
+
+size_t max_request;            /* maximal size of a request */
+
+static char *max_request_str;  /* `max_request' as a string */
+
+time_t kdc_warn_pwexpire;      /* time before expiration to print a warning */
+
+struct dbinfo *databases;
+HDB **db;
+int num_db;
+
+const char *port_str;
+
+int detach_from_console = -1;
+#define DETACH_IS_DEFAULT FALSE
+
+int enable_http = -1;
+krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */
+
+krb5_boolean check_ticket_addresses;
+krb5_boolean allow_null_ticket_addresses;
+krb5_boolean allow_anonymous;
+int trpolicy;
+static const char *trpolicy_str;
+
+static struct getarg_strings addresses_str;    /* addresses to listen on */
+krb5_addresses explicit_addresses;
+
+static int disable_des = -1;
+
+char *v4_realm;
+int enable_v4 = -1;
+int enable_kaserver = -1;
+
+int enable_524 = -1;
+int enable_v4_cross_realm = -1;
+
+static int builtin_hdb_flag;
+static int help_flag;
+static int version_flag;
+
+static struct getargs args[] = {
+    { 
+       "config-file",  'c',    arg_string,     &config_file, 
+       "location of config file",      "file" 
+    },
+    { 
+       "require-preauth",      'p',    arg_negative_flag, &require_preauth, 
+       "don't require pa-data in as-reqs"
+    },
+    { 
+       "max-request",  0,      arg_string, &max_request, 
+       "max size for a kdc-request", "size"
+    },
+#if 0
+    {
+       "database",     'd',    arg_string, &databases,
+       "location of database", "database"
+    },
+#endif
+    { "enable-http", 'H', arg_flag, &enable_http, "turn on HTTP support" },
+    {  "524",          0,      arg_negative_flag, &enable_524,
+       "don't respond to 524 requests" 
+    },
+    {
+       "kaserver", 'K', arg_flag,   &enable_kaserver,
+       "enable kaserver support"
+    },
+    {  "kerberos4",    0,      arg_flag, &enable_v4,
+       "respond to kerberos 4 requests" 
+    },
+    { 
+       "v4-realm",     'r',    arg_string, &v4_realm, 
+       "realm to serve v4-requests for"
+    },
+    {  "kerberos4-cross-realm",        0,      arg_flag,
+       &enable_v4_cross_realm,
+       "respond to kerberos 4 requests from foreign realms" 
+    },
+    {  "ports",        'P',    arg_string, &port_str,
+       "ports to listen to", "portspec"
+    },
+#if DETACH_IS_DEFAULT
+    {
+       "detach",       'D',      arg_negative_flag, &detach_from_console, 
+       "don't detach from console"
+    },
+#else
+    {
+       "detach",       0 ,      arg_flag, &detach_from_console, 
+       "detach from console"
+    },
+#endif
+    {  "addresses",    0,      arg_strings, &addresses_str,
+       "addresses to listen on", "list of addresses" },
+    {  "disable-des",  0,      arg_flag, &disable_des,
+       "disable DES" },
+    {  "builtin-hdb",  0,      arg_flag,   &builtin_hdb_flag,
+       "list builtin hdb backends"},
+    {  "help",         'h',    arg_flag,   &help_flag },
+    {  "version",      'v',    arg_flag,   &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, num_args, NULL, "");
+    exit (ret);
+}
+
+static void
+get_dbinfo(void)
+{
+    const krb5_config_binding *top_binding = NULL;
+    const krb5_config_binding *db_binding;
+    const krb5_config_binding *default_binding = NULL;
+    struct dbinfo *di, **dt;
+    const char *default_dbname = HDB_DEFAULT_DB;
+    const char *default_mkey = HDB_DB_DIR "/m-key";
+    const char *p;
+
+    databases = NULL;
+    dt = &databases;
+    while((db_binding = (const krb5_config_binding *)
+          krb5_config_get_next(context, NULL, &top_binding, 
+                               krb5_config_list, 
+                               "kdc", 
+                               "database",
+                               NULL))) {
+       p = krb5_config_get_string(context, db_binding, "realm", NULL);
+       if(p == NULL) {
+           if(default_binding) {
+               krb5_warnx(context, "WARNING: more than one realm-less "
+                          "database specification");
+               krb5_warnx(context, "WARNING: using the first encountered");
+           } else
+               default_binding = db_binding;
+           continue;
+       }
+       di = calloc(1, sizeof(*di));
+       di->realm = strdup(p);
+       p = krb5_config_get_string(context, db_binding, "dbname", NULL);
+       if(p)
+           di->dbname = strdup(p);
+       p = krb5_config_get_string(context, db_binding, "mkey_file", NULL);
+       if(p)
+           di->mkey_file = strdup(p);
+       *dt = di;
+       dt = &di->next;
+    }
+    if(default_binding) {
+       di = calloc(1, sizeof(*di));
+       p = krb5_config_get_string(context, default_binding, "dbname", NULL);
+       if(p) {
+           di->dbname = strdup(p);
+           default_dbname = p;
+       }
+       p = krb5_config_get_string(context, default_binding, "mkey_file", NULL);
+       if(p) {
+           di->mkey_file = strdup(p);
+           default_mkey = p;
+       }
+       *dt = di;
+       dt = &di->next;
+    } else if(databases == NULL) {
+       /* if there are none specified, use some default */
+       di = calloc(1, sizeof(*di));
+       di->dbname = strdup(default_dbname);
+       di->mkey_file = strdup(default_mkey);
+       *dt = di;
+       dt = &di->next;
+    }
+    for(di = databases; di; di = di->next) {
+       if(di->dbname == NULL)
+           di->dbname = strdup(default_dbname);
+       if(di->mkey_file == NULL) {
+           p = strrchr(di->dbname, '.');
+           if(p == NULL || strchr(p, '/') != NULL)
+               /* final pathname component does not contain a . */
+               asprintf(&di->mkey_file, "%s.mkey", di->dbname);
+           else
+               /* the filename is something.else, replace .else with
+                   .mkey */
+               asprintf(&di->mkey_file, "%.*s.mkey", 
+                        (int)(p - di->dbname), di->dbname);
+       }
+    }
+}
+
+static void
+add_one_address (const char *str, int first)
+{
+    krb5_error_code ret;
+    krb5_addresses tmp;
+
+    ret = krb5_parse_address (context, str, &tmp);
+    if (ret)
+       krb5_err (context, 1, ret, "parse_address `%s'", str);
+    if (first)
+       krb5_copy_addresses(context, &tmp, &explicit_addresses);
+    else
+       krb5_append_addresses(context, &explicit_addresses, &tmp);
+    krb5_free_addresses (context, &tmp);
+}
+
+void
+configure(int argc, char **argv)
+{
+    krb5_error_code ret;
+    int optind = 0;
+    const char *p;
+    
+    while(getarg(args, num_args, argc, argv, &optind))
+       warnx("error at argument `%s'", argv[optind]);
+
+    if(help_flag)
+       usage (0);
+
+    if (version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (builtin_hdb_flag) {
+       char *list;
+       ret = hdb_list_builtin(context, &list);
+       if (ret)
+           krb5_err(context, 1, ret, "listing builtin hdb backends");
+       printf("builtin hdb backends: %s\n", list);
+       free(list);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0)
+       usage(1);
+    
+    {
+       char **files;
+
+       if(config_file == NULL)
+           config_file = _PATH_KDC_CONF;
+
+       ret = krb5_prepend_config_files_default(config_file, &files);
+       if (ret)
+           krb5_err(context, 1, ret, "getting configuration files");
+           
+       ret = krb5_set_config_files(context, files);
+       krb5_free_config_files(files);
+       if(ret) 
+           krb5_err(context, 1, ret, "reading configuration files");
+    }
+
+    get_dbinfo();
+    
+    if(max_request_str)
+       max_request = parse_bytes(max_request_str, NULL);
+
+    if(max_request == 0){
+       p = krb5_config_get_string (context,
+                                   NULL,
+                                   "kdc",
+                                   "max-request",
+                                   NULL);
+       if(p)
+           max_request = parse_bytes(p, NULL);
+    }
+    
+    if(require_preauth == -1)
+       require_preauth = krb5_config_get_bool(context, NULL, "kdc", 
+                                              "require-preauth", NULL);
+
+    if(port_str == NULL){
+       p = krb5_config_get_string(context, NULL, "kdc", "ports", NULL);
+       if (p != NULL)
+           port_str = strdup(p);
+    }
+
+    explicit_addresses.len = 0;
+
+    if (addresses_str.num_strings) {
+       int i;
+
+       for (i = 0; i < addresses_str.num_strings; ++i)
+           add_one_address (addresses_str.strings[i], i == 0);
+       free_getarg_strings (&addresses_str);
+    } else {
+       char **foo = krb5_config_get_strings (context, NULL,
+                                             "kdc", "addresses", NULL);
+
+       if (foo != NULL) {
+           add_one_address (*foo++, TRUE);
+           while (*foo)
+               add_one_address (*foo++, FALSE);
+       }
+    }
+
+    if(enable_v4 == -1)
+       enable_v4 = krb5_config_get_bool_default(context, NULL, FALSE, "kdc", 
+                                                "enable-kerberos4", NULL);
+    if(enable_v4_cross_realm == -1)
+       enable_v4_cross_realm =
+           krb5_config_get_bool_default(context, NULL,
+                                        FALSE, "kdc", 
+                                        "enable-kerberos4-cross-realm",
+                                        NULL);
+    if(enable_524 == -1)
+       enable_524 = krb5_config_get_bool_default(context, NULL, enable_v4, 
+                                                 "kdc", "enable-524", NULL);
+
+    if(enable_http == -1)
+       enable_http = krb5_config_get_bool(context, NULL, "kdc", 
+                                          "enable-http", NULL);
+    check_ticket_addresses = 
+       krb5_config_get_bool_default(context, NULL, TRUE, "kdc", 
+                                    "check-ticket-addresses", NULL);
+    allow_null_ticket_addresses = 
+       krb5_config_get_bool_default(context, NULL, TRUE, "kdc", 
+                                    "allow-null-ticket-addresses", NULL);
+
+    allow_anonymous = 
+       krb5_config_get_bool(context, NULL, "kdc", 
+                            "allow-anonymous", NULL);
+    trpolicy_str = 
+       krb5_config_get_string_default(context, NULL, "always-check", "kdc", 
+                                      "transited-policy", NULL);
+    if(strcasecmp(trpolicy_str, "always-check") == 0)
+       trpolicy = TRPOLICY_ALWAYS_CHECK;
+    else if(strcasecmp(trpolicy_str, "allow-per-principal") == 0)
+       trpolicy = TRPOLICY_ALLOW_PER_PRINCIPAL;
+    else if(strcasecmp(trpolicy_str, "always-honour-request") == 0)
+       trpolicy = TRPOLICY_ALWAYS_HONOUR_REQUEST;
+    else {
+       kdc_log(0, "unknown transited-policy: %s, reverting to always-check", 
+               trpolicy_str);
+       trpolicy = TRPOLICY_ALWAYS_CHECK;
+    }
+       
+    if (krb5_config_get_string(context, NULL, "kdc", 
+                              "enforce-transited-policy", NULL))
+       krb5_errx(context, 1, "enforce-transited-policy deprecated, "
+                 "use [kdc]transited-policy instead");
+
+    if(v4_realm == NULL){
+       p = krb5_config_get_string (context, NULL, 
+                                   "kdc",
+                                   "v4-realm",
+                                   NULL);
+       if(p != NULL) {
+           v4_realm = strdup(p);
+           if (v4_realm == NULL)
+               krb5_errx(context, 1, "out of memory");
+       }
+    }
+    if (enable_kaserver == -1)
+       enable_kaserver = krb5_config_get_bool_default(context, NULL, FALSE,
+                                                      "kdc",
+                                                      "enable-kaserver",
+                                                      NULL);
+
+    encode_as_rep_as_tgs_rep = krb5_config_get_bool(context, NULL, "kdc", 
+                                                   "encode_as_rep_as_tgs_rep", 
+                                                   NULL);
+
+    kdc_warn_pwexpire = krb5_config_get_time (context, NULL,
+                                             "kdc",
+                                             "kdc_warn_pwexpire",
+                                             NULL);
+
+    if(detach_from_console == -1) 
+       detach_from_console = krb5_config_get_bool_default(context, NULL, 
+                                                          DETACH_IS_DEFAULT,
+                                                          "kdc",
+                                                          "detach", NULL);
+    kdc_openlog();
+    if(max_request == 0)
+       max_request = 64 * 1024;
+    if(require_preauth == -1)
+       require_preauth = 1;
+    if (port_str == NULL)
+       port_str = "+";
+
+#ifdef PKINIT
+    enable_pkinit = krb5_config_get_bool_default(context, NULL, FALSE,
+                                                "kdc",
+                                                "enable-pkinit",
+                                                NULL);
+    if (enable_pkinit) {
+       const char *user_id, *x509_anchors;
+
+       user_id = krb5_config_get_string(context, NULL,
+                                         "kdc",
+                                         "pki-identity",
+                                         NULL);
+       if (user_id == NULL)
+           krb5_errx(context, 1, "pkinit enabled but no identity");
+
+       x509_anchors = krb5_config_get_string(context, NULL,
+                                             "kdc",
+                                             "pki-anchors",
+                                             NULL);
+       if (x509_anchors == NULL)
+           krb5_errx(context, 1, "pkinit enabled but no X509 anchors");
+
+       pk_initialize(user_id, x509_anchors);
+
+       enable_pkinit_princ_in_cert = 
+           krb5_config_get_bool_default(context, 
+                                        NULL, TRUE,
+                                        "kdc",
+                                        "pkinit-principal-in-certificate",
+                                        NULL);
+    }
+#endif
+
+    if(v4_realm == NULL && (enable_kaserver || enable_v4)){
+#ifdef KRB4
+       v4_realm = malloc(40); /* REALM_SZ */
+       if (v4_realm == NULL)
+           krb5_errx(context, 1, "out of memory");
+       krb_get_lrealm(v4_realm, 1);
+#else
+       krb5_errx(context, 1, "No Kerberos 4 realm configured");
+#endif
+    }
+    if(disable_des == -1)
+       disable_des = krb5_config_get_bool_default(context, NULL, 
+                                                  0,
+                                                  "kdc",
+                                                  "disable-des", NULL);
+    if(disable_des) {
+       krb5_enctype_disable(context, ETYPE_DES_CBC_CRC);
+       krb5_enctype_disable(context, ETYPE_DES_CBC_MD4);
+       krb5_enctype_disable(context, ETYPE_DES_CBC_MD5);
+       krb5_enctype_disable(context, ETYPE_DES_CBC_NONE);
+       krb5_enctype_disable(context, ETYPE_DES_CFB64_NONE);
+       krb5_enctype_disable(context, ETYPE_DES_PCBC_NONE);
+
+       kdc_log(0, "DES was disabled, turned off Kerberos V4, 524 "
+               "and kaserver");
+       enable_v4 = 0;
+       enable_524 = 0;
+       enable_kaserver = 0;
+    }
+}
diff --git a/src/kerberosV/src/kdc/connect.c b/src/kerberosV/src/kdc/connect.c
new file mode 100644 (file)
index 0000000..df22d90
--- /dev/null
@@ -0,0 +1,853 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+RCSID("$KTH: connect.c,v 1.104 2005/05/30 20:56:18 joda Exp $");
+
+/*
+ * a tuple describing on what to listen
+ */
+
+struct port_desc{
+    int family;
+    int type;
+    int port;
+};
+
+/* the current ones */
+
+static struct port_desc *ports;
+static int num_ports;
+
+/*
+ * add `family, port, protocol' to the list with duplicate suppresion.
+ */
+
+static void
+add_port(int family, int port, const char *protocol)
+{
+    int type;
+    int i;
+
+    if(strcmp(protocol, "udp") == 0)
+       type = SOCK_DGRAM;
+    else if(strcmp(protocol, "tcp") == 0)
+       type = SOCK_STREAM;
+    else
+       return;
+    for(i = 0; i < num_ports; i++){
+       if(ports[i].type == type
+          && ports[i].port == port
+          && ports[i].family == family)
+           return;
+    }
+    ports = realloc(ports, (num_ports + 1) * sizeof(*ports));
+    if (ports == NULL)
+       krb5_err (context, 1, errno, "realloc");
+    ports[num_ports].family = family;
+    ports[num_ports].type   = type;
+    ports[num_ports].port   = port;
+    num_ports++;
+}
+
+/*
+ * add a triple but with service -> port lookup
+ * (this prints warnings for stuff that does not exist)
+ */
+
+static void
+add_port_service(int family, const char *service, int port,
+                const char *protocol)
+{
+    port = krb5_getportbyname (context, service, protocol, port);
+    add_port (family, port, protocol);
+}
+
+/*
+ * add the port with service -> port lookup or string -> number
+ * (no warning is printed)
+ */
+
+static void
+add_port_string (int family, const char *port_str, const char *protocol)
+{
+    struct servent *sp;
+    int port;
+
+    sp = roken_getservbyname (port_str, protocol);
+    if (sp != NULL) {
+       port = sp->s_port;
+    } else {
+       char *end;
+
+       port = htons(strtol(port_str, &end, 0));
+       if (end == port_str)
+           return;
+    }
+    add_port (family, port, protocol);
+}
+
+/*
+ * add the standard collection of ports for `family'
+ */
+
+static void
+add_standard_ports (int family)
+{
+    add_port_service(family, "kerberos", 88, "udp");
+    add_port_service(family, "kerberos", 88, "tcp");
+    add_port_service(family, "kerberos-sec", 88, "udp");
+    add_port_service(family, "kerberos-sec", 88, "tcp");
+    if(enable_http)
+       add_port_service(family, "http", 80, "tcp");
+    if(enable_524) {
+       add_port_service(family, "krb524", 4444, "udp");
+       add_port_service(family, "krb524", 4444, "tcp");
+    }
+    if(enable_v4) {
+       add_port_service(family, "kerberos-iv", 750, "udp");
+       add_port_service(family, "kerberos-iv", 750, "tcp");
+    }
+    if (enable_kaserver)
+       add_port_service(family, "afs3-kaserver", 7004, "udp");
+}
+
+/*
+ * parse the set of space-delimited ports in `str' and add them.
+ * "+" => all the standard ones
+ * otherwise it's port|service[/protocol]
+ */
+
+static void
+parse_ports(const char *str)
+{
+    char *pos = NULL;
+    char *p;
+    char *str_copy = strdup (str);
+
+    p = strtok_r(str_copy, " \t", &pos);
+    while(p != NULL) {
+       if(strcmp(p, "+") == 0) {
+#ifdef HAVE_IPV6
+           add_standard_ports(AF_INET6);
+#endif
+           add_standard_ports(AF_INET);
+       } else {
+           char *q = strchr(p, '/');
+           if(q){
+               *q++ = 0;
+#ifdef HAVE_IPV6
+               add_port_string(AF_INET6, p, q);
+#endif
+               add_port_string(AF_INET, p, q);
+           }else {
+#ifdef HAVE_IPV6
+               add_port_string(AF_INET6, p, "udp");
+               add_port_string(AF_INET6, p, "tcp");
+#endif
+               add_port_string(AF_INET, p, "udp");
+               add_port_string(AF_INET, p, "tcp");
+           }
+       }
+           
+       p = strtok_r(NULL, " \t", &pos);
+    }
+    free (str_copy);
+}
+
+/*
+ * every socket we listen on
+ */
+
+struct descr {
+    int s;
+    int type;
+    int port;
+    unsigned char *buf;
+    size_t size;
+    size_t len;
+    time_t timeout;
+    struct sockaddr_storage __ss;
+    struct sockaddr *sa;
+    socklen_t sock_len;
+    char addr_string[128];
+};
+
+static void
+init_descr(struct descr *d)
+{
+    memset(d, 0, sizeof(*d));
+    d->sa = (struct sockaddr *)&d->__ss;
+    d->s = -1;
+}
+
+/*
+ * re-initialize all `n' ->sa in `d'.
+ */
+
+static void
+reinit_descrs (struct descr *d, int n)
+{
+    int i;
+
+    for (i = 0; i < n; ++i)
+       d[i].sa = (struct sockaddr *)&d[i].__ss;
+}
+
+/*
+ * Create the socket (family, type, port) in `d'
+ */
+
+static void 
+init_socket(struct descr *d, krb5_address *a, int family, int type, int port)
+{
+    krb5_error_code ret;
+    struct sockaddr_storage __ss;
+    struct sockaddr *sa = (struct sockaddr *)&__ss;
+    krb5_socklen_t sa_size = sizeof(__ss);
+
+    init_descr (d);
+
+    ret = krb5_addr2sockaddr (context, a, sa, &sa_size, port);
+    if (ret) {
+       krb5_warn(context, ret, "krb5_addr2sockaddr");
+       close(d->s);
+       d->s = -1;
+       return;
+    }
+
+    if (sa->sa_family != family)
+       return;
+
+    d->s = socket(family, type, 0);
+    if(d->s < 0){
+       krb5_warn(context, errno, "socket(%d, %d, 0)", family, type);
+       d->s = -1;
+       return;
+    }
+#if defined(HAVE_SETSOCKOPT) && defined(SOL_SOCKET) && defined(SO_REUSEADDR)
+    {
+       int one = 1;
+       setsockopt(d->s, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
+    }
+#endif
+    d->type = type;
+    d->port = port;
+
+    if(bind(d->s, sa, sa_size) < 0){
+       char a_str[256];
+       size_t len;
+
+       krb5_print_address (a, a_str, sizeof(a_str), &len);
+       krb5_warn(context, errno, "bind %s/%d", a_str, ntohs(port));
+       close(d->s);
+       d->s = -1;
+       return;
+    }
+    if(type == SOCK_STREAM && listen(d->s, SOMAXCONN) < 0){
+       char a_str[256];
+       size_t len;
+
+       krb5_print_address (a, a_str, sizeof(a_str), &len);
+       krb5_warn(context, errno, "listen %s/%d", a_str, ntohs(port));
+       close(d->s);
+       d->s = -1;
+       return;
+    }
+}
+
+/*
+ * Allocate descriptors for all the sockets that we should listen on
+ * and return the number of them.
+ */
+
+static int
+init_sockets(struct descr **desc)
+{
+    krb5_error_code ret;
+    int i, j;
+    struct descr *d, *tmp;
+    int num = 0;
+    krb5_addresses addresses;
+
+    if (explicit_addresses.len) {
+       addresses = explicit_addresses;
+    } else {
+       ret = krb5_get_all_server_addrs (context, &addresses);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_get_all_server_addrs");
+    }
+    parse_ports(port_str);
+    d = malloc(addresses.len * num_ports * sizeof(*d));
+    if (d == NULL)
+       krb5_errx(context, 1, "malloc(%lu) failed",
+                 (unsigned long)num_ports * sizeof(*d));
+
+    for (i = 0; i < num_ports; i++){
+       for (j = 0; j < addresses.len; ++j) {
+           init_socket(&d[num], &addresses.val[j],
+                       ports[i].family, ports[i].type, ports[i].port);
+           if(d[num].s != -1){
+               char a_str[80];
+               size_t len;
+
+               krb5_print_address (&addresses.val[j], a_str,
+                                   sizeof(a_str), &len);
+
+               kdc_log(5, "listening on %s port %u/%s",
+                       a_str,
+                       ntohs(ports[i].port), 
+                       (ports[i].type == SOCK_STREAM) ? "tcp" : "udp");
+               /* XXX */
+               num++;
+           }
+       }
+    }
+    krb5_free_addresses (context, &addresses);
+    tmp = realloc(d, num * sizeof(*d));
+    if (tmp == NULL && num != 0) {
+       free(d);
+       krb5_errx(context, 1, "realloc(%lu) failed",
+                 (unsigned long)num * sizeof(*d));
+    }
+    d = tmp;
+    reinit_descrs (d, num);
+    *desc = d;
+    return num;
+}
+
+/*
+ *
+ */
+
+static const char *
+descr_type(struct descr *d)
+{
+    if (d->type == SOCK_DGRAM)
+       return "udp";
+    else if (d->type == SOCK_STREAM)
+       return "tcp";
+    return "unknown";
+}
+
+/*
+ * handle the request in `buf, len', from `addr' (or `from' as a string),
+ * sending a reply in `reply'.
+ */
+
+static int
+process_request(unsigned char *buf, 
+               size_t len, 
+               krb5_data *reply,
+               krb5_boolean *prependlength,
+               const char *from,
+               struct sockaddr *addr)
+{
+    KDC_REQ req;
+    Ticket ticket;
+    krb5_error_code ret;
+    size_t i;
+
+    gettimeofday(&now, NULL);
+    if(decode_AS_REQ(buf, len, &req, &i) == 0){
+       ret = as_rep(&req, reply, from, addr);
+       free_AS_REQ(&req);
+       return ret;
+    }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){
+       ret = tgs_rep(&req, reply, from, addr);
+       free_TGS_REQ(&req);
+       return ret;
+    }else if(decode_Ticket(buf, len, &ticket, &i) == 0){
+       ret = do_524(&ticket, reply, from, addr);
+       free_Ticket(&ticket);
+       return ret;
+    } else if(maybe_version4(buf, len)){
+       *prependlength = FALSE; /* elbitapmoc sdrawkcab XXX */
+       do_version4(buf, len, reply, from, (struct sockaddr_in*)addr);
+       return 0;
+    } else if (enable_kaserver) {
+       ret = do_kaserver (buf, len, reply, from, (struct sockaddr_in*)addr);
+       return ret;
+    }
+                         
+    return -1;
+}
+
+static void
+addr_to_string(struct sockaddr *addr, size_t addr_len, char *str, size_t len)
+{
+    krb5_address a;
+    if(krb5_sockaddr2address(context, addr, &a) == 0) {
+       if(krb5_print_address(&a, str, len, &len) == 0) {
+           krb5_free_address(context, &a);
+           return;
+       }
+       krb5_free_address(context, &a);
+    }
+    snprintf(str, len, "<family=%d>", addr->sa_family);
+}
+
+/*
+ * Handle the request in `buf, len' to socket `d'
+ */
+
+static void
+do_request(void *buf, size_t len, krb5_boolean prependlength,
+          struct descr *d)
+{
+    krb5_error_code ret;
+    krb5_data reply;
+    
+    reply.length = 0;
+    ret = process_request(buf, len, &reply, &prependlength,
+                         d->addr_string, d->sa);
+    if(reply.length){
+       kdc_log(5, "sending %lu bytes to %s", (unsigned long)reply.length,
+               d->addr_string);
+       if(prependlength){
+           unsigned char len[4];
+           len[0] = (reply.length >> 24) & 0xff;
+           len[1] = (reply.length >> 16) & 0xff;
+           len[2] = (reply.length >> 8) & 0xff;
+           len[3] = reply.length & 0xff;
+           if(sendto(d->s, len, sizeof(len), 0, d->sa, d->sock_len) < 0) {
+               kdc_log (0, "sendto(%s): %s", d->addr_string, strerror(errno));
+               krb5_data_free(&reply);
+               return;
+           }
+       }
+       if(sendto(d->s, reply.data, reply.length, 0, d->sa, d->sock_len) < 0) {
+           kdc_log (0, "sendto(%s): %s", d->addr_string, strerror(errno));
+           krb5_data_free(&reply);
+           return;
+       }
+       krb5_data_free(&reply);
+    }
+    if(ret)
+       kdc_log(0, "Failed processing %lu byte request from %s", 
+               (unsigned long)len, d->addr_string);
+}
+
+/*
+ * Handle incoming data to the UDP socket in `d'
+ */
+
+static void
+handle_udp(struct descr *d)
+{
+    unsigned char *buf;
+    int n;
+
+    buf = malloc(max_request);
+    if(buf == NULL){
+       kdc_log(0, "Failed to allocate %lu bytes", (unsigned long)max_request);
+       return;
+    }
+
+    d->sock_len = sizeof(d->__ss);
+    n = recvfrom(d->s, buf, max_request, 0, d->sa, &d->sock_len);
+    if(n < 0)
+       krb5_warn(context, errno, "recvfrom");
+    else {
+       addr_to_string (d->sa, d->sock_len,
+                       d->addr_string, sizeof(d->addr_string));
+       do_request(buf, n, FALSE, d);
+    }
+    free (buf);
+}
+
+static void
+clear_descr(struct descr *d)
+{
+    if(d->buf)
+       memset(d->buf, 0, d->size);
+    d->len = 0;
+    if(d->s != -1)
+       close(d->s);
+    d->s = -1;
+}
+
+
+/* remove HTTP %-quoting from buf */
+static int
+de_http(char *buf)
+{
+    unsigned char *p, *q;
+    for(p = q = (unsigned char *)buf; *p; p++, q++) {
+       if(*p == '%' && isxdigit(p[1]) && isxdigit(p[2])) {
+           unsigned int x;
+           if(sscanf(p + 1, "%2x", &x) != 1)
+               return -1;
+           *q = x;
+           p += 2;
+       } else
+           *q = *p;
+    }
+    *q = '\0';
+    return 0;
+}
+
+#define TCP_TIMEOUT 4
+
+/*
+ * accept a new TCP connection on `d[parent]' and store it in `d[child]'
+ */
+
+static void
+add_new_tcp (struct descr *d, int parent, int child)
+{
+    int s;
+
+    if (child == -1)
+       return;
+
+    d[child].sock_len = sizeof(d[child].__ss);
+    s = accept(d[parent].s, d[child].sa, &d[child].sock_len);
+    if(s < 0) {
+       krb5_warn(context, errno, "accept");
+       return;
+    }
+           
+    if (s >= FD_SETSIZE) {
+       krb5_warnx(context, "socket FD too large");
+       close (s);
+       return;
+    }
+
+    d[child].s = s;
+    d[child].timeout = time(NULL) + TCP_TIMEOUT;
+    d[child].type = SOCK_STREAM;
+    addr_to_string (d[child].sa, d[child].sock_len,
+                   d[child].addr_string, sizeof(d[child].addr_string));
+}
+
+/*
+ * Grow `d' to handle at least `n'.
+ * Return != 0 if fails
+ */
+
+static int
+grow_descr (struct descr *d, size_t n)
+{
+    if (d->size - d->len < n) {
+       unsigned char *tmp;
+       size_t grow; 
+
+       grow = max(1024, d->len + n);
+       if (d->size + grow > max_request) {
+           kdc_log(0, "Request exceeds max request size (%lu bytes).",
+                   (unsigned long)d->size + grow);
+           clear_descr(d);
+           return -1;
+       }
+       tmp = realloc (d->buf, d->size + grow);
+       if (tmp == NULL) {
+           kdc_log(0, "Failed to re-allocate %lu bytes.",
+                   (unsigned long)d->size + grow);
+           clear_descr(d);
+           return -1;
+       }
+       d->size += grow;
+       d->buf = tmp;
+    }
+    return 0;
+}
+
+/*
+ * Try to handle the TCP data at `d->buf, d->len'.
+ * Return -1 if failed, 0 if succesful, and 1 if data is complete.
+ */
+
+static int
+handle_vanilla_tcp (struct descr *d)
+{
+    krb5_storage *sp;
+    int32_t len;
+
+    sp = krb5_storage_from_mem(d->buf, d->len);
+    if (sp == NULL) {
+       kdc_log (0, "krb5_storage_from_mem failed");
+       return -1;
+    }
+    krb5_ret_int32(sp, &len);
+    krb5_storage_free(sp);
+    if(d->len - 4 >= len) {
+       memmove(d->buf, d->buf + 4, d->len - 4);
+       return 1;
+    }
+    return 0;
+}
+
+/*
+ * Try to handle the TCP/HTTP data at `d->buf, d->len'.
+ * Return -1 if failed, 0 if succesful, and 1 if data is complete.
+ */
+
+static int
+handle_http_tcp (struct descr *d)
+{
+    char *s, *p, *t;
+    void *data;
+    char *proto;
+    int len;
+
+    s = (char *)d->buf;
+
+    p = strstr(s, "\r\n");
+    if (p == NULL) {
+       kdc_log(0, "Malformed HTTP request from %s", d->addr_string);
+       return -1;
+    }
+    *p = 0;
+
+    p = NULL;
+    t = strtok_r(s, " \t", &p);
+    if (t == NULL) {
+       kdc_log(0, "Malformed HTTP request from %s", d->addr_string);
+       return -1;
+    }
+    t = strtok_r(NULL, " \t", &p);
+    if(t == NULL) {
+       kdc_log(0, "Malformed HTTP request from %s", d->addr_string);
+       return -1;
+    }
+    data = malloc(strlen(t));
+    if (data == NULL) {
+       kdc_log(0, "Failed to allocate %lu bytes",
+               (unsigned long)strlen(t));
+       return -1;
+    }
+    if(*t == '/')
+       t++;
+    if(de_http(t) != 0) {
+       kdc_log(0, "Malformed HTTP request from %s", d->addr_string);
+       kdc_log(5, "HTTP request: %s", t);
+       free(data);
+       return -1;
+    }
+    proto = strtok_r(NULL, " \t", &p);
+    if (proto == NULL) {
+       kdc_log(0, "Malformed HTTP request from %s", d->addr_string);
+       free(data);
+       return -1;
+    }
+    len = base64_decode(t, data);
+    if(len <= 0){
+       const char *msg = 
+           " 404 Not found\r\n"
+           "Server: Heimdal/" VERSION "\r\n"
+           "Cache-Control: no-cache\r\n"
+           "Pragma: no-cache\r\n"
+           "Content-type: text/html\r\n"
+           "Content-transfer-encoding: 8bit\r\n\r\n"
+           "<TITLE>404 Not found</TITLE>\r\n"
+           "<H1>404 Not found</H1>\r\n"
+           "That page doesn't exist, maybe you are looking for "
+           "<A HREF=\"http://www.pdc.kth.se/heimdal/\">Heimdal</A>?\r\n";
+       kdc_log(0, "HTTP request from %s is non KDC request", d->addr_string);
+       kdc_log(5, "HTTP request: %s", t);
+       free(data);
+       if (write(d->s, proto, strlen(proto)) < 0) {
+           kdc_log(0, "HTTP write failed: %s: %s", 
+                   d->addr_string, strerror(errno));
+           return -1;
+       }
+       if (write(d->s, msg, strlen(msg)) < 0) {
+           kdc_log(0, "HTTP write failed: %s: %s", 
+                   d->addr_string, strerror(errno));
+           return -1;
+       }
+       return -1;
+    }
+    {
+       const char *msg = 
+           " 200 OK\r\n"
+           "Server: Heimdal/" VERSION "\r\n"
+           "Cache-Control: no-cache\r\n"
+           "Pragma: no-cache\r\n"
+           "Content-type: application/octet-stream\r\n"
+           "Content-transfer-encoding: binary\r\n\r\n";
+       if (write(d->s, proto, strlen(proto)) < 0) {
+           kdc_log(0, "HTTP write failed: %s: %s", 
+                   d->addr_string, strerror(errno));
+           return -1;
+       }
+       if (write(d->s, msg, strlen(msg)) < 0) {
+           kdc_log(0, "HTTP write failed: %s: %s", 
+                   d->addr_string, strerror(errno));
+           return -1;
+       }
+    }
+    memcpy(d->buf, data, len);
+    d->len = len;
+    free(data);
+    return 1;
+}
+
+/*
+ * Handle incoming data to the TCP socket in `d[index]'
+ */
+
+static void
+handle_tcp(struct descr *d, int index, int min_free)
+{
+    unsigned char buf[1024];
+    int n;
+    int ret = 0;
+
+    if (d[index].timeout == 0) {
+       add_new_tcp (d, index, min_free);
+       return;
+    }
+
+    n = recvfrom(d[index].s, buf, sizeof(buf), 0, NULL, NULL);
+    if(n < 0){
+       krb5_warn(context, errno, "recvfrom failed from %s to %s/%d",
+                 d[index].addr_string, descr_type(d + index), 
+                 ntohs(d[index].port));
+       return;
+    } else if (n == 0) {
+       krb5_warnx(context, "connection closed before end of data after %lu "
+                  "bytes from %s to %s/%d", (unsigned long)d[index].len, 
+                  d[index].addr_string, descr_type(d + index), 
+                  ntohs(d[index].port));
+       clear_descr (d + index);
+       return;
+    }
+    if (grow_descr (&d[index], n))
+       return;
+    memcpy(d[index].buf + d[index].len, buf, n);
+    d[index].len += n;
+    if(d[index].len > 4 && d[index].buf[0] == 0) {
+       ret = handle_vanilla_tcp (&d[index]);
+    } else if(enable_http &&
+             d[index].len >= 4 &&
+             strncmp((char *)d[index].buf, "GET ", 4) == 0 && 
+             strncmp((char *)d[index].buf + d[index].len - 4,
+                     "\r\n\r\n", 4) == 0) {
+       ret = handle_http_tcp (&d[index]);
+       if (ret < 0)
+           clear_descr (d + index);
+    } else if (d[index].len > 4) {
+       kdc_log (0, "TCP data of strange type from %s to %s/%d",
+                d[index].addr_string, descr_type(d + index), 
+                ntohs(d[index].port));
+       clear_descr(d + index);
+       return;
+    }
+    if (ret < 0)
+       return;
+    else if (ret == 1) {
+       do_request(d[index].buf, d[index].len, TRUE, &d[index]);
+       clear_descr(d + index);
+    }
+}
+
+void
+loop(void)
+{
+    struct descr *d;
+    int ndescr;
+
+    ndescr = init_sockets(&d);
+    if(ndescr <= 0)
+       krb5_errx(context, 1, "No sockets!");
+    while(exit_flag == 0){
+       struct timeval tmout;
+       fd_set fds;
+       int min_free = -1;
+       int max_fd = 0;
+       int i;
+
+       FD_ZERO(&fds);
+       for(i = 0; i < ndescr; i++) {
+           if(d[i].s >= 0){
+               if(d[i].type == SOCK_STREAM && 
+                  d[i].timeout && d[i].timeout < time(NULL)) {
+                   kdc_log(1, "TCP-connection from %s expired after %lu bytes",
+                           d[i].addr_string, (unsigned long)d[i].len);
+                   clear_descr(&d[i]);
+                   continue;
+               }
+               if(max_fd < d[i].s)
+                   max_fd = d[i].s;
+               if (max_fd >= FD_SETSIZE)
+                   krb5_errx(context, 1, "fd too large");
+               FD_SET(d[i].s, &fds);
+           } else if(min_free < 0 || i < min_free)
+               min_free = i;
+       }
+       if(min_free == -1){
+           struct descr *tmp;
+           tmp = realloc(d, (ndescr + 4) * sizeof(*d));
+           if(tmp == NULL)
+               krb5_warnx(context, "No memory");
+           else {
+               d = tmp;
+               reinit_descrs (d, ndescr);
+               memset(d + ndescr, 0, 4 * sizeof(*d));
+               for(i = ndescr; i < ndescr + 4; i++)
+                   init_descr (&d[i]);
+               min_free = ndescr;
+               ndescr += 4;
+           }
+       }
+    
+       tmout.tv_sec = TCP_TIMEOUT;
+       tmout.tv_usec = 0;
+       switch(select(max_fd + 1, &fds, 0, 0, &tmout)){
+       case 0:
+           break;
+       case -1:
+           if (errno != EINTR)
+               krb5_warn(context, errno, "select");
+           break;
+       default:
+           for(i = 0; i < ndescr; i++)
+               if(d[i].s >= 0 && FD_ISSET(d[i].s, &fds)) {
+                   if(d[i].type == SOCK_DGRAM)
+                       handle_udp(&d[i]);
+                   else if(d[i].type == SOCK_STREAM)
+                       handle_tcp(d, i, min_free);
+               }
+       }
+    }
+    if(exit_flag == SIGXCPU)
+       kdc_log(0, "CPU time limit exceeded");
+    else if(exit_flag == SIGINT || exit_flag == SIGTERM)
+       kdc_log(0, "Terminated");
+    else
+       kdc_log(0, "Unexpected exit reason: %d", exit_flag);
+    free (d);
+}
diff --git a/src/kerberosV/src/kdc/headers.h b/src/kerberosV/src/kdc/headers.h
new file mode 100644 (file)
index 0000000..471bc57
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* 
+ * $KTH: headers.h,v 1.16 2005/04/24 13:49:00 lha Exp $ 
+ */
+
+#ifndef __HEADERS_H__
+#define __HEADERS_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#include <err.h>
+#include <roken.h>
+#include <getarg.h>
+#include <base64.h>
+#include <parse_units.h>
+#include <krb5.h>
+#include <krb5_locl.h>
+#include <hdb.h>
+#include <hdb_err.h>
+#include <der.h> /* copy_octet_string */
+
+#undef ALLOC
+#define ALLOC(X) ((X) = malloc(sizeof(*(X))))
+#undef ALLOC_SEQ
+#define ALLOC_SEQ(X, N) do { (X)->len = (N); \
+(X)->val = calloc((X)->len, sizeof(*(X)->val)); } while(0)
+
+#endif /* __HEADERS_H__ */
diff --git a/src/kerberosV/src/kdc/hprop.8 b/src/kerberosV/src/kdc/hprop.8
new file mode 100644 (file)
index 0000000..732c85c
--- /dev/null
@@ -0,0 +1,203 @@
+.\" Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: hprop.8,v 1.20 2004/12/08 17:34:22 lha Exp $
+.\"
+.Dd December  8, 2004
+.Dt HPROP 8
+.Os HEIMDAL
+.Sh NAME
+.Nm hprop
+.Nd propagate the KDC database
+.Sh SYNOPSIS
+.Nm hprop
+.Bk -words
+.Oo Fl m Ar file \*(Ba Xo
+.Fl -master-key= Ns Pa file
+.Xc
+.Oc
+.Oo Fl d Ar file \*(Ba Xo
+.Fl -database= Ns Pa file
+.Xc
+.Oc
+.Op Fl -source= Ns Ar heimdal|mit-dump|krb4-dump|krb4-db|kaserver
+.Oo Fl r Ar string \*(Ba Xo
+.Fl -v4-realm= Ns Ar string
+.Xc
+.Oc
+.Oo Fl c Ar cell \*(Ba Xo
+.Fl -cell= Ns Ar cell
+.Xc
+.Oc
+.Op Fl S | Fl -kaspecials
+.Oo Fl k Ar keytab \*(Ba Xo
+.Fl -keytab= Ns Ar keytab
+.Xc
+.Oc
+.Oo Fl R Ar string \*(Ba Xo
+.Fl -v5-realm= Ns Ar string
+.Xc
+.Oc
+.Op Fl D | Fl -decrypt
+.Op Fl E | Fl -encrypt
+.Op Fl n | Fl -stdout
+.Op Fl v | Fl -verbose
+.Op Fl -version
+.Op Fl h | Fl -help
+.Op Ar host Ns Op : Ns Ar port
+.Ar ...
+.Ek
+.Sh DESCRIPTION
+.Nm
+takes a principal database in a specified format and converts it into
+a stream of Heimdal database records. This stream can either be
+written to standard out, or (more commonly) be propagated to a
+.Xr hpropd 8
+server running on a different machine.
+.Pp
+If propagating, it connects to all
+.Ar hosts
+specified on the command by opening a TCP connection to port 754
+(service hprop) and sends the database in encrypted form.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl m Ar file ,
+.Fl -master-key= Ns Pa file
+.Xc
+Where to find the master key to encrypt or decrypt keys with.
+.It Xo
+.Fl d Ar file ,
+.Fl -database= Ns Pa file
+.Xc
+The database to be propagated.
+.It Xo
+.Fl -source= Ns Ar heimdal|mit-dump|krb4-dump|krb4-db|kaserver
+.Xc
+Specifies the type of the source database. Alternatives include:
+.Pp
+.Bl -tag -width krb4-dump -compact -offset indent
+.It heimdal
+a Heimdal database
+.It mit-dump
+a MIT Kerberos 5 dump file
+.It krb4-db
+a Kerberos 4 database
+.It krb4-dump
+a Kerberos 4 dump file
+.It kaserver
+an AFS kaserver database
+.El
+.It Xo
+.Fl k Ar keytab ,
+.Fl -keytab= Ns Ar keytab
+.Xc
+The keytab to use for fetching the key to be used for authenticating
+to the propagation daemon(s). The key
+.Pa kadmin/hprop
+is used from this keytab.  The default is to fetch the key from the
+KDC database.
+.It Xo
+.Fl R Ar string ,
+.Fl -v5-realm= Ns Ar string
+.Xc
+Local realm override.
+.It Xo
+.Fl D ,
+.Fl -decrypt
+.Xc
+The encryption keys in the database can either be in clear, or
+encrypted with a master key. This option transmits the database with
+unencrypted keys.
+.It Xo
+.Fl E ,
+.Fl -encrypt
+.Xc
+This option transmits the database with encrypted keys.
+.It Xo
+.Fl n ,
+.Fl -stdout
+.Xc
+Dump the database on stdout, in a format that can be fed to hpropd.
+.El
+.Pp
+The following options are only valid if
+.Nm hprop
+is compiled with support for Kerberos 4 (kaserver).
+.Bl -tag -width Ds
+.It Xo
+.Fl r Ar string ,
+.Fl -v4-realm= Ns Ar string
+.Xc
+v4 realm to use.
+.It Xo
+.Fl c Ar cell ,
+.Fl -cell= Ns Ar cell
+.Xc
+The AFS cell name, used if reading a kaserver database.
+.It Xo
+.Fl S ,
+.Fl -kaspecials
+.Xc
+Also dump the principals marked as special in the kaserver database.
+.It Xo
+.Fl 4 ,
+.Fl -v4-db
+.Xc
+Deprecated, identical to
+.Sq --source=krb4-db .
+.It Xo
+.Fl K ,
+.Fl -ka-db
+.Xc
+Deprecated, identical to
+.Sq --source=kaserver .
+.El
+.Sh EXAMPLES
+The following will propagate a database to another machine (which
+should run
+.Xr hpropd 8 ):
+.Bd -literal -offset indent
+$ hprop slave-1 slave-2
+.Ed
+.Pp
+Copy a Kerberos 4 database to a Kerberos 5 slave:
+.Bd -literal -offset indent
+$ hprop --source=krb4-db -E krb5-slave
+.Ed
+.Pp
+Convert a Kerberos 4 dump-file for use with a Heimdal KDC:
+.Bd -literal -offset indent
+$ hprop -n --source=krb4-dump -d /var/kerberos/principal.dump --master-key=/.k | hpropd -n
+.Ed
+.Sh SEE ALSO
+.Xr hpropd 8
diff --git a/src/kerberosV/src/kdc/hprop.c b/src/kerberosV/src/kdc/hprop.c
new file mode 100644 (file)
index 0000000..3e50f06
--- /dev/null
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hprop.h"
+
+#ifdef KRB4
+#include <krb.h>
+#include <prot.h>
+#define Principal Principal4
+#include <krb_db.h>
+#endif
+
+RCSID("$KTH: hprop.c,v 1.76 2005/04/24 13:48:37 lha Exp $");
+
+static int version_flag;
+static int help_flag;
+static const char *ktname = HPROP_KEYTAB;
+static const char *database;
+static char *mkeyfile;
+static int to_stdout;
+static int verbose_flag;
+static int encrypt_flag;
+static int decrypt_flag;
+static hdb_master_key mkey5;
+
+static char *source_type;
+
+static char *afs_cell;
+static char *v4_realm;
+
+static int kaspecials_flag;
+static int ka_use_null_salt;
+
+static char *local_realm=NULL;
+
+static int
+open_socket(krb5_context context, const char *hostname, const char *port)
+{
+    struct addrinfo *ai, *a;
+    struct addrinfo hints;
+    int error;
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+
+    error = getaddrinfo (hostname, port, &hints, &ai);
+    if (error) {
+       warnx ("%s: %s", hostname, gai_strerror(error));
+       return -1;
+    }
+    
+    for (a = ai; a != NULL; a = a->ai_next) {
+       int s;
+
+       s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (s < 0)
+           continue;
+       if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+           warn ("connect(%s)", hostname);
+           close (s);
+           continue;
+       }
+       freeaddrinfo (ai);
+       return s;
+    }
+    warnx ("failed to contact %s", hostname);
+    freeaddrinfo (ai);
+    return -1;
+}
+
+krb5_error_code
+v5_prop(krb5_context context, HDB *db, hdb_entry *entry, void *appdata)
+{
+    krb5_error_code ret;
+    struct prop_data *pd = appdata;
+    krb5_data data;
+
+    if(encrypt_flag) {
+       ret = hdb_seal_keys_mkey(context, entry, mkey5);
+       if (ret) {
+           krb5_warn(context, ret, "hdb_seal_keys_mkey");
+           return ret;
+       }
+    }
+    if(decrypt_flag) {
+       ret = hdb_unseal_keys_mkey(context, entry, mkey5);
+       if (ret) {
+           krb5_warn(context, ret, "hdb_unseal_keys_mkey");
+           return ret;
+       }
+    }  
+
+    ret = hdb_entry2value(context, entry, &data);
+    if(ret) {
+       krb5_warn(context, ret, "hdb_entry2value");
+       return ret;
+    }
+
+    if(to_stdout)
+       ret = krb5_write_message(context, &pd->sock, &data);
+    else
+       ret = krb5_write_priv_message(context, pd->auth_context, 
+                                     &pd->sock, &data);
+    krb5_data_free(&data);
+    return ret;
+}
+
+#ifdef KRB4
+
+static char realm_buf[REALM_SZ];
+
+static int
+kdb_prop(void *arg, Principal *p)
+{
+    int ret;
+    struct v4_principal pr;
+
+    memset(&pr, 0, sizeof(pr));
+
+    if(p->attributes != 0) {
+       warnx("%s.%s has non-zero attributes - skipping", 
+             p->name, p->instance);
+           return 0;
+    }
+    strlcpy(pr.name, p->name, sizeof(pr.name));
+    strlcpy(pr.instance, p->instance, sizeof(pr.instance));
+
+    copy_to_key(&p->key_low, &p->key_high, pr.key);
+    pr.exp_date = p->exp_date;
+    pr.mod_date = p->mod_date;
+    strlcpy(pr.mod_name, p->mod_name, sizeof(pr.mod_name));
+    strlcpy(pr.mod_instance, p->mod_instance, sizeof(pr.mod_instance));
+    pr.max_life = p->max_life;
+    pr.mkvno = p->kdc_key_ver;
+    pr.kvno = p->key_version;
+    
+    ret = v4_prop(arg, &pr);
+    memset(&pr, 0, sizeof(pr));
+    return ret;
+}
+
+#endif /* KRB4 */
+
+#ifndef KRB4
+static time_t
+krb_life_to_time(time_t start, int life)
+{
+    static int lifetimes[] = {
+         38400,   41055,   43894,   46929,   50174,   53643,   57352,   61318,
+         65558,   70091,   74937,   80119,   85658,   91581,   97914,  104684,
+        111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
+        191077,  204289,  218415,  233517,  249664,  266926,  285383,  305116,
+        326213,  348769,  372885,  398668,  426234,  455705,  487215,  520904,
+        556921,  595430,  636601,  680618,  727680,  777995,  831789,  889303,
+        950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
+       1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
+    };
+
+#if 0
+    int i;
+    double q = exp((log(2592000.0) - log(38400.0)) / 63);
+    double x = 38400;
+    for(i = 0; i < 64; i++) {
+       lifetimes[i] = (int)x;
+       x *= q;
+    }
+#endif
+
+    if(life == 0xff)
+       return NEVERDATE;
+    if(life < 0x80)
+       return start + life * 5 * 60;
+    if(life > 0xbf)
+       life = 0xbf;
+    return start + lifetimes[life - 0x80];
+}
+#endif /* !KRB4 */
+
+int
+v4_prop(void *arg, struct v4_principal *p)
+{
+    struct prop_data *pd = arg;
+    hdb_entry ent;
+    krb5_error_code ret;
+
+    memset(&ent, 0, sizeof(ent));
+
+    ret = krb5_425_conv_principal(pd->context, p->name, p->instance, v4_realm,
+                                 &ent.principal);
+    if(ret) {
+       krb5_warn(pd->context, ret,
+                 "krb5_425_conv_principal %s.%s@%s",
+                 p->name, p->instance, v4_realm);
+       return 0;
+    }
+
+    if(verbose_flag) {
+       char *s;
+       krb5_unparse_name_short(pd->context, ent.principal, &s);
+       krb5_warnx(pd->context, "%s.%s -> %s", p->name, p->instance, s);
+       free(s);
+    }
+
+    ent.kvno = p->kvno;
+    ent.keys.len = 3;
+    ent.keys.val = malloc(ent.keys.len * sizeof(*ent.keys.val));
+    if(p->mkvno != -1) {
+       ent.keys.val[0].mkvno = malloc (sizeof(*ent.keys.val[0].mkvno));
+       *(ent.keys.val[0].mkvno) = p->mkvno;
+    } else
+       ent.keys.val[0].mkvno = NULL;
+    ent.keys.val[0].salt = calloc(1, sizeof(*ent.keys.val[0].salt));
+    ent.keys.val[0].salt->type = KRB5_PADATA_PW_SALT;
+    ent.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
+    krb5_data_alloc(&ent.keys.val[0].key.keyvalue, DES_KEY_SZ);
+    memcpy(ent.keys.val[0].key.keyvalue.data, p->key, 8);
+
+    copy_Key(&ent.keys.val[0], &ent.keys.val[1]);
+    ent.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
+    copy_Key(&ent.keys.val[0], &ent.keys.val[2]);
+    ent.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
+
+    {
+       int life = krb_life_to_time(0, p->max_life);
+       if(life == NEVERDATE){
+           ent.max_life = NULL;
+       } else {
+           /* clean up lifetime a bit */
+           if(life > 86400)
+               life = (life + 86399) / 86400 * 86400;
+           else if(life > 3600)
+               life = (life + 3599) / 3600 * 3600;
+           ALLOC(ent.max_life);
+           *ent.max_life = life;
+       }
+    }
+
+    ALLOC(ent.valid_end);
+    *ent.valid_end = p->exp_date;
+
+    ret = krb5_make_principal(pd->context, &ent.created_by.principal,
+                             v4_realm,
+                             "kadmin",
+                             "hprop",
+                             NULL);
+    if(ret){
+       krb5_warn(pd->context, ret, "krb5_make_principal");
+       ret = 0;
+       goto out;
+    }
+    ent.created_by.time = time(NULL);
+    ALLOC(ent.modified_by);
+    ret = krb5_425_conv_principal(pd->context, p->mod_name, p->mod_instance, 
+                                 v4_realm, &ent.modified_by->principal);
+    if(ret){
+       krb5_warn(pd->context, ret, "%s.%s@%s", p->name, p->instance, v4_realm);
+       ent.modified_by->principal = NULL;
+       ret = 0;
+       goto out;
+    }
+    ent.modified_by->time = p->mod_date;
+
+    ent.flags.forwardable = 1;
+    ent.flags.renewable = 1;
+    ent.flags.proxiable = 1;
+    ent.flags.postdate = 1;
+    ent.flags.client = 1;
+    ent.flags.server = 1;
+    
+    /* special case password changing service */
+    if(strcmp(p->name, "changepw") == 0 && 
+       strcmp(p->instance, "kerberos") == 0) {
+       ent.flags.forwardable = 0;
+       ent.flags.renewable = 0;
+       ent.flags.proxiable = 0;
+       ent.flags.postdate = 0;
+       ent.flags.initial = 1;
+       ent.flags.change_pw = 1;
+    }
+
+    ret = v5_prop(pd->context, NULL, &ent, pd);
+
+    if (strcmp (p->name, "krbtgt") == 0
+       && strcmp (v4_realm, p->instance) != 0) {
+       krb5_free_principal (pd->context, ent.principal);
+       ret = krb5_425_conv_principal (pd->context, p->name,
+                                      v4_realm, p->instance,
+                                      &ent.principal);
+       if (ret == 0)
+           ret = v5_prop (pd->context, NULL, &ent, pd);
+    }
+
+  out:
+    hdb_free_entry(pd->context, &ent);
+    return ret;
+}
+
+#include "kadb.h"
+
+/* read a `ka_entry' from `fd' at offset `pos' */
+static void
+read_block(krb5_context context, int fd, int32_t pos, void *buf, size_t len)
+{
+    krb5_error_code ret;
+#ifdef HAVE_PREAD
+    if((ret = pread(fd, buf, len, 64 + pos)) < 0)
+       krb5_err(context, 1, errno, "pread(%u)", 64 + pos);
+#else
+    if(lseek(fd, 64 + pos, SEEK_SET) == (off_t)-1)
+       krb5_err(context, 1, errno, "lseek(%u)", 64 + pos);
+    ret = read(fd, buf, len);
+    if(ret < 0)
+       krb5_err(context, 1, errno, "read(%lu)", (unsigned long)len);
+#endif
+    if(ret != len)
+       krb5_errx(context, 1, "read(%lu) = %u", (unsigned long)len, ret);
+}
+
+static int
+ka_convert(struct prop_data *pd, int fd, struct ka_entry *ent)
+{
+    int32_t flags = ntohl(ent->flags);
+    krb5_error_code ret;
+    hdb_entry hdb;
+
+    if(!kaspecials_flag
+       && (flags & KAFNORMAL) == 0) /* remove special entries */
+       return 0;
+    memset(&hdb, 0, sizeof(hdb));
+    ret = krb5_425_conv_principal(pd->context, ent->name, ent->instance, 
+                                 v4_realm, &hdb.principal);
+    if(ret) {
+       krb5_warn(pd->context, ret,
+                 "krb5_425_conv_principal (%s.%s@%s)",
+                 ent->name, ent->instance, v4_realm);
+       return 0;
+    }
+    hdb.kvno = ntohl(ent->kvno);
+    hdb.keys.len = 3;
+    hdb.keys.val = malloc(hdb.keys.len * sizeof(*hdb.keys.val));
+    hdb.keys.val[0].mkvno = NULL;
+    hdb.keys.val[0].salt = calloc(1, sizeof(*hdb.keys.val[0].salt));
+    if (ka_use_null_salt) {
+       hdb.keys.val[0].salt->type = hdb_pw_salt;
+       hdb.keys.val[0].salt->salt.data = NULL;
+       hdb.keys.val[0].salt->salt.length = 0;
+    } else {
+       hdb.keys.val[0].salt->type = hdb_afs3_salt;
+       hdb.keys.val[0].salt->salt.data = strdup(afs_cell);
+       hdb.keys.val[0].salt->salt.length = strlen(afs_cell);
+    }
+    
+    hdb.keys.val[0].key.keytype = ETYPE_DES_CBC_MD5;
+    krb5_data_copy(&hdb.keys.val[0].key.keyvalue, ent->key, sizeof(ent->key));
+    copy_Key(&hdb.keys.val[0], &hdb.keys.val[1]);
+    hdb.keys.val[1].key.keytype = ETYPE_DES_CBC_MD4;
+    copy_Key(&hdb.keys.val[0], &hdb.keys.val[2]);
+    hdb.keys.val[2].key.keytype = ETYPE_DES_CBC_CRC;
+
+    ALLOC(hdb.max_life);
+    *hdb.max_life = ntohl(ent->max_life);
+
+    if(ntohl(ent->valid_end) != NEVERDATE && ntohl(ent->valid_end) != 0xffffffff) {
+       ALLOC(hdb.valid_end);
+       *hdb.valid_end = ntohl(ent->valid_end);
+    }
+    
+    if (ntohl(ent->pw_change) != NEVERDATE && 
+       ent->pw_expire != 255 &&
+       ent->pw_expire != 0) {
+       ALLOC(hdb.pw_end);
+       *hdb.pw_end = ntohl(ent->pw_change)
+           + 24 * 60 * 60 * ent->pw_expire;
+    }
+
+    ret = krb5_make_principal(pd->context, &hdb.created_by.principal,
+                             v4_realm,
+                             "kadmin",
+                             "hprop",
+                             NULL);
+    hdb.created_by.time = time(NULL);
+
+    if(ent->mod_ptr){
+       struct ka_entry mod;
+       ALLOC(hdb.modified_by);
+       read_block(pd->context, fd, ntohl(ent->mod_ptr), &mod, sizeof(mod));
+       
+       krb5_425_conv_principal(pd->context, mod.name, mod.instance, v4_realm, 
+                               &hdb.modified_by->principal);
+       hdb.modified_by->time = ntohl(ent->mod_time);
+       memset(&mod, 0, sizeof(mod));
+    }
+
+    hdb.flags.forwardable = 1;
+    hdb.flags.renewable = 1;
+    hdb.flags.proxiable = 1;
+    hdb.flags.postdate = 1;
+    /* XXX - AFS 3.4a creates krbtgt.REALMOFCELL as NOTGS+NOSEAL */
+    if (strcmp(ent->name, "krbtgt") == 0 &&
+       (flags & (KAFNOTGS|KAFNOSEAL)) == (KAFNOTGS|KAFNOSEAL))
+       flags &= ~(KAFNOTGS|KAFNOSEAL);
+
+    hdb.flags.client = (flags & KAFNOTGS) == 0;
+    hdb.flags.server = (flags & KAFNOSEAL) == 0;
+
+    ret = v5_prop(pd->context, NULL, &hdb, pd);
+    hdb_free_entry(pd->context, &hdb);
+    return ret;
+}
+
+static int
+ka_dump(struct prop_data *pd, const char *file)
+{
+    struct ka_header header;
+    int i;
+    int fd = open(file, O_RDONLY);
+
+    if(fd < 0)
+       krb5_err(pd->context, 1, errno, "open(%s)", file);
+    read_block(pd->context, fd, 0, &header, sizeof(header));
+    if(header.version1 != header.version2)
+       krb5_errx(pd->context, 1, "Version mismatch in header: %ld/%ld",
+                 (long)ntohl(header.version1), (long)ntohl(header.version2));
+    if(ntohl(header.version1) != 5)
+       krb5_errx(pd->context, 1, "Unknown database version %ld (expected 5)", 
+                 (long)ntohl(header.version1));
+    for(i = 0; i < ntohl(header.hashsize); i++){
+       int32_t pos = ntohl(header.hash[i]);
+       while(pos){
+           struct ka_entry ent;
+           read_block(pd->context, fd, pos, &ent, sizeof(ent));
+           ka_convert(pd, fd, &ent);
+           pos = ntohl(ent.next);
+       }
+    }
+    return 0;
+}
+
+
+
+struct getargs args[] = {
+    { "master-key", 'm', arg_string, &mkeyfile, "v5 master key file", "file" },
+    { "database", 'd', arg_string, &database, "database", "file" },
+    { "source",   0,   arg_string, &source_type, "type of database to read", 
+      "heimdal"
+      "|mit-dump"
+      "|krb4-dump"
+#ifdef KRB4
+      "|krb4-db"
+#endif
+      "|kaserver"
+    },
+      
+    { "v4-realm", 'r',  arg_string, &v4_realm, "v4 realm to use" },
+    { "cell",    'c',  arg_string, &afs_cell, "name of AFS cell" },
+    { "kaspecials", 'S', arg_flag,   &kaspecials_flag, "dump KASPECIAL keys"},
+    { "keytab",   'k', arg_string, &ktname, "keytab to use for authentication", "keytab" },
+    { "v5-realm", 'R',  arg_string, &local_realm, "v5 realm to use" },
+    { "decrypt",  'D',  arg_flag,   &decrypt_flag,   "decrypt keys" },
+    { "encrypt",  'E',  arg_flag,   &encrypt_flag,   "encrypt keys" },
+    { "stdout",          'n',  arg_flag,   &to_stdout, "dump to stdout" },
+    { "verbose",  'v', arg_flag, &verbose_flag },
+    { "version",   0,  arg_flag, &version_flag },
+    { "help",     'h', arg_flag, &help_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, num_args, NULL, "[host[:port]] ...");
+    exit (ret);
+}
+
+static void
+get_creds(krb5_context context, krb5_ccache *cache)
+{
+    krb5_keytab keytab;
+    krb5_principal client;
+    krb5_error_code ret;
+    krb5_get_init_creds_opt *init_opts;
+    krb5_preauthtype preauth = KRB5_PADATA_ENC_TIMESTAMP;
+    krb5_creds creds;
+    
+    ret = krb5_kt_register(context, &hdb_kt_ops);
+    if(ret) krb5_err(context, 1, ret, "krb5_kt_register");
+
+    ret = krb5_kt_resolve(context, ktname, &keytab);
+    if(ret) krb5_err(context, 1, ret, "krb5_kt_resolve");
+    
+    ret = krb5_make_principal(context, &client, NULL, 
+                             "kadmin", HPROP_NAME, NULL);
+    if(ret) krb5_err(context, 1, ret, "krb5_make_principal");
+
+    ret = krb5_get_init_creds_opt_alloc(context, &init_opts);
+    if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
+    krb5_get_init_creds_opt_set_preauth_list(init_opts, &preauth, 1);
+
+    ret = krb5_get_init_creds_keytab(context, &creds, client, keytab, 0, NULL, init_opts);
+    if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
+
+    krb5_get_init_creds_opt_free(init_opts);
+    
+    ret = krb5_kt_close(context, keytab);
+    if(ret) krb5_err(context, 1, ret, "krb5_kt_close");
+    
+    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache);
+    if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new");
+
+    ret = krb5_cc_initialize(context, *cache, client);
+    if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+    krb5_free_principal(context, client);
+
+    ret = krb5_cc_store_cred(context, *cache, &creds);
+    if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");
+
+    krb5_free_cred_contents(context, &creds);
+}
+
+enum hprop_source {
+    HPROP_HEIMDAL = 1,
+    HPROP_KRB4_DB,
+    HPROP_KRB4_DUMP,
+    HPROP_KASERVER,
+    HPROP_MIT_DUMP
+};
+
+#define IS_TYPE_V4(X) ((X) == HPROP_KRB4_DB || (X) == HPROP_KRB4_DUMP || (X) == HPROP_KASERVER)
+
+struct {
+    int type;
+    const char *name;
+} types[] = {
+    { HPROP_HEIMDAL,   "heimdal" },
+    { HPROP_KRB4_DUMP, "krb4-dump" },
+#ifdef KRB4
+    { HPROP_KRB4_DB,   "krb4-db" },
+#endif
+    { HPROP_KASERVER,  "kaserver" },
+    { HPROP_MIT_DUMP,  "mit-dump" }
+};
+
+static int
+parse_source_type(const char *s)
+{
+    int i;
+    for(i = 0; i < sizeof(types) / sizeof(types[0]); i++) {
+       if(strstr(types[i].name, s) == types[i].name)
+           return types[i].type;
+    }
+    return 0;
+}
+
+static void
+iterate (krb5_context context,
+        const char *database,
+        HDB *db,
+        int type,
+        struct prop_data *pd)
+{
+    int ret;
+
+    switch(type) {
+    case HPROP_KRB4_DUMP:
+       ret = v4_prop_dump(pd, database);
+       break;
+#ifdef KRB4
+    case HPROP_KRB4_DB:
+       ret = kerb_db_iterate ((k_iter_proc_t)kdb_prop, pd);
+       if(ret)
+           krb5_errx(context, 1, "kerb_db_iterate: %s", 
+                     krb_get_err_text(ret));
+       break;
+#endif /* KRB4 */
+    case HPROP_KASERVER:
+       ret = ka_dump(pd, database);
+       if(ret)
+           krb5_err(context, 1, ret, "ka_dump");
+       break;
+    case HPROP_MIT_DUMP:
+       ret = mit_prop_dump(pd, database);
+       if (ret)
+           krb5_errx(context, 1, "mit_prop_dump: %s",
+                     krb5_get_err_text(context, ret));
+       break;
+    case HPROP_HEIMDAL:
+       ret = hdb_foreach(context, db, HDB_F_DECRYPT, v5_prop, pd);
+       if(ret)
+           krb5_err(context, 1, ret, "hdb_foreach");
+       break;
+    }
+}
+
+static int
+dump_database (krb5_context context, int type,
+              const char *database, HDB *db)
+{
+    krb5_error_code ret;
+    struct prop_data pd;
+    krb5_data data;
+
+    pd.context      = context;
+    pd.auth_context = NULL;
+    pd.sock         = STDOUT_FILENO;
+       
+    iterate (context, database, db, type, &pd);
+    krb5_data_zero (&data);
+    ret = krb5_write_message (context, &pd.sock, &data);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_write_message");
+
+    return 0;
+}
+
+static int
+propagate_database (krb5_context context, int type,
+                   const char *database, 
+                   HDB *db, krb5_ccache ccache,
+                   int optind, int argc, char **argv)
+{
+    krb5_principal server;
+    krb5_error_code ret;
+    int i;
+
+    for(i = optind; i < argc; i++){
+       krb5_auth_context auth_context;
+       int fd;
+       struct prop_data pd;
+       krb5_data data;
+
+       char *port, portstr[NI_MAXSERV];
+       
+       port = strchr(argv[i], ':');
+       if(port == NULL) {
+           snprintf(portstr, sizeof(portstr), "%u", 
+                    ntohs(krb5_getportbyname (context, "hprop", "tcp", 
+                                              HPROP_PORT)));
+           port = portstr;
+       } else
+           *port++ = '\0';
+
+       fd = open_socket(context, argv[i], port);
+       if(fd < 0) {
+           krb5_warn (context, errno, "connect %s", argv[i]);
+           continue;
+       }
+
+       ret = krb5_sname_to_principal(context, argv[i],
+                                     HPROP_NAME, KRB5_NT_SRV_HST, &server);
+       if(ret) {
+           krb5_warn(context, ret, "krb5_sname_to_principal(%s)", argv[i]);
+           close(fd);
+           continue;
+       }
+
+        if (local_realm) {
+            krb5_realm my_realm;
+            krb5_get_default_realm(context,&my_realm);
+
+           free (*krb5_princ_realm(context, server));
+            krb5_princ_set_realm(context,server,&my_realm);
+        }
+    
+       auth_context = NULL;
+       ret = krb5_sendauth(context,
+                           &auth_context,
+                           &fd,
+                           HPROP_VERSION,
+                           NULL,
+                           server,
+                           AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
+                           NULL, /* in_data */
+                           NULL, /* in_creds */
+                           ccache,
+                           NULL,
+                           NULL,
+                           NULL);
+
+       krb5_free_principal(context, server);
+
+       if(ret) {
+           krb5_warn(context, ret, "krb5_sendauth");
+           close(fd);
+           continue;
+       }
+       
+       pd.context      = context;
+       pd.auth_context = auth_context;
+       pd.sock         = fd;
+
+       iterate (context, database, db, type, &pd);
+
+       krb5_data_zero (&data);
+       ret = krb5_write_priv_message(context, auth_context, &fd, &data);
+       if(ret)
+           krb5_warn(context, ret, "krb5_write_priv_message");
+
+       ret = krb5_read_priv_message(context, auth_context, &fd, &data);
+       if(ret)
+           krb5_warn(context, ret, "krb5_read_priv_message");
+       else
+           krb5_data_free (&data);
+       
+       krb5_auth_con_free(context, auth_context);
+       close(fd);
+    }
+    return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_ccache ccache = NULL;
+    HDB *db = NULL;
+    int optind = 0;
+
+    int type = 0;
+
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+
+    if(help_flag)
+       usage(0);
+    
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    ret = krb5_init_context(&context);
+    if(ret)
+       exit(1);
+
+    if(local_realm)
+       krb5_set_default_realm(context, local_realm);
+
+    if(v4_realm == NULL) {
+       ret = krb5_get_default_realm(context, &v4_realm);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_get_default_realm");
+    }
+
+    if(afs_cell == NULL) {
+       afs_cell = strdup(v4_realm);
+       if(afs_cell == NULL)
+           krb5_errx(context, 1, "out of memory");
+       strlwr(afs_cell);
+    }
+
+
+    if(encrypt_flag && decrypt_flag)
+       krb5_errx(context, 1, 
+                 "only one of `--encrypt' and `--decrypt' is meaningful");
+
+    if(source_type != NULL) {
+       type = parse_source_type(source_type);
+       if(type == 0)
+           krb5_errx(context, 1, "unknown source type `%s'", source_type);
+    } else if(type == 0)
+       type = HPROP_HEIMDAL;
+
+    if(!to_stdout)
+       get_creds(context, &ccache);
+    
+    if(decrypt_flag || encrypt_flag) {
+       ret = hdb_read_master_key(context, mkeyfile, &mkey5);
+       if(ret && ret != ENOENT)
+           krb5_err(context, 1, ret, "hdb_read_master_key");
+       if(ret)
+           krb5_errx(context, 1, "No master key file found");
+    }
+    
+#ifdef KRB4
+    if (IS_TYPE_V4(type)) {
+       int e;
+
+       if (v4_realm == NULL) {
+           e = krb_get_lrealm(realm_buf, 1);
+           if(e)
+               krb5_errx(context, 1, "krb_get_lrealm: %s",
+                         krb_get_err_text(e));
+           v4_realm = realm_buf;
+       }
+    }
+#endif
+
+    switch(type) {
+#ifdef KRB4
+    case HPROP_KRB4_DB:
+       if (database == NULL)
+           krb5_errx(context, 1, "no database specified");
+       break;
+#endif
+    case HPROP_KASERVER:
+       if (database == NULL)
+           database = DEFAULT_DATABASE;
+       ka_use_null_salt = krb5_config_get_bool_default(context, NULL, FALSE, 
+                                                       "hprop", 
+                                                       "afs_uses_null_salt", 
+                                                       NULL);
+
+       break;
+    case HPROP_KRB4_DUMP:
+       if (database == NULL)
+           krb5_errx(context, 1, "no dump file specified");
+       
+       break;
+    case HPROP_MIT_DUMP:
+       if (database == NULL)
+           krb5_errx(context, 1, "no dump file specified");
+       break;
+    case HPROP_HEIMDAL:
+       ret = hdb_create (context, &db, database);
+       if(ret)
+           krb5_err(context, 1, ret, "hdb_create: %s", database);
+       ret = db->hdb_open(context, db, O_RDONLY, 0);
+       if(ret)
+           krb5_err(context, 1, ret, "db->hdb_open");
+       break;
+    default:
+       krb5_errx(context, 1, "unknown dump type `%d'", type);
+       break;
+    }
+
+    if (to_stdout)
+       dump_database (context, type, database, db);
+    else
+       propagate_database (context, type, database, 
+                           db, ccache, optind, argc, argv);
+
+    if(ccache != NULL)
+       krb5_cc_destroy(context, ccache);
+       
+    if(db != NULL)
+       (*db->hdb_destroy)(context, db);
+
+    krb5_free_context(context);
+    return 0;
+}
diff --git a/src/kerberosV/src/kdc/hprop.h b/src/kerberosV/src/kdc/hprop.h
new file mode 100644 (file)
index 0000000..4a45341
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: hprop.h,v 1.14 2003/09/03 11:46:51 lha Exp $ */
+
+#ifndef __HPROP_H__
+#define __HPROP_H__
+
+#include "headers.h"
+
+struct prop_data{
+    krb5_context context;
+    krb5_auth_context auth_context;
+    int sock;
+};
+
+#define HPROP_VERSION "hprop-0.0"
+#define HPROP_NAME "hprop"
+#define HPROP_KEYTAB "HDB:"
+#define HPROP_PORT 754
+
+#ifndef NEVERDATE
+#define NEVERDATE ((1U << 31) - 1)
+#endif
+
+krb5_error_code v5_prop(krb5_context, HDB*, hdb_entry*, void*);
+int mit_prop_dump(void*, const char*);
+
+struct v4_principal {
+    char name[64];
+    char instance[64];
+    DES_cblock key;
+    int kvno;
+    int mkvno;
+    time_t exp_date;
+    time_t mod_date;
+    char mod_name[64];
+    char mod_instance[64];
+    int max_life;
+};
+
+int v4_prop(void*, struct v4_principal*);
+int v4_prop_dump(void *arg, const char*);
+
+#endif /* __HPROP_H__ */
diff --git a/src/kerberosV/src/kdc/hpropd.8 b/src/kerberosV/src/kdc/hpropd.8
new file mode 100644 (file)
index 0000000..bab0aaa
--- /dev/null
@@ -0,0 +1,107 @@
+.\" Copyright (c) 1997, 2000 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: hpropd.8,v 1.13 2004/12/10 09:44:05 lha Exp $
+.\"
+.Dd August 27, 1997
+.Dt HPROPD 8
+.Os HEIMDAL
+.Sh NAME
+.Nm hpropd
+.Nd receive a propagated database
+.Sh SYNOPSIS
+.Nm hpropd
+.Bk -words
+.Oo Fl d Ar file \*(Ba Xo
+.Fl -database= Ns Ar file
+.Xc
+.Oc
+.Op Fl n | Fl -stdin
+.Op Fl -print
+.Op Fl i | Fl -no-inetd
+.Oo Fl k Ar keytab \*(Ba Xo
+.Fl -keytab= Ns Ar keytab
+.Xc
+.Oc
+.Op Fl 4 | Fl -v4dump
+.Ek
+.Sh DESCRIPTION
+.Nm
+receives a database sent by
+.Nm hprop .
+and writes it as a local database.
+.Pp
+By default,
+.Nm
+expects to be started from
+.Nm inetd
+if stdin is a socket and expects to receive the dumped database over
+stdin otherwise.
+If the database is sent over the network, it is authenticated and
+encrypted.
+Only connections authenticated with the principal
+.Nm kadmin Ns / Ns Nm hprop
+are accepted.
+.Pp
+Options supported:
+.Bl -tag -width Ds
+.It Xo
+.Fl d Ar file ,
+.Fl -database= Ns Ar file
+.Xc
+database
+.It Xo
+.Fl n ,
+.Fl -stdin
+.Xc
+read from stdin
+.It Xo
+.Fl -print
+.Xc
+print dump to stdout
+.It Xo
+.Fl i ,
+.Fl -no-inetd
+.Xc
+not started from inetd
+.It Xo
+.Fl k Ar keytab ,
+.Fl -keytab= Ns Ar keytab
+.Xc
+keytab to use for authentication
+.It Xo
+.Fl 4 ,
+.Fl -v4dump
+.Xc
+create v4 type DB
+.El
+.Sh SEE ALSO
+.Xr hprop 8
diff --git a/src/kerberosV/src/kdc/hpropd.c b/src/kerberosV/src/kdc/hpropd.c
new file mode 100644 (file)
index 0000000..62b35c1
--- /dev/null
@@ -0,0 +1,451 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hprop.h"
+
+RCSID("$KTH: hpropd.c,v 1.40 2005/04/24 13:48:08 lha Exp $");
+
+#ifdef KRB4
+#include <krb.h>
+#include <prot.h>
+#define Principal Principal4
+#include <krb_db.h>
+
+static des_cblock mkey4;
+static des_key_schedule msched4;
+
+static char *
+time2str(time_t t)
+{
+    static char buf[128];
+    strftime(buf, sizeof(buf), "%Y%m%d%H%M", gmtime(&t));
+    return buf;
+}
+
+static int 
+dump_krb4(krb5_context context, hdb_entry *ent, int fd)
+{
+    char name[ANAME_SZ];  
+    char instance[INST_SZ];
+    char realm[REALM_SZ];
+    char buf[1024];
+    char *p;
+    int i;
+    int ret;
+    char *princ_name;
+    Event *modifier;
+    krb5_realm *realms;
+    int cmp;
+  
+    ret = krb5_524_conv_principal(context, ent->principal,
+                                 name, instance, realm);
+    if (ret) {
+       ret = krb5_unparse_name(context, ent->principal, &princ_name);
+       if (ret == 0) {
+           krb5_warn(context, ret, "%s", princ_name);
+           free(princ_name);
+       }
+       return -1;
+    }
+
+    ret = krb5_get_default_realms (context, &realms);
+    if (ret) {
+       krb5_warn(context, ret, "krb5_get_default_realms");
+       return -1;
+    }
+
+    cmp = strcmp (realms[0], ent->principal->realm);
+    krb5_free_host_realm (context, realms);
+    if (cmp != 0)
+        return -1;
+
+    snprintf (buf, sizeof(buf), "%s %s ", name,
+             (strlen(instance) != 0) ? instance : "*");
+
+    if (ent->max_life) { 
+       asprintf(&p, "%d", krb_time_to_life(0, *ent->max_life));
+       strlcat(buf, p, sizeof(buf));
+       free(p);
+    } else 
+       strlcat(buf, "255", sizeof(buf)); 
+    strlcat(buf, " ", sizeof(buf));
+
+    i = 0;
+    while (i < ent->keys.len &&
+          ent->keys.val[i].key.keytype != KEYTYPE_DES)
+       ++i;
+
+    if (i == ent->keys.len) {
+       krb5_warnx(context, "No DES key for %s.%s", name, instance);
+       return -1;
+    }
+
+    if (ent->keys.val[i].mkvno)
+       asprintf(&p, "%d ", *ent->keys.val[i].mkvno);
+    else
+       asprintf(&p, "%d ", 1);
+    strlcat(buf, p, sizeof(buf));
+    free(p);
+
+    asprintf(&p, "%d ", ent->kvno);
+    strlcat(buf, p, sizeof(buf));
+    free(p);
+
+    asprintf(&p, "%d ", 0); /* Attributes are always 0*/  
+    strlcat(buf, p, sizeof(buf));
+    free(p);
+
+    { 
+       u_int32_t *key = ent->keys.val[i].key.keyvalue.data;
+       kdb_encrypt_key((des_cblock*)key, (des_cblock*)key,
+                       &mkey4, msched4, DES_ENCRYPT);
+       asprintf(&p, "%x %x ", (int)htonl(*key), (int)htonl(*(key+1)));
+       strlcat(buf, p, sizeof(buf));
+       free(p);
+    }
+    if (ent->valid_end == NULL)
+       strlcat(buf, time2str(60*60*24*365*50), sizeof(buf)); /*no expiration*/
+    else
+       strlcat(buf, time2str(*ent->valid_end), sizeof(buf));
+    strlcat(buf, " ", sizeof(buf));
+
+    if (ent->modified_by == NULL) 
+       modifier = &ent->created_by;
+    else  
+       modifier = ent->modified_by;
+    
+    ret = krb5_524_conv_principal(context, modifier->principal,
+                                 name, instance, realm);
+    if (ret) { 
+       ret = krb5_unparse_name(context, modifier->principal, &princ_name);
+       if (ret == 0) {
+           krb5_warn(context, ret, "%s", princ_name);
+           free(princ_name);
+       }
+       return -1;
+    } 
+    asprintf(&p, "%s %s %s\n", time2str(modifier->time), 
+            (strlen(name) != 0) ? name : "*", 
+            (strlen(instance) != 0) ? instance : "*");
+    strlcat(buf, p, sizeof(buf));
+    free(p);
+
+    ret = write(fd, buf, strlen(buf));
+    if (ret == -1)
+       krb5_warnx(context, "write");
+    return 0;
+}
+#endif /* KRB4 */
+
+static int inetd_flag = -1;
+static int help_flag;
+static int version_flag;
+static int print_dump;
+static const char *database = HDB_DEFAULT_DB;
+static int from_stdin;
+static char *local_realm;
+#ifdef KRB4
+static int v4dump;
+#endif
+static char *ktname = NULL;
+
+struct getargs args[] = {
+    { "database", 'd', arg_string, &database, "database", "file" },
+    { "stdin",    'n', arg_flag, &from_stdin, "read from stdin" },
+    { "print",     0, arg_flag, &print_dump, "print dump to stdout" },
+    { "inetd",    'i', arg_negative_flag,      &inetd_flag,
+      "Not started from inetd" },
+    { "keytab",   'k', arg_string, &ktname,    "keytab to use for authentication", "keytab" },
+    { "realm",   'r',  arg_string, &local_realm, "realm to use" },
+#ifdef KRB4
+    { "v4dump",       '4',  arg_flag, &v4dump, "create v4 type DB" },
+#endif
+    { "version",    0, arg_flag, &version_flag, NULL, NULL },
+    { "help",    'h',  arg_flag, &help_flag, NULL, NULL}
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int ret)
+{
+    arg_printusage (args, num_args, NULL, "");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_auth_context ac = NULL;
+    krb5_principal c1, c2;
+    krb5_authenticator authent;
+    krb5_keytab keytab;
+    int fd;
+    HDB *db;
+    int optind = 0;
+    char *tmp_db;
+    krb5_log_facility *fac;
+    int nprincs;
+#ifdef KRB4
+    int e;
+    int fd_out = -1;
+#endif
+
+    ret = krb5_init_context(&context);
+    if(ret)
+       exit(1);
+
+    ret = krb5_openlog(context, "hpropd", &fac);
+    if(ret)
+       ;
+    krb5_set_warn_dest(context, fac);
+  
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+
+#ifdef KRB4
+    if (v4dump && database == HDB_DEFAULT_DB)
+       database = "/var/kerberos/524_dump";
+#endif /* KRB4 */
+
+    if(local_realm != NULL)
+       krb5_set_default_realm(context, local_realm);
+    
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0)
+       usage(1);
+
+    if(from_stdin)
+       fd = STDIN_FILENO;
+    else {
+       struct sockaddr_storage ss;
+       struct sockaddr *sa = (struct sockaddr *)&ss;
+       socklen_t sin_len = sizeof(ss);
+       char addr_name[256];
+       krb5_ticket *ticket;
+       char *server;
+
+       fd = STDIN_FILENO;
+       if (inetd_flag == -1) {
+           if (getpeername (fd, sa, &sin_len) < 0)
+               inetd_flag = 0;
+           else
+               inetd_flag = 1;
+       }
+       if (!inetd_flag) {
+           mini_inetd (krb5_getportbyname (context, "hprop", "tcp",
+                                           HPROP_PORT));
+       }
+       sin_len = sizeof(ss);
+       if(getpeername(fd, sa, &sin_len) < 0)
+           krb5_err(context, 1, errno, "getpeername");
+
+       if (inet_ntop(sa->sa_family,
+                     socket_get_address (sa),
+                     addr_name,
+                     sizeof(addr_name)) == NULL)
+           strlcpy (addr_name, "unknown address",
+                            sizeof(addr_name));
+
+       krb5_log(context, fac, 0, "Connection from %s", addr_name);
+    
+       ret = krb5_kt_register(context, &hdb_kt_ops);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_kt_register");
+
+       if (ktname != NULL) {
+           ret = krb5_kt_resolve(context, ktname, &keytab);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_kt_resolve %s", ktname);
+       } else {
+           ret = krb5_kt_default (context, &keytab);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_kt_default");
+       }
+
+       ret = krb5_recvauth(context, &ac, &fd, HPROP_VERSION, NULL,
+                           0, keytab, &ticket);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_recvauth");
+       
+       ret = krb5_unparse_name(context, ticket->server, &server);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_unparse_name");
+       if (strncmp(server, "hprop/", 5) != 0)
+           krb5_errx(context, 1, "ticket not for hprop (%s)", server);
+
+       free(server);
+       krb5_free_ticket (context, ticket);
+
+       ret = krb5_auth_con_getauthenticator(context, ac, &authent);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_auth_con_getauthenticator");
+       
+       ret = krb5_make_principal(context, &c1, NULL, "kadmin", "hprop", NULL);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_make_principal");
+       _krb5_principalname2krb5_principal(&c2, 
+                                          authent->cname, authent->crealm);
+       if(!krb5_principal_compare(context, c1, c2)) {
+           char *s;
+           ret = krb5_unparse_name(context, c2, &s);
+           if (ret)
+               s = "unparseable name";
+           krb5_errx(context, 1, "Unauthorized connection from %s", s);
+       }
+       krb5_free_principal(context, c1);
+       krb5_free_principal(context, c2);
+
+       ret = krb5_kt_close(context, keytab);
+       if(ret)
+           krb5_err(context, 1, ret, "krb5_kt_close");
+    }
+    
+    if(!print_dump) {
+       asprintf(&tmp_db, "%s~", database);
+#ifdef KRB4
+       if (v4dump) {
+           fd_out = open(tmp_db, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+           if (fd_out == -1)
+               krb5_errx(context, 1, "%s", strerror(errno));
+       }
+       else
+#endif /* KRB4 */
+       {
+           ret = hdb_create(context, &db, tmp_db);
+           if(ret)
+               krb5_err(context, 1, ret, "hdb_create(%s)", tmp_db);
+           ret = db->hdb_open(context, db, O_RDWR | O_CREAT | O_TRUNC, 0600);
+           if(ret)
+               krb5_err(context, 1, ret, "hdb_open(%s)", tmp_db);
+       }
+    }
+
+#ifdef KRB4
+    if (v4dump) {
+       e = kdb_get_master_key(0, &mkey4, msched4);
+       if(e)
+           krb5_errx(context, 1, "kdb_get_master_key: %s",
+                     krb_get_err_text(e));
+    }
+#endif /* KRB4 */
+
+    nprincs = 0;
+    while(1){
+       krb5_data data;
+       hdb_entry entry;
+
+       if(from_stdin) {
+           ret = krb5_read_message(context, &fd, &data);
+           if(ret != 0 && ret != HEIM_ERR_EOF)
+               krb5_err(context, 1, ret, "krb5_read_message");
+       } else {
+           ret = krb5_read_priv_message(context, ac, &fd, &data);
+           if(ret)
+               krb5_err(context, 1, ret, "krb5_read_priv_message");
+       }
+
+       if(ret == HEIM_ERR_EOF || data.length == 0) {
+           if(!from_stdin) {
+               data.data = NULL;
+               data.length = 0;
+               krb5_write_priv_message(context, ac, &fd, &data);
+           }
+           if(!print_dump) {
+#ifdef KRB4
+               if (v4dump) {
+                   ret = rename(tmp_db, database);
+                   if (ret)
+                       krb5_errx(context, 1, "rename");
+                   ret = close(fd_out);
+                   if (ret)
+                       krb5_errx(context, 1, "close");
+               } else
+#endif /* KRB4 */
+               {
+                   ret = db->hdb_rename(context, db, database);
+                   if(ret)
+                       krb5_err(context, 1, ret, "db_rename");
+                   ret = db->hdb_close(context, db);
+                   if(ret)
+                       krb5_err(context, 1, ret, "db_close");
+               }
+           }
+           break;
+       }
+       ret = hdb_value2entry(context, &data, &entry);
+       if(ret)
+           krb5_err(context, 1, ret, "hdb_value2entry");
+       if(print_dump)
+           hdb_print_entry(context, db, &entry, stdout);
+       else {
+#ifdef KRB4
+           if (v4dump) {
+               ret = dump_krb4(context, &entry, fd_out);
+               if(!ret) nprincs++;
+           }
+           else
+#endif /* KRB4 */
+           {
+               ret = db->hdb_store(context, db, 0, &entry);
+               if(ret == HDB_ERR_EXISTS) {
+                   char *s;
+                   ret = krb5_unparse_name(context, entry.principal, &s);
+                   if (ret)
+                       s = strdup("unparseable name");
+                   krb5_warnx(context, "Entry exists: %s", s);
+                   free(s);
+               } else if(ret) 
+                   krb5_err(context, 1, ret, "db_store");
+               else
+                   nprincs++;
+           }
+       }
+       hdb_free_entry(context, &entry);
+    }
+    if (!print_dump)
+       krb5_log(context, fac, 0, "Received %d principals", nprincs);
+    exit(0);
+}
diff --git a/src/kerberosV/src/kdc/kadb.h b/src/kerberosV/src/kdc/kadb.h
new file mode 100644 (file)
index 0000000..aff65ef
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1998 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: kadb.h,v 1.3 2000/03/03 12:36:26 assar Exp $ */
+
+#ifndef __kadb_h__
+#define __kadb_h__
+
+#define HASHSIZE 8191
+
+struct ka_header {
+    int32_t version1;                  /* file format version, should
+                                          match version2 */
+    int32_t size;
+    int32_t free_ptr;
+    int32_t eof_ptr;
+    int32_t kvno_ptr;
+    int32_t stats[8];
+    int32_t admin_accounts;
+    int32_t special_keys_version;
+    int32_t hashsize;                  /* allocated size of hash */
+    int32_t hash[HASHSIZE];
+    int32_t version2;
+};
+
+struct ka_entry {
+    int32_t flags;                     /* see below */
+    int32_t next;                      /* next in hash list */
+    int32_t valid_end;                 /* expiration date */
+    int32_t mod_time;                  /* time last modified */
+    int32_t mod_ptr;                   /* pointer to modifier */
+    int32_t pw_change;                 /* last pw change */
+    int32_t max_life;                  /* max ticket life */
+    int32_t kvno;
+    int32_t foo2[2];                   /* huh? */
+    char name[64];
+    char instance[64];
+    char key[8];
+    u_char pw_expire;                  /* # days before password expires  */
+    u_char spare;
+    u_char attempts;
+    u_char locktime;
+};
+
+#define KAFNORMAL      (1<<0)
+#define KAFADMIN        (1<<2) /* an administrator */
+#define KAFNOTGS        (1<<3) /* ! allow principal to get or use TGT */
+#define KAFNOSEAL       (1<<5) /* ! allow principal as server in GetTicket */
+#define KAFNOCPW        (1<<6) /* ! allow principal to change its own key */
+#define KAFSPECIAL      (1<<8) /* set if special AuthServer principal */
+
+#define DEFAULT_DATABASE "/usr/afs/db/kaserver.DB0"
+
+#endif /* __kadb_h__ */
diff --git a/src/kerberosV/src/kdc/kaserver.c b/src/kerberosV/src/kdc/kaserver.c
new file mode 100644 (file)
index 0000000..e27c740
--- /dev/null
@@ -0,0 +1,874 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+RCSID("$KTH: kaserver.c,v 1.27 2005/06/08 17:58:09 lha Exp $");
+
+#include <krb5-v4compat.h>
+#include <rx.h>
+
+#define KA_AUTHENTICATION_SERVICE 731
+#define KA_TICKET_GRANTING_SERVICE 732
+#define KA_MAINTENANCE_SERVICE 733
+
+#define AUTHENTICATE_OLD        1
+#define CHANGEPASSWORD          2
+#define GETTICKET_OLD           3
+#define SETPASSWORD             4
+#define SETFIELDS               5
+#define CREATEUSER              6
+#define DELETEUSER              7
+#define GETENTRY                8
+#define LISTENTRY               9
+#define GETSTATS               10
+#define DEBUG                  11
+#define GETPASSWORD            12
+#define GETRANDOMKEY           13
+#define AUTHENTICATE           21
+#define AUTHENTICATE_V2                22
+#define GETTICKET              23
+
+/* XXX - Where do we get these? */
+
+#define RXGEN_OPCODE (-455)
+
+#define KADATABASEINCONSISTENT                   (180480L)
+#define KAEXIST                                  (180481L)
+#define KAIO                                     (180482L)
+#define KACREATEFAIL                             (180483L)
+#define KANOENT                                  (180484L)
+#define KAEMPTY                                  (180485L)
+#define KABADNAME                                (180486L)
+#define KABADINDEX                               (180487L)
+#define KANOAUTH                                 (180488L)
+#define KAANSWERTOOLONG                          (180489L)
+#define KABADREQUEST                             (180490L)
+#define KAOLDINTERFACE                           (180491L)
+#define KABADARGUMENT                            (180492L)
+#define KABADCMD                                 (180493L)
+#define KANOKEYS                                 (180494L)
+#define KAREADPW                                 (180495L)
+#define KABADKEY                                 (180496L)
+#define KAUBIKINIT                               (180497L)
+#define KAUBIKCALL                               (180498L)
+#define KABADPROTOCOL                            (180499L)
+#define KANOCELLS                                (180500L)
+#define KANOCELL                                 (180501L)
+#define KATOOMANYUBIKS                           (180502L)
+#define KATOOMANYKEYS                            (180503L)
+#define KABADTICKET                              (180504L)
+#define KAUNKNOWNKEY                             (180505L)
+#define KAKEYCACHEINVALID                        (180506L)
+#define KABADSERVER                              (180507L)
+#define KABADUSER                                (180508L)
+#define KABADCPW                                 (180509L)
+#define KABADCREATE                              (180510L)
+#define KANOTICKET                               (180511L)
+#define KAASSOCUSER                              (180512L)
+#define KANOTSPECIAL                             (180513L)
+#define KACLOCKSKEW                              (180514L)
+#define KANORECURSE                              (180515L)
+#define KARXFAIL                                 (180516L)
+#define KANULLPASSWORD                           (180517L)
+#define KAINTERNALERROR                          (180518L)
+#define KAPWEXPIRED                              (180519L)
+#define KAREUSED                                 (180520L)
+#define KATOOSOON                                (180521L)
+#define KALOCKED                                 (180522L)
+
+static void
+decode_rx_header (krb5_storage *sp,
+                 struct rx_header *h)
+{
+    krb5_ret_int32(sp, &h->epoch);
+    krb5_ret_int32(sp, &h->connid);
+    krb5_ret_int32(sp, &h->callid);
+    krb5_ret_int32(sp, &h->seqno);
+    krb5_ret_int32(sp, &h->serialno);
+    krb5_ret_int8(sp,  &h->type);
+    krb5_ret_int8(sp,  &h->flags);
+    krb5_ret_int8(sp,  &h->status);
+    krb5_ret_int8(sp,  &h->secindex);
+    krb5_ret_int16(sp, &h->reserved);
+    krb5_ret_int16(sp, &h->serviceid);
+}
+
+static void
+encode_rx_header (struct rx_header *h,
+                 krb5_storage *sp)
+{
+    krb5_store_int32(sp, h->epoch);
+    krb5_store_int32(sp, h->connid);
+    krb5_store_int32(sp, h->callid);
+    krb5_store_int32(sp, h->seqno);
+    krb5_store_int32(sp, h->serialno);
+    krb5_store_int8(sp,  h->type);
+    krb5_store_int8(sp,  h->flags);
+    krb5_store_int8(sp,  h->status);
+    krb5_store_int8(sp,  h->secindex);
+    krb5_store_int16(sp, h->reserved);
+    krb5_store_int16(sp, h->serviceid);
+}
+
+static void
+init_reply_header (struct rx_header *hdr,
+                  struct rx_header *reply_hdr,
+                  u_char type,
+                  u_char flags)
+{
+    reply_hdr->epoch     = hdr->epoch;
+    reply_hdr->connid    = hdr->connid;
+    reply_hdr->callid    = hdr->callid;
+    reply_hdr->seqno     = 1;
+    reply_hdr->serialno  = 1;
+    reply_hdr->type      = type;
+    reply_hdr->flags     = flags;
+    reply_hdr->status    = 0;
+    reply_hdr->secindex  = 0;
+    reply_hdr->reserved  = 0;
+    reply_hdr->serviceid = hdr->serviceid;
+}
+
+static void
+make_error_reply (struct rx_header *hdr,
+                 u_int32_t ret,
+                 krb5_data *reply)
+
+{
+    krb5_storage *sp;
+    struct rx_header reply_hdr;
+
+    init_reply_header (hdr, &reply_hdr, HT_ABORT, HF_LAST);
+    sp = krb5_storage_emem();
+    encode_rx_header (&reply_hdr, sp);
+    krb5_store_int32(sp, ret);
+    krb5_storage_to_data (sp, reply);
+    krb5_storage_free (sp);
+}
+
+static krb5_error_code
+krb5_ret_xdr_data(krb5_storage *sp,
+                 krb5_data *data)
+{
+    int ret;
+    int size;
+    ret = krb5_ret_int32(sp, &size);
+    if(ret)
+       return ret;
+    if(size < 0)
+       return ERANGE;
+    data->length = size;
+    if (size) {
+       u_char foo[4];
+       size_t pad = (4 - size % 4) % 4;
+
+       data->data = malloc(size);
+       if (data->data == NULL)
+           return ENOMEM;
+       ret = krb5_storage_read(sp, data->data, size);
+       if(ret != size)
+           return (ret < 0)? errno : KRB5_CC_END;
+       if (pad) {
+           ret = krb5_storage_read(sp, foo, pad);
+           if (ret != pad)
+               return (ret < 0)? errno : KRB5_CC_END;
+       }
+    } else
+       data->data = NULL;
+    return 0;
+}
+
+static krb5_error_code
+krb5_store_xdr_data(krb5_storage *sp,
+                   krb5_data data)
+{
+    u_char zero[4] = {0, 0, 0, 0};
+    int ret;
+    size_t pad;
+
+    ret = krb5_store_int32(sp, data.length);
+    if(ret < 0)
+       return ret;
+    ret = krb5_storage_write(sp, data.data, data.length);
+    if(ret != data.length){
+       if(ret < 0)
+           return errno;
+       return KRB5_CC_END;
+    }
+    pad = (4 - data.length % 4) % 4;
+    if (pad) {
+       ret = krb5_storage_write(sp, zero, pad);
+       if (ret != pad) {
+           if (ret < 0)
+               return errno;
+           return KRB5_CC_END;
+       }
+    }
+    return 0;
+}
+
+
+static krb5_error_code
+create_reply_ticket (struct rx_header *hdr,
+                    Key *skey,
+                    char *name, char *instance, char *realm,
+                    struct sockaddr_in *addr,
+                    int life,
+                    int kvno,
+                    int32_t max_seq_len,
+                    const char *sname, const char *sinstance,
+                    u_int32_t challenge,
+                    const char *label,
+                    krb5_keyblock *key,
+                    krb5_data *reply)
+{
+    krb5_data ticket;
+    krb5_keyblock session;
+    krb5_storage *sp;
+    krb5_data enc_data;
+    struct rx_header reply_hdr;
+    char zero[8];
+    size_t pad;
+    unsigned fyrtiosjuelva;
+
+    /* create the ticket */
+
+    krb5_generate_random_keyblock(context, ETYPE_DES_PCBC_NONE, &session);
+
+    _krb5_krb_create_ticket(context,
+                           0,
+                           name,
+                           instance,
+                           realm,
+                           addr->sin_addr.s_addr,
+                           &session,
+                           life,
+                           kdc_time,
+                           sname,
+                           sinstance,
+                           &skey->key,
+                           &ticket);
+
+    /* create the encrypted part of the reply */
+    sp = krb5_storage_emem ();
+    krb5_generate_random_block(&fyrtiosjuelva, sizeof(fyrtiosjuelva));
+    fyrtiosjuelva &= 0xffffffff;
+    krb5_store_int32 (sp, fyrtiosjuelva);
+    krb5_store_int32 (sp, challenge);
+    krb5_storage_write  (sp, session.keyvalue.data, 8);
+    krb5_free_keyblock_contents(context, &session);
+    krb5_store_int32 (sp, kdc_time);
+    krb5_store_int32 (sp, kdc_time + _krb5_krb_life_to_time (0, life));
+    krb5_store_int32 (sp, kvno);
+    krb5_store_int32 (sp, ticket.length);
+    krb5_store_stringz (sp, name);
+    krb5_store_stringz (sp, instance);
+#if 1 /* XXX - Why shouldn't the realm go here? */
+    krb5_store_stringz (sp, "");
+#else
+    krb5_store_stringz (sp, realm);
+#endif
+    krb5_store_stringz (sp, sname);
+    krb5_store_stringz (sp, sinstance);
+    krb5_storage_write (sp, ticket.data, ticket.length);
+    krb5_storage_write (sp, label, strlen(label));
+
+    /* pad to DES block */
+    memset (zero, 0, sizeof(zero));
+    pad = (8 - krb5_storage_seek (sp, 0, SEEK_CUR) % 8) % 8;
+    krb5_storage_write (sp, zero, pad);
+
+    krb5_storage_to_data (sp, &enc_data);
+    krb5_storage_free (sp);
+
+    if (enc_data.length > max_seq_len) {
+       krb5_data_free (&enc_data);
+       make_error_reply (hdr, KAANSWERTOOLONG, reply);
+       return 0;
+    }
+
+    /* encrypt it */
+    {
+        DES_key_schedule schedule;
+       DES_cblock deskey;
+       
+       memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+       DES_set_key (&deskey, &schedule);
+       DES_pcbc_encrypt (enc_data.data,
+                         enc_data.data,
+                         enc_data.length,
+                         &schedule,
+                         &deskey,
+                         DES_ENCRYPT);
+       memset (&schedule, 0, sizeof(schedule));
+       memset (&deskey, 0, sizeof(deskey));
+    }
+
+    /* create the reply packet */
+    init_reply_header (hdr, &reply_hdr, HT_DATA, HF_LAST);
+    sp = krb5_storage_emem ();
+    encode_rx_header (&reply_hdr, sp);
+    krb5_store_int32 (sp, max_seq_len);
+    krb5_store_xdr_data (sp, enc_data);
+    krb5_data_free (&enc_data);
+    krb5_storage_to_data (sp, reply);
+    krb5_storage_free (sp);
+    return 0;
+}
+
+static krb5_error_code
+unparse_auth_args (krb5_storage *sp,
+                  char **name,
+                  char **instance,
+                  time_t *start_time,
+                  time_t *end_time,
+                  krb5_data *request,
+                  int32_t *max_seq_len)
+{
+    krb5_data data;
+    int32_t tmp;
+
+    krb5_ret_xdr_data (sp, &data);
+    *name = malloc(data.length + 1);
+    if (*name == NULL)
+       return ENOMEM;
+    memcpy (*name, data.data, data.length);
+    (*name)[data.length] = '\0';
+    krb5_data_free (&data);
+
+    krb5_ret_xdr_data (sp, &data);
+    *instance = malloc(data.length + 1);
+    if (*instance == NULL) {
+       free (*name);
+       return ENOMEM;
+    }
+    memcpy (*instance, data.data, data.length);
+    (*instance)[data.length] = '\0';
+    krb5_data_free (&data);
+
+    krb5_ret_int32 (sp, &tmp);
+    *start_time = tmp;
+    krb5_ret_int32 (sp, &tmp);
+    *end_time = tmp;
+    krb5_ret_xdr_data (sp, request);
+    krb5_ret_int32 (sp, max_seq_len);
+    /* ignore the rest */
+    return 0;
+}
+
+static void
+do_authenticate (struct rx_header *hdr,
+                krb5_storage *sp,
+                struct sockaddr_in *addr,
+                krb5_data *reply)
+{
+    krb5_error_code ret;
+    char *name = NULL;
+    char *instance = NULL;
+    time_t start_time;
+    time_t end_time;
+    krb5_data request;
+    int32_t max_seq_len;
+    hdb_entry *client_entry = NULL;
+    hdb_entry *server_entry = NULL;
+    Key *ckey = NULL;
+    Key *skey = NULL;
+    krb5_storage *reply_sp;
+    time_t max_life;
+    u_int8_t life;
+    int32_t chal;
+    char client_name[256];
+    char server_name[256];
+       
+    krb5_data_zero (&request);
+
+    ret = unparse_auth_args (sp, &name, &instance, &start_time, &end_time,
+                            &request, &max_seq_len);
+    if (ret != 0 || request.length < 8) {
+       make_error_reply (hdr, KABADREQUEST, reply);
+       goto out;
+    }
+
+    snprintf (client_name, sizeof(client_name), "%s.%s@%s",
+             name, instance, v4_realm);
+
+    ret = db_fetch4 (name, instance, v4_realm, &client_entry);
+    if (ret) {
+       kdc_log(0, "Client not found in database: %s: %s",
+               client_name, krb5_get_err_text(context, ret));
+       make_error_reply (hdr, KANOENT, reply);
+       goto out;
+    }
+
+    snprintf (server_name, sizeof(server_name), "%s.%s@%s",
+             "krbtgt", v4_realm, v4_realm);
+
+    ret = db_fetch4 ("krbtgt", v4_realm, v4_realm, &server_entry);
+    if (ret) {
+       kdc_log(0, "Server not found in database: %s: %s",
+               server_name, krb5_get_err_text(context, ret));
+       make_error_reply (hdr, KANOENT, reply);
+       goto out;
+    }
+
+    ret = check_flags (client_entry, client_name,
+                      server_entry, server_name,
+                      TRUE);
+    if (ret) {
+       make_error_reply (hdr, KAPWEXPIRED, reply);
+       goto out;
+    }
+
+    /* find a DES key */
+    ret = get_des_key(client_entry, FALSE, TRUE, &ckey);
+    if(ret){
+       kdc_log(0, "no suitable DES key for client");
+       make_error_reply (hdr, KANOKEYS, reply);
+       goto out;
+    }
+
+    /* find a DES key */
+    ret = get_des_key(server_entry, TRUE, TRUE, &skey);
+    if(ret){
+       kdc_log(0, "no suitable DES key for server");
+       make_error_reply (hdr, KANOKEYS, reply);
+       goto out;
+    }
+
+    {
+       DES_cblock key;
+       DES_key_schedule schedule;
+       
+       /* try to decode the `request' */
+       memcpy (&key, ckey->key.keyvalue.data, sizeof(key));
+       DES_set_key (&key, &schedule);
+       DES_pcbc_encrypt (request.data,
+                         request.data,
+                         request.length,
+                         &schedule,
+                         &key,
+                         DES_DECRYPT);
+       memset (&schedule, 0, sizeof(schedule));
+       memset (&key, 0, sizeof(key));
+    }
+
+    /* check for the magic label */
+    if (memcmp ((char *)request.data + 4, "gTGS", 4) != 0) {
+       kdc_log(0, "preauth failed for %s", client_name);
+       make_error_reply (hdr, KABADREQUEST, reply);
+       goto out;
+    }
+
+    reply_sp = krb5_storage_from_mem (request.data, 4);
+    krb5_ret_int32 (reply_sp, &chal);
+    krb5_storage_free (reply_sp);
+
+    if (abs(chal - kdc_time) > context->max_skew) {
+       make_error_reply (hdr, KACLOCKSKEW, reply);
+       goto out;
+    }
+
+    /* life */
+    max_life = end_time - kdc_time;
+    /* end_time - kdc_time can sometimes be non-positive due to slight
+       time skew between client and server. Let's make sure it is postive */
+    if(max_life < 1)
+       max_life = 1;
+    if (client_entry->max_life)
+       max_life = min(max_life, *client_entry->max_life);
+    if (server_entry->max_life)
+       max_life = min(max_life, *server_entry->max_life);
+
+    life = krb_time_to_life(kdc_time, kdc_time + max_life);
+
+    create_reply_ticket (hdr, skey,
+                        name, instance, v4_realm,
+                        addr, life, server_entry->kvno,
+                        max_seq_len,
+                        "krbtgt", v4_realm,
+                        chal + 1, "tgsT",
+                        &ckey->key, reply);
+
+out:
+    if (request.length) {
+       memset (request.data, 0, request.length);
+       krb5_data_free (&request);
+    }
+    if (name)
+       free (name);
+    if (instance)
+       free (instance);
+    if (client_entry)
+       free_ent (client_entry);
+    if (server_entry)
+       free_ent (server_entry);
+}
+
+static krb5_error_code
+unparse_getticket_args (krb5_storage *sp,
+                       int *kvno,
+                       char **auth_domain,
+                       krb5_data *ticket,
+                       char **name,
+                       char **instance,
+                       krb5_data *times,
+                       int32_t *max_seq_len)
+{
+    krb5_data data;
+    int32_t tmp;
+
+    krb5_ret_int32 (sp, &tmp);
+    *kvno = tmp;
+
+    krb5_ret_xdr_data (sp, &data);
+    *auth_domain = malloc(data.length + 1);
+    if (*auth_domain == NULL)
+       return ENOMEM;
+    memcpy (*auth_domain, data.data, data.length);
+    (*auth_domain)[data.length] = '\0';
+    krb5_data_free (&data);
+
+    krb5_ret_xdr_data (sp, ticket);
+
+    krb5_ret_xdr_data (sp, &data);
+    *name = malloc(data.length + 1);
+    if (*name == NULL) {
+       free (*auth_domain);
+       return ENOMEM;
+    }
+    memcpy (*name, data.data, data.length);
+    (*name)[data.length] = '\0';
+    krb5_data_free (&data);
+
+    krb5_ret_xdr_data (sp, &data);
+    *instance = malloc(data.length + 1);
+    if (*instance == NULL) {
+       free (*auth_domain);
+       free (*name);
+       return ENOMEM;
+    }
+    memcpy (*instance, data.data, data.length);
+    (*instance)[data.length] = '\0';
+    krb5_data_free (&data);
+
+    krb5_ret_xdr_data (sp, times);
+
+    krb5_ret_int32 (sp, max_seq_len);
+    /* ignore the rest */
+    return 0;
+}
+
+static void
+do_getticket (struct rx_header *hdr,
+             krb5_storage *sp,
+             struct sockaddr_in *addr,
+             krb5_data *reply)
+{
+    krb5_error_code ret;
+    int kvno;
+    char *auth_domain = NULL;
+    krb5_data aticket;
+    char *name = NULL;
+    char *instance = NULL;
+    krb5_data times;
+    int32_t max_seq_len;
+    hdb_entry *server_entry = NULL;
+    hdb_entry *client_entry = NULL;
+    hdb_entry *krbtgt_entry = NULL;
+    Key *kkey = NULL;
+    Key *skey = NULL;
+    DES_cblock key;
+    DES_key_schedule schedule;
+    DES_cblock session;
+    time_t max_life;
+    int8_t life;
+    time_t start_time, end_time;
+    char server_name[256];
+    char client_name[256];
+    struct _krb5_krb_auth_data ad;
+
+    krb5_data_zero (&aticket);
+    krb5_data_zero (&times);
+
+    memset(&ad, 0, sizeof(ad));
+
+    unparse_getticket_args (sp, &kvno, &auth_domain, &aticket,
+                           &name, &instance, &times, &max_seq_len);
+    if (times.length < 8) {
+       make_error_reply (hdr, KABADREQUEST, reply);
+       goto out;
+       
+    }
+
+    snprintf (server_name, sizeof(server_name),
+             "%s.%s@%s", name, instance, v4_realm);
+
+    ret = db_fetch4 (name, instance, v4_realm, &server_entry);
+    if (ret) {
+       kdc_log(0, "Server not found in database: %s: %s",
+               server_name, krb5_get_err_text(context, ret));
+       make_error_reply (hdr, KANOENT, reply);
+       goto out;
+    }
+
+    ret = db_fetch4 ("krbtgt", v4_realm, v4_realm, &krbtgt_entry);
+    if (ret) {
+       kdc_log(0, "Server not found in database: %s.%s@%s: %s",
+               "krbtgt", v4_realm, v4_realm, krb5_get_err_text(context, ret));
+       make_error_reply (hdr, KANOENT, reply);
+       goto out;
+    }
+
+    /* find a DES key */
+    ret = get_des_key(krbtgt_entry, TRUE, TRUE, &kkey);
+    if(ret){
+       kdc_log(0, "no suitable DES key for krbtgt");
+       make_error_reply (hdr, KANOKEYS, reply);
+       goto out;
+    }
+
+    /* find a DES key */
+    ret = get_des_key(server_entry, TRUE, TRUE, &skey);
+    if(ret){
+       kdc_log(0, "no suitable DES key for server");
+       make_error_reply (hdr, KANOKEYS, reply);
+       goto out;
+    }
+
+    /* decrypt the incoming ticket */
+    memcpy (&key, kkey->key.keyvalue.data, sizeof(key));
+
+    /* unpack the ticket */
+    {
+       char *sname = NULL;
+       char *sinstance = NULL;
+
+       ret = _krb5_krb_decomp_ticket(context, &aticket, &kkey->key, 
+                                     v4_realm, &sname, &sinstance, &ad);
+       if (ret) {
+           kdc_log(0, "kaserver: decomp failed for %s.%s with %d",
+                   sname, sinstance, ret);
+           make_error_reply (hdr, KABADTICKET, reply);
+           goto out;
+       }
+
+       if (strcmp (sname, "krbtgt") != 0
+           || strcmp (sinstance, v4_realm) != 0) {
+           kdc_log(0, "no TGT: %s.%s for %s.%s@%s",
+                   sname, sinstance,
+                   ad.pname, ad.pinst, ad.prealm);
+           make_error_reply (hdr, KABADTICKET, reply);
+           free(sname);
+           free(sinstance);
+           goto out;
+       }
+       free(sname);
+       free(sinstance);
+
+       if (kdc_time > _krb5_krb_life_to_time(ad.time_sec, ad.life)) {
+           kdc_log(0, "TGT expired: %s.%s@%s",
+                   ad.pname, ad.pinst, ad.prealm);
+           make_error_reply (hdr, KABADTICKET, reply);
+           goto out;
+       }
+    }
+
+    snprintf (client_name, sizeof(client_name),
+             "%s.%s@%s", ad.pname, ad.pinst, ad.prealm);
+
+    ret = db_fetch4 (ad.pname, ad.pinst, ad.prealm, &client_entry);
+    if(ret && ret != HDB_ERR_NOENTRY) {
+       kdc_log(0, "Client not found in database: (krb4) %s: %s",
+               client_name, krb5_get_err_text(context, ret));
+       make_error_reply (hdr, KANOENT, reply);
+       goto out;
+    }
+    if (client_entry == NULL && strcmp(ad.prealm, v4_realm) == 0) {
+       kdc_log(0, "Local client not found in database: (krb4) "
+               "%s", client_name);
+       make_error_reply (hdr, KANOENT, reply);
+       goto out;
+    }
+
+    ret = check_flags (client_entry, client_name,
+                      server_entry, server_name,
+                      FALSE);
+    if (ret) {
+       make_error_reply (hdr, KAPWEXPIRED, reply);
+       goto out;
+    }
+
+    /* decrypt the times */
+    memcpy(&session, ad.session.keyvalue.data, sizeof(session));
+    DES_set_key (&session, &schedule);
+    DES_ecb_encrypt (times.data,
+                    times.data,
+                    &schedule,
+                    DES_DECRYPT);
+    memset (&schedule, 0, sizeof(schedule));
+    memset (&session, 0, sizeof(session));
+
+    /* and extract them */
+    {
+       krb5_storage *sp;
+       int32_t tmp;
+
+       sp = krb5_storage_from_mem (times.data, times.length);
+       krb5_ret_int32 (sp, &tmp);
+       start_time = tmp;
+       krb5_ret_int32 (sp, &tmp);
+       end_time = tmp;
+       krb5_storage_free (sp);
+    }
+
+    /* life */
+    max_life = end_time - kdc_time;
+    /* end_time - kdc_time can sometimes be non-positive due to slight
+       time skew between client and server. Let's make sure it is postive */
+    if(max_life < 1)
+       max_life = 1;
+    if (krbtgt_entry->max_life)
+       max_life = min(max_life, *krbtgt_entry->max_life);
+    if (server_entry->max_life)
+       max_life = min(max_life, *server_entry->max_life);
+    /* if this is a cross realm request, the client_entry will likely
+       be NULL */
+    if (client_entry && client_entry->max_life)
+       max_life = min(max_life, *client_entry->max_life);
+
+    life = _krb5_krb_time_to_life(kdc_time, kdc_time + max_life);
+
+    create_reply_ticket (hdr, skey,
+                        ad.pname, ad.pinst, ad.prealm,
+                        addr, life, server_entry->kvno,
+                        max_seq_len,
+                        name, instance,
+                        0, "gtkt",
+                        &ad.session, reply);
+    
+out:
+    _krb5_krb_free_auth_data(context, &ad);
+    if (aticket.length) {
+       memset (aticket.data, 0, aticket.length);
+       krb5_data_free (&aticket);
+    }
+    if (times.length) {
+       memset (times.data, 0, times.length);
+       krb5_data_free (&times);
+    }
+    if (auth_domain)
+       free (auth_domain);
+    if (name)
+       free (name);
+    if (instance)
+       free (instance);
+    if (krbtgt_entry)
+       free_ent (krbtgt_entry);
+    if (server_entry)
+       free_ent (server_entry);
+}
+
+krb5_error_code
+do_kaserver(unsigned char *buf,
+           size_t len,
+           krb5_data *reply,
+           const char *from,
+           struct sockaddr_in *addr)
+{
+    krb5_error_code ret = 0;
+    struct rx_header hdr;
+    u_int32_t op;
+    krb5_storage *sp;
+
+    if (len < RX_HEADER_SIZE)
+       return -1;
+    sp = krb5_storage_from_mem (buf, len);
+
+    decode_rx_header (sp, &hdr);
+    buf += RX_HEADER_SIZE;
+    len -= RX_HEADER_SIZE;
+
+    switch (hdr.type) {
+    case HT_DATA :
+       break;
+    case HT_ACK :
+    case HT_BUSY :
+    case HT_ABORT :
+    case HT_ACKALL :
+    case HT_CHAL :
+    case HT_RESP :
+    case HT_DEBUG :
+    default:
+       /* drop */
+       goto out;
+    }
+
+
+    if (hdr.serviceid != KA_AUTHENTICATION_SERVICE
+       && hdr.serviceid != KA_TICKET_GRANTING_SERVICE) {
+       ret = -1;
+       goto out;
+    }
+
+    krb5_ret_int32(sp, &op);
+    switch (op) {
+    case AUTHENTICATE :
+    case AUTHENTICATE_V2 :
+       do_authenticate (&hdr, sp, addr, reply);
+       break;
+    case GETTICKET :
+       do_getticket (&hdr, sp, addr, reply);
+       break;
+    case AUTHENTICATE_OLD :
+    case CHANGEPASSWORD :
+    case GETTICKET_OLD :
+    case SETPASSWORD :
+    case SETFIELDS :
+    case CREATEUSER :
+    case DELETEUSER :
+    case GETENTRY :
+    case LISTENTRY :
+    case GETSTATS :
+    case DEBUG :
+    case GETPASSWORD :
+    case GETRANDOMKEY :
+    default :
+       make_error_reply (&hdr, RXGEN_OPCODE, reply);
+       break;
+    }
+
+out:
+    krb5_storage_free (sp);
+    return ret;
+}
diff --git a/src/kerberosV/src/kdc/kdc.8 b/src/kerberosV/src/kdc/kdc.8
new file mode 100644 (file)
index 0000000..70abaaa
--- /dev/null
@@ -0,0 +1,256 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\"
+.\" $KTH: kdc.8,v 1.29 2004/12/17 18:36:19 lha Exp $
+.\"
+.Dd December 17, 2004
+.Dt KDC 8
+.Os HEIMDAL
+.Sh NAME
+.Nm kdc
+.Nd Kerberos 5 server
+.Sh SYNOPSIS
+.Nm kdc
+.Bk -words
+.Oo Fl c Ar file \*(Ba Xo
+.Fl -config-file= Ns Ar file
+.Xc
+.Oc
+.Op Fl p | Fl -no-require-preauth
+.Op Fl -max-request= Ns Ar size
+.Op Fl H | Fl -enable-http
+.Op Fl -no-524
+.Op Fl -kerberos4
+.Op Fl -kerberos4-cross-realm
+.Oo Fl r Ar string \*(Ba Xo
+.Fl -v4-realm= Ns Ar string
+.Xc
+.Oc
+.Op Fl K | Fl -kaserver
+.Oo Fl P Ar portspec \*(Ba Xo
+.Fl -ports= Ns Ar portspec
+.Xc
+.Oc
+.Op Fl -detach
+.Op Fl -disable-DES
+.Op Fl -addresses= Ns Ar list of addresses
+.Ek
+.Sh DESCRIPTION
+.Nm
+serves requests for tickets.
+When it starts, it first checks the flags passed, any options that are
+not specified with a command line flag are taken from a config file,
+or from a default compiled-in value.
+.Pp
+Options supported:
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar file ,
+.Fl -config-file= Ns Ar file
+.Xc
+Specifies the location of the config file, the default is
+.Pa /var/heimdal/kdc.conf .
+This is the only value that can't be specified in the config file.
+.It Xo
+.Fl p ,
+.Fl -no-require-preauth
+.Xc
+Turn off the requirement for pre-autentication in the initial AS-REQ
+for all principals.
+The use of pre-authentication makes it more difficult to do offline
+password attacks.
+You might want to turn it off if you have clients
+that don't support pre-authentication.
+Since the version 4 protocol doesn't support any pre-authentication,
+serving version 4 clients is just about the same as not requiring
+pre-athentication.
+The default is to require pre-authentication.
+Adding the require-preauth per principal is a more flexible way of
+handling this.
+.It Xo
+.Fl -max-request= Ns Ar size
+.Xc
+Gives an upper limit on the size of the requests that the kdc is
+willing to handle.
+.It Xo
+.Fl H ,
+.Fl -enable-http
+.Xc
+Makes the kdc listen on port 80 and handle requests encapsulated in HTTP.
+.It Xo
+.Fl -no-524
+.Xc
+don't respond to 524 requests
+.It Xo
+.Fl -kerberos4
+.Xc
+respond to Kerberos 4 requests
+.It Xo
+.Fl -kerberos4-cross-realm
+.Xc
+respond to Kerberos 4 requests from foreign realms.
+This is a known security hole and should not be enabled unless you
+understand the consequences and are willing to live with them.
+.It Xo
+.Fl r Ar string ,
+.Fl -v4-realm= Ns Ar string
+.Xc
+What realm this server should act as when dealing with version 4
+requests.
+The database can contain any number of realms, but since the version 4
+protocol doesn't contain a realm for the server, it must be explicitly
+specified.
+The default is whatever is returned by
+.Fn krb_get_lrealm .
+This option is only availabe if the KDC has been compiled with version
+4 support.
+.It Xo
+.Fl K ,
+.Fl -kaserver
+.Xc
+Enable kaserver emulation (in case it's compiled in).
+.It Xo
+.Fl P Ar portspec ,
+.Fl -ports= Ns Ar portspec
+.Xc
+Specifies the set of ports the KDC should listen on.
+It is given as a
+white-space separated list of services or port numbers.
+.It Fl -addresses= Ns Ar list of addresses
+The list of addresses to listen for requests on.
+By default, the kdc will listen on all the locally configured
+addresses.
+If only a subset is desired, or the automatic detection fails, this
+option might be used.
+.It Fl -detach
+detach from pty and run as a daemon.
+.It Fl -disable-DES
+disable add des encryption types, makes the kdc not use them.
+.El
+.Pp
+All activities are logged to one or more destinations, see
+.Xr krb5.conf 5 ,
+and
+.Xr krb5_openlog 3 .
+The entity used for logging is
+.Nm kdc .
+.Sh CONFIGURATION FILE
+The configuration file has the same syntax as 
+.Xr krb5.conf 5 ,
+but will be read before 
+.Pa /etc/kerberosV/krb5.conf ,
+so it may override settings found there.
+Options specific to the KDC only are found in the
+.Dq [kdc] 
+section.
+All the command-line options can preferably be added in the
+configuration file.
+The only difference is the pre-authentication flag, which has to be
+specified as:
+.Pp
+.Dl require-preauth = no
+.Pp
+(in fact you can specify the option as
+.Fl -require-preauth=no ) .
+.Pp
+And there are some configuration options which do not have
+command-line equivalents:
+.Bl -tag -width "xxx" -offset indent
+.It Li check-ticket-addresses = Va boolean
+Check the addresses in the ticket when processing TGS requests.
+The default is TRUE.
+.It Li allow-null-ticket-addresses = Va boolean
+Permit tickets with no addresses.
+This option is only relevant when check-ticket-addresses is TRUE.
+.It Li allow-anonymous = Va boolean
+Permit anonymous tickets with no addresses.
+.It Li transited-policy = Xo
+.Li always-check \*(Ba
+.Li allow-per-principal |
+.Li always-honour-request
+.Xc
+This controls how KDC requests with the
+.Li disable-transited-check
+flag are handled. It can be one of:
+.Bl -tag -width "xxx" -offset indent
+.It Li always-check
+Always check transited encoding, this is the default.
+.It Li allow-per-principal
+Currently this is identical to
+.Li always-check .
+In a future release, it will be possible to mark a principal as able
+to handle unchecked requests.
+.It Li always-honour-request
+Always do what the client asked.
+In a future release, it will be possible to force a check per
+principal.
+.El
+.It encode_as_rep_as_tgs_rep = Va boolean
+Encode AS-Rep as TGS-Rep to be bug-compatible with old DCE code.
+The Heimdal clients allow both.
+.It kdc_warn_pwexpire = Va time
+How long before password/principal expiration the KDC should start
+sending out warning messages.
+.El
+.Pp
+The configuration file is only read when the 
+.Nm
+is started.
+If changes made to the configuration file are to take effect, the
+.Nm
+needs to be restarted.
+.Pp
+An example of a config file:
+.Bd -literal -offset indent
+[kdc]
+       require-preauth = no
+       v4-realm = FOO.SE
+.Ed
+.Sh BUGS
+If the machine running the KDC has new addresses added to it, the KDC
+will have to be restarted to listen to them.
+The reason it doesn't just listen to wildcarded (like INADDR_ANY)
+addresses, is that the replies has to come from the same address they
+were sent to, and most OS:es doesn't pass this information to the
+application.
+If your normal mode of operation require that you add and remove
+addresses, the best option is probably to listen to a wildcarded TCP
+socket, and make sure your clients use TCP to connect.
+For instance, this will listen to IPv4 TCP port 88 only:
+.Bd -literal -offset indent
+kdc --addresses=0.0.0.0 --ports="88/tcp" 
+.Ed
+.Pp
+There should be a way to specify protocol, port, and address triplets,
+not just addresses and protocol, port tuples.
+.Sh SEE ALSO
+.Xr kinit 1 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/kdc/kdc_locl.h b/src/kerberosV/src/kdc/kdc_locl.h
new file mode 100644 (file)
index 0000000..384a586
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* 
+ * $KTH: kdc_locl.h,v 1.66 2005/04/23 19:52:51 lha Exp $ 
+ */
+
+#ifndef __KDC_LOCL_H__
+#define __KDC_LOCL_H__
+
+#include "headers.h"
+
+extern krb5_context context;
+
+extern int require_preauth;
+extern volatile sig_atomic_t exit_flag;
+extern size_t max_request;
+extern time_t kdc_warn_pwexpire;
+extern struct dbinfo {
+    char *realm;
+    char *dbname;
+    char *mkey_file;
+    struct dbinfo *next;
+} *databases;
+extern HDB **db;
+extern int num_db;
+extern const char *port_str;
+extern krb5_addresses explicit_addresses;
+
+extern int enable_http;
+extern krb5_boolean encode_as_rep_as_tgs_rep;
+extern krb5_boolean check_ticket_addresses;
+extern krb5_boolean allow_null_ticket_addresses;
+extern krb5_boolean allow_anonymous;
+enum { TRPOLICY_ALWAYS_CHECK,
+       TRPOLICY_ALLOW_PER_PRINCIPAL, 
+       TRPOLICY_ALWAYS_HONOUR_REQUEST };
+extern int trpolicy;
+extern int enable_524;
+extern int enable_v4_cross_realm;
+
+#ifdef PKINIT
+extern int enable_pkinit;
+extern int enable_pkinit_princ_in_cert;
+#endif
+
+#define _PATH_KDC_CONF         HDB_DB_DIR "/kdc.conf"
+#define DEFAULT_LOG_DEST       "0-1/FILE:" HDB_DB_DIR "/kdc.log"
+
+extern struct timeval now;
+#define kdc_time (now.tv_sec)
+
+krb5_error_code as_rep (KDC_REQ*, krb5_data*, const char*, struct sockaddr*);
+void configure (int, char**);
+krb5_error_code db_fetch (krb5_principal, hdb_entry**);
+void free_ent(hdb_entry *);
+void kdc_log (int, const char*, ...)
+    __attribute__ ((format (printf, 2,3)));
+
+char* kdc_log_msg (int, const char*, ...)
+    __attribute__ ((format (printf, 2,3)));
+char* kdc_log_msg_va (int, const char*, va_list)
+    __attribute__ ((format (printf, 2,0)));
+void kdc_openlog (void);
+void loop (void);
+void set_master_key (EncryptionKey);
+krb5_error_code tgs_rep (KDC_REQ*, krb5_data*, const char*, struct sockaddr *);
+Key* unseal_key (Key*);
+krb5_error_code check_flags(hdb_entry *client, const char *client_name,
+                           hdb_entry *server, const char *server_name,
+                           krb5_boolean is_as_req);
+
+krb5_error_code get_des_key(hdb_entry*, krb5_boolean, krb5_boolean, Key**);
+krb5_error_code encode_v4_ticket (void*, size_t, const EncTicketPart*, 
+                                 const PrincipalName*, size_t*);
+krb5_error_code do_524 (const Ticket*, krb5_data*, const char*, struct sockaddr*);
+
+#ifdef HAVE_OPENSSL
+#define des_new_random_key des_random_key
+#endif
+
+#ifdef PKINIT
+typedef struct pk_client_params pk_client_params;
+krb5_error_code pk_initialize(const char *, const char *);
+krb5_error_code pk_rd_padata(krb5_context, KDC_REQ *,
+                            PA_DATA *, pk_client_params **);
+krb5_error_code        pk_mk_pa_reply(krb5_context,
+                              pk_client_params *,
+                              const hdb_entry *,
+                              const KDC_REQ *,
+                              krb5_keyblock **,
+                              METHOD_DATA *);
+krb5_error_code pk_check_client(krb5_context, krb5_principal,
+                               const hdb_entry *, 
+                               pk_client_params *, char **);
+void pk_free_client_param(krb5_context, pk_client_params *);
+#endif
+
+/*
+ * Kerberos 4
+ */
+
+extern char *v4_realm;
+extern int enable_v4;
+extern krb5_boolean enable_kaserver;
+
+krb5_error_code db_fetch4 (const char*, const char*, const char*, hdb_entry**);
+krb5_error_code do_version4 (unsigned char*, size_t, krb5_data*, const char*, 
+                            struct sockaddr_in*);
+int maybe_version4 (unsigned char*, int);
+
+krb5_error_code do_kaserver (unsigned char*, size_t, krb5_data*, const char*, 
+                            struct sockaddr_in*);
+
+
+
+#endif /* __KDC_LOCL_H__ */
diff --git a/src/kerberosV/src/kdc/kerberos4.c b/src/kerberosV/src/kdc/kerberos4.c
new file mode 100644 (file)
index 0000000..1420765
--- /dev/null
@@ -0,0 +1,752 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+#include <krb5-v4compat.h>
+
+RCSID("$KTH: kerberos4.c,v 1.52 2005/04/23 20:11:55 lha Exp $");
+
+#ifndef swap32
+static u_int32_t
+swap32(u_int32_t x)
+{
+    return ((x << 24) & 0xff000000) |
+       ((x << 8) & 0xff0000) |
+       ((x >> 8) & 0xff00) |
+       ((x >> 24) & 0xff);
+}
+#endif /* swap32 */
+
+int
+maybe_version4(unsigned char *buf, int len)
+{
+    return len > 0 && *buf == 4;
+}
+
+static void
+make_err_reply(krb5_context context, krb5_data *reply,
+              int code, const char *msg)
+{
+    _krb5_krb_cr_err_reply(context, "", "", "", 
+                          kdc_time, code, msg, reply);
+}
+
+static krb5_boolean
+valid_princ(krb5_context context, krb5_principal princ)
+{
+    krb5_error_code ret;
+    char *s;
+    hdb_entry *ent;
+
+    ret = krb5_unparse_name(context, princ, &s);
+    if (ret)
+       return FALSE;
+    ret = db_fetch(princ, &ent);
+    if (ret) {
+       kdc_log(7, "Lookup %s failed: %s", s,
+               krb5_get_err_text (context, ret));
+       free(s);
+       return FALSE;
+    }
+    kdc_log(7, "Lookup %s succeeded", s);
+    free(s);
+    free_ent(ent);
+    return TRUE;
+}
+
+krb5_error_code
+db_fetch4(const char *name, const char *instance, const char *realm,
+         hdb_entry **ent)
+{
+    krb5_principal p;
+    krb5_error_code ret;
+    
+    ret = krb5_425_conv_principal_ext(context, name, instance, realm, 
+                                     valid_princ, 0, &p);
+    if(ret)
+       return ret;
+    ret = db_fetch(p, ent);
+    krb5_free_principal(context, p);
+    return ret;
+}
+
+#define RCHECK(X, L) if(X){make_err_reply(context, reply, KFAILURE, "Packet too short"); goto L;}
+
+/*
+ * Process the v4 request in `buf, len' (received from `addr'
+ * (with string `from').
+ * Return an error code and a reply in `reply'.
+ */
+
+krb5_error_code
+do_version4(unsigned char *buf,
+           size_t len,
+           krb5_data *reply,
+           const char *from,
+           struct sockaddr_in *addr)
+{
+    krb5_storage *sp;
+    krb5_error_code ret;
+    hdb_entry *client = NULL, *server = NULL;
+    Key *ckey, *skey;
+    int8_t pvno;
+    int8_t msg_type;
+    int lsb;
+    char *name = NULL, *inst = NULL, *realm = NULL;
+    char *sname = NULL, *sinst = NULL;
+    int32_t req_time;
+    time_t max_life;
+    u_int8_t life;
+    char client_name[256];
+    char server_name[256];
+
+    if(!enable_v4) {
+       kdc_log(0, "Rejected version 4 request from %s", from);
+       make_err_reply(context, reply, KDC_GEN_ERR, "function not enabled");
+       return 0;
+    }
+
+    sp = krb5_storage_from_mem(buf, len);
+    RCHECK(krb5_ret_int8(sp, &pvno), out);
+    if(pvno != 4){
+       kdc_log(0, "Protocol version mismatch (krb4) (%d)", pvno);
+       make_err_reply(context, reply, KDC_PKT_VER, "protocol mismatch");
+       goto out;
+    }
+    RCHECK(krb5_ret_int8(sp, &msg_type), out);
+    lsb = msg_type & 1;
+    msg_type &= ~1;
+    switch(msg_type){
+    case AUTH_MSG_KDC_REQUEST: {
+       krb5_data ticket, cipher;
+       krb5_keyblock session;
+       
+       krb5_data_zero(&ticket);
+       krb5_data_zero(&cipher);
+
+       RCHECK(krb5_ret_stringz(sp, &name), out1);
+       RCHECK(krb5_ret_stringz(sp, &inst), out1);
+       RCHECK(krb5_ret_stringz(sp, &realm), out1);
+       RCHECK(krb5_ret_int32(sp, &req_time), out1);
+       if(lsb)
+           req_time = swap32(req_time);
+       RCHECK(krb5_ret_int8(sp, &life), out1);
+       RCHECK(krb5_ret_stringz(sp, &sname), out1);
+       RCHECK(krb5_ret_stringz(sp, &sinst), out1);
+       snprintf (client_name, sizeof(client_name),
+                 "%s.%s@%s", name, inst, realm);
+       snprintf (server_name, sizeof(server_name),
+                 "%s.%s@%s", sname, sinst, v4_realm);
+       
+       kdc_log(0, "AS-REQ (krb4) %s from %s for %s",
+               client_name, from, server_name);
+
+       ret = db_fetch4(name, inst, realm, &client);
+       if(ret) {
+           kdc_log(0, "Client not found in database: %s: %s",
+                   client_name, krb5_get_err_text(context, ret));
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN,
+                          "principal unknown");
+           goto out1;
+       }
+       ret = db_fetch4(sname, sinst, v4_realm, &server);
+       if(ret){
+           kdc_log(0, "Server not found in database: %s: %s",
+                   server_name, krb5_get_err_text(context, ret));
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN,
+                          "principal unknown");
+           goto out1;
+       }
+
+       ret = check_flags (client, client_name,
+                          server, server_name,
+                          TRUE);
+       if (ret) {
+           /* good error code? */
+           make_err_reply(context, reply, KERB_ERR_NAME_EXP,
+                          "operation not allowed");
+           goto out1;
+       }
+
+       /*
+        * There's no way to do pre-authentication in v4 and thus no
+        * good error code to return if preauthentication is required.
+        */
+
+       if (require_preauth
+           || client->flags.require_preauth
+           || server->flags.require_preauth) {
+           kdc_log(0,
+                   "Pre-authentication required for v4-request: "
+                   "%s for %s",
+                   client_name, server_name);
+           make_err_reply(context, reply, KERB_ERR_NULL_KEY,
+                          "preauth required");
+           goto out1;
+       }
+
+       ret = get_des_key(client, FALSE, FALSE, &ckey);
+       if(ret){
+           kdc_log(0, "no suitable DES key for client");
+           make_err_reply(context, reply, KDC_NULL_KEY, 
+                          "no suitable DES key for client");
+           goto out1;
+       }
+
+#if 0
+       /* this is not necessary with the new code in libkrb */
+       /* find a properly salted key */
+       while(ckey->salt == NULL || ckey->salt->salt.length != 0)
+           ret = hdb_next_keytype2key(context, client, KEYTYPE_DES, &ckey);
+       if(ret){
+           kdc_log(0, "No version-4 salted key in database -- %s.%s@%s", 
+                   name, inst, realm);
+           make_err_reply(context, reply, KDC_NULL_KEY, 
+                          "No version-4 salted key in database");
+           goto out1;
+       }
+#endif
+       
+       ret = get_des_key(server, TRUE, FALSE, &skey);
+       if(ret){
+           kdc_log(0, "no suitable DES key for server");
+           /* XXX */
+           make_err_reply(context, reply, KDC_NULL_KEY, 
+                          "no suitable DES key for server");
+           goto out1;
+       }
+
+       max_life = _krb5_krb_life_to_time(0, life);
+       if(client->max_life)
+           max_life = min(max_life, *client->max_life);
+       if(server->max_life)
+           max_life = min(max_life, *server->max_life);
+
+       life = krb_time_to_life(kdc_time, kdc_time + max_life);
+    
+       ret = krb5_generate_random_keyblock(context,
+                                           ETYPE_DES_PCBC_NONE,
+                                           &session);
+       if (ret) {
+           make_err_reply(context, reply, KFAILURE,
+                          "Not enough random i KDC");
+           goto out1;
+       }
+       
+       ret = _krb5_krb_create_ticket(context,
+                                     0,
+                                     name,
+                                     inst,
+                                     v4_realm,
+                                     addr->sin_addr.s_addr,
+                                     &session,
+                                     life,
+                                     kdc_time,
+                                     sname,
+                                     sinst,
+                                     &skey->key,
+                                     &ticket);
+       if (ret) {
+           krb5_free_keyblock_contents(context, &session);
+           make_err_reply(context, reply, KFAILURE,
+                          "failed to create v4 ticket");
+           goto out1;
+       }
+
+       ret = _krb5_krb_create_ciph(context,
+                                   &session,
+                                   sname,
+                                   sinst,
+                                   v4_realm,
+                                   life,
+                                   server->kvno % 255,
+                                   &ticket,
+                                   kdc_time,
+                                   &ckey->key,
+                                   &cipher);
+       krb5_free_keyblock_contents(context, &session);
+       krb5_data_free(&ticket);
+       if (ret) {
+           make_err_reply(context, reply, KFAILURE, 
+                          "Failed to create v4 cipher");
+           goto out1;
+       }
+       
+       ret = _krb5_krb_create_auth_reply(context,
+                                         name,
+                                         inst,
+                                         realm,
+                                         req_time,
+                                         0,
+                                         client->pw_end ? *client->pw_end : 0,
+                                         client->kvno % 256,
+                                         &cipher,
+                                         reply);
+       krb5_data_free(&cipher);
+
+    out1:
+       break;
+    }
+    case AUTH_MSG_APPL_REQUEST: {
+       struct _krb5_krb_auth_data ad;
+       int8_t kvno;
+       int8_t ticket_len;
+       int8_t req_len;
+       krb5_data auth;
+       int32_t address;
+       size_t pos;
+       krb5_principal tgt_princ = NULL;
+       hdb_entry *tgt = NULL;
+       Key *tkey;
+       time_t max_end, actual_end, issue_time;
+       
+       memset(&ad, 0, sizeof(ad));
+       krb5_data_zero(&auth);
+
+       RCHECK(krb5_ret_int8(sp, &kvno), out2);
+       RCHECK(krb5_ret_stringz(sp, &realm), out2);
+       
+       ret = krb5_425_conv_principal(context, "krbtgt", realm, v4_realm,
+                                     &tgt_princ);
+       if(ret){
+           kdc_log(0, "Converting krbtgt principal (krb4): %s", 
+                   krb5_get_err_text(context, ret));
+           make_err_reply(context, reply, KFAILURE, 
+                          "Failed to convert v4 principal (krbtgt)");
+           goto out2;
+       }
+
+       ret = db_fetch(tgt_princ, &tgt);
+       if(ret){
+           char *s;
+           s = kdc_log_msg(0, "Ticket-granting ticket not "
+                           "found in database (krb4): krbtgt.%s@%s: %s", 
+                           realm, v4_realm,
+                           krb5_get_err_text(context, ret));
+           make_err_reply(context, reply, KFAILURE, s);
+           free(s);
+           goto out2;
+       }
+       
+       if(tgt->kvno % 256 != kvno){
+           kdc_log(0, "tgs-req (krb4) with old kvno %d (current %d) for "
+                   "krbtgt.%s@%s", kvno, tgt->kvno % 256, realm, v4_realm);
+           make_err_reply(context, reply, KDC_AUTH_EXP,
+                          "old krbtgt kvno used");
+           goto out2;
+       }
+
+       ret = get_des_key(tgt, TRUE, FALSE, &tkey);
+       if(ret){
+           kdc_log(0, "no suitable DES key for krbtgt (krb4)");
+           /* XXX */
+           make_err_reply(context, reply, KDC_NULL_KEY, 
+                          "no suitable DES key for krbtgt");
+           goto out2;
+       }
+
+       RCHECK(krb5_ret_int8(sp, &ticket_len), out2);
+       RCHECK(krb5_ret_int8(sp, &req_len), out2);
+       
+       pos = krb5_storage_seek(sp, ticket_len + req_len, SEEK_CUR);
+       
+       auth.data = buf;
+       auth.length = pos;
+
+       if (check_ticket_addresses)
+           address = addr->sin_addr.s_addr;
+       else
+           address = 0;
+
+       ret = _krb5_krb_rd_req(context, &auth, "krbtgt", realm, v4_realm,
+                              address, &tkey->key, &ad);
+       if(ret){
+           kdc_log(0, "krb_rd_req: %d", ret);
+           make_err_reply(context, reply, ret, "failed to parse request");
+           goto out2;
+       }
+       
+       RCHECK(krb5_ret_int32(sp, &req_time), out2);
+       if(lsb)
+           req_time = swap32(req_time);
+       RCHECK(krb5_ret_int8(sp, &life), out2);
+       RCHECK(krb5_ret_stringz(sp, &sname), out2);
+       RCHECK(krb5_ret_stringz(sp, &sinst), out2);
+       snprintf (server_name, sizeof(server_name),
+                 "%s.%s@%s",
+                 sname, sinst, v4_realm);
+       snprintf (client_name, sizeof(client_name),
+                 "%s.%s@%s",
+                 ad.pname, ad.pinst, ad.prealm);
+
+       kdc_log(0, "TGS-REQ (krb4) %s from %s for %s",
+               client_name, from, server_name);
+       
+       if(strcmp(ad.prealm, realm)){
+           kdc_log(0, "Can't hop realms (krb4) %s -> %s", realm, ad.prealm);
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, 
+                          "Can't hop realms");
+           goto out2;
+       }
+
+       if (!enable_v4_cross_realm && strcmp(realm, v4_realm) != 0) {
+           kdc_log(0, "krb4 Cross-realm %s -> %s disabled", realm, v4_realm);
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, 
+                          "Can't hop realms");
+           goto out2;
+       }
+
+       if(strcmp(sname, "changepw") == 0){
+           kdc_log(0, "Bad request for changepw ticket (krb4)");
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, 
+                          "Can't authorize password change based on TGT");
+           goto out2;
+       }
+       
+       ret = db_fetch4(ad.pname, ad.pinst, ad.prealm, &client);
+       if(ret && ret != HDB_ERR_NOENTRY) {
+           char *s;
+           s = kdc_log_msg(0, "Client not found in database: (krb4) %s: %s",
+                           client_name, krb5_get_err_text(context, ret));
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, s);
+           free(s);
+           goto out2;
+       }
+       if (client == NULL && strcmp(ad.prealm, v4_realm) == 0) {
+           char *s;
+           s = kdc_log_msg(0, "Local client not found in database: (krb4) "
+                           "%s", client_name);
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, s);
+           free(s);
+           goto out2;
+       }
+
+       ret = db_fetch4(sname, sinst, v4_realm, &server);
+       if(ret){
+           char *s;
+           s = kdc_log_msg(0, "Server not found in database (krb4): %s: %s",
+                           server_name, krb5_get_err_text(context, ret));
+           make_err_reply(context, reply, KERB_ERR_PRINCIPAL_UNKNOWN, s);
+           free(s);
+           goto out2;
+       }
+
+       ret = check_flags (client, client_name,
+                          server, server_name,
+                          FALSE);
+       if (ret) {
+           /* good error code? */
+           make_err_reply(context, reply, KERB_ERR_NAME_EXP,
+                          "operation not allowed");
+           goto out2;
+       }
+
+       ret = get_des_key(server, TRUE, FALSE, &skey);
+       if(ret){
+           kdc_log(0, "no suitable DES key for server (krb4)");
+           /* XXX */
+           make_err_reply(context, reply, KDC_NULL_KEY, 
+                          "no suitable DES key for server");
+           goto out2;
+       }
+
+       max_end = _krb5_krb_life_to_time(ad.time_sec, ad.life);
+       max_end = min(max_end, _krb5_krb_life_to_time(kdc_time, life));
+       if(server->max_life)
+           max_end = min(max_end, kdc_time + *server->max_life);
+       if(client && client->max_life)
+           max_end = min(max_end, kdc_time + *client->max_life);
+       life = min(life, krb_time_to_life(kdc_time, max_end));
+       
+       issue_time = kdc_time;
+       actual_end = _krb5_krb_life_to_time(issue_time, life);
+       while (actual_end > max_end && life > 1) {
+           /* move them into the next earlier lifetime bracket */
+           life--;
+           actual_end = _krb5_krb_life_to_time(issue_time, life);
+       }
+       if (actual_end > max_end) {
+           /* if life <= 1 and it's still too long, backdate the ticket */
+           issue_time -= actual_end - max_end;
+       }
+
+       {
+           krb5_data ticket, cipher;
+           krb5_keyblock session;
+
+           krb5_data_zero(&ticket);
+           krb5_data_zero(&cipher);
+
+           ret = krb5_generate_random_keyblock(context,
+                                               ETYPE_DES_PCBC_NONE,
+                                               &session);
+           if (ret) {
+               make_err_reply(context, reply, KFAILURE,
+                              "Not enough random i KDC");
+               goto out2;
+           }
+       
+           ret = _krb5_krb_create_ticket(context,
+                                         0,
+                                         ad.pname,
+                                         ad.pinst,
+                                         ad.prealm,
+                                         addr->sin_addr.s_addr,
+                                         &session,
+                                         life,
+                                         issue_time,
+                                         sname,
+                                         sinst,
+                                         &skey->key,
+                                         &ticket);
+           if (ret) {
+               krb5_free_keyblock_contents(context, &session);
+               make_err_reply(context, reply, KFAILURE,
+                              "failed to create v4 ticket");
+               goto out2;
+           }
+
+           ret = _krb5_krb_create_ciph(context,
+                                       &session,
+                                       sname,
+                                       sinst,
+                                       v4_realm,
+                                       life,
+                                       server->kvno % 255,
+                                       &ticket,
+                                       issue_time,
+                                       &ad.session,
+                                       &cipher);
+           krb5_free_keyblock_contents(context, &session);
+           if (ret) {
+               make_err_reply(context, reply, KFAILURE,
+                              "failed to create v4 cipher");
+               goto out2;
+           }
+           
+           ret = _krb5_krb_create_auth_reply(context,
+                                             ad.pname,
+                                             ad.pinst,
+                                             ad.prealm,
+                                             req_time,
+                                             0,
+                                             0,
+                                             0,
+                                             &cipher,
+                                             reply);
+           krb5_data_free(&cipher);
+       }
+    out2:
+       _krb5_krb_free_auth_data(context, &ad);
+       if(tgt_princ)
+           krb5_free_principal(context, tgt_princ);
+       if(tgt)
+           free_ent(tgt);
+       break;
+    }
+    case AUTH_MSG_ERR_REPLY:
+       break;
+    default:
+       kdc_log(0, "Unknown message type (krb4): %d from %s", 
+               msg_type, from);
+       
+       make_err_reply(context, reply, KFAILURE, "Unknown message type");
+    }
+ out:
+    if(name)
+       free(name);
+    if(inst)
+       free(inst);
+    if(realm)
+       free(realm);
+    if(sname)
+       free(sname);
+    if(sinst)
+       free(sinst);
+    if(client)
+       free_ent(client);
+    if(server)
+       free_ent(server);
+    krb5_storage_free(sp);
+    return 0;
+}
+
+krb5_error_code
+encode_v4_ticket(void *buf, size_t len, const EncTicketPart *et,
+                const PrincipalName *service, size_t *size)
+{
+    krb5_storage *sp;
+    krb5_error_code ret;
+    char name[40], inst[40], realm[40];
+    char sname[40], sinst[40];
+
+    {
+       krb5_principal princ;
+       _krb5_principalname2krb5_principal(&princ,
+                                          *service,
+                                          et->crealm);
+       ret = krb5_524_conv_principal(context, 
+                                     princ,
+                                     sname,
+                                     sinst,
+                                     realm);
+       krb5_free_principal(context, princ);
+       if(ret)
+           return ret;
+
+       _krb5_principalname2krb5_principal(&princ,
+                                          et->cname,
+                                          et->crealm);
+                                    
+       ret = krb5_524_conv_principal(context, 
+                                     princ,
+                                     name,
+                                     inst,
+                                     realm);
+       krb5_free_principal(context, princ);
+    }
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_emem();
+    
+    krb5_store_int8(sp, 0); /* flags */
+    krb5_store_stringz(sp, name);
+    krb5_store_stringz(sp, inst);
+    krb5_store_stringz(sp, realm);
+    {
+       unsigned char tmp[4] = { 0, 0, 0, 0 };
+       int i;
+       if(et->caddr){
+           for(i = 0; i < et->caddr->len; i++)
+               if(et->caddr->val[i].addr_type == AF_INET &&
+                  et->caddr->val[i].address.length == 4){
+                   memcpy(tmp, et->caddr->val[i].address.data, 4);
+                   break;
+               }
+       }
+       krb5_storage_write(sp, tmp, sizeof(tmp));
+    }
+
+    if((et->key.keytype != ETYPE_DES_CBC_MD5 &&
+       et->key.keytype != ETYPE_DES_CBC_MD4 &&
+       et->key.keytype != ETYPE_DES_CBC_CRC) || 
+       et->key.keyvalue.length != 8)
+       return -1;
+    krb5_storage_write(sp, et->key.keyvalue.data, 8);
+    
+    {
+       time_t start = et->starttime ? *et->starttime : et->authtime;
+       krb5_store_int8(sp, krb_time_to_life(start, et->endtime));
+       krb5_store_int32(sp, start);
+    }
+
+    krb5_store_stringz(sp, sname);
+    krb5_store_stringz(sp, sinst);
+    
+    {
+       krb5_data data;
+       krb5_storage_to_data(sp, &data);
+       krb5_storage_free(sp);
+       *size = (data.length + 7) & ~7; /* pad to 8 bytes */
+       if(*size > len)
+           return -1;
+       memset((unsigned char*)buf - *size + 1, 0, *size);
+       memcpy((unsigned char*)buf - *size + 1, data.data, data.length);
+       krb5_data_free(&data);
+    }
+    return 0;
+}
+
+krb5_error_code
+get_des_key(hdb_entry *principal, krb5_boolean is_server, 
+           krb5_boolean prefer_afs_key, Key **ret_key)
+{
+    Key *v5_key = NULL, *v4_key = NULL, *afs_key = NULL, *server_key = NULL;
+    int i;
+    krb5_enctype etypes[] = { ETYPE_DES_CBC_MD5, 
+                             ETYPE_DES_CBC_MD4, 
+                             ETYPE_DES_CBC_CRC };
+
+    for(i = 0;
+       i < sizeof(etypes)/sizeof(etypes[0])
+           && (v5_key == NULL || v4_key == NULL || 
+               afs_key == NULL || server_key == NULL);
+       ++i) {
+       Key *key = NULL;
+       while(hdb_next_enctype2key(context, principal, etypes[i], &key) == 0) {
+           if(key->salt == NULL) {
+               if(v5_key == NULL)
+                   v5_key = key;
+           } else if(key->salt->type == hdb_pw_salt && 
+                     key->salt->salt.length == 0) {
+               if(v4_key == NULL)
+                   v4_key = key;
+           } else if(key->salt->type == hdb_afs3_salt) {
+               if(afs_key == NULL)
+                   afs_key = key;
+           } else if(server_key == NULL)
+               server_key = key;
+       }
+    }
+
+    if(prefer_afs_key) {
+       if(afs_key)
+           *ret_key = afs_key;
+       else if(v4_key)
+           *ret_key = v4_key;
+       else if(v5_key)
+           *ret_key = v5_key;
+       else if(is_server && server_key)
+           *ret_key = server_key;
+       else
+           return KERB_ERR_NULL_KEY;
+    } else {
+       if(v4_key)
+           *ret_key = v4_key;
+       else if(afs_key)
+           *ret_key = afs_key;
+       else  if(v5_key)
+           *ret_key = v5_key;
+       else if(is_server && server_key)
+           *ret_key = server_key;
+       else
+           return KERB_ERR_NULL_KEY;
+    }
+
+    if((*ret_key)->key.keyvalue.length == 0)
+       return KERB_ERR_NULL_KEY;
+    return 0;
+}
+
diff --git a/src/kerberosV/src/kdc/kerberos5.c b/src/kerberosV/src/kdc/kerberos5.c
new file mode 100644 (file)
index 0000000..3f0b614
--- /dev/null
@@ -0,0 +1,2219 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+RCSID("$KTH: kerberos5.c,v 1.173.2.2 2005/06/15 11:33:33 lha Exp $");
+
+#define MAX_TIME ((time_t)((1U << 31) - 1))
+
+static void
+fix_time(time_t **t)
+{
+    if(*t == NULL){
+       ALLOC(*t);
+       **t = MAX_TIME;
+    }
+    if(**t == 0) **t = MAX_TIME; /* fix for old clients */
+}
+
+static int
+realloc_method_data(METHOD_DATA *md)
+{
+    PA_DATA *pa;
+    pa = realloc(md->val, (md->len + 1) * sizeof(*md->val));
+    if(pa == NULL)
+       return ENOMEM;
+    md->val = pa;
+    md->len++;
+    return 0;
+}
+
+static void
+set_salt_padata (METHOD_DATA *md, Salt *salt)
+{
+    if (salt) {
+       realloc_method_data(md);
+       md->val[md->len - 1].padata_type = salt->type;
+       copy_octet_string(&salt->salt,
+                         &md->val[md->len - 1].padata_value);
+    }
+}
+
+static PA_DATA*
+find_padata(KDC_REQ *req, int *start, int type)
+{
+    while(*start < req->padata->len){
+       (*start)++;
+       if(req->padata->val[*start - 1].padata_type == type)
+           return &req->padata->val[*start - 1];
+    }
+    return NULL;
+}
+
+/*
+ * return the first appropriate key of `princ' in `ret_key'.  Look for
+ * all the etypes in (`etypes', `len'), stopping as soon as we find
+ * one, but preferring one that has default salt
+ */
+
+static krb5_error_code
+find_etype(hdb_entry *princ, krb5_enctype *etypes, unsigned len, 
+          Key **ret_key, krb5_enctype *ret_etype)
+{
+    int i;
+    krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP;
+
+    for(i = 0; ret != 0 && i < len ; i++) {
+       Key *key = NULL;
+
+       if (krb5_enctype_valid(context, etypes[i]) != 0)
+           continue;
+
+       while (hdb_next_enctype2key(context, princ, etypes[i], &key) == 0) {
+           if (key->key.keyvalue.length == 0) {
+               ret = KRB5KDC_ERR_NULL_KEY;
+               continue;
+           }
+           *ret_key   = key;
+           *ret_etype = etypes[i];
+           ret = 0;
+           if (key->salt == NULL)
+               return ret;
+       }
+    }
+    return ret;
+}
+
+static krb5_error_code
+find_keys(hdb_entry *client,
+         hdb_entry *server, 
+         Key **ckey,
+         krb5_enctype *cetype,
+         Key **skey,
+         krb5_enctype *setype, 
+         krb5_enctype *etypes,
+         unsigned num_etypes)
+{
+    char unparse_name[] = "krb5_unparse_name failed";
+    krb5_error_code ret;
+    char *name;
+
+    if(client){
+       /* find client key */
+       ret = find_etype(client, etypes, num_etypes, ckey, cetype);
+       if (ret) {
+           if (krb5_unparse_name(context, client->principal, &name) != 0)
+               name = unparse_name;
+           kdc_log(0, "Client (%s) has no support for etypes", name);
+           if (name != unparse_name)
+               free(name);
+           return ret;
+       }
+    }
+
+    if(server){
+       /* find server key */
+       ret = find_etype(server, etypes, num_etypes, skey, setype);
+       if (ret) {
+           if (krb5_unparse_name(context, server->principal, &name) != 0)
+               name = unparse_name;
+           kdc_log(0, "Server (%s) has no support for etypes", name);
+           if (name != unparse_name)
+               free(name);
+           return ret;
+       }
+    }
+    return 0;
+}
+
+static krb5_error_code
+make_anonymous_principalname (PrincipalName *pn)
+{
+    pn->name_type = KRB5_NT_PRINCIPAL;
+    pn->name_string.len = 1;
+    pn->name_string.val = malloc(sizeof(*pn->name_string.val));
+    if (pn->name_string.val == NULL)
+       return ENOMEM;
+    pn->name_string.val[0] = strdup("anonymous");
+    if (pn->name_string.val[0] == NULL) {
+       free(pn->name_string.val);
+       pn->name_string.val = NULL;
+       return ENOMEM;
+    }
+    return 0;
+}
+
+static krb5_error_code
+encode_reply(KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, 
+            krb5_enctype etype, 
+            int skvno, EncryptionKey *skey,
+            int ckvno, EncryptionKey *ckey,
+            const char **e_text,
+            krb5_data *reply)
+{
+    unsigned char *buf;
+    size_t buf_size;
+    size_t len;
+    krb5_error_code ret;
+    krb5_crypto crypto;
+
+    ASN1_MALLOC_ENCODE(EncTicketPart, buf, buf_size, et, &len, ret);
+    if(ret) {
+       kdc_log(0, "Failed to encode ticket: %s", 
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    if(buf_size != len) {
+       free(buf);
+       kdc_log(0, "Internal error in ASN.1 encoder");
+       *e_text = "KDC internal error";
+       return KRB5KRB_ERR_GENERIC;
+    }
+
+    ret = krb5_crypto_init(context, skey, etype, &crypto);
+    if (ret) {
+       free(buf);
+       kdc_log(0, "krb5_crypto_init failed: %s",
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+
+    ret = krb5_encrypt_EncryptedData(context, 
+                                    crypto,
+                                    KRB5_KU_TICKET,
+                                    buf,
+                                    len,
+                                    skvno,
+                                    &rep->ticket.enc_part);
+    free(buf);
+    krb5_crypto_destroy(context, crypto);
+    if(ret) {
+       kdc_log(0, "Failed to encrypt data: %s",
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    
+    if(rep->msg_type == krb_as_rep && !encode_as_rep_as_tgs_rep)
+       ASN1_MALLOC_ENCODE(EncASRepPart, buf, buf_size, ek, &len, ret);
+    else
+       ASN1_MALLOC_ENCODE(EncTGSRepPart, buf, buf_size, ek, &len, ret);
+    if(ret) {
+       kdc_log(0, "Failed to encode KDC-REP: %s", 
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    if(buf_size != len) {
+       free(buf);
+       kdc_log(0, "Internal error in ASN.1 encoder");
+       *e_text = "KDC internal error";
+       return KRB5KRB_ERR_GENERIC;
+    }
+    ret = krb5_crypto_init(context, ckey, 0, &crypto);
+    if (ret) {
+       free(buf);
+       kdc_log(0, "krb5_crypto_init failed: %s",
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    if(rep->msg_type == krb_as_rep) {
+       krb5_encrypt_EncryptedData(context,
+                                  crypto,
+                                  KRB5_KU_AS_REP_ENC_PART,
+                                  buf,
+                                  len,
+                                  ckvno,
+                                  &rep->enc_part);
+       free(buf);
+       ASN1_MALLOC_ENCODE(AS_REP, buf, buf_size, rep, &len, ret);
+    } else {
+       krb5_encrypt_EncryptedData(context,
+                                  crypto,
+                                  KRB5_KU_TGS_REP_ENC_PART_SESSION,
+                                  buf,
+                                  len,
+                                  ckvno,
+                                  &rep->enc_part);
+       free(buf);
+       ASN1_MALLOC_ENCODE(TGS_REP, buf, buf_size, rep, &len, ret);
+    }
+    krb5_crypto_destroy(context, crypto);
+    if(ret) {
+       kdc_log(0, "Failed to encode KDC-REP: %s", 
+               krb5_get_err_text(context, ret));
+       return ret;
+    }
+    if(buf_size != len) {
+       free(buf);
+       kdc_log(0, "Internal error in ASN.1 encoder");
+       *e_text = "KDC internal error";
+       return KRB5KRB_ERR_GENERIC;
+    }
+    reply->data = buf;
+    reply->length = buf_size;
+    return 0;
+}
+
+static krb5_error_code
+make_etype_info_entry(ETYPE_INFO_ENTRY *ent, Key *key)
+{
+    ent->etype = key->key.keytype;
+    if(key->salt){
+       ALLOC(ent->salttype);
+#if 0
+       if(key->salt->type == hdb_pw_salt)
+           *ent->salttype = 0; /* or 1? or NULL? */
+       else if(key->salt->type == hdb_afs3_salt)
+           *ent->salttype = 2;
+       else {
+           kdc_log(0, "unknown salt-type: %d", 
+                   key->salt->type);
+           return KRB5KRB_ERR_GENERIC;
+       }
+       /* according to `the specs', we can't send a salt if
+          we have AFS3 salted key, but that requires that you
+          *know* what cell you are using (e.g by assuming
+          that the cell is the same as the realm in lower
+          case) */
+#else
+       *ent->salttype = key->salt->type;
+#endif
+       krb5_copy_data(context, &key->salt->salt,
+                      &ent->salt);
+    } else {
+       /* we return no salt type at all, as that should indicate
+        * the default salt type and make everybody happy.  some
+        * systems (like w2k) dislike being told the salt type
+        * here. */
+
+       ent->salttype = NULL;
+       ent->salt = NULL;
+    }
+    return 0;
+}
+
+static krb5_error_code
+get_pa_etype_info(METHOD_DATA *md, hdb_entry *client, 
+                 ENCTYPE *etypes, unsigned int etypes_len)
+{
+    krb5_error_code ret = 0;
+    int i, j;
+    unsigned int n = 0;
+    ETYPE_INFO pa;
+    unsigned char *buf;
+    size_t len;
+    
+
+    pa.len = client->keys.len;
+    if(pa.len > UINT_MAX/sizeof(*pa.val))
+       return ERANGE;
+    pa.val = malloc(pa.len * sizeof(*pa.val));
+    if(pa.val == NULL)
+       return ENOMEM;
+    memset(pa.val, 0, pa.len * sizeof(*pa.val));
+
+    for(j = 0; j < etypes_len; j++) {
+       for (i = 0; i < n; i++)
+           if (pa.val[i].etype == etypes[j])
+               goto skip1;
+       for(i = 0; i < client->keys.len; i++) {
+           if(client->keys.val[i].key.keytype == etypes[j]) {
+               if (krb5_enctype_valid(context, etypes[j]) != 0)
+                   continue;
+               if((ret = make_etype_info_entry(&pa.val[n++], 
+                                               &client->keys.val[i])) != 0) {
+                   free_ETYPE_INFO(&pa);
+                   return ret;
+               }
+           }
+       }
+    skip1:;
+    }
+    for(i = 0; i < client->keys.len; i++) {
+       for(j = 0; j < etypes_len; j++) {
+           if(client->keys.val[i].key.keytype == etypes[j])
+               goto skip2;
+       }
+       if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
+           continue;
+       if((ret = make_etype_info_entry(&pa.val[n++], 
+                                       &client->keys.val[i])) != 0) {
+           free_ETYPE_INFO(&pa);
+           return ret;
+       }
+    skip2:;
+    }
+    
+    if(n != pa.len) {
+       char *name;
+       ret = krb5_unparse_name(context, client->principal, &name);
+       if (ret)
+           name = "<unparse_name failed>";
+       kdc_log(0, "internal error in get_pa_etype_info(%s): %d != %d", 
+               name, n, pa.len);
+       if (ret == 0)
+           free(name);
+       pa.len = n;
+    }
+
+    ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
+    free_ETYPE_INFO(&pa);
+    if(ret)
+       return ret;
+    ret = realloc_method_data(md);
+    if(ret) {
+       free(buf);
+       return ret;
+    }
+    md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO;
+    md->val[md->len - 1].padata_value.length = len;
+    md->val[md->len - 1].padata_value.data = buf;
+    return 0;
+}
+
+/*
+ *
+ */
+
+extern int _krb5_AES_string_to_default_iterator;
+
+static krb5_error_code
+make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
+{
+    ent->etype = key->key.keytype;
+    if(key->salt) {
+       ALLOC(ent->salt);
+       if (ent->salt == NULL)
+           return ENOMEM;
+       *ent->salt = malloc(key->salt->salt.length + 1);
+       if (*ent->salt == NULL) {
+           free(ent->salt);
+           ent->salt = NULL;
+           return ENOMEM;
+       }
+       memcpy(*ent->salt, key->salt->salt.data, key->salt->salt.length);
+       (*ent->salt)[key->salt->salt.length] = '\0';
+    } else
+       ent->salt = NULL;
+
+    ent->s2kparams = NULL;
+
+    switch (key->key.keytype) {
+    case KEYTYPE_AES128:
+    case KEYTYPE_AES256:
+       ALLOC(ent->s2kparams);
+       if (ent->s2kparams == NULL)
+           return ENOMEM;
+       ent->s2kparams->length = 4;
+       ent->s2kparams->data = malloc(ent->s2kparams->length);
+       if (ent->s2kparams->data == NULL) {
+           free(ent->s2kparams);
+           ent->s2kparams = NULL;
+           return ENOMEM;
+       }
+       _krb5_put_int(ent->s2kparams->data, 
+                     _krb5_AES_string_to_default_iterator, 
+                     ent->s2kparams->length);
+       break;
+    default:
+       break;
+    }
+    return 0;
+}
+
+/*
+ * Return 1 if the client have only older enctypes, this is for
+ * determining if the server should send ETYPE_INFO2 or not.
+ */
+
+static int
+only_older_enctype_p(const KDC_REQ *req)
+{
+    int i;
+
+    for(i = 0; i < req->req_body.etype.len; i++) {
+       switch (req->req_body.etype.val[i]) {
+       case ETYPE_DES_CBC_CRC:
+       case ETYPE_DES_CBC_MD4:
+       case ETYPE_DES_CBC_MD5:
+       case ETYPE_DES3_CBC_SHA1:
+       case ETYPE_ARCFOUR_HMAC_MD5:
+       case ETYPE_ARCFOUR_HMAC_MD5_56:
+           break;
+       default:
+           return 0;
+       }
+    }
+    return 1;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+get_pa_etype_info2(METHOD_DATA *md, hdb_entry *client, 
+                  ENCTYPE *etypes, unsigned int etypes_len)
+{
+    krb5_error_code ret = 0;
+    int i, j;
+    unsigned int n = 0;
+    ETYPE_INFO2 pa;
+    unsigned char *buf;
+    size_t len;
+
+    pa.len = client->keys.len;
+    if(pa.len > UINT_MAX/sizeof(*pa.val))
+       return ERANGE;
+    pa.val = malloc(pa.len * sizeof(*pa.val));
+    if(pa.val == NULL)
+       return ENOMEM;
+    memset(pa.val, 0, pa.len * sizeof(*pa.val));
+
+    for(j = 0; j < etypes_len; j++) {
+       for (i = 0; i < n; i++)
+           if (pa.val[i].etype == etypes[j])
+               goto skip1;
+       for(i = 0; i < client->keys.len; i++) {
+           if(client->keys.val[i].key.keytype == etypes[j]) {
+               if (krb5_enctype_valid(context, etypes[j]) != 0)
+                   continue;
+               if((ret = make_etype_info2_entry(&pa.val[n++], 
+                                                &client->keys.val[i])) != 0) {
+                   free_ETYPE_INFO2(&pa);
+                   return ret;
+               }
+           }
+       }
+    skip1:;
+    }
+    for(i = 0; i < client->keys.len; i++) {
+       for(j = 0; j < etypes_len; j++) {
+           if(client->keys.val[i].key.keytype == etypes[j])
+               goto skip2;
+       }
+       if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
+           continue;
+       if((ret = make_etype_info2_entry(&pa.val[n++],
+                                        &client->keys.val[i])) != 0) {
+           free_ETYPE_INFO2(&pa);
+           return ret;
+       }
+      skip2:;
+    }
+    
+    if(n != pa.len) {
+       char *name;
+       ret = krb5_unparse_name(context, client->principal, &name);
+       if (ret)
+           name = "<unparse_name failed>";
+       kdc_log(0, "internal error in get_pa_etype_info2(%s): %d != %d", 
+               name, n, pa.len);
+       if (ret == 0)
+           free(name);
+       pa.len = n;
+    }
+
+    ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
+    free_ETYPE_INFO2(&pa);
+    if(ret)
+       return ret;
+    ret = realloc_method_data(md);
+    if(ret) {
+       free(buf);
+       return ret;
+    }
+    md->val[md->len - 1].padata_type = KRB5_PADATA_ETYPE_INFO2;
+    md->val[md->len - 1].padata_value.length = len;
+    md->val[md->len - 1].padata_value.data = buf;
+    return 0;
+}
+
+/*
+ * verify the flags on `client' and `server', returning 0
+ * if they are OK and generating an error messages and returning
+ * and error code otherwise.
+ */
+
+krb5_error_code
+check_flags(hdb_entry *client, const char *client_name,
+           hdb_entry *server, const char *server_name,
+           krb5_boolean is_as_req)
+{
+    if(client != NULL) {
+       /* check client */
+       if (client->flags.invalid) {
+           kdc_log(0, "Client (%s) has invalid bit set", client_name);
+           return KRB5KDC_ERR_POLICY;
+       }
+       
+       if(!client->flags.client){
+           kdc_log(0, "Principal may not act as client -- %s", 
+                   client_name);
+           return KRB5KDC_ERR_POLICY;
+       }
+       
+       if (client->valid_start && *client->valid_start > kdc_time) {
+           kdc_log(0, "Client not yet valid -- %s", client_name);
+           return KRB5KDC_ERR_CLIENT_NOTYET;
+       }
+       
+       if (client->valid_end && *client->valid_end < kdc_time) {
+           kdc_log(0, "Client expired -- %s", client_name);
+           return KRB5KDC_ERR_NAME_EXP;
+       }
+       
+       if (client->pw_end && *client->pw_end < kdc_time
+           && !server->flags.change_pw) {
+           kdc_log(0, "Client's key has expired -- %s", client_name);
+           return KRB5KDC_ERR_KEY_EXPIRED;
+       }
+    }
+
+    /* check server */
+    
+    if (server != NULL) {
+       if (server->flags.invalid) {
+           kdc_log(0, "Server has invalid flag set -- %s", server_name);
+           return KRB5KDC_ERR_POLICY;
+       }
+
+       if(!server->flags.server){
+           kdc_log(0, "Principal may not act as server -- %s", 
+                   server_name);
+           return KRB5KDC_ERR_POLICY;
+       }
+
+       if(!is_as_req && server->flags.initial) {
+           kdc_log(0, "AS-REQ is required for server -- %s", server_name);
+           return KRB5KDC_ERR_POLICY;
+       }
+
+       if (server->valid_start && *server->valid_start > kdc_time) {
+           kdc_log(0, "Server not yet valid -- %s", server_name);
+           return KRB5KDC_ERR_SERVICE_NOTYET;
+       }
+
+       if (server->valid_end && *server->valid_end < kdc_time) {
+           kdc_log(0, "Server expired -- %s", server_name);
+           return KRB5KDC_ERR_SERVICE_EXP;
+       }
+
+       if (server->pw_end && *server->pw_end < kdc_time) {
+           kdc_log(0, "Server's key has expired -- %s", server_name);
+           return KRB5KDC_ERR_KEY_EXPIRED;
+       }
+    }
+    return 0;
+}
+
+/*
+ * Return TRUE if `from' is part of `addresses' taking into consideration
+ * the configuration variables that tells us how strict we should be about
+ * these checks
+ */
+
+static krb5_boolean
+check_addresses(HostAddresses *addresses, const struct sockaddr *from)
+{
+    krb5_error_code ret;
+    krb5_address addr;
+    krb5_boolean result;
+    
+    if(check_ticket_addresses == 0)
+       return TRUE;
+
+    if(addresses == NULL)
+       return allow_null_ticket_addresses;
+    
+    ret = krb5_sockaddr2address (context, from, &addr);
+    if(ret)
+       return FALSE;
+
+    result = krb5_address_search(context, &addr, addresses);
+    krb5_free_address (context, &addr);
+    return result;
+}
+
+krb5_error_code
+as_rep(KDC_REQ *req, 
+       krb5_data *reply,
+       const char *from,
+       struct sockaddr *from_addr)
+{
+    KDC_REQ_BODY *b = &req->req_body;
+    AS_REP rep;
+    KDCOptions f = b->kdc_options;
+    hdb_entry *client = NULL, *server = NULL;
+    krb5_enctype cetype, setype;
+    EncTicketPart et;
+    EncKDCRepPart ek;
+    krb5_principal client_princ = NULL, server_princ = NULL;
+    char *client_name = NULL, *server_name = NULL;
+    krb5_error_code ret = 0;
+    const char *e_text = NULL;
+    krb5_crypto crypto;
+    Key *ckey, *skey;
+    EncryptionKey *reply_key;
+#ifdef PKINIT
+    pk_client_params *pkp = NULL;
+#endif
+
+    memset(&rep, 0, sizeof(rep));
+
+    if(b->sname == NULL){
+       ret = KRB5KRB_ERR_GENERIC;
+       e_text = "No server in request";
+    } else{
+       _krb5_principalname2krb5_principal (&server_princ,
+                                           *(b->sname), b->realm);
+       ret = krb5_unparse_name(context, server_princ, &server_name);
+    }
+    if (ret) {
+       kdc_log(0, "AS-REQ malformed server name from %s", from);
+       goto out;
+    }
+    
+    if(b->cname == NULL){
+       ret = KRB5KRB_ERR_GENERIC;
+       e_text = "No client in request";
+    } else {
+       _krb5_principalname2krb5_principal (&client_princ,
+                                           *(b->cname), b->realm);
+       ret = krb5_unparse_name(context, client_princ, &client_name);
+    }
+    if (ret) {
+       kdc_log(0, "AS-REQ malformed client name from %s", from);
+       goto out;
+    }
+
+    kdc_log(0, "AS-REQ %s from %s for %s", 
+           client_name, from, server_name);
+
+    ret = db_fetch(client_princ, &client);
+    if(ret){
+       kdc_log(0, "UNKNOWN -- %s: %s", client_name,
+               krb5_get_err_text(context, ret));
+       ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+       goto out;
+    }
+
+    ret = db_fetch(server_princ, &server);
+    if(ret){
+       kdc_log(0, "UNKNOWN -- %s: %s", server_name,
+               krb5_get_err_text(context, ret));
+       ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+       goto out;
+    }
+
+    ret = check_flags(client, client_name, server, server_name, TRUE);
+    if(ret)
+       goto out;
+
+    memset(&et, 0, sizeof(et));
+    memset(&ek, 0, sizeof(ek));
+
+    if(req->padata){
+       int i = 0;
+       PA_DATA *pa;
+       int found_pa = 0;
+
+#ifdef PKINIT
+       kdc_log(5, "Looking for PKINIT pa-data -- %s", client_name);
+
+       e_text = "No PKINIT PA found";
+
+       i = 0;
+       if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
+           ;
+       if (pa == NULL) {
+           i = 0;
+           if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_19)))
+               ;
+       }
+       if (pa == NULL) {
+           i = 0;
+           if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
+               ;
+       }
+       if (pa) {
+           char *client_cert = NULL;
+
+           ret = pk_rd_padata(context, req, pa, &pkp);
+           if (ret) {
+               ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+               kdc_log(5, "Failed to decode PKINIT PA-DATA -- %s", 
+                       client_name);
+               goto ts_enc;
+           }
+           if (ret == 0 && pkp == NULL)
+               goto ts_enc;
+
+           ret = pk_check_client(context, 
+                                 client_princ, 
+                                 client,
+                                 pkp,
+                                 &client_cert);
+           if (ret) {
+               e_text = "PKINIT certificate not allowed to "
+                   "impersonate principal";
+               pk_free_client_param(context, pkp);
+               pkp = NULL;
+               goto ts_enc;
+           }
+           found_pa = 1;
+           et.flags.pre_authent = 1;
+           kdc_log(2, "PKINIT pre-authentication succeeded -- %s using %s", 
+                   client_name, client_cert);
+           free(client_cert);
+           if (pkp)
+               goto preauth_done;
+       }
+    ts_enc:
+#endif
+       kdc_log(5, "Looking for ENC-TS pa-data -- %s", client_name);
+
+       i = 0;
+       e_text = "No ENC-TS found";
+       while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){
+           krb5_data ts_data;
+           PA_ENC_TS_ENC p;
+           size_t len;
+           EncryptedData enc_data;
+           Key *pa_key;
+           
+           found_pa = 1;
+           
+           ret = decode_EncryptedData(pa->padata_value.data,
+                                      pa->padata_value.length,
+                                      &enc_data,
+                                      &len);
+           if (ret) {
+               ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+               kdc_log(5, "Failed to decode PA-DATA -- %s", 
+                       client_name);
+               goto out;
+           }
+           
+           ret = hdb_enctype2key(context, client, enc_data.etype, &pa_key);
+           if(ret){
+               char *estr;
+               e_text = "No key matches pa-data";
+               ret = KRB5KDC_ERR_PREAUTH_FAILED;
+               if(krb5_enctype_to_string(context, enc_data.etype, &estr))
+                   estr = NULL;
+               if(estr == NULL)
+                   kdc_log(5, "No client key matching pa-data (%d) -- %s", 
+                           enc_data.etype, client_name);
+               else
+                   kdc_log(5, "No client key matching pa-data (%s) -- %s", 
+                           estr, client_name);
+               free(estr);
+                   
+               free_EncryptedData(&enc_data);
+               continue;
+           }
+
+         try_next_key:
+           ret = krb5_crypto_init(context, &pa_key->key, 0, &crypto);
+           if (ret) {
+               kdc_log(0, "krb5_crypto_init failed: %s",
+                       krb5_get_err_text(context, ret));
+               free_EncryptedData(&enc_data);
+               continue;
+           }
+
+           ret = krb5_decrypt_EncryptedData (context,
+                                             crypto,
+                                             KRB5_KU_PA_ENC_TIMESTAMP,
+                                             &enc_data,
+                                             &ts_data);
+           krb5_crypto_destroy(context, crypto);
+           if(ret){
+               if(hdb_next_enctype2key(context, client, 
+                                       enc_data.etype, &pa_key) == 0)
+                   goto try_next_key;
+               free_EncryptedData(&enc_data);
+               e_text = "Failed to decrypt PA-DATA";
+               kdc_log (5, "Failed to decrypt PA-DATA -- %s",
+                        client_name);
+               ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+               continue;
+           }
+           free_EncryptedData(&enc_data);
+           ret = decode_PA_ENC_TS_ENC(ts_data.data,
+                                      ts_data.length,
+                                      &p,
+                                      &len);
+           krb5_data_free(&ts_data);
+           if(ret){
+               e_text = "Failed to decode PA-ENC-TS-ENC";
+               ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+               kdc_log (5, "Failed to decode PA-ENC-TS_ENC -- %s",
+                        client_name);
+               continue;
+           }
+           free_PA_ENC_TS_ENC(&p);
+           if (abs(kdc_time - p.patimestamp) > context->max_skew) {
+               ret = KRB5KDC_ERR_PREAUTH_FAILED;
+               e_text = "Too large time skew";
+               kdc_log(0, "Too large time skew -- %s", client_name);
+               goto out;
+           }
+           et.flags.pre_authent = 1;
+           kdc_log(2, "ENC-TS Pre-authentication succeeded -- %s", 
+                   client_name);
+           break;
+       }
+#ifdef PKINIT
+    preauth_done:
+#endif
+       if(found_pa == 0 && require_preauth)
+           goto use_pa;
+       /* We come here if we found a pa-enc-timestamp, but if there
+           was some problem with it, other than too large skew */
+       if(found_pa && et.flags.pre_authent == 0){
+           kdc_log(0, "%s -- %s", e_text, client_name);
+           e_text = NULL;
+           goto out;
+       }
+    }else if (require_preauth
+             || client->flags.require_preauth
+             || server->flags.require_preauth) {
+       METHOD_DATA method_data;
+       PA_DATA *pa;
+       unsigned char *buf;
+       size_t len;
+       krb5_data foo_data;
+
+      use_pa: 
+       method_data.len = 0;
+       method_data.val = NULL;
+
+       ret = realloc_method_data(&method_data);
+       pa = &method_data.val[method_data.len-1];
+       pa->padata_type         = KRB5_PADATA_ENC_TIMESTAMP;
+       pa->padata_value.length = 0;
+       pa->padata_value.data   = NULL;
+
+#ifdef PKINIT
+       ret = realloc_method_data(&method_data);
+       pa = &method_data.val[method_data.len-1];
+       pa->padata_type         = KRB5_PADATA_PK_AS_REQ;
+       pa->padata_value.length = 0;
+       pa->padata_value.data   = NULL;
+
+       ret = realloc_method_data(&method_data);
+       pa = &method_data.val[method_data.len-1];
+       pa->padata_type         = KRB5_PADATA_PK_AS_REQ_19;
+       pa->padata_value.length = 0;
+       pa->padata_value.data   = NULL;
+#endif
+
+       /* XXX check ret */
+       if (only_older_enctype_p(req))
+           ret = get_pa_etype_info(&method_data, client, 
+                                   b->etype.val, b->etype.len); 
+       /* XXX check ret */
+       ret = get_pa_etype_info2(&method_data, client, 
+                                b->etype.val, b->etype.len);
+
+       
+       ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
+       free_METHOD_DATA(&method_data);
+       foo_data.data   = buf;
+       foo_data.length = len;
+       
+       ret = KRB5KDC_ERR_PREAUTH_REQUIRED;
+       krb5_mk_error(context,
+                     ret,
+                     "Need to use PA-ENC-TIMESTAMP/PA-PK-AS-REQ",
+                     &foo_data,
+                     client_princ,
+                     server_princ,
+                     NULL,
+                     NULL,
+                     reply);
+       free(buf);
+       kdc_log(0, "No preauth found, returning PREAUTH-REQUIRED -- %s",
+               client_name);
+       ret = 0;
+       goto out2;
+    }
+    
+    ret = find_keys(client, server, &ckey, &cetype, &skey, &setype,
+                   b->etype.val, b->etype.len);
+    if(ret) {
+       kdc_log(0, "Server/client has no support for etypes");
+       goto out;
+    }
+       
+    {
+       char *cet;
+       char *set;
+
+       ret = krb5_enctype_to_string(context, cetype, &cet);
+       if(ret == 0) {
+           ret = krb5_enctype_to_string(context, setype, &set);
+           if (ret == 0) {
+               kdc_log(5, "Using %s/%s", cet, set);
+               free(set);
+           }
+           free(cet);
+       }
+       if (ret != 0)
+           kdc_log(5, "Using e-types %d/%d", cetype, setype);
+    }
+    
+    {
+       char str[128];
+       unparse_flags(KDCOptions2int(f), asn1_KDCOptions_units(), 
+                     str, sizeof(str));
+       if(*str)
+           kdc_log(2, "Requested flags: %s", str);
+    }
+    
+
+    if(f.renew || f.validate || f.proxy || f.forwarded || f.enc_tkt_in_skey
+       || (f.request_anonymous && !allow_anonymous)) {
+       ret = KRB5KDC_ERR_BADOPTION;
+       kdc_log(0, "Bad KDC options -- %s", client_name);
+       goto out;
+    }
+    
+    rep.pvno = 5;
+    rep.msg_type = krb_as_rep;
+    copy_Realm(&b->realm, &rep.crealm);
+    if (f.request_anonymous)
+       make_anonymous_principalname (&rep.cname);
+    else
+       copy_PrincipalName(b->cname, &rep.cname);
+    rep.ticket.tkt_vno = 5;
+    copy_Realm(&b->realm, &rep.ticket.realm);
+    copy_PrincipalName(b->sname, &rep.ticket.sname);
+
+    et.flags.initial = 1;
+    if(client->flags.forwardable && server->flags.forwardable)
+       et.flags.forwardable = f.forwardable;
+    else if (f.forwardable) {
+       ret = KRB5KDC_ERR_POLICY;
+       kdc_log(0, "Ticket may not be forwardable -- %s", client_name);
+       goto out;
+    }
+    if(client->flags.proxiable && server->flags.proxiable)
+       et.flags.proxiable = f.proxiable;
+    else if (f.proxiable) {
+       ret = KRB5KDC_ERR_POLICY;
+       kdc_log(0, "Ticket may not be proxiable -- %s", client_name);
+       goto out;
+    }
+    if(client->flags.postdate && server->flags.postdate)
+       et.flags.may_postdate = f.allow_postdate;
+    else if (f.allow_postdate){
+       ret = KRB5KDC_ERR_POLICY;
+       kdc_log(0, "Ticket may not be postdatable -- %s", client_name);
+       goto out;
+    }
+
+    /* check for valid set of addresses */
+    if(!check_addresses(b->addresses, from_addr)) {
+       ret = KRB5KRB_AP_ERR_BADADDR;
+       kdc_log(0, "Bad address list requested -- %s", client_name);
+       goto out;
+    }
+
+    krb5_generate_random_keyblock(context, setype, &et.key);
+    copy_PrincipalName(&rep.cname, &et.cname);
+    copy_Realm(&b->realm, &et.crealm);
+    
+    {
+       time_t start;
+       time_t t;
+       
+       start = et.authtime = kdc_time;
+    
+       if(f.postdated && req->req_body.from){
+           ALLOC(et.starttime);
+           start = *et.starttime = *req->req_body.from;
+           et.flags.invalid = 1;
+           et.flags.postdated = 1; /* XXX ??? */
+       }
+       fix_time(&b->till);
+       t = *b->till;
+
+       /* be careful not overflowing */
+
+       if(client->max_life)
+           t = start + min(t - start, *client->max_life);
+       if(server->max_life)
+           t = start + min(t - start, *server->max_life);
+#if 0
+       t = min(t, start + realm->max_life);
+#endif
+       et.endtime = t;
+       if(f.renewable_ok && et.endtime < *b->till){
+           f.renewable = 1;
+           if(b->rtime == NULL){
+               ALLOC(b->rtime);
+               *b->rtime = 0;
+           }
+           if(*b->rtime < *b->till)
+               *b->rtime = *b->till;
+       }
+       if(f.renewable && b->rtime){
+           t = *b->rtime;
+           if(t == 0)
+               t = MAX_TIME;
+           if(client->max_renew)
+               t = start + min(t - start, *client->max_renew);
+           if(server->max_renew)
+               t = start + min(t - start, *server->max_renew);
+#if 0
+           t = min(t, start + realm->max_renew);
+#endif
+           ALLOC(et.renew_till);
+           *et.renew_till = t;
+           et.flags.renewable = 1;
+       }
+    }
+
+    if (f.request_anonymous)
+       et.flags.anonymous = 1;
+    
+    if(b->addresses){
+       ALLOC(et.caddr);
+       copy_HostAddresses(b->addresses, et.caddr);
+    }
+    
+    et.transited.tr_type = DOMAIN_X500_COMPRESS;
+    krb5_data_zero(&et.transited.contents); 
+     
+    copy_EncryptionKey(&et.key, &ek.key);
+
+    /* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
+     * as 0 and as 0x80 (meaning indefinite length) apart, and is thus
+     * incapable of correctly decoding SEQUENCE OF's of zero length.
+     *
+     * To fix this, always send at least one no-op last_req
+     *
+     * If there's a pw_end or valid_end we will use that,
+     * otherwise just a dummy lr.
+     */
+    ek.last_req.val = malloc(2 * sizeof(*ek.last_req.val));
+    ek.last_req.len = 0;
+    if (client->pw_end
+       && (kdc_warn_pwexpire == 0
+           || kdc_time + kdc_warn_pwexpire <= *client->pw_end)) {
+       ek.last_req.val[ek.last_req.len].lr_type  = LR_PW_EXPTIME;
+       ek.last_req.val[ek.last_req.len].lr_value = *client->pw_end;
+       ++ek.last_req.len;
+    }
+    if (client->valid_end) {
+       ek.last_req.val[ek.last_req.len].lr_type  = LR_ACCT_EXPTIME;
+       ek.last_req.val[ek.last_req.len].lr_value = *client->valid_end;
+       ++ek.last_req.len;
+    }
+    if (ek.last_req.len == 0) {
+       ek.last_req.val[ek.last_req.len].lr_type  = LR_NONE;
+       ek.last_req.val[ek.last_req.len].lr_value = 0;
+       ++ek.last_req.len;
+    }
+    ek.nonce = b->nonce;
+    if (client->valid_end || client->pw_end) {
+       ALLOC(ek.key_expiration);
+       if (client->valid_end) {
+           if (client->pw_end)
+               *ek.key_expiration = min(*client->valid_end, *client->pw_end);
+           else
+               *ek.key_expiration = *client->valid_end;
+       } else
+           *ek.key_expiration = *client->pw_end;
+    } else
+       ek.key_expiration = NULL;
+    ek.flags = et.flags;
+    ek.authtime = et.authtime;
+    if (et.starttime) {
+       ALLOC(ek.starttime);
+       *ek.starttime = *et.starttime;
+    }
+    ek.endtime = et.endtime;
+    if (et.renew_till) {
+       ALLOC(ek.renew_till);
+       *ek.renew_till = *et.renew_till;
+    }
+    copy_Realm(&rep.ticket.realm, &ek.srealm);
+    copy_PrincipalName(&rep.ticket.sname, &ek.sname);
+    if(et.caddr){
+       ALLOC(ek.caddr);
+       copy_HostAddresses(et.caddr, ek.caddr);
+    }
+
+    ALLOC(rep.padata);
+    rep.padata->len = 0;
+    rep.padata->val = NULL;
+
+    reply_key = &ckey->key;
+#if PKINIT
+    if (pkp) {
+       ret = pk_mk_pa_reply(context, pkp, client, req,
+                            &reply_key, rep.padata);
+       if (ret)
+           goto out;
+    }
+#endif
+
+    set_salt_padata (rep.padata, ckey->salt);
+
+    if (rep.padata->len == 0) {
+       free(rep.padata);
+       rep.padata = NULL;
+    }
+
+    ret = encode_reply(&rep, &et, &ek, setype, server->kvno, &skey->key,
+                      client->kvno, reply_key, &e_text, reply);
+    free_EncTicketPart(&et);
+    free_EncKDCRepPart(&ek);
+  out:
+    free_AS_REP(&rep);
+    if(ret){
+       krb5_mk_error(context,
+                     ret,
+                     e_text,
+                     NULL,
+                     client_princ,
+                     server_princ,
+                     NULL,
+                     NULL,
+                     reply);
+       ret = 0;
+    }
+  out2:
+#ifdef PKINIT
+    if (pkp)
+       pk_free_client_param(context, pkp);
+#endif
+    if (client_princ)
+       krb5_free_principal(context, client_princ);
+    free(client_name);
+    if (server_princ)
+       krb5_free_principal(context, server_princ);
+    free(server_name);
+    if(client)
+       free_ent(client);
+    if(server)
+       free_ent(server);
+    return ret;
+}
+
+
+static krb5_error_code
+check_tgs_flags(KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et)
+{
+    KDCOptions f = b->kdc_options;
+       
+    if(f.validate){
+       if(!tgt->flags.invalid || tgt->starttime == NULL){
+           kdc_log(0, "Bad request to validate ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       if(*tgt->starttime > kdc_time){
+           kdc_log(0, "Early request to validate ticket");
+           return KRB5KRB_AP_ERR_TKT_NYV;
+       }
+       /* XXX  tkt = tgt */
+       et->flags.invalid = 0;
+    }else if(tgt->flags.invalid){
+       kdc_log(0, "Ticket-granting ticket has INVALID flag set");
+       return KRB5KRB_AP_ERR_TKT_INVALID;
+    }
+
+    if(f.forwardable){
+       if(!tgt->flags.forwardable){
+           kdc_log(0, "Bad request for forwardable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       et->flags.forwardable = 1;
+    }
+    if(f.forwarded){
+       if(!tgt->flags.forwardable){
+           kdc_log(0, "Request to forward non-forwardable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       et->flags.forwarded = 1;
+       et->caddr = b->addresses;
+    }
+    if(tgt->flags.forwarded)
+       et->flags.forwarded = 1;
+       
+    if(f.proxiable){
+       if(!tgt->flags.proxiable){
+           kdc_log(0, "Bad request for proxiable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       et->flags.proxiable = 1;
+    }
+    if(f.proxy){
+       if(!tgt->flags.proxiable){
+           kdc_log(0, "Request to proxy non-proxiable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       et->flags.proxy = 1;
+       et->caddr = b->addresses;
+    }
+    if(tgt->flags.proxy)
+       et->flags.proxy = 1;
+
+    if(f.allow_postdate){
+       if(!tgt->flags.may_postdate){
+           kdc_log(0, "Bad request for post-datable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       et->flags.may_postdate = 1;
+    }
+    if(f.postdated){
+       if(!tgt->flags.may_postdate){
+           kdc_log(0, "Bad request for postdated ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       if(b->from)
+           *et->starttime = *b->from;
+       et->flags.postdated = 1;
+       et->flags.invalid = 1;
+    }else if(b->from && *b->from > kdc_time + context->max_skew){
+       kdc_log(0, "Ticket cannot be postdated");
+       return KRB5KDC_ERR_CANNOT_POSTDATE;
+    }
+
+    if(f.renewable){
+       if(!tgt->flags.renewable){
+           kdc_log(0, "Bad request for renewable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       et->flags.renewable = 1;
+       ALLOC(et->renew_till);
+       fix_time(&b->rtime);
+       *et->renew_till = *b->rtime;
+    }
+    if(f.renew){
+       time_t old_life;
+       if(!tgt->flags.renewable || tgt->renew_till == NULL){
+           kdc_log(0, "Request to renew non-renewable ticket");
+           return KRB5KDC_ERR_BADOPTION;
+       }
+       old_life = tgt->endtime;
+       if(tgt->starttime)
+           old_life -= *tgt->starttime;
+       else
+           old_life -= tgt->authtime;
+       et->endtime = *et->starttime + old_life;
+       if (et->renew_till != NULL)
+           et->endtime = min(*et->renew_till, et->endtime);
+    }      
+    
+    /* checks for excess flags */
+    if(f.request_anonymous && !allow_anonymous){
+       kdc_log(0, "Request for anonymous ticket");
+       return KRB5KDC_ERR_BADOPTION;
+    }
+    return 0;
+}
+
+static krb5_error_code
+fix_transited_encoding(krb5_boolean check_policy,
+                      TransitedEncoding *tr, 
+                      EncTicketPart *et, 
+                      const char *client_realm, 
+                      const char *server_realm, 
+                      const char *tgt_realm)
+{
+    krb5_error_code ret = 0;
+    char **realms, **tmp;
+    int num_realms;
+    int i;
+
+    if(tr->tr_type != DOMAIN_X500_COMPRESS) {
+       kdc_log(0, "Unknown transited type: %u", tr->tr_type);
+       return KRB5KDC_ERR_TRTYPE_NOSUPP;
+    }
+
+    ret = krb5_domain_x500_decode(context, 
+                                 tr->contents,
+                                 &realms, 
+                                 &num_realms,
+                                 client_realm,
+                                 server_realm);
+    if(ret){
+       krb5_warn(context, ret, "Decoding transited encoding");
+       return ret;
+    }
+    if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) {
+       /* not us, so add the previous realm to transited set */
+       if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) {
+           ret = ERANGE;
+           goto free_realms;
+       }
+       tmp = realloc(realms, (num_realms + 1) * sizeof(*realms));
+       if(tmp == NULL){
+           ret = ENOMEM;
+           goto free_realms;
+       }
+       realms = tmp;
+       realms[num_realms] = strdup(tgt_realm);
+       if(realms[num_realms] == NULL){
+           ret = ENOMEM;
+           goto free_realms;
+       }
+       num_realms++;
+    }
+    if(num_realms == 0) {
+       if(strcmp(client_realm, server_realm)) 
+           kdc_log(0, "cross-realm %s -> %s", client_realm, server_realm);
+    } else {
+       size_t l = 0;
+       char *rs;
+       for(i = 0; i < num_realms; i++)
+           l += strlen(realms[i]) + 2;
+       rs = malloc(l);
+       if(rs != NULL) {
+           *rs = '\0';
+           for(i = 0; i < num_realms; i++) {
+               if(i > 0)
+                   strlcat(rs, ", ", l);
+               strlcat(rs, realms[i], l);
+           }
+           kdc_log(0, "cross-realm %s -> %s via [%s]", client_realm, server_realm, rs);
+           free(rs);
+       }
+    }
+    if(check_policy) {
+       ret = krb5_check_transited(context, client_realm, 
+                                  server_realm, 
+                                  realms, num_realms, NULL);
+       if(ret) {
+           krb5_warn(context, ret, "cross-realm %s -> %s", 
+                     client_realm, server_realm);
+           goto free_realms;
+       }
+       et->flags.transited_policy_checked = 1;
+    }
+    et->transited.tr_type = DOMAIN_X500_COMPRESS;
+    ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents);
+    if(ret)
+       krb5_warn(context, ret, "Encoding transited encoding");
+  free_realms:
+    for(i = 0; i < num_realms; i++)
+       free(realms[i]);
+    free(realms);
+    return ret;
+}
+
+
+static krb5_error_code
+tgs_make_reply(KDC_REQ_BODY *b, 
+              EncTicketPart *tgt, 
+              EncTicketPart *adtkt, 
+              AuthorizationData *auth_data,
+              hdb_entry *server, 
+              hdb_entry *client, 
+              krb5_principal client_principal, 
+              hdb_entry *krbtgt,
+              krb5_enctype cetype,
+              const char **e_text,
+              krb5_data *reply)
+{
+    KDC_REP rep;
+    EncKDCRepPart ek;
+    EncTicketPart et;
+    KDCOptions f = b->kdc_options;
+    krb5_error_code ret;
+    krb5_enctype etype;
+    Key *skey;
+    EncryptionKey *ekey;
+    
+    if(adtkt) {
+       int i;
+       krb5_keytype kt;
+       ekey = &adtkt->key;
+       for(i = 0; i < b->etype.len; i++){
+           ret = krb5_enctype_to_keytype(context, b->etype.val[i], &kt);
+           if(ret)
+               continue;
+           if(adtkt->key.keytype == kt)
+               break;
+       }
+       if(i == b->etype.len)
+           return KRB5KDC_ERR_ETYPE_NOSUPP;
+       etype = b->etype.val[i];
+    }else{
+       ret = find_keys(NULL, server, NULL, NULL, &skey, &etype, 
+                       b->etype.val, b->etype.len);
+       if(ret) {
+           kdc_log(0, "Server has no support for etypes");
+           return ret;
+       }
+       ekey = &skey->key;
+    }
+    
+    memset(&rep, 0, sizeof(rep));
+    memset(&et, 0, sizeof(et));
+    memset(&ek, 0, sizeof(ek));
+    
+    rep.pvno = 5;
+    rep.msg_type = krb_tgs_rep;
+
+    et.authtime = tgt->authtime;
+    fix_time(&b->till);
+    et.endtime = min(tgt->endtime, *b->till);
+    ALLOC(et.starttime);
+    *et.starttime = kdc_time;
+    
+    ret = check_tgs_flags(b, tgt, &et);
+    if(ret)
+       goto out;
+
+    /* We should check the transited encoding if:
+       1) the request doesn't ask not to be checked
+       2) globally enforcing a check
+       3) principal requires checking
+       4) we allow non-check per-principal, but principal isn't marked as allowing this
+       5) we don't globally allow this
+    */
+
+#define GLOBAL_FORCE_TRANSITED_CHECK           (trpolicy == TRPOLICY_ALWAYS_CHECK)
+#define GLOBAL_ALLOW_PER_PRINCIPAL             (trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL)
+#define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK   (trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST)
+/* these will consult the database in future release */
+#define PRINCIPAL_FORCE_TRANSITED_CHECK(P)             0
+#define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P)     0
+
+    ret = fix_transited_encoding(!f.disable_transited_check ||
+                                GLOBAL_FORCE_TRANSITED_CHECK ||
+                                PRINCIPAL_FORCE_TRANSITED_CHECK(server) ||
+                                !((GLOBAL_ALLOW_PER_PRINCIPAL && 
+                                   PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
+                                  GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
+                                &tgt->transited, &et,
+                                *krb5_princ_realm(context, client_principal),
+                                *krb5_princ_realm(context, server->principal),
+                                *krb5_princ_realm(context, krbtgt->principal));
+    if(ret)
+       goto out;
+
+    copy_Realm(krb5_princ_realm(context, server->principal), 
+              &rep.ticket.realm);
+    _krb5_principal2principalname(&rep.ticket.sname, server->principal);
+    copy_Realm(&tgt->crealm, &rep.crealm);
+    if (f.request_anonymous)
+       make_anonymous_principalname (&tgt->cname);
+    else
+       copy_PrincipalName(&tgt->cname, &rep.cname);
+    rep.ticket.tkt_vno = 5;
+
+    ek.caddr = et.caddr;
+    if(et.caddr == NULL)
+       et.caddr = tgt->caddr;
+
+    {
+       time_t life;
+       life = et.endtime - *et.starttime;
+       if(client && client->max_life)
+           life = min(life, *client->max_life);
+       if(server->max_life)
+           life = min(life, *server->max_life);
+       et.endtime = *et.starttime + life;
+    }
+    if(f.renewable_ok && tgt->flags.renewable && 
+       et.renew_till == NULL && et.endtime < *b->till){
+       et.flags.renewable = 1;
+       ALLOC(et.renew_till);
+       *et.renew_till = *b->till;
+    }
+    if(et.renew_till){
+       time_t renew;
+       renew = *et.renew_till - et.authtime;
+       if(client && client->max_renew)
+           renew = min(renew, *client->max_renew);
+       if(server->max_renew)
+           renew = min(renew, *server->max_renew);
+       *et.renew_till = et.authtime + renew;
+    }
+           
+    if(et.renew_till){
+       *et.renew_till = min(*et.renew_till, *tgt->renew_till);
+       *et.starttime = min(*et.starttime, *et.renew_till);
+       et.endtime = min(et.endtime, *et.renew_till);
+    }
+    
+    *et.starttime = min(*et.starttime, et.endtime);
+
+    if(*et.starttime == et.endtime){
+       ret = KRB5KDC_ERR_NEVER_VALID;
+       goto out;
+    }
+    if(et.renew_till && et.endtime == *et.renew_till){
+       free(et.renew_till);
+       et.renew_till = NULL;
+       et.flags.renewable = 0;
+    }
+    
+    et.flags.pre_authent = tgt->flags.pre_authent;
+    et.flags.hw_authent  = tgt->flags.hw_authent;
+    et.flags.anonymous   = tgt->flags.anonymous;
+    et.flags.ok_as_delegate = server->flags.ok_as_delegate;
+           
+    /* XXX Check enc-authorization-data */
+    et.authorization_data = auth_data;
+
+    krb5_generate_random_keyblock(context, etype, &et.key);
+    et.crealm = tgt->crealm;
+    et.cname = tgt->cname;
+           
+    ek.key = et.key;
+    /* MIT must have at least one last_req */
+    ek.last_req.len = 1;
+    ek.last_req.val = calloc(1, sizeof(*ek.last_req.val));
+    ek.nonce = b->nonce;
+    ek.flags = et.flags;
+    ek.authtime = et.authtime;
+    ek.starttime = et.starttime;
+    ek.endtime = et.endtime;
+    ek.renew_till = et.renew_till;
+    ek.srealm = rep.ticket.realm;
+    ek.sname = rep.ticket.sname;
+           
+    /* It is somewhat unclear where the etype in the following
+       encryption should come from. What we have is a session
+       key in the passed tgt, and a list of preferred etypes
+       *for the new ticket*. Should we pick the best possible
+       etype, given the keytype in the tgt, or should we look
+       at the etype list here as well?  What if the tgt
+       session key is DES3 and we want a ticket with a (say)
+       CAST session key. Should the DES3 etype be added to the
+       etype list, even if we don't want a session key with
+       DES3? */
+    ret = encode_reply(&rep, &et, &ek, etype, adtkt ? 0 : server->kvno, ekey,
+                      0, &tgt->key, e_text, reply);
+  out:
+    free_TGS_REP(&rep);
+    free_TransitedEncoding(&et.transited);
+    if(et.starttime)
+       free(et.starttime);
+    if(et.renew_till)
+       free(et.renew_till);
+    free_LastReq(&ek.last_req);
+    memset(et.key.keyvalue.data, 0, et.key.keyvalue.length);
+    free_EncryptionKey(&et.key);
+    return ret;
+}
+
+static krb5_error_code
+tgs_check_authenticator(krb5_auth_context ac,
+                       KDC_REQ_BODY *b, 
+                       const char **e_text,
+                       krb5_keyblock *key)
+{
+    krb5_authenticator auth;
+    size_t len;
+    unsigned char *buf;
+    size_t buf_size;
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    
+    krb5_auth_con_getauthenticator(context, ac, &auth);
+    if(auth->cksum == NULL){
+       kdc_log(0, "No authenticator in request");
+       ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
+       goto out;
+    }
+    /*
+     * according to RFC1510 it doesn't need to be keyed,
+     * but according to the latest draft it needs to.
+     */
+    if (
+#if 0
+!krb5_checksum_is_keyed(context, auth->cksum->cksumtype)
+       ||
+#endif
+ !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) {
+       kdc_log(0, "Bad checksum type in authenticator: %d", 
+               auth->cksum->cksumtype);
+       ret =  KRB5KRB_AP_ERR_INAPP_CKSUM;
+       goto out;
+    }
+               
+    /* XXX should not re-encode this */
+    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret);
+    if(ret){
+       kdc_log(0, "Failed to encode KDC-REQ-BODY: %s", 
+               krb5_get_err_text(context, ret));
+       goto out;
+    }
+    if(buf_size != len) {
+       free(buf);
+       kdc_log(0, "Internal error in ASN.1 encoder");
+       *e_text = "KDC internal error";
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret) {
+       free(buf);
+       kdc_log(0, "krb5_crypto_init failed: %s",
+               krb5_get_err_text(context, ret));
+       goto out;
+    }
+    ret = krb5_verify_checksum(context,
+                              crypto,
+                              KRB5_KU_TGS_REQ_AUTH_CKSUM,
+                              buf, 
+                              len,
+                              auth->cksum);
+    free(buf);
+    krb5_crypto_destroy(context, crypto);
+    if(ret){
+       kdc_log(0, "Failed to verify checksum: %s", 
+               krb5_get_err_text(context, ret));
+    }
+out:
+    free_Authenticator(auth);
+    free(auth);
+    return ret;
+}
+
+/*
+ * return the realm of a krbtgt-ticket or NULL
+ */
+
+static Realm 
+get_krbtgt_realm(const PrincipalName *p)
+{
+    if(p->name_string.len == 2
+       && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0)
+       return p->name_string.val[1];
+    else
+       return NULL;
+}
+
+static Realm
+find_rpath(Realm crealm, Realm srealm)
+{
+    const char *new_realm = krb5_config_get_string(context,
+                                                  NULL,
+                                                  "capaths", 
+                                                  crealm,
+                                                  srealm,
+                                                  NULL);
+    return (Realm)new_realm;
+}
+           
+
+static krb5_boolean
+need_referral(krb5_principal server, krb5_realm **realms)
+{
+    if(server->name.name_type != KRB5_NT_SRV_INST ||
+       server->name.name_string.len != 2)
+       return FALSE;
+    return _krb5_get_host_realm_int(context, server->name.name_string.val[1],
+                                   FALSE, realms) == 0;
+}
+
+static krb5_error_code
+tgs_rep2(KDC_REQ_BODY *b,
+        PA_DATA *tgs_req,
+        krb5_data *reply,
+        const char *from,
+        const struct sockaddr *from_addr,
+        time_t **csec,
+        int **cusec)
+{
+    krb5_ap_req ap_req;
+    krb5_error_code ret;
+    krb5_principal princ;
+    krb5_auth_context ac = NULL;
+    krb5_ticket *ticket = NULL;
+    krb5_flags ap_req_options;
+    krb5_flags verify_ap_req_flags;
+    const char *e_text = NULL;
+    krb5_crypto crypto;
+
+    hdb_entry *krbtgt = NULL;
+    EncTicketPart *tgt;
+    Key *tkey;
+    krb5_enctype cetype;
+    krb5_principal cp = NULL;
+    krb5_principal sp = NULL;
+    AuthorizationData *auth_data = NULL;
+
+    *csec  = NULL;
+    *cusec = NULL;
+
+    memset(&ap_req, 0, sizeof(ap_req));
+    ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req);
+    if(ret){
+       kdc_log(0, "Failed to decode AP-REQ: %s", 
+               krb5_get_err_text(context, ret));
+       goto out2;
+    }
+    
+    if(!get_krbtgt_realm(&ap_req.ticket.sname)){
+       /* XXX check for ticket.sname == req.sname */
+       kdc_log(0, "PA-DATA is not a ticket-granting ticket");
+       ret = KRB5KDC_ERR_POLICY; /* ? */
+       goto out2;
+    }
+    
+    _krb5_principalname2krb5_principal(&princ,
+                                      ap_req.ticket.sname,
+                                      ap_req.ticket.realm);
+    
+    ret = db_fetch(princ, &krbtgt);
+
+    if(ret) {
+       char *p;
+       ret = krb5_unparse_name(context, princ, &p);
+       if (ret != 0)
+           p = "<unparse_name failed>";
+       krb5_free_principal(context, princ);
+       kdc_log(0, "Ticket-granting ticket not found in database: %s: %s",
+               p, krb5_get_err_text(context, ret));
+       if (ret == 0)
+           free(p);
+       ret = KRB5KRB_AP_ERR_NOT_US;
+       goto out2;
+    }
+    
+    if(ap_req.ticket.enc_part.kvno && 
+       *ap_req.ticket.enc_part.kvno != krbtgt->kvno){
+       char *p;
+
+       ret = krb5_unparse_name (context, princ, &p);
+       krb5_free_principal(context, princ);
+       if (ret != 0)
+           p = "<unparse_name failed>";
+       kdc_log(0, "Ticket kvno = %d, DB kvno = %d (%s)", 
+               *ap_req.ticket.enc_part.kvno,
+               krbtgt->kvno,
+               p);
+       if (ret == 0)
+           free (p);
+       ret = KRB5KRB_AP_ERR_BADKEYVER;
+       goto out2;
+    }
+
+    ret = hdb_enctype2key(context, krbtgt, ap_req.ticket.enc_part.etype, &tkey);
+    if(ret){
+       char *str;
+       krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str);
+       kdc_log(0, "No server key found for %s", str);
+       free(str);
+       ret = KRB5KRB_AP_ERR_BADKEYVER;
+       goto out2;
+    }
+    
+    if (b->kdc_options.validate)
+       verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID;
+    else
+       verify_ap_req_flags = 0;
+
+    ret = krb5_verify_ap_req2(context,
+                             &ac,
+                             &ap_req,
+                             princ,
+                             &tkey->key,
+                             verify_ap_req_flags,
+                             &ap_req_options,
+                             &ticket,
+                             KRB5_KU_TGS_REQ_AUTH);
+                            
+    krb5_free_principal(context, princ);
+    if(ret) {
+       kdc_log(0, "Failed to verify AP-REQ: %s", 
+               krb5_get_err_text(context, ret));
+       goto out2;
+    }
+
+    {
+       krb5_authenticator auth;
+
+       ret = krb5_auth_con_getauthenticator(context, ac, &auth);
+       if (ret == 0) {
+           *csec   = malloc(sizeof(**csec));
+           if (*csec == NULL) {
+               krb5_free_authenticator(context, &auth);
+               kdc_log(0, "malloc failed");
+               goto out2;
+           }
+           **csec  = auth->ctime;
+           *cusec  = malloc(sizeof(**cusec));
+           if (*cusec == NULL) {
+               krb5_free_authenticator(context, &auth);
+               kdc_log(0, "malloc failed");
+               goto out2;
+           }
+           **csec  = auth->cusec;
+           krb5_free_authenticator(context, &auth);
+       }
+    }
+
+    cetype = ap_req.authenticator.etype;
+
+    tgt = &ticket->ticket;
+
+    ret = tgs_check_authenticator(ac, b, &e_text, &tgt->key);
+
+    if (b->enc_authorization_data) {
+       krb5_keyblock *subkey;
+       krb5_data ad;
+       ret = krb5_auth_con_getremotesubkey(context,
+                                           ac,
+                                           &subkey);
+       if(ret){
+           krb5_auth_con_free(context, ac);
+           kdc_log(0, "Failed to get remote subkey: %s", 
+                   krb5_get_err_text(context, ret));
+           goto out2;
+       }
+       if(subkey == NULL){
+           ret = krb5_auth_con_getkey(context, ac, &subkey);
+           if(ret) {
+               krb5_auth_con_free(context, ac);
+               kdc_log(0, "Failed to get session key: %s", 
+                       krb5_get_err_text(context, ret));
+               goto out2;
+           }
+       }
+       if(subkey == NULL){
+           krb5_auth_con_free(context, ac);
+           kdc_log(0, "Failed to get key for enc-authorization-data");
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+           goto out2;
+       }
+       ret = krb5_crypto_init(context, subkey, 0, &crypto);
+       if (ret) {
+           krb5_auth_con_free(context, ac);
+           kdc_log(0, "krb5_crypto_init failed: %s",
+                   krb5_get_err_text(context, ret));
+           goto out2;
+       }
+       ret = krb5_decrypt_EncryptedData (context,
+                                         crypto,
+                                         KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY,
+                                         b->enc_authorization_data,
+                                         &ad);
+       krb5_crypto_destroy(context, crypto);
+       if(ret){
+           krb5_auth_con_free(context, ac);
+           kdc_log(0, "Failed to decrypt enc-authorization-data");
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+           goto out2;
+       }
+       krb5_free_keyblock(context, subkey);
+       ALLOC(auth_data);
+       ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL);
+       if(ret){
+           krb5_auth_con_free(context, ac);
+           free(auth_data);
+           auth_data = NULL;
+           kdc_log(0, "Failed to decode authorization data");
+           ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
+           goto out2;
+       }
+    }
+
+    krb5_auth_con_free(context, ac);
+
+    if(ret){
+       kdc_log(0, "Failed to verify authenticator: %s", 
+               krb5_get_err_text(context, ret));
+       goto out2;
+    }
+    
+    {
+       PrincipalName *s;
+       Realm r;
+       char *spn = NULL, *cpn = NULL;
+       hdb_entry *server = NULL, *client = NULL;
+       int loop = 0;
+       EncTicketPart adtkt;
+       char opt_str[128];
+
+       s = b->sname;
+       r = b->realm;
+       if(b->kdc_options.enc_tkt_in_skey){
+           Ticket *t;
+           hdb_entry *uu;
+           krb5_principal p;
+           Key *tkey;
+           
+           if(b->additional_tickets == NULL || 
+              b->additional_tickets->len == 0){
+               ret = KRB5KDC_ERR_BADOPTION; /* ? */
+               kdc_log(0, "No second ticket present in request");
+               goto out;
+           }
+           t = &b->additional_tickets->val[0];
+           if(!get_krbtgt_realm(&t->sname)){
+               kdc_log(0, "Additional ticket is not a ticket-granting ticket");
+               ret = KRB5KDC_ERR_POLICY;
+               goto out2;
+           }
+           _krb5_principalname2krb5_principal(&p, t->sname, t->realm);
+           ret = db_fetch(p, &uu);
+           krb5_free_principal(context, p);
+           if(ret){
+               if (ret == HDB_ERR_NOENTRY)
+                   ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+               goto out;
+           }
+           ret = hdb_enctype2key(context, uu, t->enc_part.etype, &tkey);
+           if(ret){
+               ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */
+               goto out;
+           }
+           ret = krb5_decrypt_ticket(context, t, &tkey->key, &adtkt, 0);
+
+           if(ret)
+               goto out;
+           s = &adtkt.cname;
+           r = adtkt.crealm;
+       }
+
+       _krb5_principalname2krb5_principal(&sp, *s, r);
+       ret = krb5_unparse_name(context, sp, &spn);     
+       if (ret)
+           goto out;
+       _krb5_principalname2krb5_principal(&cp, tgt->cname, tgt->crealm);
+       ret = krb5_unparse_name(context, cp, &cpn);
+       if (ret)
+           goto out;
+       unparse_flags (KDCOptions2int(b->kdc_options),
+                      asn1_KDCOptions_units(),
+                      opt_str, sizeof(opt_str));
+       if(*opt_str)
+           kdc_log(0, "TGS-REQ %s from %s for %s [%s]", 
+                   cpn, from, spn, opt_str);
+       else
+           kdc_log(0, "TGS-REQ %s from %s for %s", cpn, from, spn);
+    server_lookup:
+       ret = db_fetch(sp, &server);
+
+       if(ret){
+           Realm req_rlm, new_rlm;
+           krb5_realm *realms;
+
+           if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) {
+               if(loop++ < 2) {
+                   new_rlm = find_rpath(tgt->crealm, req_rlm);
+                   if(new_rlm) {
+                       kdc_log(5, "krbtgt for realm %s not found, trying %s", 
+                               req_rlm, new_rlm);
+                       krb5_free_principal(context, sp);
+                       free(spn);
+                       krb5_make_principal(context, &sp, r, 
+                                           KRB5_TGS_NAME, new_rlm, NULL);
+                       ret = krb5_unparse_name(context, sp, &spn);     
+                       if (ret)
+                           goto out;
+                       goto server_lookup;
+                   }
+               }
+           } else if(need_referral(sp, &realms)) {
+               if (strcmp(realms[0], sp->realm) != 0) {
+                   kdc_log(5, "returning a referral to realm %s for "
+                           "server %s that was not found",
+                           realms[0], spn);
+                   krb5_free_principal(context, sp);
+                   free(spn);
+                   krb5_make_principal(context, &sp, r, KRB5_TGS_NAME,
+                                       realms[0], NULL);
+                   ret = krb5_unparse_name(context, sp, &spn);
+                   if (ret)
+                       goto out;
+                   krb5_free_host_realm(context, realms);
+                   goto server_lookup;
+               }
+               krb5_free_host_realm(context, realms);
+           }
+           kdc_log(0, "Server not found in database: %s: %s", spn,
+                   krb5_get_err_text(context, ret));
+           if (ret == HDB_ERR_NOENTRY)
+               ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
+           goto out;
+       }
+
+       ret = db_fetch(cp, &client);
+       if(ret)
+           kdc_log(1, "Client not found in database: %s: %s",
+                   cpn, krb5_get_err_text(context, ret));
+#if 0
+       /* XXX check client only if same realm as krbtgt-instance */
+       if(ret){
+           kdc_log(0, "Client not found in database: %s: %s",
+                   cpn, krb5_get_err_text(context, ret));
+           if (ret == HDB_ERR_NOENTRY)
+               ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+           goto out;
+       }
+#endif
+
+       if(strcmp(krb5_principal_get_realm(context, sp),
+                 krb5_principal_get_comp_string(context, krbtgt->principal, 1)) != 0) {
+           char *tpn;
+           ret = krb5_unparse_name(context, krbtgt->principal, &tpn);
+           kdc_log(0, "Request with wrong krbtgt: %s", (ret == 0) ? tpn : "<unknown>");
+           if(ret == 0)
+               free(tpn);
+           ret = KRB5KRB_AP_ERR_NOT_US;
+           goto out;
+           
+       }
+
+       ret = check_flags(client, cpn, server, spn, FALSE);
+       if(ret)
+           goto out;
+
+       if((b->kdc_options.validate || b->kdc_options.renew) && 
+          !krb5_principal_compare(context, 
+                                  krbtgt->principal,
+                                  server->principal)){
+           kdc_log(0, "Inconsistent request.");
+           ret = KRB5KDC_ERR_SERVER_NOMATCH;
+           goto out;
+       }
+
+       /* check for valid set of addresses */
+       if(!check_addresses(tgt->caddr, from_addr)) {
+           ret = KRB5KRB_AP_ERR_BADADDR;
+           kdc_log(0, "Request from wrong address");
+           goto out;
+       }
+       
+       ret = tgs_make_reply(b, 
+                            tgt, 
+                            b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, 
+                            auth_data,
+                            server, 
+                            client, 
+                            cp, 
+                            krbtgt, 
+                            cetype, 
+                            &e_text,
+                            reply);
+       
+    out:
+       free(spn);
+       free(cpn);
+           
+       if(server)
+           free_ent(server);
+       if(client)
+           free_ent(client);
+    }
+out2:
+    if(ret) {
+       krb5_mk_error(context,
+                     ret,
+                     e_text,
+                     NULL,
+                     cp,
+                     sp,
+                     NULL,
+                     NULL,
+                     reply);
+       free(*csec);
+       free(*cusec);
+       *csec  = NULL;
+       *cusec = NULL;
+    }
+    krb5_free_principal(context, cp);
+    krb5_free_principal(context, sp);
+    if (ticket)
+       krb5_free_ticket(context, ticket);
+    free_AP_REQ(&ap_req);
+    if(auth_data){
+       free_AuthorizationData(auth_data);
+       free(auth_data);
+    }
+
+    if(krbtgt)
+       free_ent(krbtgt);
+
+    return ret;
+}
+
+
+krb5_error_code
+tgs_rep(KDC_REQ *req, 
+       krb5_data *data,
+       const char *from,
+       struct sockaddr *from_addr)
+{
+    krb5_error_code ret;
+    int i = 0;
+    PA_DATA *tgs_req = NULL;
+    time_t *csec = NULL;
+    int *cusec = NULL;
+
+    if(req->padata == NULL){
+       ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */
+       kdc_log(0, "TGS-REQ from %s without PA-DATA", from);
+       goto out;
+    }
+    
+    tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ);
+
+    if(tgs_req == NULL){
+       ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+       
+       kdc_log(0, "TGS-REQ from %s without PA-TGS-REQ", from);
+       goto out;
+    }
+    ret = tgs_rep2(&req->req_body, tgs_req, data, from, from_addr,
+                  &csec, &cusec);
+out:
+    if(ret && data->data == NULL){
+       krb5_mk_error(context,
+                     ret,
+                     NULL,
+                     NULL,
+                     NULL,
+                     NULL,
+                     csec,
+                     cusec,
+                     data);
+    }
+    free(csec);
+    free(cusec);
+    return 0;
+}
diff --git a/src/kerberosV/src/kdc/kstash.8 b/src/kerberosV/src/kdc/kstash.8
new file mode 100644 (file)
index 0000000..8bf4b0c
--- /dev/null
@@ -0,0 +1,104 @@
+.\" Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\"
+.\" $KTH: kstash.8,v 1.8 2004/12/09 12:15:20 lha Exp $
+.\"
+.Dd December  9, 2004
+.Dt KSTASH 8
+.Os HEIMDAL
+.Sh NAME
+.Nm kstash
+.Nd "store the KDC master password in a file"
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Oo Fl e Ar string \*(Ba Xo
+.Fl -enctype= Ns Ar string
+.Xc
+.Oc
+.Oo Fl k Ar file \*(Ba Xo
+.Fl -key-file= Ns Ar file
+.Xc
+.Oc
+.Op Fl -convert-file
+.Op Fl -random-key
+.Op Fl -master-key-fd= Ns Ar fd
+.Op Fl -random-key
+.Op Fl h | Fl -help
+.Op Fl -version
+.Ek
+.Sh DESCRIPTION
+.Nm
+reads the Kerberos master key and stores it in a file that will be
+used by the KDC.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl e Ar string ,
+.Fl -enctype= Ns Ar string
+.Xc
+the encryption type to use, defaults to DES3-CBC-SHA1.
+.It Xo
+.Fl k Ar file ,
+.Fl -key-file= Ns Ar file
+.Xc
+the name of the master key file.
+.It Xo
+.Fl -convert-file
+.Xc
+don't ask for a new master key, just read an old master key file, and
+write it back in the new keyfile format.
+.It Xo
+.Fl -random-key
+.Xc
+generate a random master key.
+.It Xo
+.Fl -master-key-fd= Ns Ar fd
+.Xc
+filedescriptor to read passphrase from, if not specified the
+passphrase will be read from the terminal.
+.El
+.\".Sh ENVIRONMENT
+.Sh FILES
+.Pa /var/heimdal/m-key
+is the default keyfile if no other keyfile is specified.
+The format of a Heimdal master key is the same as a keytab, so
+.Nm ktutil
+list can be used to list the content of the file.
+.\".Sh EXAMPLES
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr kdc 8
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/src/kerberosV/src/kdc/kstash.c b/src/kerberosV/src/kdc/kstash.c
new file mode 100644 (file)
index 0000000..4e12e68
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "headers.h"
+
+RCSID("$KTH: kstash.c,v 1.18 2005/01/17 13:40:08 lha Exp $");
+
+krb5_context context;
+
+static const char *keyfile = HDB_DB_DIR "/m-key";
+static int convert_flag;
+static int help_flag;
+static int version_flag;
+
+static int master_key_fd = -1;
+static int random_key_flag;
+
+static const char *enctype_str = "des3-cbc-sha1";
+
+static struct getargs args[] = {
+    { "enctype", 'e', arg_string, &enctype_str, "encryption type" },
+    { "key-file", 'k', arg_string, &keyfile, "master key file", "file" },
+    { "convert-file", 0, arg_flag, &convert_flag, 
+      "just convert keyfile to new format" },
+    { "master-key-fd", 0, arg_integer, &master_key_fd, 
+      "filedescriptor to read passphrase from", "fd" },
+    { "random-key", 0, arg_flag, &random_key_flag, "generate a random master key" },
+    { "help", 'h', arg_flag, &help_flag },
+    { "version", 0, arg_flag, &version_flag }
+};
+
+int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    char buf[1024];
+    krb5_error_code ret;
+    
+    krb5_enctype enctype;
+
+    hdb_master_key mkey;
+    
+    krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (master_key_fd != -1 && random_key_flag)
+       krb5_errx(context, 1, "random-key and master-key-fd "
+                 "is mutual exclusive");
+
+    ret = krb5_string_to_enctype(context, enctype_str, &enctype);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_string_to_enctype");
+
+    ret = hdb_read_master_key(context, keyfile, &mkey);
+    if(ret && ret != ENOENT)
+       krb5_err(context, 1, ret, "reading master key from %s", keyfile);
+
+    if (convert_flag) {
+       if (ret)
+           krb5_err(context, 1, ret, "reading master key from %s", keyfile);
+    } else {
+       krb5_keyblock key;
+       krb5_salt salt;
+       salt.salttype = KRB5_PW_SALT;
+       /* XXX better value? */
+       salt.saltvalue.data = NULL;
+       salt.saltvalue.length = 0;
+       if (random_key_flag) {
+           ret = krb5_generate_random_keyblock(context, enctype, &key);
+           if (ret)
+               krb5_err(context, 1, ret, "krb5_generate_random_keyblock");
+
+       } else {
+           if(master_key_fd != -1) {
+               ssize_t n;
+               n = read(master_key_fd, buf, sizeof(buf));
+               if(n <= 0)
+                   krb5_err(context, 1, errno, "failed to read passphrase");
+               buf[n] = '\0';
+               buf[strcspn(buf, "\r\n")] = '\0';
+               
+           } else {
+               if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Master key: ", 1))
+                   exit(1);
+           }
+           krb5_string_to_key_salt(context, enctype, buf, salt, &key);
+       }
+       ret = hdb_add_master_key(context, &key, &mkey);
+       
+       krb5_free_keyblock_contents(context, &key);
+
+    }
+    
+    {
+       char *new, *old;
+       asprintf(&old, "%s.old", keyfile);
+       asprintf(&new, "%s.new", keyfile);
+       if(unlink(new) < 0 && errno != ENOENT) {
+           ret = errno;
+           goto out;
+       }
+       krb5_warnx(context, "writing key to `%s'", keyfile);
+       ret = hdb_write_master_key(context, new, mkey);
+       if(ret)
+           unlink(new);
+       else {
+           unlink(old);
+           if(link(keyfile, old) < 0 && errno != ENOENT) {
+               ret = errno;
+               unlink(new);
+           } else if(rename(new, keyfile) < 0) {
+               ret = errno;
+           }
+       }
+    out:
+       free(old);
+       free(new);
+       if(ret)
+           krb5_warn(context, errno, "writing master key file");
+    }
+
+    hdb_free_master_key(context, mkey);
+
+    exit(ret != 0);
+}
diff --git a/src/kerberosV/src/kdc/log.c b/src/kerberosV/src/kdc/log.c
new file mode 100644 (file)
index 0000000..36b1a71
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1997, 1998, 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+RCSID("$KTH: log.c,v 1.14 2002/08/19 12:17:49 joda Exp $");
+
+static krb5_log_facility *logf;
+
+void
+kdc_openlog(void)
+{
+    char **s = NULL, **p;
+    krb5_initlog(context, "kdc", &logf);
+    s = krb5_config_get_strings(context, NULL, "kdc", "logging", NULL);
+    if(s == NULL)
+       s = krb5_config_get_strings(context, NULL, "logging", "kdc", NULL);
+    if(s){
+       for(p = s; *p; p++)
+           krb5_addlog_dest(context, logf, *p);
+       krb5_config_free_strings(s);
+    }else
+       krb5_addlog_dest(context, logf, DEFAULT_LOG_DEST);
+    krb5_set_warn_dest(context, logf);
+}
+
+char*
+kdc_log_msg_va(int level, const char *fmt, va_list ap)
+{
+    char *msg;
+    krb5_vlog_msg(context, logf, &msg, level, fmt, ap);
+    return msg;
+}
+
+char*
+kdc_log_msg(int level, const char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    va_start(ap, fmt);
+    s = kdc_log_msg_va(level, fmt, ap);
+    va_end(ap);
+    return s;
+}
+
+void
+kdc_log(int level, const char *fmt, ...)
+{
+    va_list ap;
+    char *s;
+    va_start(ap, fmt);
+    s = kdc_log_msg_va(level, fmt, ap);
+    if(s) free(s);
+    va_end(ap);
+}
diff --git a/src/kerberosV/src/kdc/main.c b/src/kerberosV/src/kdc/main.c
new file mode 100644 (file)
index 0000000..dbc0076
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+RCSID("$KTH: main.c,v 1.31 2005/06/14 00:13:11 lha Exp $");
+
+volatile sig_atomic_t exit_flag = 0;
+krb5_context context;
+
+extern int detach_from_console;
+
+static RETSIGTYPE
+sigterm(int sig)
+{
+    exit_flag = sig;
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    
+    ret = krb5_init_context(&context);
+    if (ret == KRB5_CONFIG_BADFORMAT)
+       errx (1, "krb5_init_context failed to parse configuration file");
+    else if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    configure(argc, argv);
+
+    if(databases == NULL) {
+       db = malloc(sizeof(*db));
+       num_db = 1;
+       ret = hdb_create(context, &db[0], NULL);
+       if(ret)
+           krb5_err(context, 1, ret, "hdb_create %s", HDB_DEFAULT_DB);
+       ret = hdb_set_master_keyfile(context, db[0], NULL);
+       if (ret)
+           krb5_err(context, 1, ret, "hdb_set_master_keyfile");
+    } else {
+       struct dbinfo *d;
+       int i;
+       /* count databases */
+       for(d = databases, i = 0; d; d = d->next, i++);
+       db = malloc(i * sizeof(*db));
+       for(d = databases, num_db = 0; d; d = d->next, num_db++) {
+           ret = hdb_create(context, &db[num_db], d->dbname);
+           if(ret)
+               krb5_err(context, 1, ret, "hdb_create %s", d->dbname);
+           ret = hdb_set_master_keyfile(context, db[num_db], d->mkey_file);
+           if (ret)
+               krb5_err(context, 1, ret, "hdb_set_master_keyfile");
+       }
+    }
+
+#ifdef HAVE_SIGACTION
+    {
+       struct sigaction sa;
+
+       sa.sa_flags = 0;
+       sa.sa_handler = sigterm;
+       sigemptyset(&sa.sa_mask);
+
+       sigaction(SIGINT, &sa, NULL);
+       sigaction(SIGTERM, &sa, NULL);
+       sigaction(SIGXCPU, &sa, NULL);
+
+       sa.sa_handler = SIG_IGN;
+       sigaction(SIGPIPE, &sa, NULL);
+    }
+#else
+    signal(SIGINT, sigterm);
+    signal(SIGTERM, sigterm);
+    signal(SIGXCPU, sigterm);
+    signal(SIGPIPE, SIG_IGN);
+#endif
+    if (detach_from_console)
+       daemon(0, 0);
+    pidfile(NULL);
+    loop();
+    krb5_free_context(context);
+    return 0;
+}
diff --git a/src/kerberosV/src/kdc/misc.c b/src/kerberosV/src/kdc/misc.c
new file mode 100644 (file)
index 0000000..61c2e9c
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+RCSID("$KTH: misc.c,v 1.23 2003/09/19 00:16:57 lha Exp $");
+
+struct timeval now;
+
+krb5_error_code
+db_fetch(krb5_principal principal, hdb_entry **h)
+{
+    hdb_entry *ent;
+    krb5_error_code ret = HDB_ERR_NOENTRY;
+    int i;
+
+    ent = malloc (sizeof (*ent));
+    if (ent == NULL)
+       return ENOMEM;
+    ent->principal = principal;
+
+    for(i = 0; i < num_db; i++) {
+       ret = db[i]->hdb_open(context, db[i], O_RDONLY, 0);
+       if (ret) {
+           kdc_log(0, "Failed to open database: %s", 
+                   krb5_get_err_text(context, ret));
+           continue;
+       }
+       ret = db[i]->hdb_fetch(context, db[i], HDB_F_DECRYPT, ent);
+       db[i]->hdb_close(context, db[i]);
+       if(ret == 0) {
+           *h = ent;
+           return 0;
+       }
+    }
+    free(ent);
+    return ret;
+}
+
+void
+free_ent(hdb_entry *ent)
+{
+    hdb_free_entry (context, ent);
+    free (ent);
+}
+
diff --git a/src/kerberosV/src/kdc/mit_dump.c b/src/kerberosV/src/kdc/mit_dump.c
new file mode 100644 (file)
index 0000000..623333a
--- /dev/null
@@ -0,0 +1,371 @@
+/*
+ * Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "hprop.h"
+
+RCSID("$KTH: mit_dump.c,v 1.5 2005/06/02 09:55:43 lha Exp $");
+
+/*
+can have any number of princ stanzas.
+format is as follows (only \n indicates newlines)
+princ\t%d\t (%d is KRB5_KDB_V1_BASE_LENGTH, always 38)
+%d\t (strlen of principal e.g. shadow/foo@ANDREW.CMU.EDU)
+%d\t (number of tl_data)
+%d\t (number of key data, e.g. how many keys for this user)
+%d\t (extra data length) 
+%s\t (principal name)
+%d\t (attributes)
+%d\t (max lifetime, seconds)
+%d\t (max renewable life, seconds)
+%d\t (expiration, seconds since epoch or 2145830400 for never)
+%d\t (password expiration, seconds, 0 for never) 
+%d\t (last successful auth, seconds since epoch)
+%d\t (last failed auth, per above)
+%d\t (failed auth count)
+foreach tl_data 0 to number of tl_data - 1 as above
+  %d\t%d\t (data type, data length)
+  foreach tl_data 0 to length-1
+    %02x (tl data contents[element n])
+  except if tl_data length is 0
+    %d (always -1)
+  \t
+foreach key 0 to number of keys - 1 as above
+  %d\t%d\t (key data version, kvno)
+  foreach version 0 to key data version - 1 (a key or a salt)
+    %d\t%d\t(data type for this key, data length for this key)
+    foreach key data length 0 to length-1
+      %02x (key data contents[element n])
+    except if key_data length is 0
+      %d (always -1)
+    \t    
+foreach extra data length 0 to length - 1
+  %02x (extra data part)
+unless no extra data
+  %d (always -1)
+;\n
+
+*/
+
+static int
+hex_to_octet_string(const char *ptr, krb5_data *data)
+{
+    int i;
+    unsigned int v;
+    for(i = 0; i < data->length; i++) {
+       if(sscanf(ptr + 2 * i, "%02x", &v) != 1)
+           return -1;
+       ((unsigned char*)data->data)[i] = v;
+    }
+    return 2 * i;
+}
+
+static char *
+nexttoken(char **p)
+{
+    char *q;
+    do {
+       q = strsep(p, " \t");
+    } while(q && *q == '\0');
+    return q;
+}
+
+static size_t
+getdata(char **p, unsigned char *buf, size_t len)
+{
+    size_t i;
+    int v;
+    char *q = nexttoken(p);
+    i = 0;
+    while(*q && i < len) {
+       if(sscanf(q, "%02x", &v) != 1)
+           break;
+       buf[i++] = v;
+       q += 2;
+    }
+    return i;
+}
+
+static int
+getint(char **p)
+{
+    int val;
+    char *q = nexttoken(p);
+    sscanf(q, "%d", &val);
+    return val;
+}
+
+#include <kadm5/admin.h>
+
+static void
+attr_to_flags(unsigned attr, HDBFlags *flags)
+{
+    flags->postdate =          !(attr & KRB5_KDB_DISALLOW_POSTDATED);
+    flags->forwardable =       !(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
+    flags->initial =          !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
+    flags->renewable =         !(attr & KRB5_KDB_DISALLOW_RENEWABLE);
+    flags->proxiable =         !(attr & KRB5_KDB_DISALLOW_PROXIABLE);
+    /* DUP_SKEY */
+    flags->invalid =          !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
+    flags->require_preauth =   !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
+    /* HW_AUTH */
+    flags->server =            !(attr & KRB5_KDB_DISALLOW_SVR);
+    flags->change_pw =                !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
+    flags->client =            1; /* XXX */
+}
+
+#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
+
+static krb5_error_code
+fix_salt(krb5_context context, hdb_entry *ent, int key_num)
+{
+    krb5_error_code ret;
+    Salt *salt = ent->keys.val[key_num].salt;
+    /* fix salt type */
+    switch((int)salt->type) {
+    case KRB5_KDB_SALTTYPE_NORMAL:
+       salt->type = KRB5_PADATA_PW_SALT;
+       break;
+    case KRB5_KDB_SALTTYPE_V4:
+       krb5_data_free(&salt->salt);
+       salt->type = KRB5_PADATA_PW_SALT;
+       break;
+    case KRB5_KDB_SALTTYPE_NOREALM:
+    {
+       size_t len;
+       int i;
+       krb5_error_code ret;
+       char *p;
+           
+       len = 0;
+       for (i = 0; i < ent->principal->name.name_string.len; ++i)
+           len += strlen(ent->principal->name.name_string.val[i]);
+       ret = krb5_data_alloc (&salt->salt, len);
+       if (ret)
+           return ret;
+       p = salt->salt.data;
+       for (i = 0; i < ent->principal->name.name_string.len; ++i) {
+           memcpy (p,
+                   ent->principal->name.name_string.val[i],
+                   strlen(ent->principal->name.name_string.val[i]));
+           p += strlen(ent->principal->name.name_string.val[i]);
+       }
+
+       salt->type = KRB5_PADATA_PW_SALT;
+       break;
+    }
+    case KRB5_KDB_SALTTYPE_ONLYREALM:
+       krb5_data_free(&salt->salt);
+       ret = krb5_data_copy(&salt->salt, 
+                            ent->principal->realm, 
+                            strlen(ent->principal->realm));
+       if(ret)
+           return ret;
+       salt->type = KRB5_PADATA_PW_SALT;
+       break;
+    case KRB5_KDB_SALTTYPE_SPECIAL:
+       salt->type = KRB5_PADATA_PW_SALT;
+       break;
+    case KRB5_KDB_SALTTYPE_AFS3:
+       krb5_data_free(&salt->salt);
+       ret = krb5_data_copy(&salt->salt, 
+                      ent->principal->realm, 
+                      strlen(ent->principal->realm));
+       if(ret)
+           return ret;
+       salt->type = KRB5_PADATA_AFS3_SALT;
+       break;
+    default:
+       abort();
+    }
+    return 0;
+}
+
+int
+mit_prop_dump(void *arg, const char *file)
+{
+    krb5_error_code ret;
+    char buf [1024];
+    FILE *f;
+    int lineno = 0;
+    struct hdb_entry ent;
+
+    struct prop_data *pd = arg;
+
+    f = fopen(file, "r");
+    if(f == NULL)
+       return errno;
+    
+    while(fgets(buf, sizeof(buf), f)) {
+       char *p = buf, *q;
+
+       int i;
+
+       int num_tl_data;
+       int num_key_data;
+       int extra_data_length;
+       int attributes;
+
+       int tmp;
+
+       lineno++;
+
+       memset(&ent, 0, sizeof(ent));
+
+       q = nexttoken(&p);
+       if(strcmp(q, "kdb5_util") == 0) {
+           int major;
+           q = nexttoken(&p); /* load_dump */
+           if(strcmp(q, "load_dump"))
+               errx(1, "line %d: unknown version", lineno);
+           q = nexttoken(&p); /* load_dump */
+           if(strcmp(q, "version"))
+               errx(1, "line %d: unknown version", lineno);
+           q = nexttoken(&p); /* x.0 */
+           if(sscanf(q, "%d", &major) != 1)
+               errx(1, "line %d: unknown version", lineno);
+           if(major != 4)
+               errx(1, "unknown dump file format, got %d, expected 4", major);
+           continue;
+       } else if(strcmp(q, "princ") != 0) {
+           warnx("line %d: not a principal", lineno);
+           continue;
+       }
+       tmp = getint(&p);
+       if(tmp != 38) {
+           warnx("line %d: bad base length %d != 38", lineno, tmp);
+           continue;
+       }
+       q = nexttoken(&p); /* length of principal */
+       num_tl_data = getint(&p); /* number of tl-data */
+       num_key_data = getint(&p); /* number of key-data */
+       extra_data_length = getint(&p);  /* length of extra data */
+       q = nexttoken(&p); /* principal name */
+       krb5_parse_name(pd->context, q, &ent.principal);
+       attributes = getint(&p); /* attributes */
+       attr_to_flags(attributes, &ent.flags);
+       tmp = getint(&p); /* max life */
+       if(tmp != 0) {
+           ALLOC(ent.max_life);
+           *ent.max_life = tmp;
+       }
+       tmp = getint(&p); /* max renewable life */
+       if(tmp != 0) {
+           ALLOC(ent.max_renew);
+           *ent.max_renew = tmp;
+       }
+       tmp = getint(&p); /* expiration */
+       if(tmp != 0 && tmp != 2145830400) {
+           ALLOC(ent.valid_end);
+           *ent.valid_end = tmp;
+       }
+       tmp = getint(&p); /* pw expiration */
+       if(tmp != 0) {
+           ALLOC(ent.pw_end);
+           *ent.pw_end = tmp;
+       }
+       q = nexttoken(&p); /* last auth */
+       q = nexttoken(&p); /* last failed auth */
+       q = nexttoken(&p); /* fail auth count */
+       for(i = 0; i < num_tl_data; i++) {
+           unsigned long val;
+           int tl_type, tl_length;
+           unsigned char *buf;
+           krb5_principal princ;
+
+           tl_type = getint(&p); /* data type */
+           tl_length = getint(&p); /* data length */
+
+#define mit_KRB5_TL_LAST_PWD_CHANGE    1
+#define mit_KRB5_TL_MOD_PRINC          2
+           switch(tl_type) {
+           case mit_KRB5_TL_MOD_PRINC:
+               buf = malloc(tl_length);
+               getdata(&p, buf, tl_length); /* data itself */
+               val = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24);
+               ret = krb5_parse_name(pd->context, (char *)buf + 4, &princ);
+               free(buf);
+               ALLOC(ent.modified_by);
+               ent.modified_by->time = val;
+               ent.modified_by->principal = princ;
+               break;
+           default:
+               nexttoken(&p);
+               break;
+           }
+       }
+       ALLOC_SEQ(&ent.keys, num_key_data);
+       for(i = 0; i < num_key_data; i++) {
+           int key_versions;
+           key_versions = getint(&p); /* key data version */
+           ent.kvno = getint(&p); /* XXX kvno */
+           
+           ALLOC(ent.keys.val[i].mkvno);
+           *ent.keys.val[i].mkvno = 0;
+           
+           /* key version 0 -- actual key */
+           ent.keys.val[i].key.keytype = getint(&p); /* key type */
+           tmp = getint(&p); /* key length */
+           /* the first two bytes of the key is the key length --
+              skip it */
+           krb5_data_alloc(&ent.keys.val[i].key.keyvalue, tmp - 2);
+           q = nexttoken(&p); /* key itself */
+           hex_to_octet_string(q + 4, &ent.keys.val[i].key.keyvalue);
+
+           if(key_versions > 1) {
+               /* key version 1 -- optional salt */
+               ALLOC(ent.keys.val[i].salt);
+               ent.keys.val[i].salt->type = getint(&p); /* salt type */
+               tmp = getint(&p); /* salt length */
+               if(tmp > 0) {
+                   krb5_data_alloc(&ent.keys.val[i].salt->salt, tmp - 2);
+                   q = nexttoken(&p); /* salt itself */
+                   hex_to_octet_string(q + 4, &ent.keys.val[i].salt->salt);
+               } else {
+                   ent.keys.val[i].salt->salt.length = 0;
+                   ent.keys.val[i].salt->salt.data = NULL;
+                   tmp = getint(&p);   /* -1, if no data. */
+               }
+               fix_salt(pd->context, &ent, i);
+           }
+       }
+       q = nexttoken(&p); /* extra data */
+       v5_prop(pd->context, NULL, &ent, arg);
+    }
+    fclose(f);
+    return 0;
+}
diff --git a/src/kerberosV/src/kdc/pkinit.c b/src/kerberosV/src/kdc/pkinit.c
new file mode 100644 (file)
index 0000000..e20f03d
--- /dev/null
@@ -0,0 +1,1598 @@
+/*
+ * Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kdc_locl.h"
+
+RCSID("$KTH: pkinit.c,v 1.32 2005/06/11 00:42:20 lha Exp $");
+
+#ifdef PKINIT
+
+#include <heim_asn1.h>
+#include <rfc2459_asn1.h>
+#include <cms_asn1.h>
+#include <pkinit_asn1.h>
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/bn.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+
+int enable_pkinit = 0;
+int enable_pkinit_princ_in_cert = 0;
+
+/* XXX copied from lib/krb5/pkinit.c */
+struct krb5_pk_identity {
+    EVP_PKEY *private_key;
+    STACK_OF(X509) *cert;
+    STACK_OF(X509) *trusted_certs;
+    STACK_OF(X509_CRL) *crls;
+    ENGINE *engine;
+};
+
+/* XXX copied from lib/krb5/pkinit.c */
+struct krb5_pk_cert {
+    X509 *cert;
+};
+
+enum pkinit_type {
+    PKINIT_COMPAT_WIN2K = 1,
+    PKINIT_COMPAT_19 = 2,
+    PKINIT_COMPAT_25 = 3
+};
+
+struct pk_client_params {
+    enum pkinit_type type;
+    BIGNUM *dh_public_key;
+    struct krb5_pk_cert *certificate;
+    unsigned nonce;
+    DH *dh;
+    EncryptionKey reply_key;
+};
+
+struct pk_principal_mapping {
+    unsigned int len;
+    struct pk_allowed_princ {
+       krb5_principal principal;
+       char *subject;
+    } *val;
+};
+
+/* XXX copied from lib/krb5/pkinit.c */
+#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R)                     \
+{                                                                      \
+  unsigned char *p;                                                    \
+  (BL) = i2d_##T((S), NULL);                                           \
+  if ((BL) <= 0) {                                                     \
+     (R) = EINVAL;                                                     \
+  } else {                                                             \
+    (B) = malloc((BL));                                                        \
+    if ((B) == NULL) {                                                 \
+       (R) = ENOMEM;                                                   \
+    } else {                                                           \
+        p = (B);                                                       \
+        (R) = 0;                                                       \
+        (BL) = i2d_##T((S), &p);                                       \
+        if ((BL) <= 0) {                                               \
+           free((B));                                                          \
+           (R) = ASN1_OVERRUN;                                         \
+        }                                                              \
+    }                                                                  \
+  }                                                                    \
+}
+
+static struct krb5_pk_identity *kdc_identity;
+static struct pk_principal_mapping principal_mappings;
+
+/*
+ *
+ */
+
+static krb5_error_code
+pk_check_pkauthenticator_win2k(krb5_context context,
+                              PKAuthenticator_Win2k *a,
+                              KDC_REQ *req)
+{
+    krb5_timestamp now;
+
+    krb5_timeofday (context, &now);
+
+    /* XXX cusec */
+    if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {
+       krb5_clear_error_string(context);
+       return KRB5KRB_AP_ERR_SKEW;
+    }
+    return 0;
+}
+
+static krb5_error_code
+pk_check_pkauthenticator_19(krb5_context context,
+                           PKAuthenticator_19 *a,
+                           KDC_REQ *req)
+{
+    u_char *buf = NULL;
+    size_t buf_size;
+    krb5_error_code ret;
+    size_t len;
+    krb5_timestamp now;
+
+    krb5_timeofday (context, &now);
+
+    /* XXX cusec */
+    if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {
+       krb5_clear_error_string(context);
+       return KRB5KRB_AP_ERR_SKEW;
+    }
+
+    if (a->paChecksum.cksumtype != CKSUMTYPE_RSA_MD5 &&
+       a->paChecksum.cksumtype != CKSUMTYPE_SHA1)
+    {
+       krb5_clear_error_string(context);
+       ret = KRB5KRB_ERR_GENERIC;
+    }
+
+    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret);
+    if (ret) {
+       krb5_clear_error_string(context);
+       return ret;
+    }
+    if (buf_size != len)
+       krb5_abortx(context, "Internal error in ASN.1 encoder");
+
+    ret = krb5_verify_checksum(context, NULL, 0, buf, len,
+                              &a->paChecksum);
+    if (ret)
+       krb5_clear_error_string(context);
+
+    free(buf);
+    return ret;
+}
+
+static krb5_error_code
+pk_check_pkauthenticator(krb5_context context,
+                        PKAuthenticator *a,
+                        KDC_REQ *req)
+{
+    u_char *buf = NULL;
+    size_t buf_size;
+    krb5_error_code ret;
+    size_t len;
+    krb5_timestamp now;
+    Checksum checksum;
+
+    krb5_timeofday (context, &now);
+
+    /* XXX cusec */
+    if (a->ctime == 0 || abs(a->ctime - now) > context->max_skew) {
+       krb5_clear_error_string(context);
+       return KRB5KRB_AP_ERR_SKEW;
+    }
+
+    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, &req->req_body, &len, ret);
+    if (ret) {
+       krb5_clear_error_string(context);
+       return ret;
+    }
+    if (buf_size != len)
+       krb5_abortx(context, "Internal error in ASN.1 encoder");
+
+    ret = krb5_create_checksum(context,
+                              NULL,
+                              0,
+                              CKSUMTYPE_SHA1,
+                              buf,
+                              len,
+                              &checksum);
+    free(buf);
+    if (ret) {
+       krb5_clear_error_string(context);
+       return ret;
+    }
+       
+    if (a->paChecksum.length != checksum.checksum.length ||
+       memcmp(a->paChecksum.data, checksum.checksum.data, 
+              checksum.checksum.length) != 0)
+    {
+       krb5_clear_error_string(context);
+       ret = KRB5KRB_ERR_GENERIC;
+    }
+    free_Checksum(&checksum);
+
+    return ret;
+}
+
+static krb5_error_code
+pk_encrypt_key(krb5_context context,
+              krb5_keyblock *key,
+               EVP_PKEY *public_key,
+              krb5_data *encrypted_key,
+              const heim_oid **oid)
+{
+    krb5_error_code ret;
+
+    encrypted_key->length = EVP_PKEY_size(public_key);
+
+    if (encrypted_key->length < key->keyvalue.length + 11) { /* XXX */
+       krb5_set_error_string(context, "pkinit: encrypted key too long");
+       return KRB5KRB_ERR_GENERIC;
+    }
+
+    encrypted_key->data = malloc(encrypted_key->length);
+    if (encrypted_key->data == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ret = EVP_PKEY_encrypt(encrypted_key->data, 
+                          key->keyvalue.data,
+                          key->keyvalue.length,
+                          public_key);
+    if (ret < 0) {
+       free(encrypted_key->data);
+       krb5_set_error_string(context, "Can't encrypt key: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       return KRB5KRB_ERR_GENERIC;
+    }
+    if (encrypted_key->length != ret)
+       krb5_abortx(context, "size of EVP_PKEY_size is not the "
+                   "size of the output");
+
+    *oid = oid_id_pkcs1_rsaEncryption();
+
+    return 0;
+}
+
+void
+pk_free_client_param(krb5_context context, pk_client_params *client_params)
+{
+    if (client_params->certificate)
+       _krb5_pk_cert_free(client_params->certificate);
+    if (client_params->dh)
+       DH_free(client_params->dh);
+    if (client_params->dh_public_key)
+       BN_free(client_params->dh_public_key);
+    krb5_free_keyblock_contents(context, &client_params->reply_key);
+    memset(client_params, 0, sizeof(*client_params));
+    free(client_params);
+}
+
+static krb5_error_code
+check_dh_params(DH *dh)
+{
+    /* XXX check the DH parameters come from 1st or 2nd Oeakley Group */
+    return 0;
+}
+
+static krb5_error_code
+generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
+                     krb5_enctype enctype, krb5_keyblock *reply_key)
+{
+    unsigned char *dh_gen_key = NULL;
+    krb5_keyblock key;
+    int dh_gen_keylen;
+    krb5_error_code ret;
+
+    memset(&key, 0, sizeof(key));
+
+    dh_gen_key = malloc(DH_size(client_params->dh));
+    if (dh_gen_key == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    if (!DH_generate_key(client_params->dh)) {
+       krb5_set_error_string(context, "Can't generate Diffie-Hellman "
+                             "keys (%s)",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+    if (client_params->dh_public_key == NULL) {
+       krb5_set_error_string(context, "dh_public_key");
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+
+    dh_gen_keylen = DH_compute_key(dh_gen_key, 
+                                  client_params->dh_public_key,
+                                  client_params->dh);
+    if (dh_gen_keylen == -1) {
+       krb5_set_error_string(context, "Can't compute Diffie-Hellman key (%s)",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+
+    ret = krb5_random_to_key(context, enctype, 
+                            dh_gen_key, dh_gen_keylen, &key);
+
+    if (ret) {
+       krb5_set_error_string(context, 
+                             "pkinit - can't create key from DH key");
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+    ret = krb5_copy_keyblock_contents(context, &key, reply_key);
+
+ out:
+    if (dh_gen_key)
+       free(dh_gen_key);
+    if (key.keyvalue.data)
+       krb5_free_keyblock_contents(context, &key);
+
+    return ret;
+}
+
+static BIGNUM *
+integer_to_BN(krb5_context context, const char *field, heim_integer *f)
+{
+    BIGNUM *bn;
+
+    bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL);
+    if (bn == NULL) {
+       krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field);
+       return NULL;
+    }
+    bn->neg = f->negative;
+    return bn;
+}
+
+static krb5_error_code
+get_dh_param(krb5_context context, SubjectPublicKeyInfo *dh_key_info,
+            pk_client_params *client_params)
+{
+    DomainParameters dhparam;
+    DH *dh = NULL;
+    krb5_error_code ret;
+    int dhret;
+
+    memset(&dhparam, 0, sizeof(dhparam));
+
+    if (heim_oid_cmp(&dh_key_info->algorithm.algorithm, oid_id_dhpublicnumber())) {
+       krb5_set_error_string(context,
+                             "PKINIT invalid oid in clientPublicValue");
+       return KRB5_BADMSGTYPE;
+    }
+
+    if (dh_key_info->algorithm.parameters == NULL) {
+       krb5_set_error_string(context, "PKINIT missing algorithm parameter "
+                             "in clientPublicValue");
+       return KRB5_BADMSGTYPE;
+    }
+
+    ret = decode_DomainParameters(dh_key_info->algorithm.parameters->data,
+                                 dh_key_info->algorithm.parameters->length,
+                                 &dhparam,
+                                 NULL);
+    if (ret) {
+       krb5_set_error_string(context, "Can't decode algorithm "
+                             "parameters in clientPublicValue");
+       goto out;
+    }
+
+    dh = DH_new();
+    if (dh == NULL) {
+       krb5_set_error_string(context, "Cannot create DH structure (%s)",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = KRB5_BADMSGTYPE;
+    dh->p = integer_to_BN(context, "DH prime", &dhparam.p);
+    if (dh->p == NULL)
+       goto out;
+    dh->g = integer_to_BN(context, "DH base", &dhparam.g);
+    if (dh->g == NULL)
+       goto out;
+    dh->q = integer_to_BN(context, "DH p-1 factor", &dhparam.q);
+    if (dh->g == NULL)
+       goto out;
+
+    {
+       heim_integer glue;
+       glue.data = dh_key_info->subjectPublicKey.data;
+       glue.length = dh_key_info->subjectPublicKey.length;
+
+       client_params->dh_public_key = integer_to_BN(context,
+                                                    "subjectPublicKey",
+                                                    &glue);
+       if (client_params->dh_public_key == NULL) {
+           krb5_clear_error_string(context);
+           goto out;
+       }
+    }
+
+    if (DH_check(dh, &dhret) != 1) {
+       krb5_set_error_string(context, "PKINIT DH data not ok: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = KRB5_KDC_ERR_KEY_SIZE;
+       goto out;
+    }
+
+    client_params->dh = dh;
+    dh = NULL;
+    ret = 0;
+    
+ out:
+    if (dh)
+       DH_free(dh);
+    free_DomainParameters(&dhparam);
+    return ret;
+}
+
+#if 0
+/* 
+ * XXX We only need this function if there are several certs for the
+ * KDC to choose from, and right now, we can't handle that so punt for
+ * now.
+ *
+ * If client has sent a list of CA's trusted by him, make sure our
+ * CA is in the list.
+ *
+ */
+
+static void
+verify_trusted_ca(PA_PK_AS_REQ_19 *r)
+{
+
+    if (r.trustedCertifiers != NULL) {
+       X509_NAME *kdc_issuer;
+       X509 *kdc_cert;
+
+       kdc_cert = sk_X509_value(kdc_identity->cert, 0);
+       kdc_issuer = X509_get_issuer_name(kdc_cert);
+     
+       /* XXX will work for heirarchical CA's ? */
+       /* XXX also serial_number should be compared */
+
+       ret = KRB5_KDC_ERR_KDC_NOT_TRUSTED;
+       for (i = 0; i < r.trustedCertifiers->len; i++) {
+           TrustedCA_19 *ca = &r.trustedCertifiers->val[i];
+
+           switch (ca->element) {
+           case choice_TrustedCA_19_caName: {
+               X509_NAME *name;
+               unsigned char *p;
+
+               p = ca->u.caName.data;
+               name = d2i_X509_NAME(NULL, &p, ca->u.caName.length);
+               if (name == NULL) /* XXX should this be a failure instead ? */
+                   break;
+               if (X509_NAME_cmp(name, kdc_issuer) == 0)
+                   ret = 0;
+               X509_NAME_free(name);
+               break;
+           }
+           case choice_TrustedCA_19_issuerAndSerial:
+               /* IssuerAndSerialNumber issuerAndSerial */
+               break;
+           default:
+               break;
+           }
+           if (ret == 0)
+               break;
+       }
+       if (ret)
+           goto out;
+    }
+}
+#endif /* 0 */
+
+krb5_error_code
+pk_rd_padata(krb5_context context,
+             KDC_REQ *req,
+             PA_DATA *pa,
+            pk_client_params **ret_params)
+{
+    pk_client_params *client_params;
+    krb5_error_code ret;
+    heim_oid eContentType = { 0, NULL };
+    krb5_data eContent = { 0, NULL };
+    krb5_data signed_content = { 0, NULL };
+    const char *type = "unknown type";
+    const heim_oid *pa_contentType;
+
+    *ret_params = NULL;
+    
+    if (!enable_pkinit) {
+       krb5_clear_error_string(context);
+       return 0;
+    }
+
+    client_params = malloc(sizeof(*client_params));
+    if (client_params == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+    memset(client_params, 0, sizeof(*client_params));
+
+    if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
+       PA_PK_AS_REQ_Win2k r;
+       ContentInfo info;
+
+       type = "PK-INIT-Win2k";
+       pa_contentType = oid_id_pkcs7_data();
+
+       ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data,
+                                       pa->padata_value.length,
+                                       &r,
+                                       NULL);
+       if (ret) {
+           krb5_set_error_string(context, "Can't decode "
+                                 "PK-AS-REQ-Win2k: %d", ret);
+           goto out;
+       }
+       
+       ret = decode_ContentInfo(r.signed_auth_pack.data,
+                                r.signed_auth_pack.length, &info, NULL);
+       free_PA_PK_AS_REQ_Win2k(&r);
+       if (ret) {
+           krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret);
+           goto out;
+       }
+
+       if (heim_oid_cmp(&info.contentType, oid_id_pkcs7_signedData())) {
+           krb5_set_error_string(context, "PK-AS-REQ-Win2k invalid content "
+                                 "type oid");
+           free_ContentInfo(&info);
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+       
+       if (info.content == NULL) {
+           krb5_set_error_string(context,
+                                 "PK-AS-REQ-Win2k no signed auth pack");
+           free_ContentInfo(&info);
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+
+       signed_content.data = malloc(info.content->length);
+       if (signed_content.data == NULL) {
+           ret = ENOMEM;
+           free_ContentInfo(&info);
+           krb5_set_error_string(context, "PK-AS-REQ-Win2k out of memory");
+           goto out;
+       }
+       signed_content.length = info.content->length;
+       memcpy(signed_content.data, info.content->data, signed_content.length);
+
+       free_ContentInfo(&info);
+
+    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_19) {
+       PA_PK_AS_REQ_19 r;
+
+       type = "PK-INIT-19";
+       pa_contentType = oid_id_pkauthdata();
+
+       ret = decode_PA_PK_AS_REQ_19(pa->padata_value.data,
+                                    pa->padata_value.length,
+                                    &r,
+                                    NULL);
+       if (ret) {
+           krb5_set_error_string(context, "Can't decode "
+                                 "PK-AS-REQ-19: %d", ret);
+           goto out;
+       }
+       
+       if (heim_oid_cmp(&r.signedAuthPack.contentType, 
+                        oid_id_pkcs7_signedData()))
+       {
+           krb5_set_error_string(context, "PK-AS-REQ-19 invalid content "
+                                 "type oid");
+           free_PA_PK_AS_REQ_19(&r);
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+       
+       if (r.signedAuthPack.content == NULL) {
+           krb5_set_error_string(context, "PK-AS-REQ-19 no signed auth pack");
+           free_PA_PK_AS_REQ_19(&r);
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+
+       signed_content.data = malloc(r.signedAuthPack.content->length);
+       if (signed_content.data == NULL) {
+           ret = ENOMEM;
+           free_PA_PK_AS_REQ_19(&r);
+           krb5_set_error_string(context, "PK-AS-REQ-19 out of memory");
+           goto out;
+       }
+       signed_content.length = r.signedAuthPack.content->length;
+       memcpy(signed_content.data, r.signedAuthPack.content->data,
+              signed_content.length);
+
+       free_PA_PK_AS_REQ_19(&r);
+    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {
+       PA_PK_AS_REQ r;
+       ContentInfo info;
+
+       type = "PK-INIT-25";
+       pa_contentType = oid_id_pkauthdata();
+
+       ret = decode_PA_PK_AS_REQ(pa->padata_value.data,
+                                 pa->padata_value.length,
+                                 &r,
+                                 NULL);
+       if (ret) {
+           krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret);
+           goto out;
+       }
+       
+       ret = decode_ContentInfo(r.signedAuthPack.data,
+                                r.signedAuthPack.length, &info, NULL);
+       if (ret) {
+           krb5_set_error_string(context, "Can't decode PK-AS-REQ: %d", ret);
+           goto out;
+       }
+
+       if (heim_oid_cmp(&info.contentType, oid_id_pkcs7_signedData())) {
+           krb5_set_error_string(context, "PK-AS-REQ invalid content "
+                                 "type oid");
+           free_ContentInfo(&info);
+           free_PA_PK_AS_REQ(&r);
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+       
+       if (info.content == NULL) {
+           krb5_set_error_string(context, "PK-AS-REQ no signed auth pack");
+           free_PA_PK_AS_REQ(&r);
+           free_ContentInfo(&info);
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+
+       signed_content.data = malloc(info.content->length);
+       if (signed_content.data == NULL) {
+           ret = ENOMEM;
+           free_ContentInfo(&info);
+           free_PA_PK_AS_REQ(&r);
+           krb5_set_error_string(context, "PK-AS-REQ out of memory");
+           goto out;
+       }
+       signed_content.length = info.content->length;
+       memcpy(signed_content.data, info.content->data, signed_content.length);
+
+       free_ContentInfo(&info);
+       free_PA_PK_AS_REQ(&r);
+
+    } else { 
+       krb5_clear_error_string(context);
+       ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+       goto out;
+    }
+
+    ret = _krb5_pk_verify_sign(context,
+                              signed_content.data,
+                              signed_content.length,
+                              kdc_identity,
+                              &eContentType,
+                              &eContent,
+                              &client_params->certificate);
+    if (ret)
+       goto out;
+
+    /* Signature is correct, now verify the signed message */
+    if (heim_oid_cmp(&eContentType, pa_contentType)) {
+       krb5_set_error_string(context, "got wrong oid for pkauthdata");
+       ret = KRB5_BADMSGTYPE;
+       goto out;
+    }
+
+    if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
+       AuthPack_Win2k ap;
+
+       ret = decode_AuthPack_Win2k(eContent.data,
+                                   eContent.length,
+                                   &ap,
+                                   NULL);
+       if (ret) {
+           krb5_set_error_string(context, "can't decode AuthPack: %d", ret);
+           goto out;
+       }
+  
+       ret = pk_check_pkauthenticator_win2k(context, 
+                                            &ap.pkAuthenticator,
+                                            req);
+       if (ret) {
+           free_AuthPack_Win2k(&ap);
+           goto out;
+       }
+
+       client_params->type = PKINIT_COMPAT_WIN2K;
+       client_params->nonce = ap.pkAuthenticator.nonce;
+
+       if (ap.clientPublicValue) {
+           krb5_set_error_string(context, "DH not supported for windows");
+           ret = KRB5KRB_ERR_GENERIC;
+           goto out;
+       }
+       free_AuthPack_Win2k(&ap);
+
+    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_19) {
+       AuthPack_19 ap;
+
+       ret = decode_AuthPack_19(eContent.data,
+                                eContent.length,
+                                &ap,
+                                NULL);
+       if (ret) {
+           krb5_set_error_string(context, "can't decode AuthPack: %d", ret);
+           free_AuthPack_19(&ap);
+           goto out;
+       }
+  
+       ret = pk_check_pkauthenticator_19(context, 
+                                         &ap.pkAuthenticator,
+                                         req);
+       if (ret) {
+           free_AuthPack_19(&ap);
+           goto out;
+       }
+
+       client_params->type = PKINIT_COMPAT_19;
+       client_params->nonce = ap.pkAuthenticator.nonce;
+
+       if (ap.clientPublicValue) {
+           ret = get_dh_param(context, ap.clientPublicValue, client_params);
+           if (ret) {
+               free_AuthPack_19(&ap);
+               goto out;
+           }
+       }
+       free_AuthPack_19(&ap);
+    } else if (pa->padata_type == KRB5_PADATA_PK_AS_REQ) {
+       AuthPack ap;
+
+       ret = decode_AuthPack(eContent.data,
+                             eContent.length,
+                             &ap,
+                             NULL);
+       if (ret) {
+           krb5_set_error_string(context, "can't decode AuthPack: %d", ret);
+           free_AuthPack(&ap);
+           goto out;
+       }
+  
+       ret = pk_check_pkauthenticator(context, 
+                                      &ap.pkAuthenticator,
+                                      req);
+       if (ret) {
+           free_AuthPack(&ap);
+           goto out;
+       }
+
+       client_params->type = PKINIT_COMPAT_25;
+       client_params->nonce = ap.pkAuthenticator.nonce;
+
+       if (ap.clientPublicValue) {
+           krb5_set_error_string(context, "PK-INIT, no support for DH");
+           ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP;
+           free_AuthPack(&ap);
+           goto out;
+       }
+       free_AuthPack(&ap);
+    } else
+       krb5_abortx(context, "internal pkinit error");
+
+    /* 
+     * Remaining fields (ie kdcCert and encryptionCert) in the request
+     * are ignored for now.
+     */
+
+    kdc_log(0, "PK-INIT request of type %s", type);
+
+ out:
+
+    if (signed_content.data)
+       free(signed_content.data);
+    krb5_data_free(&eContent);
+    free_oid(&eContentType);
+    if (ret)
+       pk_free_client_param(context, client_params);
+    else
+       *ret_params = client_params;
+    return ret;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
+{
+    integer->length = BN_num_bytes(bn);
+    integer->data = malloc(integer->length);
+    if (integer->data == NULL) {
+       krb5_clear_error_string(context);
+       return ENOMEM;
+    }
+    BN_bn2bin(bn, integer->data);
+    integer->negative = bn->neg;
+    return 0;
+}
+
+static krb5_error_code
+pk_mk_pa_reply_enckey(krb5_context context,
+                     pk_client_params *client_params,
+                     const KDC_REQ *req,
+                     krb5_keyblock *reply_key,
+                     ContentInfo *content_info)
+{
+    KeyTransRecipientInfo *ri;
+    EnvelopedData ed;
+    krb5_error_code ret;
+    krb5_crypto crypto = NULL;
+    krb5_data buf, sd_data, enc_sd_data, iv, params;
+    krb5_keyblock tmp_key;
+    krb5_enctype enveloped_enctype;
+    X509_NAME *issuer_name;
+    heim_integer *serial;
+    size_t size;
+    AlgorithmIdentifier *enc_alg;
+    int i;
+
+    krb5_data_zero(&enc_sd_data);
+    krb5_data_zero(&sd_data);
+    krb5_data_zero(&iv);
+
+    memset(&tmp_key, 0, sizeof(tmp_key));
+    memset(&ed, 0, sizeof(ed));
+
+    /* default to DES3 if client doesn't tell us */
+    enveloped_enctype = ETYPE_DES3_CBC_NONE_CMS;
+
+    for (i = 0; i < req->req_body.etype.len; i++) {
+       switch(req->req_body.etype.val[i]) {
+       case 15: /* des-ede3-cbc-Env-OID */
+           enveloped_enctype = ETYPE_DES3_CBC_NONE_CMS;
+           break;
+       default:
+           break;
+       }
+    }
+
+    ret = krb5_generate_random_keyblock(context, enveloped_enctype, &tmp_key);
+    if (ret)
+       goto out;
+
+    ret = krb5_crypto_init(context, &tmp_key, 0, &crypto);
+    if (ret)
+       goto out;
+
+
+    ret = krb5_crypto_getblocksize(context, crypto, &iv.length);
+    if (ret)
+       goto out;
+
+    ret = krb5_data_alloc(&iv, iv.length);
+    if (ret) {
+       krb5_set_error_string(context, "malloc out of memory");
+       goto out;
+    }
+
+    krb5_generate_random_block(iv.data, iv.length);
+
+    enc_alg = &ed.encryptedContentInfo.contentEncryptionAlgorithm;
+
+    ret = krb5_enctype_to_oid(context, enveloped_enctype, &enc_alg->algorithm);
+    if (ret)
+       goto out;
+
+    ret = krb5_crypto_set_params(context, crypto, &iv, &params);
+    if (ret)
+       goto out;
+
+    ALLOC(enc_alg->parameters);
+    if (enc_alg->parameters == NULL) {
+       krb5_data_free(&params);
+       krb5_set_error_string(context, "malloc out of memory");
+       return ENOMEM;
+    }
+    enc_alg->parameters->data = params.data;
+    enc_alg->parameters->length = params.length;
+
+    if (client_params->type == PKINIT_COMPAT_WIN2K || client_params->type == PKINIT_COMPAT_19 || client_params->type == PKINIT_COMPAT_25) {
+       ReplyKeyPack kp;
+       memset(&kp, 0, sizeof(kp));
+
+       ret = copy_EncryptionKey(reply_key, &kp.replyKey);
+       if (ret) {
+           krb5_clear_error_string(context);
+           goto out;
+       }
+       kp.nonce = client_params->nonce;
+       
+       ASN1_MALLOC_ENCODE(ReplyKeyPack, buf.data, buf.length, &kp, &size,ret);
+       free_ReplyKeyPack(&kp);
+    } else {
+       krb5_abortx(context, "internal pkinit error");
+    }
+    if (ret) {
+       krb5_set_error_string(context, "ASN.1 encoding of ReplyKeyPack "
+                             "failed (%d)", ret);
+       goto out;
+    }
+    if (buf.length != size)
+       krb5_abortx(context, "Internal ASN.1 encoder error");
+
+    /* 
+     * CRL's are not transfered -- should be ?
+     */
+
+    ret = _krb5_pk_create_sign(context,
+                              oid_id_pkrkeydata(),
+                              &buf,
+                              kdc_identity,
+                              &sd_data);
+    krb5_data_free(&buf);
+    if (ret) 
+       goto out;
+
+    ret = krb5_encrypt_ivec(context, crypto, 0, 
+                           sd_data.data, sd_data.length,
+                           &enc_sd_data,
+                           iv.data);
+
+    ALLOC_SEQ(&ed.recipientInfos, 1);
+    if (ed.recipientInfos.val == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ri = &ed.recipientInfos.val[0];
+
+    ri->version = 0;
+    ri->rid.element = choice_CMSIdentifier_issuerAndSerialNumber;
+       
+    issuer_name = X509_get_issuer_name(client_params->certificate->cert);
+    OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, buf.data, buf.length,
+                              issuer_name, ret);
+    if (ret) {
+       krb5_clear_error_string(context);
+       goto out;
+    }
+    ret = decode_Name(buf.data, buf.length,
+                     &ri->rid.u.issuerAndSerialNumber.issuer,
+                     NULL);
+    free(buf.data);
+    if (ret) {
+       krb5_set_error_string(context, "pkinit: failed to parse Name");
+       goto out;
+    }
+
+    serial = &ri->rid.u.issuerAndSerialNumber.serialNumber;
+    {
+       ASN1_INTEGER *isn;
+       BIGNUM *bn;
+
+       isn = X509_get_serialNumber(client_params->certificate->cert);
+       bn = ASN1_INTEGER_to_BN(isn, NULL);
+       if (bn == NULL) {
+           ret = ENOMEM;
+           krb5_clear_error_string(context);
+           goto out;
+       }
+       ret = BN_to_integer(context, bn, serial);
+       BN_free(bn);
+       if (ret) {
+           krb5_clear_error_string(context);
+           goto out;
+       }
+    }
+
+    {
+       const heim_oid *pk_enc_key_oid;
+       krb5_data enc_tmp_key;
+
+       ret = pk_encrypt_key(context, &tmp_key,
+                            X509_get_pubkey(client_params->certificate->cert),
+                            &enc_tmp_key,
+                            &pk_enc_key_oid);
+       if (ret)
+           goto out;
+
+       ri->encryptedKey.length = enc_tmp_key.length;
+       ri->encryptedKey.data = enc_tmp_key.data;
+
+       ret = copy_oid(pk_enc_key_oid, &ri->keyEncryptionAlgorithm.algorithm);
+       if (ret)
+           goto out;
+    }
+
+    /*
+     *
+     */
+
+    ed.version = 0;
+    ed.originatorInfo = NULL;
+
+    ret = copy_oid(oid_id_pkcs7_signedData(), &ed.encryptedContentInfo.contentType);
+    if (ret) {
+       krb5_clear_error_string(context);
+       goto out;
+    }
+
+    ALLOC(ed.encryptedContentInfo.encryptedContent);
+    if (ed.encryptedContentInfo.encryptedContent == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ed.encryptedContentInfo.encryptedContent->data = enc_sd_data.data;
+    ed.encryptedContentInfo.encryptedContent->length = enc_sd_data.length;
+    krb5_data_zero(&enc_sd_data);
+
+    ed.unprotectedAttrs = NULL;
+
+    ASN1_MALLOC_ENCODE(EnvelopedData, buf.data, buf.length, &ed, &size, ret);
+    if (ret) {
+       krb5_set_error_string(context, 
+                             "ASN.1 encoding of EnvelopedData failed (%d)",
+                             ret);
+       goto out;
+    }
+  
+    ret = _krb5_pk_mk_ContentInfo(context,
+                                 &buf,
+                                 oid_id_pkcs7_envelopedData(),
+                                 content_info);
+    krb5_data_free(&buf);
+
+ out:
+    if (crypto)
+       krb5_crypto_destroy(context, crypto);
+    krb5_free_keyblock_contents(context, &tmp_key);
+    krb5_data_free(&enc_sd_data);
+    krb5_data_free(&iv);
+    free_EnvelopedData(&ed);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+pk_mk_pa_reply_dh(krb5_context context,
+                  DH *kdc_dh,
+                 pk_client_params *client_params,
+                  krb5_keyblock *reply_key,
+                 ContentInfo *content_info)
+{
+    ASN1_INTEGER *dh_pub_key = NULL;
+    KDCDHKeyInfo dh_info;
+    krb5_error_code ret;
+    SignedData sd;
+    krb5_data buf, sd_buf;
+    size_t size;
+
+    memset(&dh_info, 0, sizeof(dh_info));
+    memset(&sd, 0, sizeof(sd));
+    krb5_data_zero(&buf);
+    krb5_data_zero(&sd_buf);
+
+    dh_pub_key = BN_to_ASN1_INTEGER(kdc_dh->pub_key, NULL);
+    if (dh_pub_key == NULL) {
+       krb5_set_error_string(context, "BN_to_ASN1_INTEGER() failed (%s)",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = ENOMEM;
+       goto out;
+    }
+
+    OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, buf.data, buf.length, dh_pub_key,
+                              ret);
+    ASN1_INTEGER_free(dh_pub_key);
+    if (ret) {
+       krb5_set_error_string(context, "Encoding of ASN1_INTEGER failed (%s)",
+                             ERR_error_string(ERR_get_error(), NULL));
+       goto out;
+    }
+   
+    dh_info.subjectPublicKey.length = buf.length * 8;
+    dh_info.subjectPublicKey.data = buf.data;
+    
+    dh_info.nonce = client_params->nonce;
+
+    ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size, 
+                      ret);
+    if (ret) {
+       krb5_set_error_string(context, "ASN.1 encoding of "
+                             "KdcDHKeyInfo failed (%d)", ret);
+       goto out;
+    }
+    if (buf.length != size)
+       krb5_abortx(context, "Internal ASN.1 encoder error");
+
+    /* 
+     * Create the SignedData structure and sign the KdcDHKeyInfo
+     * filled in above
+     */
+
+    ret = _krb5_pk_create_sign(context, 
+                              oid_id_pkdhkeydata(),
+                              &buf,
+                              kdc_identity, 
+                              &sd_buf);
+    krb5_data_free(&buf);
+    if (ret)
+       goto out;
+
+    ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(),
+                                 content_info);
+    krb5_data_free(&sd_buf);
+
+ out:
+    free_KDCDHKeyInfo(&dh_info);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code
+pk_mk_pa_reply(krb5_context context,
+              pk_client_params *client_params,
+              const hdb_entry *client,
+              const KDC_REQ *req,
+               krb5_keyblock **reply_key,
+              METHOD_DATA *md)
+{
+    krb5_error_code ret;
+    void *buf;
+    size_t len, size;
+    krb5_enctype enctype;
+    int pa_type;
+    int i;
+
+    if (!enable_pkinit) {
+       krb5_clear_error_string(context);
+       return 0;
+    }
+
+    if (req->req_body.etype.len > 0) {
+       for (i = 0; i < req->req_body.etype.len; i++)
+           if (krb5_enctype_valid(context, req->req_body.etype.val[i]) == 0)
+               break;
+       if (req->req_body.etype.len <= i) {
+           ret = KRB5KRB_ERR_GENERIC;
+           krb5_set_error_string(context,
+                                 "No valid enctype available from client");
+           goto out;
+       }       
+       enctype = req->req_body.etype.val[i];
+    } else
+       enctype = ETYPE_DES3_CBC_SHA1;
+
+    if (client_params->type == PKINIT_COMPAT_25) {
+       PA_PK_AS_REP rep;
+
+       pa_type = KRB5_PADATA_PK_AS_REP;
+
+       memset(&rep, 0, sizeof(rep));
+
+       if (client_params->dh == NULL) {
+           rep.element = choice_PA_PK_AS_REP_encKeyPack;
+           ContentInfo info;
+
+           krb5_generate_random_keyblock(context, enctype, 
+                                         &client_params->reply_key);
+           ret = pk_mk_pa_reply_enckey(context,
+                                       client_params,
+                                       req,
+                                       &client_params->reply_key,
+                                       &info);
+           if (ret) {
+               free_PA_PK_AS_REP(&rep);
+               goto out;
+           }
+           ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data, 
+                              rep.u.encKeyPack.length, &info, &size, 
+                              ret);
+           free_ContentInfo(&info);
+           if (ret) {
+               krb5_set_error_string(context, "encoding of Key ContentInfo "
+                                     "failed %d", ret);
+               free_PA_PK_AS_REP(&rep);
+               goto out;
+           }
+           if (rep.u.encKeyPack.length != size)
+               krb5_abortx(context, "Internal ASN.1 encoder error");
+
+       } else {
+           krb5_set_error_string(context, "DH -25 not implemented");
+           ret = KRB5KRB_ERR_GENERIC;
+       }
+       if (ret) {
+           free_PA_PK_AS_REP(&rep);
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret);
+       free_PA_PK_AS_REP(&rep);
+       if (ret) {
+           krb5_set_error_string(context, "encode PA-PK-AS-REP failed %d",
+                                 ret);
+           goto out;
+       }
+       if (len != size)
+           krb5_abortx(context, "Internal ASN.1 encoder error");
+
+    } else if (client_params->type == PKINIT_COMPAT_19) {
+       PA_PK_AS_REP_19 rep;
+
+       pa_type = KRB5_PADATA_PK_AS_REP_19;
+
+       memset(&rep, 0, sizeof(rep));
+
+       if (client_params->dh == NULL) {
+           rep.element = choice_PA_PK_AS_REP_19_encKeyPack;
+           krb5_generate_random_keyblock(context, enctype, 
+                                         &client_params->reply_key);
+           ret = pk_mk_pa_reply_enckey(context,
+                                       client_params,
+                                       req,
+                                       &client_params->reply_key,
+                                       &rep.u.encKeyPack);
+       } else {
+           rep.element = choice_PA_PK_AS_REP_19_dhSignedData;
+
+           ret = check_dh_params(client_params->dh);
+           if (ret)
+               return ret;
+
+           ret = generate_dh_keyblock(context, client_params, enctype,
+                                      &client_params->reply_key);
+           if (ret)
+               return ret;
+
+           ret = pk_mk_pa_reply_dh(context, client_params->dh,
+                                   client_params, 
+                                   &client_params->reply_key,
+                                   &rep.u.dhSignedData);
+       }
+       if (ret) {
+           free_PA_PK_AS_REP_19(&rep);
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(PA_PK_AS_REP_19, buf, len, &rep, &size, ret);
+       free_PA_PK_AS_REP_19(&rep);
+       if (ret) {
+           krb5_set_error_string(context, 
+                                 "encode PA-PK-AS-REP-19 failed %d", ret);
+           goto out;
+       }
+       if (len != size)
+           krb5_abortx(context, "Internal ASN.1 encoder error");
+    } else if (client_params->type == PKINIT_COMPAT_WIN2K) {
+       PA_PK_AS_REP_Win2k rep;
+
+       pa_type = KRB5_PADATA_PK_AS_REP_19;
+
+       memset(&rep, 0, sizeof(rep));
+
+       if (client_params->dh) {
+           krb5_set_error_string(context, "DH -25 not implemented");
+           ret = KRB5KRB_ERR_GENERIC;
+       } else {
+           rep.element = choice_PA_PK_AS_REP_encKeyPack;
+           ContentInfo info;
+
+           krb5_generate_random_keyblock(context, enctype, 
+                                         &client_params->reply_key);
+           ret = pk_mk_pa_reply_enckey(context,
+                                       client_params,
+                                       req,
+                                       &client_params->reply_key,
+                                       &info);
+           if (ret) {
+               free_PA_PK_AS_REP_Win2k(&rep);
+               goto out;
+           }
+           ASN1_MALLOC_ENCODE(ContentInfo, rep.u.encKeyPack.data, 
+                              rep.u.encKeyPack.length, &info, &size, 
+                              ret);
+           free_ContentInfo(&info);
+           if (ret) {
+               krb5_set_error_string(context, "encoding of Key ContentInfo "
+                                     "failed %d", ret);
+               free_PA_PK_AS_REP_Win2k(&rep);
+               goto out;
+           }
+           if (rep.u.encKeyPack.length != size)
+               krb5_abortx(context, "Internal ASN.1 encoder error");
+
+       }
+       if (ret) {
+           free_PA_PK_AS_REP_Win2k(&rep);
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(PA_PK_AS_REP_Win2k, buf, len, &rep, &size, ret);
+       free_PA_PK_AS_REP_Win2k(&rep);
+       if (ret) {
+           krb5_set_error_string(context, 
+                                 "encode PA-PK-AS-REP-Win2k failed %d", ret);
+           goto out;
+       }
+       if (len != size)
+           krb5_abortx(context, "Internal ASN.1 encoder error");
+
+    } else
+       krb5_abortx(context, "PK-INIT internal error");
+
+
+    ret = krb5_padata_add(context, md, pa_type, buf, len);
+    if (ret) {
+       krb5_set_error_string(context, "failed adding "
+                             "PA-PK-AS-REP-19 %d", ret);
+       free(buf);
+    }
+ out:
+    if (ret == 0)
+       *reply_key = &client_params->reply_key;
+    return ret;
+}
+
+static int
+pk_principal_from_X509(krb5_context context, 
+                      struct krb5_pk_cert *client_cert, 
+                      krb5_principal *principal)
+{
+    krb5_error_code ret;
+    GENERAL_NAMES *gens;
+    GENERAL_NAME *gen;
+    ASN1_OBJECT *obj;
+    int i;
+
+    *principal = NULL;
+
+    obj = OBJ_txt2obj("1.3.6.1.5.2.2",1);
+       
+    gens = X509_get_ext_d2i(client_cert->cert, NID_subject_alt_name, 
+                           NULL, NULL);
+    if (gens == NULL)
+       return 1;
+
+    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+       KRB5PrincipalName kn;
+       size_t len, size;
+       void *p;
+
+       gen = sk_GENERAL_NAME_value(gens, i);
+       if (gen->type != GEN_OTHERNAME)
+           continue;
+
+       if(OBJ_cmp(obj, gen->d.otherName->type_id) != 0) 
+           continue;
+       
+       p = ASN1_STRING_data(gen->d.otherName->value->value.sequence);
+       len = ASN1_STRING_length(gen->d.otherName->value->value.sequence);
+
+       ret = decode_KRB5PrincipalName(p, len, &kn, &size);
+       if (ret) {
+           kdc_log(0, "Decoding kerberos name in certificate failed: %s",
+                   krb5_get_err_text(context, ret));
+           continue;
+       }
+
+       *principal = malloc(sizeof(**principal));
+       if (*principal == NULL) {
+           free_KRB5PrincipalName(&kn);
+           return 1;
+       }
+
+       (*principal)->name = kn.principalName;
+       (*principal)->realm = kn.realm;
+       return 0;
+    }
+    return 1;
+}
+
+
+/* XXX match with issuer too ? */
+
+krb5_error_code
+pk_check_client(krb5_context context,
+                krb5_principal client_princ,
+               const hdb_entry *client,
+                pk_client_params *client_params,
+               char **subject_name)
+{
+    struct krb5_pk_cert *client_cert = client_params->certificate;
+    krb5_principal cert_princ;
+    X509_NAME *name;
+    char *subject = NULL;
+    krb5_error_code ret;
+    krb5_boolean b;
+    int i;
+
+    *subject_name = NULL;
+
+    name = X509_get_subject_name(client_cert->cert);
+    if (name == NULL) {
+       krb5_set_error_string(context, "PKINIT can't get subject name");
+       return ENOMEM;
+    }
+    subject = X509_NAME_oneline(name, NULL, 0);
+    if (subject == NULL) {
+       krb5_set_error_string(context, "PKINIT can't get subject name");
+       return ENOMEM;
+    }
+    *subject_name = strdup(subject);
+    if (*subject_name == NULL) {
+       krb5_set_error_string(context, "out of memory");
+       return ENOMEM;
+    }
+    OPENSSL_free(subject);
+
+    if (enable_pkinit_princ_in_cert) {
+       ret = pk_principal_from_X509(context, client_cert, &cert_princ);
+       if (ret == 0) {
+           b = krb5_principal_compare(context, client_princ, cert_princ);
+           krb5_free_principal(context, cert_princ);
+           if (b == TRUE)
+               return 0;
+       }
+    }
+
+    for (i = 0; i < principal_mappings.len; i++) {
+       b = krb5_principal_compare(context,
+                                  client_princ,
+                                  principal_mappings.val[i].principal);
+       if (b == FALSE)
+           continue;
+       if (strcmp(principal_mappings.val[i].subject, *subject_name) != 0)
+           continue;
+       return 0;
+    }
+    free(*subject_name);
+    *subject_name = NULL;
+    krb5_set_error_string(context, "PKINIT no matching principals");
+    return KRB5_KDC_ERROR_CLIENT_NAME_MISMATCH;
+}
+
+static krb5_error_code
+add_principal_mapping(const char *principal_name, const char * subject)
+{
+   struct pk_allowed_princ *tmp;
+   krb5_principal principal;
+   krb5_error_code ret;
+
+   tmp = realloc(principal_mappings.val,
+                (principal_mappings.len + 1) * sizeof(*tmp));
+   if (tmp == NULL)
+       return ENOMEM;
+   principal_mappings.val = tmp;
+
+   ret = krb5_parse_name(context, principal_name, &principal);
+   if (ret)
+       return ret;
+
+   principal_mappings.val[principal_mappings.len].principal = principal;
+
+   principal_mappings.val[principal_mappings.len].subject = strdup(subject);
+   if (principal_mappings.val[principal_mappings.len].subject == NULL) {
+       krb5_free_principal(context, principal);
+       return ENOMEM;
+   }
+   principal_mappings.len++;
+
+   return 0;
+}
+
+
+krb5_error_code
+pk_initialize(const char *user_id, const char *x509_anchors)
+{
+    const char *mapping_file; 
+    krb5_error_code ret;
+    char buf[1024];
+    unsigned long lineno = 0;
+    FILE *f;
+
+    principal_mappings.len = 0;
+    principal_mappings.val = NULL;
+
+    ret = _krb5_pk_load_openssl_id(context,
+                                  &kdc_identity,
+                                  user_id,
+                                  x509_anchors,
+                                  NULL,
+                                  NULL,
+                                  NULL);
+    if (ret) {
+       krb5_warn(context, ret, "PKINIT: failed to load");
+       enable_pkinit = 0;
+       return ret;
+    }
+
+    mapping_file = krb5_config_get_string_default(context, 
+                                                 NULL,
+                                                 HDB_DB_DIR "/pki-mapping",
+                                                 "kdc",
+                                                 "pki-mappings-file",
+                                                 NULL);
+    f = fopen(mapping_file, "r");
+    if (f == NULL) {
+       krb5_warnx(context, "PKINIT: failed to load mappings file %s",
+                  mapping_file);
+       return 0;
+    }
+
+    while (fgets(buf, sizeof(buf), f) != NULL) {
+       char *subject_name, *p;
+    
+       buf[strcspn(buf, "\n")] = '\0';
+       lineno++;
+
+       p = buf + strspn(buf, " \t");
+
+       if (*p == '#' || *p == '\0')
+           continue;
+
+       subject_name = strchr(p, ':');
+       if (subject_name == NULL) {
+           krb5_warnx(context, "pkinit mapping file line %lu "
+                      "missing \":\" :%s",
+                      lineno, buf);
+           continue;
+       }
+       *subject_name++ = '\0';
+
+       ret = add_principal_mapping(p, subject_name);
+       if (ret) {
+           krb5_warn(context, ret, "failed to add line %lu \":\" :%s\n",
+                     lineno, buf);
+           continue;
+       }
+    } 
+
+    fclose(f);
+
+    return 0;
+}
+
+#endif /* PKINIT */
diff --git a/src/kerberosV/src/kdc/rx.h b/src/kerberosV/src/kdc/rx.h
new file mode 100644 (file)
index 0000000..cb8b947
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: rx.h,v 1.4 1999/12/02 17:05:00 joda Exp $ */
+
+#ifndef __RX_H__
+#define __RX_H__
+
+/* header of a RPC packet */
+
+enum rx_header_type {
+     HT_DATA = 1,
+     HT_ACK = 2,
+     HT_BUSY = 3,
+     HT_ABORT = 4,
+     HT_ACKALL = 5,
+     HT_CHAL = 6,
+     HT_RESP = 7,
+     HT_DEBUG = 8
+};
+
+/* For flags in header */
+
+enum rx_header_flag {
+     HF_CLIENT_INITIATED = 1,
+     HF_REQ_ACK = 2,
+     HF_LAST = 4,
+     HF_MORE = 8
+};
+
+struct rx_header {
+     u_int32_t epoch;
+     u_int32_t connid;         /* And channel ID */
+     u_int32_t callid;
+     u_int32_t seqno;
+     u_int32_t serialno;
+     u_char type;
+     u_char flags;
+     u_char status;
+     u_char secindex;
+     u_int16_t reserved;       /* ??? verifier? */
+     u_int16_t serviceid;
+/* This should be the other way around according to everything but */
+/* tcpdump */
+};
+
+#define RX_HEADER_SIZE 28
+
+#endif /* __RX_H__ */
diff --git a/src/kerberosV/src/kdc/string2key.8 b/src/kerberosV/src/kdc/string2key.8
new file mode 100644 (file)
index 0000000..461bcf4
--- /dev/null
@@ -0,0 +1,110 @@
+.\" Copyright (c) 2000 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: string2key.8,v 1.6 2003/02/16 21:10:21 lha Exp $
+.\"
+.Dd March 4, 2000
+.Dt STRING2KEY 8
+.Os HEIMDAL
+.Sh NAME
+.Nm string2key
+.Nd map a password into a key
+.Sh SYNOPSIS
+.Nm
+.Op Fl 5 | Fl -version5
+.Op Fl 4 | Fl -version4
+.Op Fl a | Fl -afs
+.Oo Fl c Ar cell \*(Ba Xo
+.Fl -cell= Ns Ar cell
+.Xc
+.Oc
+.Oo Fl w Ar password \*(Ba Xo
+.Fl -password= Ns Ar password
+.Xc
+.Oc
+.Oo Fl p Ar principal \*(Ba Xo
+.Fl -principal= Ns Ar principal
+.Xc
+.Oc
+.Oo Fl k Ar string \*(Ba Xo
+.Fl -keytype= Ns Ar string
+.Xc
+.Oc
+.Ar password
+.Sh DESCRIPTION
+.Nm
+performs the string-to-key function.
+This is useful when you want to handle the raw key instead of the password.
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl 5 ,
+.Fl -version5
+.Xc
+Output Kerberos v5 string-to-key
+.It Xo
+.Fl 4 ,
+.Fl -version4
+.Xc
+Output Kerberos v4 string-to-key
+.It Xo
+.Fl a ,
+.Fl -afs
+.Xc
+Output AFS string-to-key
+.It Xo
+.Fl c Ar cell ,
+.Fl -cell= Ns Ar cell
+.Xc
+AFS cell to use
+.It Xo
+.Fl w Ar password ,
+.Fl -password= Ns Ar password
+.Xc
+Password to use
+.It Xo
+.Fl p Ar principal ,
+.Fl -principal= Ns Ar principal
+.Xc
+Kerberos v5 principal to use
+.It Xo
+.Fl k Ar string ,
+.Fl -keytype= Ns Ar string
+.Xc
+Keytype
+.It Xo
+.Fl -version
+.Xc
+print version
+.It Xo
+.Fl -help
+.Xc
+.El
diff --git a/src/kerberosV/src/kdc/string2key.c b/src/kerberosV/src/kdc/string2key.c
new file mode 100644 (file)
index 0000000..8a2acb4
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "headers.h"
+#include <getarg.h>
+
+RCSID("$KTH: string2key.c,v 1.22 2003/09/03 09:34:15 lha Exp $");
+
+int version5;
+int version4;
+int afs;
+char *principal;
+char *cell;
+char *password;
+const char *keytype_str = "des3-cbc-sha1";
+int version;
+int help;
+
+struct getargs args[] = {
+    { "version5", '5', arg_flag,   &version5, "Output Kerberos v5 string-to-key" },
+    { "version4", '4', arg_flag,   &version4, "Output Kerberos v4 string-to-key" },
+    { "afs",      'a', arg_flag,   &afs, "Output AFS string-to-key" },
+    { "cell",     'c', arg_string, &cell, "AFS cell to use", "cell" },
+    { "password", 'w', arg_string, &password, "Password to use", "password" },
+    { "principal",'p', arg_string, &principal, "Kerberos v5 principal to use", "principal" },
+    { "keytype",  'k', arg_string, &keytype_str, "Keytype" },
+    { "version",    0, arg_flag,   &version, "print version" },
+    { "help",       0, arg_flag,   &help, NULL }
+};
+
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int status)
+{
+    arg_printusage (args, num_args, NULL, "password");
+    exit(status);
+}
+
+static void
+tokey(krb5_context context, 
+      krb5_enctype enctype, 
+      const char *password, 
+      krb5_salt salt, 
+      const char *label)
+{
+    krb5_error_code ret;
+    int i;
+    krb5_keyblock key;
+    char *e;
+
+    ret = krb5_string_to_key_salt(context, enctype, password, salt, &key);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_string_to_key_salt");
+    ret = krb5_enctype_to_string(context, enctype, &e);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_enctype_to_string");
+    printf(label, e);
+    printf(": ");
+    for(i = 0; i < key.keyvalue.length; i++)
+       printf("%02x", ((unsigned char*)key.keyvalue.data)[i]);
+    printf("\n");
+    krb5_free_keyblock_contents(context, &key);
+    free(e);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_principal princ;
+    krb5_salt salt;
+    int optind;
+    char buf[1024];
+    krb5_enctype etype;
+    krb5_error_code ret;
+
+    optind = krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+
+    if(help)
+       usage(0);
+    
+    if(version){
+       print_version (NULL);
+       return 0;
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc > 1)
+       usage(1);
+
+    if(!version5 && !version4 && !afs)
+       version5 = 1;
+
+    ret = krb5_string_to_enctype(context, keytype_str, &etype);
+    if(ret) {
+       krb5_keytype keytype;
+       int *etypes;
+       unsigned num;
+       char *str;
+       ret = krb5_string_to_keytype(context, keytype_str, &keytype);
+       if(ret)
+           krb5_err(context, 1, ret, "%s", keytype_str);
+       ret = krb5_keytype_to_enctypes(context, keytype, &num, &etypes);
+       if(ret)
+           krb5_err(context, 1, ret, "%s", keytype_str);
+       if(num == 0)
+           krb5_errx(context, 1, "there are no encryption types for that keytype");
+       etype = etypes[0];
+       krb5_enctype_to_string(context, etype, &str);
+       keytype_str = str;
+       if(num > 1 && version5)
+           krb5_warnx(context, "ambiguous keytype, using %s", keytype_str);
+    }
+    
+    if((etype != ETYPE_DES_CBC_CRC &&
+       etype != ETYPE_DES_CBC_MD4 &&
+       etype != ETYPE_DES_CBC_MD5) &&
+       (afs || version4)) {
+       if(!version5) {
+           etype = ETYPE_DES_CBC_CRC;
+       } else {
+           krb5_errx(context, 1, 
+                     "DES is the only valid keytype for AFS and Kerberos 4");
+       }
+    }
+
+    if(version5 && principal == NULL){
+       printf("Kerberos v5 principal: ");
+       if(fgets(buf, sizeof(buf), stdin) == NULL)
+           return 1;
+       buf[strcspn(buf, "\r\n")] = '\0';
+       principal = estrdup(buf);
+    }
+    if(afs && cell == NULL){
+       printf("AFS cell: ");
+       if(fgets(buf, sizeof(buf), stdin) == NULL)
+           return 1;
+       buf[strcspn(buf, "\r\n")] = '\0';
+       cell = estrdup(buf);
+    }
+    if(argv[0])
+       password = argv[0];
+    if(password == NULL){
+       if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 0))
+           return 1;
+       password = buf;
+    }
+       
+    if(version5){
+       krb5_parse_name(context, principal, &princ);
+       krb5_get_pw_salt(context, princ, &salt);
+       tokey(context, etype, password, salt, "Kerberos 5 (%s)");
+       krb5_free_salt(context, salt);
+    }
+    if(version4){
+       salt.salttype = KRB5_PW_SALT;
+       salt.saltvalue.length = 0;
+       salt.saltvalue.data = NULL;
+       tokey(context, ETYPE_DES_CBC_MD5, password, salt, "Kerberos 4");
+    }
+    if(afs){
+       salt.salttype = KRB5_AFS3_SALT;
+       salt.saltvalue.length = strlen(cell);
+       salt.saltvalue.data = cell;
+       tokey(context, ETYPE_DES_CBC_MD5, password, salt, "AFS");
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/kdc/v4_dump.c b/src/kerberosV/src/kdc/v4_dump.c
new file mode 100644 (file)
index 0000000..65ab19e
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2000 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "hprop.h"
+
+RCSID("$KTH: v4_dump.c,v 1.5 2003/04/28 11:35:55 lha Exp $");
+
+static time_t
+time_parse(const char *cp)
+{
+    char wbuf[5];
+    struct tm tp;
+    int local;
+
+    memset(&tp, 0, sizeof(tp));        /* clear out the struct */
+    
+    /* new format is YYYYMMDDHHMM UTC,
+       old format is YYMMDDHHMM local time */
+    if (strlen(cp) > 10) {             /* new format */
+       strlcpy(wbuf, cp, sizeof(wbuf));
+       tp.tm_year = atoi(wbuf) - 1900;
+       cp += 4;
+       local = 0;
+    } else {
+       wbuf[0] = *cp++;
+       wbuf[1] = *cp++;
+       wbuf[2] = '\0';
+       tp.tm_year = atoi(wbuf);
+       if(tp.tm_year < 38)
+           tp.tm_year += 100;
+       local = 1;
+    }
+
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    wbuf[2] = 0;
+    tp.tm_mon = atoi(wbuf) - 1;
+
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    tp.tm_mday = atoi(wbuf);
+    
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    tp.tm_hour = atoi(wbuf);
+    
+    wbuf[0] = *cp++;
+    wbuf[1] = *cp++;
+    tp.tm_min = atoi(wbuf);
+    
+    return(tm2time(tp, local));
+}
+
+/* convert a version 4 dump file */
+int
+v4_prop_dump(void *arg, const char *file)
+{
+    char buf [1024];
+    FILE *f;
+    int lineno = 0;
+
+    f = fopen(file, "r");
+    if(f == NULL)
+       return errno;
+    
+    while(fgets(buf, sizeof(buf), f)) {
+       int ret;
+       unsigned long key[2]; /* yes, long */
+       char exp_date[64], mod_date[64];
+       struct v4_principal pr;
+       int attributes;
+    
+       memset(&pr, 0, sizeof(pr));
+       errno = 0;
+       lineno++;
+       ret = sscanf(buf, "%63s %63s %d %d %d %d %lx %lx %63s %63s %63s %63s",
+                    pr.name, pr.instance,
+                    &pr.max_life, &pr.mkvno, &pr.kvno,
+                    &attributes,
+                    &key[0], &key[1],
+                    exp_date, mod_date,
+                    pr.mod_name, pr.mod_instance);
+       if(ret != 12){
+           warnx("Line %d malformed (ignored)", lineno);
+           continue;
+       }
+       if(attributes != 0) {
+           warnx("Line %d (%s.%s) has non-zero attributes - skipping", 
+                 lineno, pr.name, pr.instance);
+           continue;
+       }
+       pr.key[0] = (key[0] >> 24) & 0xff;
+       pr.key[1] = (key[0] >> 16) & 0xff;
+       pr.key[2] = (key[0] >> 8) & 0xff;
+       pr.key[3] = (key[0] >> 0) & 0xff;
+       pr.key[4] = (key[1] >> 24) & 0xff;
+       pr.key[5] = (key[1] >> 16) & 0xff;
+       pr.key[6] = (key[1] >> 8) & 0xff;
+       pr.key[7] = (key[1] >> 0) & 0xff;
+       pr.exp_date = time_parse(exp_date);
+       pr.mod_date = time_parse(mod_date);
+       if (pr.instance[0] == '*')
+           pr.instance[0] = '\0';
+       if (pr.mod_name[0] == '*')
+           pr.mod_name[0] = '\0';
+       if (pr.mod_instance[0] == '*')
+           pr.mod_instance[0] = '\0';
+       v4_prop(arg, &pr);
+       memset(&pr, 0, sizeof(pr));
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/kpasswd/CVS/Entries b/src/kerberosV/src/kpasswd/CVS/Entries
new file mode 100644 (file)
index 0000000..16aa457
--- /dev/null
@@ -0,0 +1,7 @@
+/kpasswd-generator.c/1.5/Mon Dec 18 21:08:28 2006//
+/kpasswd.1/1.1.1.4/Fri Apr 14 07:32:47 2006//
+/kpasswd.c/1.1.1.3/Fri Apr 14 07:32:47 2006//
+/kpasswd_locl.h/1.3/Sun May 11 03:39:59 2003//
+/kpasswdd.8/1.6/Fri Apr 14 08:15:03 2006//
+/kpasswdd.c/1.6/Fri Oct  6 07:09:10 2006//
+D
diff --git a/src/kerberosV/src/kpasswd/CVS/Repository b/src/kerberosV/src/kpasswd/CVS/Repository
new file mode 100644 (file)
index 0000000..119e9cb
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/kpasswd
diff --git a/src/kerberosV/src/kpasswd/CVS/Root b/src/kerberosV/src/kpasswd/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/kpasswd/kpasswd-generator.c b/src/kerberosV/src/kpasswd/kpasswd-generator.c
new file mode 100644 (file)
index 0000000..f11ae2d
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kpasswd_locl.h"
+
+RCSID("$KTH: kpasswd-generator.c,v 1.8 2004/04/25 19:25:32 joda Exp $");
+
+static unsigned
+read_words (const char *filename, char ***ret_w)
+{
+    unsigned n, alloc;
+    FILE *f;
+    char buf[256];
+    char **w = NULL;
+
+    f = fopen (filename, "r");
+    if (f == NULL)
+       err (1, "cannot open %s", filename);
+    alloc = n = 0;
+    while (fgets (buf, sizeof(buf), f) != NULL) {
+       buf[strcspn(buf, "\r\n")] = '\0';
+       if (n >= alloc) {
+           alloc += 16;
+           w = erealloc (w, alloc * sizeof(char **));
+       }
+       w[n++] = estrdup (buf);
+    }
+    *ret_w = w;
+    return n;
+}
+
+static int
+nop_prompter (krb5_context context,
+             void *data,
+             const char *name,
+             const char *banner,
+             int num_prompts,
+             krb5_prompt prompts[])
+{
+    return 0;
+}
+
+static void
+generate_requests (const char *filename, unsigned nreq)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    int i;
+    char **words;
+    unsigned nwords;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    nwords = read_words (filename, &words);
+
+    for (i = 0; i < nreq; ++i) {
+       char *name = words[rand() % nwords];
+       krb5_get_init_creds_opt *opt;
+       krb5_creds cred;
+       krb5_principal principal;
+       int result_code;
+       krb5_data result_code_string, result_string;
+       char *old_pwd, *new_pwd;
+
+       krb5_get_init_creds_opt_alloc (context, &opt);
+       krb5_get_init_creds_opt_set_tkt_life (opt, 300);
+       krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
+       krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
+
+       ret = krb5_parse_name (context, name, &principal);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_parse_name %s", name);
+
+       asprintf (&old_pwd, "%s", name);
+       asprintf (&new_pwd, "%s2", name);
+
+       ret = krb5_get_init_creds_password (context,
+                                           &cred,
+                                           principal,
+                                           old_pwd,
+                                           nop_prompter,
+                                           NULL,
+                                           0,
+                                           "kadmin/changepw",
+                                           opt);
+       if( ret == KRB5KRB_AP_ERR_BAD_INTEGRITY
+           || ret == KRB5KRB_AP_ERR_MODIFIED) {
+           char *tmp;
+
+           tmp = new_pwd;
+           new_pwd = old_pwd;
+           old_pwd = tmp;
+
+           ret = krb5_get_init_creds_password (context,
+                                               &cred,
+                                               principal,
+                                               old_pwd,
+                                               nop_prompter,
+                                               NULL,
+                                               0,
+                                               "kadmin/changepw",
+                                               opt);
+       }
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_get_init_creds_password");
+
+       krb5_free_principal (context, principal);
+
+       ret = krb5_change_password (context, &cred, new_pwd,
+                                   &result_code,
+                                   &result_code_string,
+                                   &result_string);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_change_password");
+
+       free (old_pwd);
+       free (new_pwd);
+       krb5_free_cred_contents (context, &cred);
+       krb5_get_init_creds_opt_free(opt);
+    }
+}
+
+static int version_flag        = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "file [number]");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    int nreq;
+    char *end;
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    if (help_flag)
+       usage (0);
+    if (version_flag) {
+       print_version(NULL);
+       return 0;
+    }
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 2)
+       usage (1);
+    srand (0);
+    nreq = strtol (argv[1], &end, 0);
+    if (argv[1] == end || *end != '\0')
+       usage (1);
+    generate_requests (argv[0], nreq);
+    return 0;
+}
diff --git a/src/kerberosV/src/kpasswd/kpasswd.1 b/src/kerberosV/src/kpasswd/kpasswd.1
new file mode 100644 (file)
index 0000000..e28deb6
--- /dev/null
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1997, 2000 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: kpasswd.1,v 1.7 2005/01/05 16:08:58 lha Exp $
+.\"
+.Dd January  5, 2005
+.Dt KPASSWD 1
+.Os HEIMDAL
+.Sh NAME
+.Nm kpasswd
+.Nd Kerberos 5 password changing program
+.Sh SYNOPSIS
+.Nm
+.Op Fl -admin-principal= Ns Ar principal
+.Oo Fl c Ar cache \*(Ba Xo
+.Fl -cache= Ns Ar cache
+.Xc
+.Oc
+.Op Ar principal ...
+.Sh DESCRIPTION
+.Nm
+is the client for changing passwords.
+.Pp
+If administrator principal is given that principal is used to change
+the password.
+.Pp
+Multiple passwords for different users can be changed at the same time,
+then the administrator principal will be used.
+If the administrator isn't specified on the command prompt, the
+principal of the default credential cache will be used.
+.Pp
+If a credential cache is given, the
+.Fl -admin-principal
+flag is ignored and use the default name of the credential cache is
+used instead.
+.Sh DIAGNOSTICS
+If the password quality check fails or some other error occurs, an
+explanation is printed.
+.Sh SEE ALSO
+.Xr kpasswdd 8
diff --git a/src/kerberosV/src/kpasswd/kpasswd.c b/src/kerberosV/src/kpasswd/kpasswd.c
new file mode 100644 (file)
index 0000000..40317bb
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kpasswd_locl.h"
+RCSID("$KTH: kpasswd.c,v 1.35 2005/01/05 16:08:03 lha Exp $");
+
+static int version_flag;
+static int help_flag;
+static char *admin_principal_str;
+static char *cred_cache_str;
+
+static struct getargs args[] = {
+    { "admin-principal",       0,   arg_string, &admin_principal_str },
+    { "cache",                 'c', arg_string, &cred_cache_str },
+    { "version",               0,   arg_flag, &version_flag },
+    { "help",                  0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret, struct getargs *a, int num_args)
+{
+    arg_printusage (a, num_args, NULL, "[principal ...]");
+    exit (ret);
+}
+
+static int
+change_password(krb5_context context,
+               krb5_principal principal,
+               krb5_ccache id)
+{
+    krb5_data result_code_string, result_string;
+    int result_code;
+    krb5_error_code ret;
+    char pwbuf[BUFSIZ];
+    char *msg, *name;
+
+    krb5_data_zero (&result_code_string);
+    krb5_data_zero (&result_string);
+
+    name = msg = NULL;
+    if (principal == NULL)
+       asprintf(&msg, "New password: ");
+    else {
+       ret = krb5_unparse_name(context, principal, &name);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_unparse_name");
+
+       asprintf(&msg, "New password for %s: ", name);
+    }
+
+    if (msg == NULL)
+       krb5_errx (context, 1, "out of memory");
+
+    ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), msg, 1);
+    free(msg);
+    if (name)
+       free(name);
+    if (ret != 0) {
+       return 1;
+    }
+
+    ret = krb5_set_password_using_ccache (context, id, pwbuf,
+                                         principal,
+                                         &result_code,
+                                         &result_code_string,
+                                         &result_string);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_set_password_using_ccache");
+       return 1;
+    }
+
+    printf ("%s%s%.*s\n", krb5_passwd_result_to_string(context, result_code),
+           result_string.length > 0 ? " : " : "",
+           (int)result_string.length,
+           result_string.length > 0 ? (char *)result_string.data : "");
+
+    krb5_data_free (&result_code_string);
+    krb5_data_free (&result_string);
+
+    return ret != 0;
+}
+
+
+int
+main (int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_principal principal;
+    int optind = 0;
+    krb5_get_init_creds_opt *opt;
+    krb5_ccache id = NULL;
+    int exit_value;
+
+    optind = krb5_program_setup(&context, argc, argv,
+                               args, sizeof(args) / sizeof(args[0]), usage);
+
+    if (help_flag)
+       usage (0, args, sizeof(args) / sizeof(args[0]));
+
+    if(version_flag){
+       print_version (NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+  
+    ret = krb5_get_init_creds_opt_alloc (context, &opt);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
+    
+    krb5_get_init_creds_opt_set_tkt_life (opt, 300);
+    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
+    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
+
+    if (cred_cache_str) {
+       ret = krb5_cc_resolve(context, cred_cache_str, &id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_resolve");
+    } else {
+       ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_gen_new");
+    }
+
+    if (cred_cache_str == NULL) {
+       krb5_principal admin_principal = NULL;
+       krb5_creds cred;
+
+       if (admin_principal_str) {
+           ret = krb5_parse_name (context, admin_principal_str,
+                                  &admin_principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_parse_name");
+       } else if (argc == 1) {
+           ret = krb5_parse_name (context, argv[0], &admin_principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_parse_name");
+       } else {
+           ret = krb5_get_default_principal (context, &admin_principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_get_default_principal");
+       }
+
+       ret = krb5_get_init_creds_password (context,
+                                           &cred,
+                                           admin_principal,
+                                           NULL,
+                                           krb5_prompter_posix,
+                                           NULL,
+                                           0,
+                                           "kadmin/changepw",
+                                           opt);
+       switch (ret) {
+       case 0:
+           break;
+       case KRB5_LIBOS_PWDINTR :
+           return 1;
+       case KRB5KRB_AP_ERR_BAD_INTEGRITY :
+       case KRB5KRB_AP_ERR_MODIFIED :
+           krb5_errx(context, 1, "Password incorrect");
+           break;
+       default:
+           krb5_err(context, 1, ret, "krb5_get_init_creds");
+       }
+       
+       krb5_get_init_creds_opt_free(opt);
+       
+       ret = krb5_cc_initialize(context, id, admin_principal);
+       krb5_free_principal(context, admin_principal);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+       ret = krb5_cc_store_cred(context, id, &cred);    
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_store_cred");
+       
+       krb5_free_cred_contents (context, &cred);
+    }
+
+    if (argc == 0) {
+       exit_value = change_password(context, NULL, id);
+    } else {
+       exit_value = 0;
+
+       while (argc-- > 0) {
+
+           ret = krb5_parse_name (context, argv[0], &principal);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_parse_name");
+
+           ret = change_password(context, principal, id);
+           if (ret)
+               exit_value = 1;
+           krb5_free_principal(context, principal);
+           argv++;
+       }
+    }
+
+    if (cred_cache_str == NULL) {
+       ret = krb5_cc_destroy(context, id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_destroy");
+    } else {
+       ret = krb5_cc_close(context, id);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_close");
+    }
+
+    krb5_free_context (context);
+    return ret;
+}
diff --git a/src/kerberosV/src/kpasswd/kpasswd_locl.h b/src/kerberosV/src/kpasswd/kpasswd_locl.h
new file mode 100644 (file)
index 0000000..2cc32c9
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: kpasswd_locl.h,v 1.13 2002/09/10 20:03:48 joda Exp $ */
+
+#ifndef __KPASSWD_LOCL_H__
+#define __KPASSWD_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+#ifdef HAVE_LIBUTIL_H
+#include <libutil.h>
+#endif
+#include <err.h>
+#include <roken.h>
+#include <getarg.h>
+#include <krb5.h>
+#include "crypto-headers.h" /* for des_read_pw_string */
+
+#endif /* __KPASSWD_LOCL_H__ */
diff --git a/src/kerberosV/src/kpasswd/kpasswdd.8 b/src/kerberosV/src/kpasswd/kpasswdd.8
new file mode 100644 (file)
index 0000000..3bc989b
--- /dev/null
@@ -0,0 +1,89 @@
+.\" $KTH: kpasswdd.8,v 1.11 2005/01/05 18:07:44 lha Exp $
+.\"
+.Dd April 19, 1999
+.Dt KPASSWDD 8
+.Os HEIMDAL
+.Sh NAME
+.Nm kpasswdd
+.Nd Kerberos 5 password changing server
+.Sh SYNOPSIS
+.Nm kpasswdd
+.Bk -words
+.Op Fl -addresses= Ns Ar address
+.Op Fl -check-library= Ns Ar library
+.Op Fl -check-function= Ns Ar function
+.Oo Fl k Ar kspec \*(Ba Xo
+.Fl -keytab= Ns Ar kspec
+.Xc
+.Oc
+.Oo Fl r Ar realm \*(Ba Xo
+.Fl -realm= Ns Ar realm
+.Xc
+.Oc
+.Oo Fl p Ar string \*(Ba Xo
+.Fl -port= Ns Ar string
+.Xc
+.Oc
+.Op Fl -version
+.Op Fl -help
+.Ek
+.Sh DESCRIPTION
+.Nm
+serves request for password changes. It listens on UDP port 464
+(service kpasswd) and processes requests when they arrive. It changes
+the database directly and should thus only run on the master KDC.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl -addresses= Ns Ar address
+.Xc
+For each till the argument is given, add the address to what kpasswdd
+should listen too.
+.It Xo
+.Fl -check-library= Ns Ar library
+.Xc
+If your system has support for dynamic loading of shared libraries,
+you can use an external function to check password quality. This
+option specifies which library to load.
+.It Xo
+.Fl -check-function= Ns Ar function
+.Xc
+This is the function to call in the loaded library. The function
+should look like this:
+.Pp
+.Ft const char *
+.Fn passwd_check "krb5_context context" "krb5_principal principal" "krb5_data *password"
+.Pp
+.Fa context
+is an initialized context;
+.Fa principal
+is the one who tries to change passwords, and
+.Fa password
+is the new password. Note that the password (in
+.Fa password->data )
+is not zero terminated.
+.It Xo
+.Fl k Ar kspec ,
+.Fl -keytab= Ns Ar kspec
+.Xc
+Keytab to get authentication key from.
+.It Xo
+.Fl r Ar realm ,
+.Fl -realm= Ns Ar realm
+.Xc
+Default realm.
+.It Xo
+.Fl p Ar string ,
+.Fl -port= Ns Ar string
+.Xc
+Port to listen on (default service kpasswd - 464).
+.El
+.Sh DIAGNOSTICS
+If an error occurs, the error message is returned to the user and/or
+logged to syslog.
+.Sh BUGS
+The default password quality checks are too basic.
+.Sh SEE ALSO
+.Xr passwd 1 ,
+.Xr kdc 8
diff --git a/src/kerberosV/src/kpasswd/kpasswdd.c b/src/kerberosV/src/kpasswd/kpasswdd.c
new file mode 100644 (file)
index 0000000..deb28e7
--- /dev/null
@@ -0,0 +1,849 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kpasswd_locl.h"
+RCSID("$KTH: kpasswdd.c,v 1.62 2005/04/22 11:03:11 lha Exp $");
+
+#include <kadm5/admin.h>
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#include <hdb.h>
+#include <kadm5/private.h>
+
+static krb5_context context;
+static krb5_log_facility *log_facility;
+
+static struct getarg_strings addresses_str;
+krb5_addresses explicit_addresses;
+
+static volatile sig_atomic_t exit_flag = 0;
+
+static void
+add_one_address (const char *str, int first)
+{
+    krb5_error_code ret;
+    krb5_addresses tmp;
+
+    ret = krb5_parse_address (context, str, &tmp);
+    if (ret)
+       krb5_err (context, 1, ret, "parse_address `%s'", str);
+    if (first)
+       krb5_copy_addresses(context, &tmp, &explicit_addresses);
+    else
+       krb5_append_addresses(context, &explicit_addresses, &tmp);
+    krb5_free_addresses (context, &tmp);
+}
+
+static void
+send_reply (int s,
+           struct sockaddr *sa,
+           int sa_size,
+           krb5_data *ap_rep,
+           krb5_data *rest)
+{
+    struct msghdr msghdr;
+    struct iovec iov[3];
+    u_int16_t len, ap_rep_len;
+    u_char header[6];
+    u_char *p;
+
+    if (ap_rep)
+       ap_rep_len = ap_rep->length;
+    else
+       ap_rep_len = 0;
+
+    len = 6 + ap_rep_len + rest->length;
+    p = header;
+    *p++ = (len >> 8) & 0xFF;
+    *p++ = (len >> 0) & 0xFF;
+    *p++ = 0;
+    *p++ = 1;
+    *p++ = (ap_rep_len >> 8) & 0xFF;
+    *p++ = (ap_rep_len >> 0) & 0xFF;
+
+    memset (&msghdr, 0, sizeof(msghdr));
+    msghdr.msg_name       = (void *)sa;
+    msghdr.msg_namelen    = sa_size;
+    msghdr.msg_iov        = iov;
+    msghdr.msg_iovlen     = sizeof(iov)/sizeof(*iov);
+#if 0
+    msghdr.msg_control    = NULL;
+    msghdr.msg_controllen = 0;
+#endif
+
+    iov[0].iov_base       = (char *)header;
+    iov[0].iov_len        = 6;
+    if (ap_rep_len) {
+       iov[1].iov_base   = ap_rep->data;
+       iov[1].iov_len    = ap_rep->length;
+    } else {
+       iov[1].iov_base   = NULL;
+       iov[1].iov_len    = 0;
+    }
+    iov[2].iov_base       = rest->data;
+    iov[2].iov_len        = rest->length;
+
+    if (sendmsg (s, &msghdr, 0) < 0)
+       krb5_warn (context, errno, "sendmsg");
+}
+
+static int
+make_result (krb5_data *data,
+            u_int16_t result_code,
+            const char *expl)
+{
+    krb5_data_zero (data);
+
+    data->length = asprintf ((char **)&data->data,
+                            "%c%c%s",
+                            (result_code >> 8) & 0xFF,
+                            result_code & 0xFF,
+                            expl);
+
+    if (data->data == NULL) {
+       krb5_warnx (context, "Out of memory generating error reply");
+       return 1;
+   }
+    return 0;
+}
+
+static void
+reply_error (krb5_realm realm,
+            int s,
+            struct sockaddr *sa,
+            int sa_size,
+            krb5_error_code error_code,
+            u_int16_t result_code,
+            const char *expl)
+{
+    krb5_error_code ret;
+    krb5_data error_data;
+    krb5_data e_data;
+    krb5_principal server = NULL;
+
+    if (make_result(&e_data, result_code, expl))
+       return;
+
+    if (realm) {
+       ret = krb5_make_principal (context, &server, realm,
+                                  "kadmin", "changepw", NULL);
+       if (ret) {
+           krb5_data_free (&e_data);
+           return;
+       }
+    }
+
+    ret = krb5_mk_error (context,
+                        error_code,
+                        NULL,
+                        &e_data,
+                        NULL,
+                        server,
+                        NULL,
+                        NULL,
+                        &error_data);
+    if (server)
+       krb5_free_principal(context, server);
+    krb5_data_free (&e_data);
+    if (ret) {
+       krb5_warn (context, ret, "Could not even generate error reply");
+       return;
+    }
+    send_reply (s, sa, sa_size, NULL, &error_data);
+    krb5_data_free (&error_data);
+}
+
+static void
+reply_priv (krb5_auth_context auth_context,
+           int s,
+           struct sockaddr *sa,
+           int sa_size,
+           u_int16_t result_code,
+           const char *expl)
+{
+    krb5_error_code ret;
+    krb5_data krb_priv_data;
+    krb5_data ap_rep_data;
+    krb5_data e_data;
+
+    ret = krb5_mk_rep (context,
+                      auth_context,
+                      &ap_rep_data);
+    if (ret) {
+       krb5_warn (context, ret, "Could not even generate error reply");
+       return;
+    }
+
+    if (make_result(&e_data, result_code, expl))
+       return;
+
+    ret = krb5_mk_priv (context,
+                       auth_context,
+                       &e_data,
+                       &krb_priv_data,
+                       NULL);
+    krb5_data_free (&e_data);
+    if (ret) {
+       krb5_warn (context, ret, "Could not even generate error reply");
+       return;
+    }
+    send_reply (s, sa, sa_size, &ap_rep_data, &krb_priv_data);
+    krb5_data_free (&ap_rep_data);
+    krb5_data_free (&krb_priv_data);
+}
+
+/*
+ * Change the password for `principal', sending the reply back on `s'
+ * (`sa', `sa_size') to `pwd_data'.
+ */
+
+static void
+change (krb5_auth_context auth_context,
+       krb5_principal admin_principal,
+       u_int16_t version,
+       int s,
+       struct sockaddr *sa,
+       int sa_size,
+       krb5_data *in_data)
+{
+    krb5_error_code ret;
+    char *client = NULL, *admin = NULL;
+    const char *pwd_reason;
+    kadm5_config_params conf;
+    void *kadm5_handle = NULL;
+    krb5_principal principal;
+    krb5_data *pwd_data = NULL;
+    char *tmp;
+    ChangePasswdDataMS chpw;
+
+    memset (&conf, 0, sizeof(conf));
+    memset(&chpw, 0, sizeof(chpw));
+    
+    if (version == KRB5_KPASSWD_VERS_CHANGEPW) {
+       ret = krb5_copy_data(context, in_data, &pwd_data);
+       if (ret) {
+           krb5_warn (context, ret, "krb5_copy_data");
+           reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED,
+                       "out out memory copying password");
+           return;
+       }
+       principal = admin_principal;
+    } else if (version == KRB5_KPASSWD_VERS_SETPW) {
+       size_t len;
+
+       ret = decode_ChangePasswdDataMS(in_data->data, in_data->length,
+                                       &chpw, &len);
+       if (ret) {
+           krb5_warn (context, ret, "decode_ChangePasswdDataMS");
+           reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED,
+                       "malformed ChangePasswdData");
+           return;
+       }
+       
+
+       ret = krb5_copy_data(context, &chpw.newpasswd, &pwd_data);
+       if (ret) {
+           krb5_warn (context, ret, "krb5_copy_data");
+           reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_MALFORMED,
+                       "out out memory copying password");
+           goto out;
+       }
+
+       if (chpw.targname == NULL && chpw.targrealm != NULL) {
+           krb5_warn (context, ret, "kadm5_init_with_password_ctx");
+           reply_priv (auth_context, s, sa, sa_size, 
+                       KRB5_KPASSWD_MALFORMED,
+                       "targrealm but not targname");
+           goto out;
+       }
+
+       if (chpw.targname) {
+           krb5_principal_data princ;
+
+           princ.name = *chpw.targname;
+           princ.realm = *chpw.targrealm;
+           if (princ.realm == NULL) {
+               ret = krb5_get_default_realm(context, &princ.realm);
+
+               if (ret) {
+                   krb5_warnx (context, 
+                               "kadm5_init_with_password_ctx: "
+                               "failed to allocate realm");
+                   reply_priv (auth_context, s, sa, sa_size, 
+                               KRB5_KPASSWD_SOFTERROR,
+                               "failed to allocate realm");
+                   goto out;
+               }
+           }
+           ret = krb5_copy_principal(context, &princ, &principal);
+           if (*chpw.targrealm == NULL)
+               free(princ.realm);
+           if (ret) {
+               krb5_warn(context, ret, "krb5_copy_principal");
+               reply_priv(auth_context, s, sa, sa_size, 
+                          KRB5_KPASSWD_HARDERROR,
+                          "failed to allocate principal");
+               goto out;
+           }
+       } else
+           principal = admin_principal;
+    } else {
+       krb5_warnx (context, "kadm5_init_with_password_ctx: unknown proto");
+       reply_priv (auth_context, s, sa, sa_size, 
+                   KRB5_KPASSWD_HARDERROR,
+                   "Unknown protocol used");
+       return;
+    }
+
+    ret = krb5_unparse_name (context, admin_principal, &admin);
+    if (ret) {
+       krb5_warn (context, ret, "unparse_name failed");
+       reply_priv (auth_context, s, sa, sa_size, 
+                   KRB5_KPASSWD_HARDERROR, "out of memory error");
+       goto out;
+    }
+
+    ret = kadm5_init_with_password_ctx(context, 
+                                      admin,
+                                      NULL,
+                                      KADM5_ADMIN_SERVICE,
+                                      &conf, 0, 0, 
+                                      &kadm5_handle);
+    if (ret) {
+       krb5_warn (context, ret, "kadm5_init_with_password_ctx");
+       reply_priv (auth_context, s, sa, sa_size, 2,
+                   "Internal error");
+       goto out;
+    }
+
+    ret = krb5_unparse_name(context, principal, &client);
+    if (ret) {
+       krb5_warn (context, ret, "unparse_name failed");
+       reply_priv (auth_context, s, sa, sa_size, 
+                   KRB5_KPASSWD_HARDERROR, "out of memory error");
+       goto out;
+    }
+
+    /*
+     * Check password quality if not changing as administrator
+     */
+
+    if (krb5_principal_compare(context, admin_principal, principal) == TRUE) {
+
+       pwd_reason = kadm5_check_password_quality (context, principal, 
+                                                  pwd_data);
+       if (pwd_reason != NULL ) {
+           krb5_warnx (context, 
+                       "%s didn't pass password quality check with error: %s",
+                       client, pwd_reason);
+           reply_priv (auth_context, s, sa, sa_size, 
+                       KRB5_KPASSWD_SOFTERROR, pwd_reason);
+           goto out;
+       }
+       krb5_warnx (context, "Changing password for %s", client);
+    } else {
+       ret = _kadm5_acl_check_permission(kadm5_handle, KADM5_PRIV_CPW, 
+                                         principal);
+       if (ret) {
+           krb5_warn (context, ret, 
+                      "Check ACL failed for %s for changing %s password",
+                      admin, client);
+           reply_priv (auth_context, s, sa, sa_size, 
+                       KRB5_KPASSWD_HARDERROR, "permission denied");
+           goto out;
+       }
+       krb5_warnx (context, "%s is changing password for %s", admin, client);
+    }
+
+    ret = krb5_data_realloc(pwd_data, pwd_data->length + 1);
+    if (ret) {
+       krb5_warn (context, ret, "malloc: out of memory");
+       reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR,
+                   "Internal error");
+       goto out;
+    }
+    tmp = pwd_data->data;
+    tmp[pwd_data->length - 1] = '\0';
+
+    ret = kadm5_s_chpass_principal_cond (kadm5_handle, principal, tmp);
+    krb5_free_data (context, pwd_data);
+    pwd_data = NULL;
+    if (ret) {
+       krb5_warn (context, ret, "kadm5_s_chpass_principal_cond");
+       reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_HARDERROR,
+                   "Internal error");
+       goto out;
+    }
+    reply_priv (auth_context, s, sa, sa_size, KRB5_KPASSWD_SUCCESS,
+               "Password changed");
+out:
+    free_ChangePasswdDataMS(&chpw);
+    if (admin)
+       free(admin);
+    if (client)
+       free(client);
+    if (pwd_data)
+       krb5_free_data(context, pwd_data);
+    if (kadm5_handle)
+       kadm5_destroy (kadm5_handle);
+}
+
+static int
+verify (krb5_auth_context *auth_context,
+       krb5_realm *realms,
+       krb5_keytab keytab,
+       krb5_ticket **ticket,
+       krb5_data *out_data,
+       u_int16_t *version,
+       int s,
+       struct sockaddr *sa,
+       int sa_size,
+       u_char *msg,
+       size_t len)
+{
+    krb5_error_code ret;
+    u_int16_t pkt_len, pkt_ver, ap_req_len;
+    krb5_data ap_req_data;
+    krb5_data krb_priv_data;
+    krb5_realm *r;
+
+    pkt_len = (msg[0] << 8) | (msg[1]);
+    pkt_ver = (msg[2] << 8) | (msg[3]);
+    ap_req_len = (msg[4] << 8) | (msg[5]);
+    if (pkt_len != len) {
+       krb5_warnx (context, "Strange len: %ld != %ld", 
+                   (long)pkt_len, (long)len);
+       reply_error (NULL, s, sa, sa_size, 0, 1, "Bad request");
+       return 1;
+    }
+    if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW &&
+       pkt_ver != KRB5_KPASSWD_VERS_SETPW) {
+       krb5_warnx (context, "Bad version (%d)", pkt_ver);
+       reply_error (NULL, s, sa, sa_size, 0, 1, "Wrong program version");
+       return 1;
+    }
+    *version = pkt_ver;
+
+    ap_req_data.data   = msg + 6;
+    ap_req_data.length = ap_req_len;
+
+    ret = krb5_rd_req (context,
+                      auth_context,
+                      &ap_req_data,
+                      NULL,
+                      keytab,
+                      NULL,
+                      ticket);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_rd_req");
+       reply_error (NULL, s, sa, sa_size, ret, 3, "Authentication failed");
+       return 1;
+    }
+
+    /* verify realm and principal */
+    for (r = realms; *r != NULL; r++) {
+       krb5_principal principal;
+       krb5_boolean same;
+
+       ret = krb5_make_principal (context, 
+                                  &principal,
+                                  *r,
+                                  "kadmin",
+                                  "changepw",
+                                  NULL);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_make_principal");
+
+       same = krb5_principal_compare(context, principal, (*ticket)->server);
+       krb5_free_principal(context, principal);
+       if (same == TRUE)
+           break;
+    }
+    if (*r == NULL) {
+       char *str;
+       krb5_unparse_name(context, (*ticket)->server, &str);
+       krb5_warnx (context, "client used not valid principal %s", str);
+       free(str);
+       reply_error (NULL, s, sa, sa_size, ret, 1,
+                    "Bad request");
+       goto out;
+    }
+
+    if (strcmp((*ticket)->server->realm, (*ticket)->client->realm) != 0) {
+       krb5_warnx (context, "server realm (%s) not same a client realm (%s)",
+                   (*ticket)->server->realm, (*ticket)->client->realm);
+       reply_error ((*ticket)->server->realm, s, sa, sa_size, ret, 1,
+                    "Bad request");
+       goto out;
+    }
+
+    if (!(*ticket)->ticket.flags.initial) {
+       krb5_warnx (context, "initial flag not set");
+       reply_error ((*ticket)->server->realm, s, sa, sa_size, ret, 1,
+                    "Bad request");
+       goto out;
+    }
+    krb_priv_data.data   = msg + 6 + ap_req_len;
+    krb_priv_data.length = len - 6 - ap_req_len;
+
+    ret = krb5_rd_priv (context,
+                       *auth_context,
+                       &krb_priv_data,
+                       out_data,
+                       NULL);
+    
+    if (ret) {
+       krb5_warn (context, ret, "krb5_rd_priv");
+       reply_error ((*ticket)->server->realm, s, sa, sa_size, ret, 3, 
+                    "Bad request");
+       goto out;
+    }
+    return 0;
+out:
+    krb5_free_ticket (context, *ticket);
+    ticket = NULL;
+    return 1;
+}
+
+static void
+process (krb5_realm *realms,
+        krb5_keytab keytab,
+        int s,
+        krb5_address *this_addr,
+        struct sockaddr *sa,
+        int sa_size,
+        u_char *msg,
+        int len)
+{
+    krb5_error_code ret;
+    krb5_auth_context auth_context = NULL;
+    krb5_data out_data;
+    krb5_ticket *ticket;
+    krb5_address other_addr;
+    u_int16_t version;
+
+
+    krb5_data_zero (&out_data);
+
+    ret = krb5_auth_con_init (context, &auth_context);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_auth_con_init");
+       return;
+    }
+
+    krb5_auth_con_setflags (context, auth_context,
+                           KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+    ret = krb5_sockaddr2address (context, sa, &other_addr);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_sockaddr2address");
+       goto out;
+    }
+
+    ret = krb5_auth_con_setaddrs (context,
+                                 auth_context,
+                                 this_addr,
+                                 &other_addr);
+    krb5_free_address (context, &other_addr);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_auth_con_setaddr");
+       goto out;
+    }
+
+    if (verify (&auth_context, realms, keytab, &ticket, &out_data,
+               &version, s, sa, sa_size, msg, len) == 0) {
+       change (auth_context,
+               ticket->client,
+               version,
+               s,
+               sa, sa_size,
+               &out_data);
+       memset (out_data.data, 0, out_data.length);
+       krb5_free_ticket (context, ticket);
+    }
+
+out:
+    krb5_data_free (&out_data);
+    krb5_auth_con_free (context, auth_context);
+}
+
+static int
+doit (krb5_keytab keytab, int port)
+{
+    krb5_error_code ret;
+    int *sockets;
+    int maxfd;
+    krb5_realm *realms;
+    krb5_addresses addrs;
+    unsigned n, i;
+    fd_set real_fdset;
+    struct sockaddr_storage __ss;
+    struct sockaddr *sa = (struct sockaddr *)&__ss;
+
+    ret = krb5_get_default_realms(context, &realms);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_get_default_realms");
+
+    if (explicit_addresses.len) {
+       addrs = explicit_addresses;
+    } else {
+       ret = krb5_get_all_server_addrs (context, &addrs);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_get_all_server_addrs");
+    }
+    n = addrs.len;
+
+    sockets = malloc (n * sizeof(*sockets));
+    if (sockets == NULL)
+       krb5_errx (context, 1, "out of memory");
+    maxfd = -1;
+    FD_ZERO(&real_fdset);
+    for (i = 0; i < n; ++i) {
+       int sa_size = sizeof(__ss);
+
+       krb5_addr2sockaddr (context, &addrs.val[i], sa, &sa_size, port);
+       
+       sockets[i] = socket (sa->sa_family, SOCK_DGRAM, 0);
+       if (sockets[i] < 0)
+           krb5_err (context, 1, errno, "socket");
+       if (bind (sockets[i], sa, sa_size) < 0) {
+           char str[128];
+           size_t len;
+           int save_errno = errno;
+
+           ret = krb5_print_address (&addrs.val[i], str, sizeof(str), &len);
+           if (ret)
+               strlcpy(str, "unknown address", sizeof(str));
+           krb5_warn (context, save_errno, "bind(%s)", str);
+           continue;
+       }
+       maxfd = max (maxfd, sockets[i]);
+       if (maxfd >= FD_SETSIZE)
+           krb5_errx (context, 1, "fd too large");
+       FD_SET(sockets[i], &real_fdset);
+    }
+    if (maxfd == -1)
+       krb5_errx (context, 1, "No sockets!");
+
+    while(exit_flag == 0) {
+       int ret;
+       fd_set fdset = real_fdset;
+
+       ret = select (maxfd + 1, &fdset, NULL, NULL, NULL);
+       if (ret < 0) {
+           if (errno == EINTR)
+               continue;
+           else
+               krb5_err (context, 1, errno, "select");
+       }
+       for (i = 0; i < n; ++i)
+           if (FD_ISSET(sockets[i], &fdset)) {
+               u_char buf[BUFSIZ];
+               socklen_t addrlen = sizeof(__ss);
+
+               ret = recvfrom (sockets[i], buf, sizeof(buf), 0,
+                               sa, &addrlen);
+               if (ret < 0) {
+                   if(errno == EINTR)
+                       break;
+                   else
+                       krb5_err (context, 1, errno, "recvfrom");
+               }
+
+               process (realms, keytab, sockets[i],
+                        &addrs.val[i],
+                        sa, addrlen,
+                        buf, ret);
+           }
+    }
+
+    for (i = 0; i < n; ++i)
+       close(sockets[i]);
+    free(sockets);
+
+    krb5_free_addresses (context, &addrs);
+    krb5_free_host_realm (context, realms);
+    krb5_free_context (context);
+    return 0;
+}
+
+static RETSIGTYPE
+sigterm(int sig)
+{
+    exit_flag = 1;
+}
+
+const char *check_library  = NULL;
+const char *check_function = NULL;
+static getarg_strings policy_libraries = { 0, NULL };
+char *keytab_str = "HDB:";
+char *realm_str;
+int version_flag;
+int help_flag;
+char *port_str;
+char *config_file;
+
+struct getargs args[] = {
+#ifdef HAVE_DLOPEN
+    { "check-library", 0, arg_string, &check_library, 
+      "library to load password check function from", "library" },
+    { "check-function", 0, arg_string, &check_function,
+      "password check function to load", "function" },
+    { "policy-libraries", 0, arg_strings, &policy_libraries,
+      "password check function to load", "function" },
+#endif
+    { "addresses",     0,      arg_strings, &addresses_str,
+      "addresses to listen on", "list of addresses" },
+    { "keytab", 'k', arg_string, &keytab_str, 
+      "keytab to get authentication key from", "kspec" },
+    { "config-file", 'c', arg_string, &config_file },
+    { "realm", 'r', arg_string, &realm_str, "default realm", "realm" },
+    { "port",  'p', arg_string, &port_str, "port" },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main (int argc, char **argv)
+{
+    int optind;
+    krb5_keytab keytab;
+    krb5_error_code ret;
+    char **files;
+    int port, i;
+    
+    optind = krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+    
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if (ret)
+       krb5_err(context, 1, ret, "reading configuration files");
+
+    if(realm_str)
+       krb5_set_default_realm(context, realm_str);
+    
+    krb5_openlog (context, "kpasswdd", &log_facility);
+    krb5_set_warn_dest(context, log_facility);
+
+    if (port_str != NULL) {
+       struct servent *s = roken_getservbyname (port_str, "udp");
+
+       if (s != NULL)
+           port = s->s_port;
+       else {
+           char *ptr;
+
+           port = strtol (port_str, &ptr, 10);
+           if (port == 0 && ptr == port_str)
+               krb5_errx (context, 1, "bad port `%s'", port_str);
+           port = htons(port);
+       }
+    } else
+       port = krb5_getportbyname (context, "kpasswd", "udp", KPASSWD_PORT);
+
+    ret = krb5_kt_register(context, &hdb_kt_ops);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_kt_register");
+
+    ret = krb5_kt_resolve(context, keytab_str, &keytab);
+    if(ret)
+       krb5_err(context, 1, ret, "%s", keytab_str);
+    
+    kadm5_setup_passwd_quality_check (context, check_library, check_function);
+
+    for (i = 0; i < policy_libraries.num_strings; i++) {
+       ret = kadm5_add_passwd_quality_verifier(context, 
+                                               policy_libraries.strings[i]);
+       if (ret)
+           krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
+    }
+    ret = kadm5_add_passwd_quality_verifier(context, NULL);
+    if (ret)
+       krb5_err(context, 1, ret, "kadm5_add_passwd_quality_verifier");
+
+
+    explicit_addresses.len = 0;
+
+    if (addresses_str.num_strings) {
+       int i;
+
+       for (i = 0; i < addresses_str.num_strings; ++i)
+           add_one_address (addresses_str.strings[i], i == 0);
+       free_getarg_strings (&addresses_str);
+    } else {
+       char **foo = krb5_config_get_strings (context, NULL,
+                                             "kdc", "addresses", NULL);
+
+       if (foo != NULL) {
+           add_one_address (*foo++, TRUE);
+           while (*foo)
+               add_one_address (*foo++, FALSE);
+       }
+    }
+
+#ifdef HAVE_SIGACTION
+    {
+       struct sigaction sa;
+
+       sa.sa_flags = 0;
+       sa.sa_handler = sigterm;
+       sigemptyset(&sa.sa_mask);
+
+       sigaction(SIGINT,  &sa, NULL);
+       sigaction(SIGTERM, &sa, NULL);
+    }
+#else
+    signal(SIGINT,  sigterm);
+    signal(SIGTERM, sigterm);
+#endif
+
+    pidfile(NULL);
+
+    return doit (keytab, port);
+}
diff --git a/src/kerberosV/src/kuser/CVS/Entries b/src/kerberosV/src/kuser/CVS/Entries
new file mode 100644 (file)
index 0000000..c97a3fa
--- /dev/null
@@ -0,0 +1,17 @@
+/copy_cred_cache.1/1.1.1.1/Fri Apr 14 07:32:48 2006//
+/copy_cred_cache.c/1.1.1.1/Fri Apr 14 07:32:48 2006//
+/generate-requests.c/1.5/Mon Dec 18 21:08:28 2006//
+/kauth_options.c/1.1.1.1/Fri May 25 07:49:49 2001//
+/kdecode_ticket.c/1.3/Fri Apr 14 08:15:04 2006//
+/kdestroy.1/1.4/Fri Apr 14 08:15:04 2006//
+/kdestroy.c/1.5/Fri Apr 14 08:15:04 2006//
+/kgetcred.1/1.1.1.4/Fri Apr 14 07:32:48 2006//
+/kgetcred.c/1.3/Fri Apr 14 08:15:04 2006//
+/kinit.1/1.6/Fri Apr 14 08:15:04 2006//
+/kinit.c/1.10/Fri Apr 14 08:15:04 2006//
+/kinit_options.c/1.1.1.1/Fri May 25 07:49:50 2001//
+/klist.1/1.4/Fri Apr 14 08:15:04 2006//
+/klist.c/1.7/Fri Apr 14 08:15:04 2006//
+/kuser_locl.h/1.3/Sun May 11 03:40:00 2003//
+/kverify.c/1.3/Fri Apr 14 08:15:04 2006//
+D
diff --git a/src/kerberosV/src/kuser/CVS/Repository b/src/kerberosV/src/kuser/CVS/Repository
new file mode 100644 (file)
index 0000000..9694429
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/kuser
diff --git a/src/kerberosV/src/kuser/CVS/Root b/src/kerberosV/src/kuser/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/kuser/copy_cred_cache.1 b/src/kerberosV/src/kuser/copy_cred_cache.1
new file mode 100644 (file)
index 0000000..e0c78ef
--- /dev/null
@@ -0,0 +1,97 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: copy_cred_cache.1,v 1.3 2004/04/25 16:03:45 joda Exp $
+.\"
+.Dd April 24, 2004
+.Dt COPY_CRED_CACHE 1
+.Os HEIMDAL
+.Sh NAME
+.Nm copy_cred_cache
+.Nd
+copy credentials from one cache to another
+.Sh SYNOPSIS
+.Nm
+.Op Fl -krbtgt-only
+.Op Fl -service= Ns Ar principal
+.Op Fl -enctype= Ns Ar enctype
+.Op Fl -flags= Ns Ar ticketflags
+.Op Fl -valid-for= Ns Ar time
+.Op Fl -fcache-version= Ns Ar integer
+.Op Aq Ar from-cache
+.Aq Ar to-cache
+.Sh DESCRIPTION
+.Nm
+copies credentials from
+.Aq Ar from-cache
+(or the default cache) to
+.Aq Ar to-cache .
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Fl -krbtgt-only
+Copies only krbtgt credentials for the client's realm. This is
+equivalent to
+.Fl -service= Ns Li krbtgt/ Ns Ao Ar CLIENTREALM Ac Ns Li @ Ns Ao Ar CLIENTREALM Ac .
+.It Fl -service= Ns Ar principal
+Copies only credentials matching this service principal.
+.It Fl -enctype= Ns Ar enctype
+Copies only credentials a matching enctype.
+.It Fl -flags= Ns Ar ticketflags
+Copies only credentials with these ticket flags set.
+.It Fl -valid-for= Ns Ar time
+Copies only credentials that are valid for at least this long. This
+does not take renewable creds into account.
+.It Fl -fcache-version= Ns Ar integer
+The created cache, If a standard
+.Li FILE
+cache is created, it will have this file format version.
+.El
+.\".Sh ENVIRONMENT
+.\".Sh FILES
+.Sh EXAMPLES
+To copy only credentials that are valid for at least one day and with
+the
+.Li initial
+flag set, try something like:
+.Bd -literal -offset indent
+$ copy_cred_cache --valid-for=1d --flags=initial FILE:/some/cache
+.Ed
+.Sh DIAGNOSTICS
+The
+.Nm
+utility exits 0 on success, and \*[Gt]0 if an error occurs, or of no
+credentials where actually copied.
+.\".Sh SEE ALSO
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/src/kerberosV/src/kuser/copy_cred_cache.c b/src/kerberosV/src/kuser/copy_cred_cache.c
new file mode 100644 (file)
index 0000000..a3c1496
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: copy_cred_cache.c,v 1.5 2005/04/25 18:08:42 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <krb5.h>
+#include <roken.h>
+#include <getarg.h>
+#include <parse_units.h>
+#include <parse_time.h>
+
+static int krbtgt_only_flag;
+static char *service_string;
+static char *enctype_string;
+static char *flags_string;
+static char *valid_string;
+static int fcache_version;
+static int help_flag;
+static int version_flag;
+
+static struct getargs args[] = {
+    { "krbtgt-only", 0, arg_flag, &krbtgt_only_flag,
+      "only copy local krbtgt" },
+    { "service", 0, arg_string, &service_string,
+      "limit to this service", "principal" },
+    { "enctype", 0, arg_string, &enctype_string,
+      "limit to this enctype", "enctype" },
+    { "flags", 0, arg_string, &flags_string,
+      "limit to these flags", "ticketflags" },
+    { "valid-for", 0, arg_string, &valid_string, 
+      "limit to creds valid for at least this long", "time" },
+    { "fcache-version", 0, arg_integer, &fcache_version,
+      "file cache version to create" },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 'h', arg_flag, &help_flag }
+};
+
+static void
+usage(int ret)
+{
+    arg_printusage(args,
+                  sizeof(args) / sizeof(*args),
+                  NULL,
+                  "[from-cache] to-cache");
+    exit(ret);
+}
+
+static int32_t
+bitswap32(int32_t b)
+{
+    int32_t r = 0;
+    int i;
+    for (i = 0; i < 32; i++) {
+       r = r << 1 | (b & 1);
+       b = b >> 1;
+    }
+    return r;
+}
+
+static void
+parse_ticket_flags(krb5_context context,
+                  const char *flags_string, krb5_ticket_flags *ret_flags)
+{
+    TicketFlags ff;
+    int flags = parse_flags(flags_string, asn1_TicketFlags_units(), 0);
+    if (flags == -1)   /* XXX */
+       krb5_errx(context, 1, "bad flags specified: \"%s\"", flags_string);
+
+    memset(&ff, 0, sizeof(ff));
+    ff.proxy = 1;
+    if (parse_flags("proxy", asn1_TicketFlags_units(), 0) == TicketFlags2int(ff))
+       ret_flags->i = flags;
+    else
+       ret_flags->i = bitswap32(flags);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    int optind = 0;
+    const char *from_name, *to_name;
+    krb5_ccache from_ccache, to_ccache;
+    krb5_flags whichfields = 0;
+    krb5_creds mcreds;
+    unsigned int matched;
+
+    setprogname(argv[0]);
+
+    memset(&mcreds, 0, sizeof(mcreds));
+
+    if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+
+    if (help_flag)
+       usage(0);
+
+    if (version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    argc -= optind;
+    argv += optind;
+
+    if (argc < 1 || argc > 2)
+       usage(1);
+
+    if (krb5_init_context(&context))
+       errx(1, "krb5_init_context failed");
+
+    if (service_string) {
+       ret = krb5_parse_name(context, service_string, &mcreds.server);
+       if (ret)
+           krb5_err(context, 1, ret, "%s", service_string);
+    }
+    if (enctype_string) {
+       krb5_enctype enctype;
+       ret = krb5_string_to_enctype(context, enctype_string, &enctype);
+       if (ret)
+           krb5_err(context, 1, ret, "%s", enctype_string);
+       whichfields |= KRB5_TC_MATCH_KEYTYPE;
+       mcreds.session.keytype = enctype;
+    }
+    if (flags_string) {
+       parse_ticket_flags(context, flags_string, &mcreds.flags);
+       whichfields |= KRB5_TC_MATCH_FLAGS;
+    }
+    if (valid_string) {
+       time_t t = parse_time(valid_string, "s");
+       if(t < 0)
+           errx(1, "unknown time \"%s\"", valid_string);
+       mcreds.times.endtime = time(NULL) + t;
+       whichfields |= KRB5_TC_MATCH_TIMES;
+    }
+    if (fcache_version)
+       krb5_set_fcache_version(context, fcache_version);
+
+    if (argc == 1) {
+       from_name = krb5_cc_default_name(context);
+       to_name = argv[0];
+    } else {
+       from_name = argv[0];
+       to_name = argv[1];
+    }
+
+    ret = krb5_cc_resolve(context, from_name, &from_ccache);
+    if (ret)
+       krb5_err(context, 1, ret, "%s", from_name);
+
+    if (krbtgt_only_flag) {
+       krb5_principal client;
+       ret = krb5_cc_get_principal(context, from_ccache, &client);
+       if (ret)
+           krb5_err(context, 1, ret, "getting default principal");
+       ret = krb5_make_principal(context, &mcreds.server,
+                                 krb5_principal_get_realm(context, client),
+                                 KRB5_TGS_NAME,
+                                 krb5_principal_get_realm(context, client),
+                                 NULL);
+       if (ret)
+           krb5_err(context, 1, ret, "constructing krbtgt principal");
+       krb5_free_principal(context, client);
+    }
+    ret = krb5_cc_resolve(context, to_name, &to_ccache);
+    if (ret)
+       krb5_err(context, 1, ret, "%s", to_name);
+
+    ret = krb5_cc_copy_cache_match(context, from_ccache, to_ccache,
+                                  whichfields, &mcreds, &matched);
+    if (ret)
+       krb5_err(context, 1, ret, "copying cred cache");
+
+    krb5_cc_close(context, from_ccache);
+    if(matched == 0)
+       krb5_cc_destroy(context, to_ccache);
+    else
+       krb5_cc_close(context, to_ccache);
+    krb5_free_context(context);
+    return matched == 0;
+}
diff --git a/src/kerberosV/src/kuser/generate-requests.c b/src/kerberosV/src/kuser/generate-requests.c
new file mode 100644 (file)
index 0000000..2c2f284
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+
+RCSID("$KTH: generate-requests.c,v 1.5 2004/04/25 19:25:33 joda Exp $");
+
+static krb5_error_code
+null_key_proc (krb5_context context,
+              krb5_enctype type,
+              krb5_salt salt,
+              krb5_const_pointer keyseed,
+              krb5_keyblock **key)
+{
+    return ENOTTY;
+}
+
+static unsigned
+read_words (const char *filename, char ***ret_w)
+{
+    unsigned n, alloc;
+    FILE *f;
+    char buf[256];
+    char **w = NULL;
+
+    f = fopen (filename, "r");
+    if (f == NULL)
+       err (1, "cannot open %s", filename);
+    alloc = n = 0;
+    while (fgets (buf, sizeof(buf), f) != NULL) {
+       buf[strcspn(buf, "\r\n")] = '\0';
+       if (n >= alloc) {
+           alloc += 16;
+           w = erealloc (w, alloc * sizeof(char **));
+       }
+       w[n++] = estrdup (buf);
+    }
+    *ret_w = w;
+    return n;
+}
+
+static void
+generate_requests (const char *filename, unsigned nreq)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_creds cred;
+    int i;
+    char **words;
+    unsigned nwords;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    nwords = read_words (filename, &words);
+
+    for (i = 0; i < nreq; ++i) {
+       char *name = words[rand() % nwords];
+       krb5_realm *client_realm;
+
+       memset(&cred, 0, sizeof(cred));
+
+       ret = krb5_parse_name (context, name, &cred.client);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_parse_name %s", name);
+       client_realm = krb5_princ_realm (context, cred.client);
+
+       ret = krb5_make_principal(context, &cred.server, *client_realm,
+                                 KRB5_TGS_NAME, *client_realm, NULL);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_make_principal");
+
+       ret = krb5_get_in_cred (context, 0, NULL, NULL, NULL, NULL,
+                               null_key_proc, NULL, NULL, NULL,
+                               &cred, NULL);
+       krb5_free_cred_contents (context, &cred);
+    }
+}
+
+static int version_flag        = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "file number");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    int nreq;
+    char *end;
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+
+    if (help_flag)
+       usage (0);
+
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 2)
+       usage (1);
+    srand (0);
+    nreq = strtol (argv[1], &end, 0);
+    if (argv[1] == end || *end != '\0')
+       usage (1);
+    generate_requests (argv[0], nreq);
+    return 0;
+}
diff --git a/src/kerberosV/src/kuser/kauth_options.c b/src/kerberosV/src/kuser/kauth_options.c
new file mode 100644 (file)
index 0000000..7cd1446
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+RCSID("$KTH: kauth_options.c,v 1.2 1999/12/02 17:05:00 joda Exp $");
+
+#ifdef KRB4
+int do_afslog          = 1;
+int get_v4_tgt         = 1;
+#endif
diff --git a/src/kerberosV/src/kuser/kdecode_ticket.c b/src/kerberosV/src/kuser/kdecode_ticket.c
new file mode 100644 (file)
index 0000000..ab14011
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+
+RCSID("$KTH: kdecode_ticket.c,v 1.6 2004/04/25 19:25:33 joda Exp $");
+
+static char *etype_str;
+static int version_flag;
+static int help_flag;
+
+static void
+print_and_decode_tkt (krb5_context context,
+                     krb5_data *ticket,
+                     krb5_principal server,
+                     krb5_enctype enctype)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    krb5_data dec_data;
+    size_t len;
+    EncTicketPart decr_part;
+    krb5_keyblock key;
+    Ticket tkt;
+
+    ret = decode_Ticket (ticket->data, ticket->length, &tkt, &len);
+    if (ret)
+       krb5_err (context, 1, ret, "decode_Ticket");
+
+    ret = krb5_string_to_key (context, enctype, "foo", server, &key);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_string_to_key");
+
+    ret = krb5_crypto_init(context, &key, 0, &crypto);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_crypto_init");
+
+    ret = krb5_decrypt_EncryptedData (context, crypto, KRB5_KU_TICKET,
+                                     &tkt.enc_part, &dec_data);
+    krb5_crypto_destroy (context, crypto);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_decrypt_EncryptedData");
+    ret = krb5_decode_EncTicketPart (context, dec_data.data, dec_data.length,
+                                    &decr_part, &len);
+    krb5_data_free (&dec_data);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_decode_EncTicketPart");
+}
+
+struct getargs args[] = {
+    { "enctype",       'e', arg_string, &etype_str,
+      "encryption type to use", "enctype"},
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "service");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_ccache cache;
+    krb5_creds in, *out;
+    int optind = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx(1, "krb5_init_context failed: %d", ret);
+  
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 1)
+       usage (1);
+
+    ret = krb5_cc_default(context, &cache);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_default");
+
+    memset(&in, 0, sizeof(in));
+
+    if (etype_str) {
+       krb5_enctype enctype;
+
+       ret = krb5_string_to_enctype(context, etype_str, &enctype);
+       if (ret)
+           krb5_errx (context, 1, "unrecognized enctype: %s", etype_str);
+       in.session.keytype = enctype;
+    }
+
+    ret = krb5_cc_get_principal(context, cache, &in.client);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_get_principal");
+
+    ret = krb5_parse_name(context, argv[0], &in.server);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]);
+
+    in.times.endtime = 0;
+    ret = krb5_get_credentials(context, 0, cache, &in, &out);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_get_credentials");
+
+    print_and_decode_tkt (context, &out->ticket, out->server,
+                         out->session.keytype);
+
+    krb5_free_cred_contents(context, out);
+    return 0;
+}
diff --git a/src/kerberosV/src/kuser/kdestroy.1 b/src/kerberosV/src/kuser/kdestroy.1
new file mode 100644 (file)
index 0000000..45291e3
--- /dev/null
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1997, 1999, 2001, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: kdestroy.1,v 1.5 2004/12/08 17:38:28 lha Exp $
+.\"
+.Dd December  8, 2004
+.Dt KDESTROY 1
+.Os HEIMDAL
+.Sh NAME
+.Nm kdestroy
+.Nd destroy the current ticket file
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Op Fl c Ar cachefile
+.Op Fl -cache= Ns Ar cachefile
+.Op Fl -no-unlog
+.Op Fl -no-delete-v4
+.Op Fl -version
+.Op Fl -help
+.Ek
+.Sh DESCRIPTION
+.Nm
+removes the current set of tickets.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Fl c Ar cachefile
+.It Fl cache= Ns Ar cachefile
+The cache file to remove.
+.It Fl -no-unlog
+Do not remove AFS tokens.
+.It Fl -no-delete-v4
+Do not remove v4 tickets.
+.El
+.Sh SEE ALSO
+.Xr kinit 1 ,
+.Xr klist 1
diff --git a/src/kerberosV/src/kuser/kdestroy.c b/src/kerberosV/src/kuser/kdestroy.c
new file mode 100644 (file)
index 0000000..9ef6fd9
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997 - 2000, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+RCSID("$KTH: kdestroy.c,v 1.16 2004/04/17 17:00:06 lha Exp $");
+
+static const char *cache;
+static const char *credential;
+static int help_flag;
+static int version_flag;
+static int unlog_flag = 1;
+static int dest_tkt_flag = 1;
+
+struct getargs args[] = {
+    { "credential",    0,   arg_string, &credential,
+      "remove one credential", "principal" },
+    { "cache",         'c', arg_string, &cache, "cache to destroy", "cache" },
+    { "unlog",         0,   arg_negative_flag, &unlog_flag,
+      "do not destroy tokens", NULL },
+    { "delete-v4",     0,   arg_negative_flag, &dest_tkt_flag,
+      "do not destroy v4 tickets", NULL },
+    { "version",       0,   arg_flag, &version_flag, NULL, NULL },
+    { "help",          'h', arg_flag, &help_flag, NULL, NULL}
+};
+
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage (int status)
+{
+    arg_printusage (args, num_args, NULL, "");
+    exit (status);
+}
+
+int
+main (int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_ccache  ccache;
+    int optind = 0;
+    int exit_val = 0;
+
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+  
+    if (help_flag)
+       usage (0);
+  
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+  
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0)
+       usage (1);
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+  
+    if(cache == NULL) {
+       cache = krb5_cc_default_name(context);
+       if (cache == NULL) {
+           warnx ("krb5_cc_default_name: %s", krb5_get_err_text(context, ret));
+           exit(1);
+       }
+    }
+
+    ret =  krb5_cc_resolve(context,
+                          cache, 
+                          &ccache);
+
+    if (ret == 0) {
+       if (credential) {
+           krb5_creds mcred;
+           
+           krb5_cc_clear_mcred(&mcred);
+
+           ret = krb5_parse_name(context, credential, &mcred.server);
+           if (ret)
+               krb5_err(context, 1, ret,
+                        "Can't parse principal %s", credential);
+
+           ret = krb5_cc_remove_cred(context, ccache, 0, &mcred);
+           if (ret)
+               krb5_err(context, 1, ret, 
+                        "Failed to remove principal %s", credential);
+
+           krb5_free_context(context);
+           return 0;
+       }
+
+       ret = krb5_cc_destroy (context, ccache);
+       if (ret) {
+           warnx ("krb5_cc_destroy: %s", krb5_get_err_text(context, ret));
+           exit_val = 1;
+       }
+    } else {
+       warnx ("krb5_cc_resolve(%s): %s", cache,
+              krb5_get_err_text(context, ret));
+       exit_val = 1;
+    }
+
+    krb5_free_context (context);
+
+#if KRB4
+    if(dest_tkt_flag && dest_tkt ())
+       exit_val = 1;
+#endif
+    if (unlog_flag && k_hasafs ()) {
+       if (k_unlog ())
+           exit_val = 1;
+    }
+
+    return exit_val;
+}
diff --git a/src/kerberosV/src/kuser/kgetcred.1 b/src/kerberosV/src/kuser/kgetcred.1
new file mode 100644 (file)
index 0000000..e5e24ff
--- /dev/null
@@ -0,0 +1,91 @@
+.\" Copyright (c) 1999, 2001 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: kgetcred.1,v 1.9 2004/08/05 18:49:47 lha Exp $
+.\"
+.Dd March 12, 2004
+.Dt KGETCRED 1
+.Os HEIMDAL
+.Sh NAME
+.Nm kgetcred
+.Nd "get a ticket for a particular service"
+.Sh SYNOPSIS
+.Nm
+.Op Fl -canonicalize
+.Oo Fl c cache \*(Ba Xo
+.Fl -cache= Ns Ar cache
+.Xc
+.Oc
+.Oo Fl e Ar enctype \*(Ba Xo
+.Fl -enctype= Ns Ar enctype
+.Xc
+.Oc
+.Op Fl -no-transit-check
+.Op Fl -version
+.Op Fl -help
+.Ar service
+.Sh DESCRIPTION
+.Nm
+obtains a ticket for a service.
+Usually tickets for services are obtained automatically when needed
+but sometimes for some odd reason you want to obtain a particular
+ticket or of a special type.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl -canonicalize
+.Xc
+requests that the KDC canonicalize the principal.
+.It Xo
+.Fl c Ar cache ,
+.Fl -cache= Ns Ar cache
+.Xc
+the credential cache to use.
+.It Xo
+.Fl e Ar enctype ,
+.Fl -enctype= Ns Ar enctype
+.Xc
+encryption type to use.
+.It Xo
+.Fl -no-transit-check
+.Xc
+requests that the KDC doesn't do trasnit checking.
+.It Xo
+.Fl -version
+.Xc
+.It Xo
+.Fl -help
+.Xc
+.El
+.Sh SEE ALSO
+.Xr kinit 1 ,
+.Xr klist 1
diff --git a/src/kerberosV/src/kuser/kgetcred.c b/src/kerberosV/src/kuser/kgetcred.c
new file mode 100644 (file)
index 0000000..3b9e9ae
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+
+RCSID("$KTH: kgetcred.c,v 1.9 2004/08/05 18:49:25 lha Exp $");
+
+static char *cache_str;
+static char *etype_str;
+static int version_flag;
+static int help_flag;
+static int transit_check = 1;
+static int canonicalize = 0;
+
+struct getargs args[] = {
+    { "cache",         'c', arg_string, &cache_str,
+      "credential cache to use", "cache"},
+    { "enctype",       'e', arg_string, &etype_str,
+      "encryption type to use", "enctype"},
+    { "transit-check", 0,   arg_negative_flag, &transit_check },
+    { "canonicalize",  0,   arg_flag, &canonicalize },
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "service");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_ccache cache;
+    krb5_creds in, *out;
+    krb5_kdc_flags flags;
+    int optind = 0;
+
+    flags.i = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx(1, "krb5_init_context failed: %d", ret);
+  
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 1)
+       usage (1);
+
+    ret = krb5_cc_default(context, &cache);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_default");
+
+    if(cache_str) {
+       ret = krb5_cc_resolve(context, cache_str, &cache);
+       if (ret)
+           krb5_err (context, 1, ret, "%s", cache_str);
+    } else {
+       ret = krb5_cc_default (context, &cache);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_resolve");
+    }
+
+    memset(&in, 0, sizeof(in));
+
+    if (etype_str) {
+       krb5_enctype enctype;
+
+       ret = krb5_string_to_enctype(context, etype_str, &enctype);
+       if (ret)
+           krb5_errx (context, 1, "unrecognized enctype: %s", etype_str);
+       in.session.keytype = enctype;
+    }
+
+    ret = krb5_cc_get_principal(context, cache, &in.client);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_get_principal");
+
+    ret = krb5_parse_name(context, argv[0], &in.server);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]);
+
+    if (!transit_check)
+       flags.b.disable_transited_check = 1;
+    if (canonicalize)
+       flags.b.canonicalize = 1;
+
+
+    in.times.endtime = 0;
+    ret = krb5_get_credentials_with_flags(context, 0, flags, cache, &in, &out);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_get_credentials");
+
+    krb5_free_cred_contents(context, out);
+    return 0;
+}
diff --git a/src/kerberosV/src/kuser/kinit.1 b/src/kerberosV/src/kuser/kinit.1
new file mode 100644 (file)
index 0000000..6062e31
--- /dev/null
@@ -0,0 +1,280 @@
+.\" Copyright (c) 1998 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: kinit.1,v 1.25 2003/06/23 11:39:49 joda Exp $
+.\"
+.Dd May 29, 1998
+.Dt KINIT 1
+.Os HEIMDAL
+.Sh NAME
+.Nm kinit
+.Nm kauth
+.Nd acquire initial tickets
+.Sh SYNOPSIS
+.Nm kinit
+.Op Fl 4 | Fl -524init
+.Op Fl 9 | Fl -524convert
+.Op Fl -afslog
+.Oo Fl c Ar cachename \*(Ba Xo
+.Fl -cache= Ns Ar cachename
+.Xc
+.Oc
+.Op Fl f | Fl -forwardable
+.Oo Fl t Ar keytabname \*(Ba Xo
+.Fl -keytab= Ns Ar keytabname
+.Xc
+.Oc
+.Oo Fl l Ar time \*(Ba Xo
+.Fl -lifetime= Ns Ar time
+.Xc
+.Oc
+.Op Fl p | Fl -proxiable
+.Op Fl R | Fl -renew
+.Op Fl -renewable
+.Oo Fl r Ar time \*(Ba Xo
+.Fl -renewable-life= Ns Ar time
+.Xc
+.Oc
+.Oo Fl S Ar principal \*(Ba Xo
+.Fl -server= Ns Ar principal
+.Xc
+.Oc
+.Oo Fl s Ar time \*(Ba Xo
+.Fl -start-time= Ns Ar time
+.Xc
+.Oc
+.Op Fl k | Fl -use-keytab
+.Op Fl v | Fl -validate
+.Oo Fl e Ar enctypes \*(Ba Xo
+.Fl -enctypes= Ns Ar enctypes
+.Xc
+.Oc
+.Oo Fl a Ar addresses \*(Ba Xo
+.Fl -extra-addresses= Ns Ar addresses
+.Xc
+.Oc
+.Op Fl -fcache-version= Ns Ar integer
+.Op Fl A | Fl -no-addresses
+.Op Fl -anonymous
+.Op Fl -version
+.Op Fl -help
+.Op Ar principal Op Ar command
+.Sh DESCRIPTION
+.Nm
+is used to authenticate to the Kerberos server as
+.Ar principal ,
+or if none is given, a system generated default (typically your login
+name at the default realm), and acquire a ticket granting ticket that
+can later be used to obtain tickets for other services.
+.Pp
+If you have compiled
+.Nm kinit
+with Kerberos 4 support and you have a
+Kerberos 4 server,
+.Nm
+will detect this and get you Kerberos 4 tickets.
+.Pp
+Supported options:
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar cachename
+.Fl -cache= Ns Ar cachename
+.Xc
+The credentials cache to put the acquired ticket in, if other than
+default.
+.It Xo
+.Fl f ,
+.Fl -forwardable
+.Xc
+Get ticket that can be forwarded to another host.
+.It Xo
+.Fl t Ar keytabname ,
+.Fl -keytab= Ns Ar keytabname
+.Xc
+Don't ask for a password, but instead get the key from the specified
+keytab.
+.It Xo
+.Fl l Ar time ,
+.Fl -lifetime= Ns Ar time
+.Xc
+Specifies the lifetime of the ticket.
+The argument can either be in seconds, or a more human readable string
+like
+.Sq 1h .
+.It Xo
+.Fl p ,
+.Fl -proxiable
+.Xc
+Request tickets with the proxiable flag set.
+.It Xo
+.Fl R ,
+.Fl -renew
+.Xc
+Try to renew ticket.
+The ticket must have the
+.Sq renewable
+flag set, and must not be expired.
+.It Fl -renewable
+The same as
+.Fl -renewable-life ,
+with an infinite time.
+.It Xo
+.Fl r Ar time ,
+.Fl -renewable-life= Ns Ar time
+.Xc
+The max renewable ticket life.
+.It Xo
+.Fl S Ar principal ,
+.Fl -server= Ns Ar principal
+.Xc
+Get a ticket for a service other than krbtgt/LOCAL.REALM.
+.It Xo
+.Fl s Ar time ,
+.Fl -start-time= Ns Ar time
+.Xc
+Obtain a ticket that starts to be valid
+.Ar time
+(which can really be a generic time specification, like
+.Sq 1h )
+seconds into the future.
+.It Xo
+.Fl k ,
+.Fl -use-keytab
+.Xc
+The same as
+.Fl -keytab ,
+but with the default keytab name (normally
+.Ar FILE:/etc/kerberosV/krb5.keytab ) .
+.It Xo
+.Fl v ,
+.Fl -validate
+.Xc
+Try to validate an invalid ticket.
+.It Xo
+.Fl e ,
+.Fl -enctypes= Ns Ar enctypes
+.Xc
+Request tickets with this particular enctype.
+.It Xo
+.Fl -fcache-version= Ns Ar version
+.Xc
+Create a credentials cache of version
+.Nm version .
+.It Xo
+.Fl a ,
+.Fl -extra-addresses= Ns Ar enctypes
+.Xc
+Adds a set of addresses that will, in addition to the systems local
+addresses, be put in the ticket.
+This can be useful if all addresses a client can use can't be
+automatically figured out.
+One such example is if the client is behind a firewall.
+Also settable via
+.Li libdefaults/extra_addresses
+in
+.Xr krb5.conf 5 .
+.It Xo
+.Fl A ,
+.Fl -no-addresses
+.Xc
+Request a ticket with no addresses.
+.It Xo
+.Fl -anonymous
+.Xc
+Request an anonymous ticket (which means that the ticket will be
+issued to an anonymous principal, typically
+.Dq anonymous@REALM ) .
+.El
+.Pp
+The following options are only available if
+.Nm
+has been compiled with support for Kerberos 4.
+.Bl -tag -width Ds
+.It Xo
+.Fl 4 ,
+.Fl -524init
+.Xc
+Try to convert the obtained Kerberos 5 krbtgt to a version 4
+compatible ticket.
+It will store this ticket in the default Kerberos 4 ticket file.
+.It Xo
+.Fl 9 ,
+.Fl -524convert
+.Xc
+only convert ticket to version 4
+.It Fl -afslog
+Gets AFS tickets, converts them to version 4 format, and stores them
+in the kernel.
+Only useful if you have AFS.
+.El
+.Pp
+The
+.Ar forwardable ,
+.Ar proxiable ,
+.Ar ticket_life ,
+and
+.Ar renewable_life
+options can be set to a default value from the
+.Dv appdefaults
+section in krb5.conf, see
+.Xr krb5_appdefault 3 .
+.Pp
+If  a
+.Ar command
+is given,
+.Nm kinit
+will set up new credentials caches, and AFS PAG, and then run the given
+command.
+When it finishes the credentials will be removed.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev KRB5CCNAME
+Specifies the default credentials cache.
+.It Ev KRB5_CONFIG
+The file name of
+.Pa krb5.conf ,
+the default being
+.Pa /etc/kerberosV/krb5.conf .
+.It Ev KRBTKFILE
+Specifies the Kerberos 4 ticket file to store version 4 tickets in.
+.El
+.\".Sh FILES
+.\".Sh EXAMPLES
+.\".Sh DIAGNOSTICS
+.Sh SEE ALSO
+.Xr kdestroy 1 ,
+.Xr klist 1 ,
+.Xr krb5_appdefault 3 ,
+.Xr krb5.conf 5
+.\".Sh STANDARDS
+.\".Sh HISTORY
+.\".Sh AUTHORS
+.\".Sh BUGS
diff --git a/src/kerberosV/src/kuser/kinit.c b/src/kerberosV/src/kuser/kinit.c
new file mode 100644 (file)
index 0000000..82782d6
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+RCSID("$KTH: kinit.c,v 1.121 2005/06/14 00:14:43 lha Exp $");
+
+#ifndef KRB4
+#include "krb5-v4compat.h"
+#endif
+
+struct krb5_pk_identity;
+struct krb5_pk_cert;
+struct ContentInfo;
+struct _krb5_krb_auth_data;
+#include "krb5-private.h"
+
+int forwardable_flag   = -1;
+int proxiable_flag     = -1;
+int renewable_flag     = -1;
+int renew_flag         = 0;
+int pac_flag           = -1;
+int validate_flag      = 0;
+int version_flag       = 0;
+int help_flag          = 0;
+int addrs_flag         = 1;
+struct getarg_strings extra_addresses;
+int anonymous_flag     = 0;
+char *lifetime                 = NULL;
+char *renew_life       = NULL;
+char *server           = NULL;
+char *cred_cache       = NULL;
+char *start_str                = NULL;
+struct getarg_strings etype_str;
+int use_keytab         = 0;
+char *keytab_str       = NULL;
+int do_afslog          = -1;
+int get_v4_tgt         = -1;
+int convert_524                = 0;
+int fcache_version;
+char *pk_user_id       = NULL;
+char *pk_x509_anchors  = NULL;
+int pk_use_dh          = -1;
+
+static char *krb4_cc_name;
+
+static struct getargs args[] = {
+    /* 
+     * used by MIT
+     * a: ~A
+     * V: verbose
+     * F: ~f
+     * P: ~p
+     * C: v4 cache name?
+     * 5: 
+     */
+    { "524init",       '4', arg_flag, &get_v4_tgt,
+      "obtain version 4 TGT" },
+
+    { "524convert",    '9', arg_flag, &convert_524,
+      "only convert ticket to version 4" },
+
+    { "afslog",        0  , arg_flag, &do_afslog,
+      "obtain afs tokens"  },
+
+    { "cache",                 'c', arg_string, &cred_cache,
+      "credentials cache", "cachename" },
+
+    { "forwardable",   'f', arg_flag, &forwardable_flag,
+      "get forwardable tickets"},
+
+    { "keytab",         't', arg_string, &keytab_str,
+      "keytab to use", "keytabname" },
+
+    { "lifetime",      'l', arg_string, &lifetime,
+      "lifetime of tickets", "time"},
+
+    { "proxiable",     'p', arg_flag, &proxiable_flag,
+      "get proxiable tickets" },
+
+    { "renew",          'R', arg_flag, &renew_flag,
+      "renew TGT" },
+
+    { "renewable",     0,   arg_flag, &renewable_flag,
+      "get renewable tickets" },
+
+    { "renewable-life",        'r', arg_string, &renew_life,
+      "renewable lifetime of tickets", "time" },
+
+    { "server",        'S', arg_string, &server,
+      "server to get ticket for", "principal" },
+
+    { "start-time",    's', arg_string, &start_str,
+      "when ticket gets valid", "time" },
+
+    { "use-keytab",     'k', arg_flag, &use_keytab,
+      "get key from keytab" },
+
+    { "validate",      'v', arg_flag, &validate_flag,
+      "validate TGT" },
+
+    { "enctypes",      'e', arg_strings, &etype_str,
+      "encryption types to use", "enctypes" },
+
+    { "fcache-version", 0,   arg_integer, &fcache_version,
+      "file cache version to create" },
+
+    { "addresses",     'A',   arg_negative_flag,       &addrs_flag,
+      "request a ticket with no addresses" },
+
+    { "extra-addresses",'a', arg_strings,      &extra_addresses,
+      "include these extra addresses", "addresses" },
+
+    { "anonymous",     0,   arg_flag,  &anonymous_flag,
+      "request an anonymous ticket" },
+
+    { "request-pac",   0,   arg_flag,  &pac_flag,
+      "request a Windows PAC" },
+
+#ifdef PKINIT
+    {  "pk-user",      'C',    arg_string,     &pk_user_id,
+       "principal's public/private/certificate identifier",
+       "id" },
+
+    {  "x509-anchors", 'D',  arg_string, &pk_x509_anchors,
+       "directory with CA certificates", "directory" },
+
+    {  "pkinit-use-dh",       0,  arg_flag, &pk_use_dh,
+       "make pkinit use DH" },
+#endif
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "[principal [command]]");
+    exit (ret);
+}
+
+#ifdef KRB4
+/* for when the KDC tells us it's a v4 one, we try to talk that */
+
+static int
+key_to_key(const char *user,
+          char *instance,
+          const char *realm,
+          const void *arg,
+          des_cblock *key)
+{
+    memcpy(key, arg, sizeof(des_cblock));
+    return 0;
+}
+
+static int
+do_v4_fallback (krb5_context context,
+               const krb5_principal principal,
+               int lifetime,
+               int use_srvtab, const char *srvtab_str,
+               const char *passwd)
+{
+    int ret;
+    krb_principal princ;
+    des_cblock key;
+    krb5_error_code kret;
+
+    if (lifetime == 0)
+       lifetime = DEFAULT_TKT_LIFE;
+    else
+       lifetime = krb_time_to_life (0, lifetime);
+
+    kret = krb5_524_conv_principal (context, principal,
+                                   princ.name,
+                                   princ.instance,
+                                   princ.realm);
+    if (kret) {
+       krb5_warn (context, kret, "krb5_524_conv_principal");
+       return 1;
+    }
+
+    if (use_srvtab || srvtab_str) {
+       if (srvtab_str == NULL)
+           srvtab_str = KEYFILE;
+
+       ret = read_service_key (princ.name, princ.instance, princ.realm,
+                               0, srvtab_str, (char *)&key);
+       if (ret) {
+           warnx ("read_service_key %s: %s", srvtab_str,
+                  krb_get_err_text (ret));
+           return 1;
+       }
+       ret = krb_get_in_tkt (princ.name, princ.instance, princ.realm,
+                             KRB_TICKET_GRANTING_TICKET, princ.realm,
+                             lifetime, key_to_key, NULL, key);
+    } else {
+       ret = krb_get_pw_in_tkt(princ.name, princ.instance, princ.realm, 
+                               KRB_TICKET_GRANTING_TICKET, princ.realm, 
+                               lifetime, passwd);
+    }
+    memset (key, 0, sizeof(key));
+    if (ret) {
+       warnx ("%s", krb_get_err_text(ret));
+       return 1;
+    }
+    if (do_afslog && k_hasafs()) {
+       if ((ret = krb_afslog(NULL, NULL)) != 0 && ret != KDC_PR_UNKNOWN) {
+           if(ret > 0)
+               warnx ("%s", krb_get_err_text(ret));
+           else
+               warnx ("failed to store AFS token");
+       }
+    }
+    return 0;
+}
+
+
+/*
+ * the special version of get_default_principal that takes v4 into account
+ */
+
+static krb5_error_code
+kinit_get_default_principal (krb5_context context,
+                            krb5_principal *princ)
+{
+    krb5_error_code ret;
+    krb5_ccache id;
+    krb_principal v4_princ;
+    int kret;
+
+    ret = krb5_cc_default (context, &id);
+    if (ret == 0) {
+       ret = krb5_cc_get_principal (context, id, princ);
+       krb5_cc_close (context, id);
+       if (ret == 0)
+           return 0;
+    }
+
+    kret = krb_get_tf_fullname (tkt_string(),
+                               v4_princ.name,
+                               v4_princ.instance,
+                               v4_princ.realm);
+    if (kret == KSUCCESS) {
+       ret = krb5_425_conv_principal (context,
+                                      v4_princ.name,
+                                      v4_princ.instance,
+                                      v4_princ.realm,
+                                      princ);
+       if (ret == 0)
+           return 0;
+    }
+    return krb5_get_default_principal (context, princ);
+}
+
+#else /* !KRB4 */
+
+static krb5_error_code
+kinit_get_default_principal (krb5_context context,
+                            krb5_principal *princ)
+{
+    return krb5_get_default_principal (context, princ);
+}
+
+#endif /* !KRB4 */
+
+static krb5_error_code
+get_server(krb5_context context,
+          krb5_principal client,
+          const char *server,
+          krb5_principal *princ)
+{
+    krb5_realm *client_realm;
+    if(server)
+       return krb5_parse_name(context, server, princ);
+
+    client_realm = krb5_princ_realm (context, client);
+    return krb5_make_principal(context, princ, *client_realm,
+                              KRB5_TGS_NAME, *client_realm, NULL);
+}
+
+static krb5_error_code
+do_524init(krb5_context context, krb5_ccache ccache, 
+          krb5_creds *creds, const char *server)
+{
+    krb5_error_code ret;
+
+    struct credentials c;
+    krb5_creds in_creds, *real_creds;
+
+    if(creds != NULL)
+       real_creds = creds;
+    else {
+       krb5_principal client;
+       krb5_cc_get_principal(context, ccache, &client);
+       memset(&in_creds, 0, sizeof(in_creds));
+       ret = get_server(context, client, server, &in_creds.server);
+       if(ret) {
+           krb5_free_principal(context, client);
+           return ret;
+       }
+       in_creds.client = client;
+       ret = krb5_get_credentials(context, 0, ccache, &in_creds, &real_creds);
+       krb5_free_principal(context, client);
+       krb5_free_principal(context, in_creds.server);
+       if(ret)
+           return ret;
+    }
+    ret = krb524_convert_creds_kdc_ccache(context, ccache, real_creds, &c);
+    if(ret)
+       krb5_warn(context, ret, "converting creds");
+    else {
+       krb5_error_code tret = _krb5_krb_tf_setup(context, &c, NULL, 0);
+       if(tret)
+           krb5_warn(context, tret, "saving v4 creds");
+    }
+
+    if(creds == NULL)
+       krb5_free_creds(context, real_creds);
+    memset(&c, 0, sizeof(c));
+
+    return ret;
+}
+
+static int
+renew_validate(krb5_context context, 
+              int renew,
+              int validate,
+              krb5_ccache cache, 
+              const char *server,
+              krb5_deltat life)
+{
+    krb5_error_code ret;
+    krb5_creds in, *out;
+    krb5_kdc_flags flags;
+
+    memset(&in, 0, sizeof(in));
+
+    ret = krb5_cc_get_principal(context, cache, &in.client);
+    if(ret) {
+       krb5_warn(context, ret, "krb5_cc_get_principal");
+       return ret;
+    }
+    ret = get_server(context, in.client, server, &in.server);
+    if(ret) {
+       krb5_warn(context, ret, "get_server");
+       goto out;
+    }
+    flags.i = 0;
+    flags.b.renewable         = flags.b.renew = renew;
+    flags.b.validate          = validate;
+    if (forwardable_flag != -1)
+       flags.b.forwardable       = forwardable_flag;
+    if (proxiable_flag != -1)
+       flags.b.proxiable         = proxiable_flag;
+    if (anonymous_flag != -1)
+       flags.b.request_anonymous = anonymous_flag;
+    if(life)
+       in.times.endtime = time(NULL) + life;
+
+    ret = krb5_get_kdc_cred(context,
+                           cache,
+                           flags,
+                           NULL,
+                           NULL,
+                           &in,
+                           &out);
+    if(ret) {
+       krb5_warn(context, ret, "krb5_get_kdc_cred");
+       goto out;
+    }
+    ret = krb5_cc_initialize(context, cache, in.client);
+    if(ret) {
+       krb5_free_creds (context, out);
+       krb5_warn(context, ret, "krb5_cc_initialize");
+       goto out;
+    }
+    ret = krb5_cc_store_cred(context, cache, out);
+
+    if(ret == 0 && server == NULL) {
+       /* only do this if it's a general renew-my-tgt request */
+       if(get_v4_tgt)
+           do_524init(context, cache, out, NULL);
+       if(do_afslog && k_hasafs())
+           krb5_afslog(context, cache, NULL, NULL);
+    }
+
+    krb5_free_creds (context, out);
+    if(ret) {
+       krb5_warn(context, ret, "krb5_cc_store_cred");
+       goto out;
+    }
+out:
+    krb5_free_cred_contents(context, &in);
+    return ret;
+}
+
+static krb5_error_code
+get_new_tickets(krb5_context context, 
+               krb5_principal principal,
+               krb5_ccache ccache,
+               krb5_deltat ticket_life,
+               int interactive)
+{
+    krb5_error_code ret;
+    krb5_get_init_creds_opt *opt;
+    krb5_addresses no_addrs;
+    krb5_creds cred;
+    char passwd[256];
+    krb5_deltat start_time = 0;
+    krb5_deltat renew = 0;
+    char *renewstr = NULL;
+
+    memset(&cred, 0, sizeof(cred));
+
+    ret = krb5_get_init_creds_opt_alloc (context, &opt);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
+    
+    krb5_get_init_creds_opt_set_default_flags(context, "kinit", 
+                                             /* XXX */principal->realm, opt);
+
+    if(forwardable_flag != -1)
+       krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);
+    if(proxiable_flag != -1)
+       krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
+    if(anonymous_flag != -1)
+       krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
+    if (pac_flag != -1)
+       krb5_get_init_creds_opt_set_pac_request(context, opt, 
+                                               pac_flag ? TRUE : FALSE);
+    if (pk_user_id) {
+       int flags = 0;
+       if (pk_use_dh == 1)
+           flags |= 1;
+       ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
+                                                principal,
+                                                pk_user_id,
+                                                pk_x509_anchors,
+                                                flags,
+                                                NULL,
+                                                NULL,
+                                                NULL);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_get_init_creds_opt_set_pkinit");
+    }
+
+    if (!addrs_flag) {
+       no_addrs.len = 0;
+       no_addrs.val = NULL;
+
+       krb5_get_init_creds_opt_set_address_list (opt, &no_addrs);
+    }
+
+    if (renew_life == NULL && renewable_flag)
+       renewstr = "1 month";
+    if (renew_life)
+       renewstr = renew_life;
+    if (renewstr) {
+       renew = parse_time (renewstr, "s");
+       if (renew < 0)
+           errx (1, "unparsable time: %s", renewstr);
+       
+       krb5_get_init_creds_opt_set_renew_life (opt, renew);
+    }
+
+    if(ticket_life != 0)
+       krb5_get_init_creds_opt_set_tkt_life (opt, ticket_life);
+
+    if(start_str) {
+       int tmp = parse_time (start_str, "s");
+       if (tmp < 0)
+           errx (1, "unparsable time: %s", start_str);
+
+       start_time = tmp;
+    }
+
+    if(etype_str.num_strings) {
+       krb5_enctype *enctype = NULL;
+       int i;
+       enctype = malloc(etype_str.num_strings * sizeof(*enctype));
+       if(enctype == NULL)
+           errx(1, "out of memory");
+       for(i = 0; i < etype_str.num_strings; i++) {
+           ret = krb5_string_to_enctype(context, 
+                                        etype_str.strings[i], 
+                                        &enctype[i]);
+           if(ret)
+               errx(1, "unrecognized enctype: %s", etype_str.strings[i]);
+       }
+       krb5_get_init_creds_opt_set_etype_list(opt, enctype, 
+                                              etype_str.num_strings);
+    }
+
+    if(use_keytab || keytab_str) {
+       krb5_keytab kt;
+       if(keytab_str)
+           ret = krb5_kt_resolve(context, keytab_str, &kt);
+       else
+           ret = krb5_kt_default(context, &kt);
+       if (ret)
+           krb5_err (context, 1, ret, "resolving keytab");
+       ret = krb5_get_init_creds_keytab (context,
+                                         &cred,
+                                         principal,
+                                         kt,
+                                         start_time,
+                                         server,
+                                         opt);
+       krb5_kt_close(context, kt);
+    } else if (pk_user_id) {
+       ret = krb5_get_init_creds_password (context,
+                                           &cred,
+                                           principal,
+                                           NULL,
+                                           krb5_prompter_posix,
+                                           NULL,
+                                           start_time,
+                                           server,
+                                           opt);
+    } else if (!interactive) {
+       krb5_warnx(context, "Not interactive, failed to get initial ticket");
+       krb5_get_init_creds_opt_free(opt);
+       return 0;
+    } else {
+       char *p, *prompt;
+
+       krb5_unparse_name (context, principal, &p);
+       asprintf (&prompt, "%s's Password: ", p);
+       free (p);
+
+       if (UI_UTIL_read_pw_string(passwd, sizeof(passwd)-1, prompt, 0)){
+           memset(passwd, 0, sizeof(passwd));
+           exit(1);
+       }
+
+       free (prompt);
+       
+       ret = krb5_get_init_creds_password (context,
+                                           &cred,
+                                           principal,
+                                           passwd,
+                                           krb5_prompter_posix,
+                                           NULL,
+                                           start_time,
+                                           server,
+                                           opt);
+    }
+    krb5_get_init_creds_opt_free(opt);
+#ifdef KRB4
+    if (ret == KRB5KRB_AP_ERR_V4_REPLY || ret == KRB5_KDC_UNREACH) {
+       int exit_val;
+
+       exit_val = do_v4_fallback (context, principal, ticket_life,
+                                  use_keytab, keytab_str, passwd);
+       get_v4_tgt = 0;
+       do_afslog  = 0;
+       memset(passwd, 0, sizeof(passwd));
+       if (exit_val == 0 || ret == KRB5KRB_AP_ERR_V4_REPLY)
+           return exit_val;
+    }
+#endif
+    memset(passwd, 0, sizeof(passwd));
+
+    switch(ret){
+    case 0:
+       break;
+    case KRB5_LIBOS_PWDINTR: /* don't print anything if it was just C-c:ed */
+       exit(1);
+    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+    case KRB5KRB_AP_ERR_MODIFIED:
+       krb5_errx(context, 1, "Password incorrect");
+       break;
+    default:
+       krb5_err(context, 1, ret, "krb5_get_init_creds");
+    }
+
+    if(ticket_life != 0) {
+       if(abs(cred.times.endtime - cred.times.starttime - ticket_life) > 30) {
+           char life[64];
+           unparse_time_approx(cred.times.endtime - cred.times.starttime, 
+                               life, sizeof(life));
+           krb5_warnx(context, "NOTICE: ticket lifetime is %s", life);
+       }
+    }
+    if(renew_life) {
+       if(abs(cred.times.renew_till - cred.times.starttime - renew) > 30) {
+           char life[64];
+           unparse_time_approx(cred.times.renew_till - cred.times.starttime, 
+                               life, sizeof(life));
+           krb5_warnx(context, "NOTICE: ticket renewable lifetime is %s", 
+                      life);
+       }
+    }
+
+    ret = krb5_cc_initialize (context, ccache, cred.client);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_initialize");
+    
+    ret = krb5_cc_store_cred (context, ccache, &cred);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_store_cred");
+
+    krb5_free_cred_contents (context, &cred);
+
+    return 0;
+}
+
+static time_t
+ticket_lifetime(krb5_context context, krb5_ccache cache, 
+               krb5_principal client, const char *server)
+{
+    krb5_creds in_cred, *cred;
+    krb5_error_code ret;
+    time_t timeout;
+
+    memset(&in_cred, 0, sizeof(in_cred));
+
+    ret = krb5_cc_get_principal(context, cache, &in_cred.client);
+    if(ret) {
+       krb5_warn(context, ret, "krb5_cc_get_principal");
+       return 0;
+    }
+    ret = get_server(context, in_cred.client, server, &in_cred.server);
+    if(ret) {
+       krb5_free_principal(context, in_cred.client);
+       krb5_warn(context, ret, "get_server");
+       return 0;
+    }
+
+    ret = krb5_get_credentials(context, KRB5_GC_CACHED,
+                              cache, &in_cred, &cred);
+    krb5_free_principal(context, in_cred.client);
+    krb5_free_principal(context, in_cred.server);
+    if(ret) {
+       krb5_warn(context, ret, "krb5_get_credentials");
+       return 0;
+    }
+    timeout = cred->times.endtime - cred->times.starttime;
+    if (timeout < 0)
+       timeout = 0;
+    krb5_free_creds(context, cred);
+    return timeout;
+}
+
+struct renew_ctx {
+    krb5_context context;
+    krb5_ccache  ccache;
+    krb5_principal principal;
+    krb5_deltat ticket_life;
+};
+
+static time_t
+renew_func(void *ptr)
+{
+    struct renew_ctx *ctx = ptr;
+    krb5_error_code ret;
+    time_t expire;
+
+
+    ret = renew_validate(ctx->context, renewable_flag, validate_flag,
+                            ctx->ccache, server, ctx->ticket_life);
+    if (ret)
+       get_new_tickets(ctx->context, ctx->principal, 
+                       ctx->ccache, ctx->ticket_life, 0);
+
+    if(get_v4_tgt || convert_524)
+       do_524init(ctx->context, ctx->ccache, NULL, server);
+    if(do_afslog && k_hasafs())
+       krb5_afslog(ctx->context, ctx->ccache, NULL, NULL);
+
+    expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
+                            server) / 2;
+    return expire + 1;
+}
+
+int
+main (int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_ccache  ccache;
+    krb5_principal principal;
+    int optind = 0;
+    krb5_deltat ticket_life = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret == KRB5_CONFIG_BADFORMAT)
+       errx (1, "krb5_init_context failed to parse configuration file");
+    else if (ret)
+       errx(1, "krb5_init_context failed: %d", ret);
+  
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argv[0]) {
+       ret = krb5_parse_name (context, argv[0], &principal);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_parse_name");
+    } else {
+       ret = kinit_get_default_principal (context, &principal);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_get_default_principal");
+    }
+
+    if(fcache_version)
+       krb5_set_fcache_version(context, fcache_version);
+
+    if(cred_cache) 
+       ret = krb5_cc_resolve(context, cred_cache, &ccache);
+    else {
+       if(argc > 1) {
+           char s[1024];
+           ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache);
+           if(ret)
+               krb5_err(context, 1, ret, "creating cred cache");
+           snprintf(s, sizeof(s), "%s:%s",
+                    krb5_cc_get_type(context, ccache),
+                    krb5_cc_get_name(context, ccache));
+           setenv("KRB5CCNAME", s, 1);
+           if (get_v4_tgt) {
+               int fd;
+               if (asprintf(&krb4_cc_name, "%s_XXXXXXXXXXX", TKT_ROOT) < 0)
+                   krb5_errx(context, 1, "out of memory");
+               if((fd = mkstemp(krb4_cc_name)) >= 0) {
+                   close(fd);
+                   setenv("KRBTKFILE", krb4_cc_name, 1);
+               } else {
+                   free(krb4_cc_name);
+                   krb4_cc_name = NULL;
+               }
+           }
+       } else
+           ret = krb5_cc_default (context, &ccache);
+    }
+    if (ret)
+       krb5_err (context, 1, ret, "resolving credentials cache");
+
+    if(argc > 1 && k_hasafs ())
+       k_setpag();
+
+    if (lifetime) {
+       int tmp = parse_time (lifetime, "s");
+       if (tmp < 0)
+           errx (1, "unparsable time: %s", lifetime);
+
+       ticket_life = tmp;
+    }
+    if(renewable_flag == -1)
+       /* this seems somewhat pointless, but whatever */
+       krb5_appdefault_boolean(context, "kinit",
+                               krb5_principal_get_realm(context, principal),
+                               "renewable", FALSE, &renewable_flag);
+    if(get_v4_tgt == -1)
+       krb5_appdefault_boolean(context, "kinit", 
+                               krb5_principal_get_realm(context, principal), 
+                               "krb4_get_tickets", FALSE, &get_v4_tgt);
+    if(do_afslog == -1)
+       krb5_appdefault_boolean(context, "kinit", 
+                               krb5_principal_get_realm(context, principal), 
+                               "afslog", TRUE, &do_afslog);
+
+    if (pk_x509_anchors == NULL)
+       krb5_appdefault_string(context, "kinit",
+                              krb5_principal_get_realm(context, principal), 
+                              "pkinit-anchors", NULL, &pk_x509_anchors);
+
+#ifdef PKINIT
+    if(pk_use_dh == -1)
+       krb5_appdefault_boolean(context, "kinit", 
+                               krb5_principal_get_realm(context, principal), 
+                               "pkinit-use-dh", FALSE, &pk_use_dh);
+#endif
+
+    if(!addrs_flag && extra_addresses.num_strings > 0)
+       krb5_errx(context, 1, "specifying both extra addresses and "
+                 "no addresses makes no sense");
+    {
+       int i;
+       krb5_addresses addresses;
+       memset(&addresses, 0, sizeof(addresses));
+       for(i = 0; i < extra_addresses.num_strings; i++) {
+           ret = krb5_parse_address(context, extra_addresses.strings[i], 
+                                    &addresses);
+           if (ret == 0) {
+               krb5_add_extra_addresses(context, &addresses);
+               krb5_free_addresses(context, &addresses);
+           }
+       }
+       free_getarg_strings(&extra_addresses);
+    }
+
+    if(renew_flag || validate_flag) {
+       ret = renew_validate(context, renew_flag, validate_flag, 
+                            ccache, server, ticket_life);
+       exit(ret != 0);
+    }
+
+    if(!convert_524)
+       get_new_tickets(context, principal, ccache, ticket_life, 1);
+
+    if(get_v4_tgt || convert_524)
+       do_524init(context, ccache, NULL, server);
+    if(do_afslog && k_hasafs())
+       krb5_afslog(context, ccache, NULL, NULL);
+    if(argc > 1) {
+       struct renew_ctx ctx;
+       time_t timeout;
+
+       timeout = ticket_lifetime(context, ccache, principal, server) / 2;
+
+       ctx.context = context;
+       ctx.ccache = ccache;
+       ctx.principal = principal;
+       ctx.ticket_life = ticket_life;
+
+       ret = simple_execvp_timed(argv[1], argv+1, 
+                                 renew_func, &ctx, timeout);
+#define EX_NOEXEC      126
+#define EX_NOTFOUND    127
+       if(ret == EX_NOEXEC)
+           krb5_warnx(context, "permission denied: %s", argv[1]);
+       else if(ret == EX_NOTFOUND)
+           krb5_warnx(context, "command not found: %s", argv[1]);
+       
+       krb5_cc_destroy(context, ccache);
+       _krb5_krb_dest_tkt(context, krb4_cc_name);
+       if(k_hasafs())
+           k_unlog();
+    } else {
+       krb5_cc_close (context, ccache);
+       ret = 0;
+    }
+    krb5_free_principal(context, principal);
+    krb5_free_context (context);
+    return ret;
+}
diff --git a/src/kerberosV/src/kuser/kinit_options.c b/src/kerberosV/src/kuser/kinit_options.c
new file mode 100644 (file)
index 0000000..977a284
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+RCSID("$KTH: kinit_options.c,v 1.2 1999/12/02 17:05:01 joda Exp $");
+
+#ifdef KRB4
+int do_afslog          = 0;
+int get_v4_tgt         = 0;
+#endif
diff --git a/src/kerberosV/src/kuser/klist.1 b/src/kerberosV/src/kuser/klist.1
new file mode 100644 (file)
index 0000000..156f47a
--- /dev/null
@@ -0,0 +1,152 @@
+.\" Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: klist.1,v 1.14 2004/12/08 17:40:10 lha Exp $
+.\"
+.Dd December  8, 2004
+.Dt KLIST 1
+.Os HEIMDAL
+.Sh NAME
+.Nm klist
+.Nd list Kerberos credentials
+.Sh SYNOPSIS
+.Nm
+.Bk -words
+.Oo Fl c Ar cache \*(Ba Xo
+.Fl -cache= Ns Ar cache
+.Xc
+.Oc
+.Op Fl s | Fl t | Fl -test
+.Op Fl 4 | Fl -v4
+.Op Fl T | Fl -tokens
+.Op Fl 5 | Fl -v5
+.Op Fl v | Fl -verbose
+.Op Fl f
+.Op Fl -version
+.Op Fl -help
+.Ek
+.Sh DESCRIPTION
+.Nm
+reads and displays the current tickets in the credential cache (also
+known as the ticket file).
+.Pp
+Options supported:
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar cache ,
+.Fl -cache= Ns Ar cache
+.Xc
+credential cache to list
+.It Xo
+.Fl s ,
+.Fl t ,
+.Fl -test
+.Xc
+Test for there being an active and valid TGT for the local realm of
+the user in the credential cache.
+.It Xo
+.Fl 4 ,
+.Fl -v4
+.Xc
+display v4 tickets
+.It Xo
+.Fl T ,
+.Fl -tokens
+.Xc
+display AFS tokens
+.It Xo
+.Fl 5 ,
+.Fl -v5
+.Xc
+display v5 cred cache (this is the default)
+.It Fl f
+Include ticket flags in short form, each character stands for a
+specific flag, as follows:
+.Bl -tag -width  XXX -compact -offset indent
+.It F
+forwardable
+.It f
+forwarded
+.It P
+proxiable
+.It p
+proxied
+.It D
+postdate-able
+.It d
+postdated
+.It R
+renewable
+.It I
+initial
+.It i
+invalid
+.It A
+pre-authenticated
+.It H
+hardware authenticated
+.El
+.Pp
+This information is also output with the
+.Fl -verbose
+option, but in a more verbose way.
+.It Xo
+.Fl v ,
+.Fl -verbose
+.Xc
+Verbose output. Include all possible information:
+.Bl -tag -width XXXX -offset indent
+.It Server
+the principal the ticket is for
+.It Ticket etype
+the encryption type used in the ticket, followed by the key version of
+the ticket, if it is available
+.It Session key
+the encryption type of the session key, if it's different from the
+encryption type of the ticket
+.It Auth time
+the time the authentication exchange took place
+.It Start time
+the time that this ticket is valid from (only printed if it's
+different from the auth time)
+.It End time
+when the ticket expires, if it has already expired this is also noted
+.It Renew till
+the maximum possible end time of any ticket derived from this one
+.It Ticket flags
+the flags set on the ticket
+.It Addresses
+the set of addresses from which this ticket is valid
+.El
+.El
+.Sh SEE ALSO
+.Xr kdestroy 1 ,
+.Xr kinit 1
diff --git a/src/kerberosV/src/kuser/klist.c b/src/kerberosV/src/kuser/klist.c
new file mode 100644 (file)
index 0000000..791f76f
--- /dev/null
@@ -0,0 +1,688 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+#include "rtbl.h"
+
+RCSID("$KTH: klist.c,v 1.76 2005/04/24 19:47:44 lha Exp $");
+
+static char*
+printable_time(time_t t)
+{
+    static char s[128];
+    strlcpy(s, ctime(&t)+ 4, sizeof(s));
+    s[15] = 0;
+    return s;
+}
+
+static char*
+printable_time_long(time_t t)
+{
+    static char s[128];
+    strlcpy(s, ctime(&t)+ 4, sizeof(s));
+    s[20] = 0;
+    return s;
+}
+
+#define COL_ISSUED             "  Issued"
+#define COL_EXPIRES            "  Expires"
+#define COL_FLAGS              "Flags"
+#define COL_PRINCIPAL          "  Principal"
+#define COL_PRINCIPAL_KVNO     "  Principal (kvno)"
+
+static void
+print_cred(krb5_context context, krb5_creds *cred, rtbl_t ct, int do_flags)
+{
+    char *str;
+    krb5_error_code ret;
+    krb5_timestamp sec;
+
+    krb5_timeofday (context, &sec);
+
+
+    if(cred->times.starttime)
+       rtbl_add_column_entry(ct, COL_ISSUED,
+                             printable_time(cred->times.starttime));
+    else
+       rtbl_add_column_entry(ct, COL_ISSUED,
+                             printable_time(cred->times.authtime));
+    
+    if(cred->times.endtime > sec)
+       rtbl_add_column_entry(ct, COL_EXPIRES,
+                             printable_time(cred->times.endtime));
+    else
+       rtbl_add_column_entry(ct, COL_EXPIRES, ">>>Expired<<<");
+    ret = krb5_unparse_name (context, cred->server, &str);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_unparse_name");
+    rtbl_add_column_entry(ct, COL_PRINCIPAL, str);
+    if(do_flags) {
+       char s[16], *sp = s;
+       if(cred->flags.b.forwardable)
+           *sp++ = 'F';
+       if(cred->flags.b.forwarded)
+           *sp++ = 'f';
+       if(cred->flags.b.proxiable)
+           *sp++ = 'P';
+       if(cred->flags.b.proxy)
+           *sp++ = 'p';
+       if(cred->flags.b.may_postdate)
+           *sp++ = 'D';
+       if(cred->flags.b.postdated)
+           *sp++ = 'd';
+       if(cred->flags.b.renewable)
+           *sp++ = 'R';
+       if(cred->flags.b.initial)
+           *sp++ = 'I';
+       if(cred->flags.b.invalid)
+           *sp++ = 'i';
+       if(cred->flags.b.pre_authent)
+           *sp++ = 'A';
+       if(cred->flags.b.hw_authent)
+           *sp++ = 'H';
+       *sp++ = '\0';
+       rtbl_add_column_entry(ct, COL_FLAGS, s);
+    }
+    free(str);
+}
+
+static void
+print_cred_verbose(krb5_context context, krb5_creds *cred)
+{
+    int j;
+    char *str;
+    krb5_error_code ret;
+    int first_flag;
+    krb5_timestamp sec;
+
+    krb5_timeofday (context, &sec);
+
+    ret = krb5_unparse_name(context, cred->server, &str);
+    if(ret)
+       exit(1);
+    printf("Server: %s\n", str);
+    free (str);
+    {
+       Ticket t;
+       size_t len;
+       char *s;
+
+       decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
+       ret = krb5_enctype_to_string(context, t.enc_part.etype, &s);
+       printf("Ticket etype: ");
+       if (ret == 0) {
+           printf("%s", s);
+           free(s);
+       } else {
+           printf("unknown(%d)", t.enc_part.etype);
+       }
+       if(t.enc_part.kvno)
+           printf(", kvno %d", *t.enc_part.kvno);
+       printf("\n");
+       if(cred->session.keytype != t.enc_part.etype) {
+           ret = krb5_enctype_to_string(context, cred->session.keytype, &str);
+           if(ret)
+               krb5_warn(context, ret, "session keytype");
+           else {
+               printf("Session key: %s\n", str);
+               free(str);
+           }
+       }
+       free_Ticket(&t);
+    }
+    printf("Auth time:  %s\n", printable_time_long(cred->times.authtime));
+    if(cred->times.authtime != cred->times.starttime)
+       printf("Start time: %s\n", printable_time_long(cred->times.starttime));
+    printf("End time:   %s", printable_time_long(cred->times.endtime));
+    if(sec > cred->times.endtime)
+       printf(" (expired)");
+    printf("\n");
+    if(cred->flags.b.renewable)
+       printf("Renew till: %s\n", 
+              printable_time_long(cred->times.renew_till));
+    printf("Ticket flags: ");
+#define PRINT_FLAG2(f, s) if(cred->flags.b.f) { if(!first_flag) printf(", "); printf("%s", #s); first_flag = 0; }
+#define PRINT_FLAG(f) PRINT_FLAG2(f, f)
+    first_flag = 1;
+    PRINT_FLAG(forwardable);
+    PRINT_FLAG(forwarded);
+    PRINT_FLAG(proxiable);
+    PRINT_FLAG(proxy);
+    PRINT_FLAG2(may_postdate, may-postdate);
+    PRINT_FLAG(postdated);
+    PRINT_FLAG(invalid);
+    PRINT_FLAG(renewable);
+    PRINT_FLAG(initial);
+    PRINT_FLAG2(pre_authent, pre-authenticated);
+    PRINT_FLAG2(hw_authent, hw-authenticated);
+    PRINT_FLAG2(transited_policy_checked, transited-policy-checked);
+    PRINT_FLAG2(ok_as_delegate, ok-as-delegate);
+    PRINT_FLAG(anonymous);
+    printf("\n");
+    printf("Addresses: ");
+    for(j = 0; j < cred->addresses.len; j++){
+       char buf[128];
+       size_t len;
+       if(j) printf(", ");
+       ret = krb5_print_address(&cred->addresses.val[j], 
+                                buf, sizeof(buf), &len);
+
+       if(ret == 0)
+           printf("%s", buf);
+    }
+    printf("\n\n");
+}
+
+/*
+ * Print all tickets in `ccache' on stdout, verbosily iff do_verbose.
+ */
+
+static void
+print_tickets (krb5_context context,
+              krb5_ccache ccache,
+              krb5_principal principal,
+              int do_verbose,
+              int do_flags)
+{
+    krb5_error_code ret;
+    char *str;
+    krb5_cc_cursor cursor;
+    krb5_creds creds;
+
+    rtbl_t ct = NULL;
+
+    ret = krb5_unparse_name (context, principal, &str);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_unparse_name");
+
+    printf ("%17s: %s:%s\n", 
+           "Credentials cache",
+           krb5_cc_get_type(context, ccache),
+           krb5_cc_get_name(context, ccache));
+    printf ("%17s: %s\n", "Principal", str);
+    free (str);
+    
+    if(do_verbose)
+       printf ("%17s: %d\n", "Cache version",
+               krb5_cc_get_version(context, ccache));
+    
+    if (do_verbose && context->kdc_sec_offset) {
+       char buf[BUFSIZ];
+       int val;
+       int sig;
+
+       val = context->kdc_sec_offset;
+       sig = 1;
+       if (val < 0) {
+           sig = -1;
+           val = -val;
+       }
+       
+       unparse_time (val, buf, sizeof(buf));
+
+       printf ("%17s: %s%s\n", "KDC time offset",
+               sig == -1 ? "-" : "", buf);
+    }
+
+    printf("\n");
+
+    ret = krb5_cc_start_seq_get (context, ccache, &cursor);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_start_seq_get");
+
+    if(!do_verbose) {
+       ct = rtbl_create();
+       rtbl_add_column(ct, COL_ISSUED, 0);
+       rtbl_add_column(ct, COL_EXPIRES, 0);
+       if(do_flags)
+           rtbl_add_column(ct, COL_FLAGS, 0);
+       rtbl_add_column(ct, COL_PRINCIPAL, 0);
+       rtbl_set_separator(ct, "  ");
+    }
+    while ((ret = krb5_cc_next_cred (context,
+                                    ccache,
+                                    &cursor,
+                                    &creds)) == 0) {
+       if(do_verbose){
+           print_cred_verbose(context, &creds);
+       }else{
+           print_cred(context, &creds, ct, do_flags);
+       }
+       krb5_free_cred_contents (context, &creds);
+    }
+    if(ret != KRB5_CC_END)
+       krb5_err(context, 1, ret, "krb5_cc_get_next");
+    ret = krb5_cc_end_seq_get (context, ccache, &cursor);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_end_seq_get");
+    if(!do_verbose) {
+       rtbl_format(ct, stdout);
+       rtbl_destroy(ct);
+    }
+}
+
+/*
+ * Check if there's a tgt for the realm of `principal' and ccache and
+ * if so return 0, else 1
+ */
+
+static int
+check_for_tgt (krb5_context context,
+              krb5_ccache ccache,
+              krb5_principal principal)
+{
+    krb5_error_code ret;
+    krb5_creds pattern;
+    krb5_creds creds;
+    krb5_realm *client_realm;
+    int expired;
+
+    krb5_cc_clear_mcred(&pattern);
+
+    client_realm = krb5_princ_realm (context, principal);
+
+    ret = krb5_make_principal (context, &pattern.server,
+                              *client_realm, KRB5_TGS_NAME, *client_realm,
+                              NULL);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_make_principal");
+    pattern.client = principal;
+
+    ret = krb5_cc_retrieve_cred (context, ccache, 0, &pattern, &creds);
+    expired = time(NULL) > creds.times.endtime;
+    krb5_free_principal (context, pattern.server);
+    krb5_free_cred_contents (context, &creds);
+    if (ret) {
+       if (ret == KRB5_CC_END)
+           return 1;
+       krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");
+    }
+    return expired;
+}
+
+#ifdef KRB4
+/* prints the approximate kdc time differential as something human
+   readable */
+
+static void
+print_time_diff(int do_verbose)
+{
+    int d = abs(krb_get_kdc_time_diff());
+    char buf[80];
+
+    if ((do_verbose && d > 0) || d > 60) {
+       unparse_time_approx (d, buf, sizeof(buf));
+       printf ("Time diff:\t%s\n", buf);
+    }
+}
+
+/*
+ * return a short representation of `dp' in string form.
+ */
+
+static char *
+short_date(int32_t dp)
+{
+    char *cp;
+    time_t t = (time_t)dp;
+
+    if (t == (time_t)(-1L)) return "***  Never  *** ";
+    cp = ctime(&t) + 4;
+    cp[15] = '\0';
+    return (cp);
+}
+
+/*
+ * Print a list of all the v4 tickets
+ */
+
+static int
+display_v4_tickets (int do_verbose)
+{
+    char *file;
+    int ret;
+    krb_principal princ;
+    CREDENTIALS cred;
+    int found = 0;
+
+    rtbl_t ct;
+
+    file = getenv ("KRBTKFILE");
+    if (file == NULL)
+       file = TKT_FILE;
+
+    printf("%17s: %s\n", "V4-ticket file", file);
+
+    ret = krb_get_tf_realm (file, princ.realm);
+    if (ret) {
+       warnx ("%s", krb_get_err_text(ret));
+       return 1;
+    }
+
+    ret = tf_init (file, R_TKT_FIL);
+    if (ret) {
+       warnx ("tf_init: %s", krb_get_err_text(ret));
+       return 1;
+    }
+    ret = tf_get_pname (princ.name);
+    if (ret) {
+       tf_close ();
+       warnx ("tf_get_pname: %s", krb_get_err_text(ret));
+       return 1;
+    }
+    ret = tf_get_pinst (princ.instance);
+    if (ret) {
+       tf_close ();
+       warnx ("tf_get_pname: %s", krb_get_err_text(ret));
+       return 1;
+    }
+
+    printf ("%17s: %s\n", "Principal", krb_unparse_name(&princ));
+    print_time_diff(do_verbose);
+    printf("\n");
+
+    ct = rtbl_create();
+    rtbl_add_column(ct, COL_ISSUED, 0);
+    rtbl_add_column(ct, COL_EXPIRES, 0);
+    if (do_verbose)
+       rtbl_add_column(ct, COL_PRINCIPAL_KVNO, 0);
+    else
+       rtbl_add_column(ct, COL_PRINCIPAL, 0);
+    rtbl_set_prefix(ct, "  ");
+    rtbl_set_column_prefix(ct, COL_ISSUED, "");
+
+    while ((ret = tf_get_cred(&cred)) == KSUCCESS) {
+       struct timeval tv;
+       char buf1[20], buf2[20];
+       const char *pp;
+
+       found++;
+
+       strlcpy(buf1,
+               short_date(cred.issue_date),
+               sizeof(buf1));
+       cred.issue_date = krb_life_to_time(cred.issue_date, cred.lifetime);
+       krb_kdctimeofday(&tv);
+       if (do_verbose || tv.tv_sec < (unsigned long) cred.issue_date)
+           strlcpy(buf2,
+                   short_date(cred.issue_date),
+                   sizeof(buf2));
+       else
+           strlcpy(buf2,
+                   ">>> Expired <<<",
+                   sizeof(buf2));
+       rtbl_add_column_entry(ct, COL_ISSUED, buf1);
+       rtbl_add_column_entry(ct, COL_EXPIRES, buf2);
+       pp = krb_unparse_name_long(cred.service,
+                                  cred.instance,
+                                  cred.realm);
+       if (do_verbose) {
+           char *tmp;
+
+           asprintf(&tmp, "%s (%d)", pp, cred.kvno);
+           rtbl_add_column_entry(ct, COL_PRINCIPAL_KVNO, tmp);
+           free(tmp);
+       } else {
+           rtbl_add_column_entry(ct, COL_PRINCIPAL, pp);
+       }
+    }
+    rtbl_format(ct, stdout);
+    rtbl_destroy(ct);
+    if (!found && ret == EOF)
+       printf("No tickets in file.\n");
+    tf_close();
+    
+    /*
+     * should do NAT stuff here
+     */
+    return 0;
+}
+#endif /* KRB4 */
+
+/*
+ * Print a list of all AFS tokens
+ */
+
+static void
+display_tokens(int do_verbose)
+{
+    u_int32_t i;
+    unsigned char t[4096];
+    struct ViceIoctl parms;
+
+    parms.in = (void *)&i;
+    parms.in_size = sizeof(i);
+    parms.out = (void *)t;
+    parms.out_size = sizeof(t);
+
+    for (i = 0;; i++) {
+        int32_t size_secret_tok, size_public_tok;
+        unsigned char *cell;
+       struct ClearToken ct;
+       unsigned char *r = t;
+       struct timeval tv;
+       char buf1[20], buf2[20];
+
+       if(k_pioctl(NULL, VIOCGETTOK, &parms, 0) < 0) {
+           if(errno == EDOM)
+               break;
+           continue;
+       }
+       if(parms.out_size > sizeof(t))
+           continue;
+       if(parms.out_size < sizeof(size_secret_tok))
+           continue;
+       t[min(parms.out_size,sizeof(t)-1)] = 0;
+       memcpy(&size_secret_tok, r, sizeof(size_secret_tok));
+       /* dont bother about the secret token */
+       r += size_secret_tok + sizeof(size_secret_tok);
+       if (parms.out_size < (r - t) + sizeof(size_public_tok))
+           continue;
+       memcpy(&size_public_tok, r, sizeof(size_public_tok));
+       r += sizeof(size_public_tok);
+       if (parms.out_size < (r - t) + size_public_tok + sizeof(int32_t))
+           continue;
+       memcpy(&ct, r, size_public_tok);
+       r += size_public_tok;
+       /* there is a int32_t with length of cellname, but we dont read it */
+       r += sizeof(int32_t);
+       cell = r;
+
+       gettimeofday (&tv, NULL);
+       strlcpy (buf1, printable_time(ct.BeginTimestamp),
+                sizeof(buf1));
+       if (do_verbose || tv.tv_sec < ct.EndTimestamp)
+           strlcpy (buf2, printable_time(ct.EndTimestamp),
+                    sizeof(buf2));
+       else
+           strlcpy (buf2, ">>> Expired <<<", sizeof(buf2));
+
+       printf("%s  %s  ", buf1, buf2);
+
+       if ((ct.EndTimestamp - ct.BeginTimestamp) & 1)
+           printf("User's (AFS ID %d) tokens for %s", ct.ViceId, cell);
+       else
+           printf("Tokens for %s", cell);
+       if (do_verbose)
+           printf(" (%d)", ct.AuthHandle);
+       putchar('\n');
+    }
+}
+
+/*
+ * display the ccache in `cred_cache'
+ */
+
+static int
+display_v5_ccache (const char *cred_cache, int do_test, int do_verbose, 
+                  int do_flags)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_ccache ccache;
+    krb5_principal principal;
+    int exit_status = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    if(cred_cache) {
+       ret = krb5_cc_resolve(context, cred_cache, &ccache);
+       if (ret)
+           krb5_err (context, 1, ret, "%s", cred_cache);
+    } else {
+       ret = krb5_cc_default (context, &ccache);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_cc_resolve");
+    }
+
+    ret = krb5_cc_get_principal (context, ccache, &principal);
+    if (ret) {
+       if(ret == ENOENT) {
+           if (!do_test)
+               krb5_warnx(context, "No ticket file: %s",
+                          krb5_cc_get_name(context, ccache));
+           return 1;
+       } else
+           krb5_err (context, 1, ret, "krb5_cc_get_principal");
+    }
+    if (do_test)
+       exit_status = check_for_tgt (context, ccache, principal);
+    else
+       print_tickets (context, ccache, principal, do_verbose, do_flags);
+
+    ret = krb5_cc_close (context, ccache);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_cc_close");
+
+    krb5_free_principal (context, principal);
+    krb5_free_context (context);
+    return exit_status;
+}
+
+static int version_flag = 0;
+static int help_flag   = 0;
+static int do_verbose  = 0;
+static int do_test     = 0;
+#ifdef KRB4
+static int do_v4       = 1;
+#endif
+static int do_tokens   = 0;
+static int do_v5       = 1;
+static char *cred_cache;
+static int do_flags = 0;
+
+static struct getargs args[] = {
+    { NULL, 'f', arg_flag, &do_flags },
+    { "cache",                 'c', arg_string, &cred_cache,
+      "credentials cache to list", "cache" },
+    { "test",                  't', arg_flag, &do_test,
+      "test for having tickets", NULL },
+    { NULL,                    's', arg_flag, &do_test },
+#ifdef KRB4
+    { "v4",                    '4',    arg_flag, &do_v4,
+      "display v4 tickets", NULL },
+#endif
+    { "tokens",                        'T',   arg_flag, &do_tokens,
+      "display AFS tokens", NULL },
+    { "v5",                    '5',    arg_flag, &do_v5,
+      "display v5 cred cache", NULL},
+    { "verbose",               'v', arg_flag, &do_verbose,
+      "verbose output", NULL },
+    { NULL,                    'a', arg_flag, &do_verbose },
+    { NULL,                    'n', arg_flag, &do_verbose },
+    { "version",               0,   arg_flag, &version_flag, 
+      "print version", NULL },
+    { "help",                  0,   arg_flag, &help_flag, 
+      NULL, NULL}
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "");
+    exit (ret);
+}
+
+int
+main (int argc, char **argv)
+{
+    int optind = 0;
+    int exit_status = 0;
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 0)
+       usage (1);
+
+    if (do_v5)
+       exit_status = display_v5_ccache (cred_cache, do_test, 
+                                        do_verbose, do_flags);
+
+    if (!do_test) {
+#ifdef KRB4
+       if (do_v4) {
+           if (do_v5)
+               printf ("\n");
+           display_v4_tickets (do_verbose);
+       }
+#endif
+       if (do_tokens && k_hasafs ()) {
+           if (do_v5)
+               printf ("\n");
+#ifdef KRB4
+           else if (do_v4)
+               printf ("\n");
+#endif
+           display_tokens (do_verbose);
+       }
+    }
+
+    return exit_status;
+}
diff --git a/src/kerberosV/src/kuser/kuser_locl.h b/src/kerberosV/src/kuser/kuser_locl.h
new file mode 100644 (file)
index 0000000..f560ea2
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: kuser_locl.h,v 1.13 2003/01/21 14:13:51 nectar Exp $ */
+
+#ifndef __KUSER_LOCL_H__
+#define __KUSER_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#include <roken.h>
+#include <getarg.h>
+#include <parse_time.h>
+#include <err.h>
+#include <krb5.h>
+
+#ifdef KRB4
+#include <krb.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <kafs.h>
+#include "crypto-headers.h" /* for des_read_pw_string */
+
+#include <sys/wait.h>
+
+#endif /* __KUSER_LOCL_H__ */
diff --git a/src/kerberosV/src/kuser/kverify.c b/src/kerberosV/src/kuser/kverify.c
new file mode 100644 (file)
index 0000000..dd6b0f1
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kuser_locl.h"
+
+RCSID("$KTH: kverify.c,v 1.9 2004/04/25 19:25:33 joda Exp $");
+
+static int help_flag = 0;
+static int version_flag = 0;
+
+static struct getargs args[] = {
+    { "version",       0,   arg_flag, &version_flag },
+    { "help",          0,   arg_flag, &help_flag }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "[principal]");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_creds cred;
+    krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
+    krb5_get_init_creds_opt *get_options;
+    krb5_verify_init_creds_opt verify_options;
+    int optind = 0;
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    ret = krb5_get_init_creds_opt_alloc (context, &get_options);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
+
+    krb5_get_init_creds_opt_set_preauth_list (get_options,
+                                             pre_auth_types,
+                                             1);
+
+    krb5_verify_init_creds_opt_init (&verify_options);
+    
+    ret = krb5_get_init_creds_password (context,
+                                       &cred,
+                                       NULL,
+                                       NULL,
+                                       krb5_prompter_posix,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       get_options);
+    if (ret)
+       errx (1, "krb5_get_init_creds: %s", krb5_get_err_text(context, ret));
+
+    ret = krb5_verify_init_creds (context,
+                                 &cred,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 &verify_options);
+    if (ret)
+       errx (1, "krb5_verify_init_creds: %s",
+             krb5_get_err_text(context, ret));
+    krb5_free_cred_contents (context, &cred);
+    krb5_free_context (context);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/45/45_locl.h b/src/kerberosV/src/lib/45/45_locl.h
new file mode 100644 (file)
index 0000000..6ab9cc3
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 __45_LOCL_H__
+#define __45_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#include <krb5.h>
+#include <krb.h>
+#include <prot.h>
+
+/*
+ * This really shouldn't be here, but the public kerberosIV include files
+ * doesn'nt declare it, so what can we do?
+ */
+void
+encrypt_ktext (KTEXT, des_cblock *, int);
+
+
+#endif /* __45_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/45/CVS/Entries b/src/kerberosV/src/lib/45/CVS/Entries
new file mode 100644 (file)
index 0000000..6423a5c
--- /dev/null
@@ -0,0 +1,4 @@
+/45_locl.h/1.2/Wed Jun 27 15:22:44 2001//
+/get_ad_tkt.c/1.1.1.2/Wed Feb  6 08:54:59 2002//
+/mk_req.c/1.1.1.2/Sun May 11 02:15:35 2003//
+D
diff --git a/src/kerberosV/src/lib/45/CVS/Repository b/src/kerberosV/src/lib/45/CVS/Repository
new file mode 100644 (file)
index 0000000..56b5689
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/45
diff --git a/src/kerberosV/src/lib/45/CVS/Root b/src/kerberosV/src/lib/45/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/45/get_ad_tkt.c b/src/kerberosV/src/lib/45/get_ad_tkt.c
new file mode 100644 (file)
index 0000000..54d43bb
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1997, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "45_locl.h"
+
+RCSID("$KTH: get_ad_tkt.c,v 1.4 2001/06/18 13:11:05 assar Exp $");
+
+/* get an additional version 4 ticket via the 524 protocol */
+
+#ifndef NEVERDATE
+#define NEVERDATE ((unsigned long)0x7fffffffL)
+#endif
+
+int
+get_ad_tkt(char *service, char *sinstance, char *realm, int lifetime)
+{
+    krb5_error_code ret;
+    int code;
+    krb5_context context;
+    krb5_ccache id;
+    krb5_creds in_creds, *out_creds;
+    CREDENTIALS cred;
+    time_t now;
+    char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
+    
+    ret = krb5_init_context(&context);
+    if(ret)
+       return KFAILURE;
+    ret = krb5_cc_default(context, &id);
+    if(ret){
+       krb5_free_context(context);
+       return KFAILURE;
+    }
+    memset(&in_creds, 0, sizeof(in_creds));
+    now = time(NULL);
+    in_creds.times.endtime = krb_life_to_time(time(NULL), lifetime);
+    if(in_creds.times.endtime == NEVERDATE)
+       in_creds.times.endtime = 0;
+    ret = krb5_cc_get_principal(context, id, &in_creds.client);
+    if(ret){
+       krb5_cc_close(context, id);
+       krb5_free_context(context);
+       return KFAILURE;
+    }
+    ret = krb5_524_conv_principal(context, in_creds.client, 
+                                 pname, pinst, prealm);
+    if(ret){
+       krb5_free_principal(context, in_creds.client);
+       krb5_cc_close(context, id);
+       krb5_free_context(context);
+       return KFAILURE;
+    }
+    ret = krb5_425_conv_principal(context, service, sinstance, realm, 
+                                 &in_creds.server);
+    if(ret){
+       krb5_free_principal(context, in_creds.client);
+       krb5_cc_close(context, id);
+       krb5_free_context(context);
+       return KFAILURE;
+    }
+    ret = krb5_get_credentials(context, 
+                              0, 
+                              id,
+                              &in_creds,
+                              &out_creds);
+    krb5_free_principal(context, in_creds.client);
+    krb5_free_principal(context, in_creds.server);
+    if(ret){
+       krb5_cc_close(context, id);
+       krb5_free_context(context);
+       return KFAILURE;
+    }
+    ret = krb524_convert_creds_kdc_ccache(context, id, out_creds, &cred);
+    krb5_cc_close(context, id);
+    krb5_free_context(context);
+    krb5_free_creds(context, out_creds);
+    if(ret)
+       return KFAILURE;
+    code = save_credentials(cred.service, cred.instance, cred.realm, 
+                           cred.session, cred.lifetime, cred.kvno, 
+                           &cred.ticket_st, now);
+    if(code == NO_TKT_FIL)
+       code = tf_setup(&cred, pname, pinst);
+    memset(&cred.session, 0, sizeof(cred.session));
+    return code;
+}
diff --git a/src/kerberosV/src/lib/45/mk_req.c b/src/kerberosV/src/lib/45/mk_req.c
new file mode 100644 (file)
index 0000000..b656e77
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 1997 - 2000, 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* implementation of krb_mk_req that uses 524 protocol */
+
+#include "45_locl.h"
+
+RCSID("$KTH: mk_req.c,v 1.7 2002/05/24 15:21:00 joda Exp $");
+
+static int lifetime = 255;
+
+static void
+build_request(KTEXT req,
+             const char *name, const char *inst, const char *realm, 
+             u_int32_t checksum)
+{
+    struct timeval tv;
+    krb5_storage *sp;
+    krb5_data data;
+    sp = krb5_storage_emem();
+    krb5_store_stringz(sp, name);
+    krb5_store_stringz(sp, inst);
+    krb5_store_stringz(sp, realm);
+    krb5_store_int32(sp, checksum);
+    gettimeofday(&tv, NULL);
+    krb5_store_int8(sp, tv.tv_usec  / 5000);
+    krb5_store_int32(sp, tv.tv_sec);
+    krb5_storage_to_data(sp, &data);
+    krb5_storage_free(sp);
+    memcpy(req->dat, data.data, data.length);
+    req->length = (data.length + 7) & ~7;
+    krb5_data_free(&data);
+}
+
+#ifdef KRB_MK_REQ_CONST
+int
+krb_mk_req(KTEXT authent,
+          const char *service, const char *instance, const char *realm, 
+          int32_t checksum)
+#else
+int
+krb_mk_req(KTEXT authent,
+          char *service, char *instance, char *realm, 
+          int32_t checksum)
+
+#endif
+{
+    CREDENTIALS cr;
+    KTEXT_ST req;
+    krb5_storage *sp;
+    int code;
+    /* XXX get user realm */
+    const char *myrealm = realm;
+    krb5_data a;
+
+    code = krb_get_cred(service, instance, realm, &cr);
+    if(code || time(NULL) > krb_life_to_time(cr.issue_date, cr.lifetime)){
+       code = get_ad_tkt((char *)service,
+                         (char *)instance, (char *)realm, lifetime);
+       if(code == KSUCCESS)
+           code = krb_get_cred(service, instance, realm, &cr);
+    }
+
+    if(code)
+       return code;
+
+    sp = krb5_storage_emem();
+
+    krb5_store_int8(sp, KRB_PROT_VERSION);
+    krb5_store_int8(sp, AUTH_MSG_APPL_REQUEST);
+    
+    krb5_store_int8(sp, cr.kvno);
+    krb5_store_stringz(sp, realm);
+    krb5_store_int8(sp, cr.ticket_st.length);
+
+    build_request(&req, cr.pname, cr.pinst, myrealm, checksum);
+    encrypt_ktext(&req, &cr.session, DES_ENCRYPT);
+
+    krb5_store_int8(sp, req.length);
+
+    krb5_storage_write(sp, cr.ticket_st.dat, cr.ticket_st.length);
+    krb5_storage_write(sp, req.dat, req.length);
+    krb5_storage_to_data(sp, &a);
+    krb5_storage_free(sp);
+    memcpy(authent->dat, a.data, a.length);
+    authent->length = a.length;
+    krb5_data_free(&a);
+
+    memset(&cr, 0, sizeof(cr));
+    memset(&req, 0, sizeof(req));
+
+    return KSUCCESS;
+}
+
+/* 
+ * krb_set_lifetime sets the default lifetime for additional tickets
+ * obtained via krb_mk_req().
+ * 
+ * It returns the previous value of the default lifetime.
+ */
+
+int
+krb_set_lifetime(int newval)
+{
+    int olife = lifetime;
+
+    lifetime = newval;
+    return(olife);
+}
diff --git a/src/kerberosV/src/lib/CVS/Entries b/src/kerberosV/src/lib/CVS/Entries
new file mode 100644 (file)
index 0000000..9a9c14f
--- /dev/null
@@ -0,0 +1,13 @@
+D/45////
+D/asn1////
+D/com_err////
+D/des////
+D/editline////
+D/gssapi////
+D/hdb////
+D/kadm5////
+D/kafs////
+D/krb5////
+D/roken////
+D/sl////
+D/vers////
diff --git a/src/kerberosV/src/lib/CVS/Repository b/src/kerberosV/src/lib/CVS/Repository
new file mode 100644 (file)
index 0000000..39796a7
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib
diff --git a/src/kerberosV/src/lib/CVS/Root b/src/kerberosV/src/lib/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/asn1/CVS/Entries b/src/kerberosV/src/lib/asn1/CVS/Entries
new file mode 100644 (file)
index 0000000..7362e82
--- /dev/null
@@ -0,0 +1,40 @@
+/asn1-common.h/1.1.1.3/Fri Apr 14 07:32:51 2006//
+/asn1_err.et/1.1.1.1/Fri May 25 07:49:53 2001//
+/asn1_print.c/1.4/Fri Apr 14 08:15:04 2006//
+/check-common.c/1.1.1.1/Sun May 11 02:15:35 2003//
+/check-common.h/1.1.1.1/Sun May 11 02:15:35 2003//
+/check-der.c/1.1.1.3/Fri Apr 14 07:32:51 2006//
+/check-gen.c/1.1.1.3/Fri Apr 14 07:32:51 2006//
+/der.h/1.1.1.3/Fri Apr 14 07:32:51 2006//
+/der_cmp.c/1.1.1.1/Fri Apr 14 07:32:52 2006//
+/der_copy.c/1.5/Fri Apr 14 08:15:04 2006//
+/der_free.c/1.1.1.4/Fri Apr 14 07:32:52 2006//
+/der_get.c/1.1.1.3/Fri Apr 14 07:32:52 2006//
+/der_length.c/1.1.1.4/Fri Apr 14 07:32:52 2006//
+/der_locl.h/1.1.1.4/Fri Apr 14 07:32:52 2006//
+/der_put.c/1.4/Fri Apr 14 08:15:04 2006//
+/gen.c/1.4/Fri Apr 14 08:15:04 2006//
+/gen.h/1.1.1.1/Fri May 25 07:49:55 2001//
+/gen_copy.c/1.1.1.3/Fri Apr 14 07:32:52 2006//
+/gen_decode.c/1.1.1.4/Fri Apr 14 07:32:52 2006//
+/gen_encode.c/1.1.1.3/Fri Apr 14 07:32:53 2006//
+/gen_free.c/1.1.1.4/Fri Apr 14 07:32:53 2006//
+/gen_glue.c/1.1.1.2/Fri Apr 14 07:32:53 2006//
+/gen_length.c/1.1.1.4/Fri Apr 14 07:32:53 2006//
+/gen_locl.h/1.1.1.2/Sun May 11 02:15:37 2003//
+/hash.c/1.2/Fri Oct  6 07:09:10 2006//
+/hash.h/1.1.1.1/Fri May 25 07:49:57 2001//
+/k5.asn1/1.1.1.5/Fri Apr 14 07:32:53 2006//
+/lex.h/1.1.1.1/Fri May 25 07:49:57 2001//
+/lex.l/1.1.1.4/Fri Apr 14 07:32:53 2006//
+/libasn1.h/1.1.1.2/Fri Jun 22 21:22:20 2001//
+/main.c/1.3/Fri Apr 14 08:15:04 2006//
+/parse.y/1.1.1.4/Fri Apr 14 07:32:53 2006//
+/pkinit.asn1/1.1.1.1/Fri May 25 07:49:58 2001//
+/rfc2459.asn1/1.1.1.1/Fri May 25 07:49:58 2001//
+/setchgpw2.asn1/1.1.1.1/Fri Apr 14 07:32:54 2006//
+/symbol.c/1.1.1.2/Sun May 11 02:15:37 2003//
+/symbol.h/1.1.1.3/Fri Apr 14 07:32:54 2006//
+/timegm.c/1.1.1.1/Fri May 25 07:49:58 2001//
+/x509.asn1/1.1.1.1/Fri May 25 07:49:58 2001//
+D
diff --git a/src/kerberosV/src/lib/asn1/CVS/Repository b/src/kerberosV/src/lib/asn1/CVS/Repository
new file mode 100644 (file)
index 0000000..4aa969a
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/asn1
diff --git a/src/kerberosV/src/lib/asn1/CVS/Root b/src/kerberosV/src/lib/asn1/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/asn1/asn1-common.h b/src/kerberosV/src/lib/asn1/asn1-common.h
new file mode 100644 (file)
index 0000000..5973a10
--- /dev/null
@@ -0,0 +1,22 @@
+/* $KTH: asn1-common.h,v 1.4 2003/07/15 13:57:31 lha Exp $ */
+
+#include <stddef.h>
+#include <time.h>
+
+#ifndef __asn1_common_definitions__
+#define __asn1_common_definitions__
+
+typedef struct heim_octet_string {
+    size_t length;
+    void *data;
+} heim_octet_string;
+
+typedef char *heim_general_string;
+typedef char *heim_utf8_string;
+
+typedef struct heim_oid {
+    size_t length;
+    unsigned *components;
+} heim_oid;
+
+#endif
diff --git a/src/kerberosV/src/lib/asn1/asn1_err.et b/src/kerberosV/src/lib/asn1/asn1_err.et
new file mode 100644 (file)
index 0000000..a8cfaad
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Error messages for the asn.1 library
+#
+# This might look like a com_err file, but is not
+#
+id "$KTH: asn1_err.et,v 1.5 1998/02/16 16:17:17 joda Exp $"
+
+error_table asn1
+prefix ASN1
+error_code BAD_TIMEFORMAT,     "ASN.1 failed call to system time library"
+error_code MISSING_FIELD,      "ASN.1 structure is missing a required field"
+error_code MISPLACED_FIELD,    "ASN.1 unexpected field number"
+error_code TYPE_MISMATCH,      "ASN.1 type numbers are inconsistent"
+error_code OVERFLOW,           "ASN.1 value too large"
+error_code OVERRUN,            "ASN.1 encoding ended unexpectedly"
+error_code BAD_ID,             "ASN.1 identifier doesn't match expected value"
+error_code BAD_LENGTH,         "ASN.1 length doesn't match expected value"
+error_code BAD_FORMAT,         "ASN.1 badly-formatted encoding"
+error_code PARSE_ERROR,                "ASN.1 parse error"
+end
diff --git a/src/kerberosV/src/lib/asn1/asn1_print.c b/src/kerberosV/src/lib/asn1/asn1_print.c
new file mode 100644 (file)
index 0000000..e01c4cd
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+#include <com_err.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$KTH: asn1_print.c,v 1.16 2005/05/29 14:23:00 lha Exp $");
+
+const char *class_names[] = {
+    "UNIV",                    /* 0 */
+    "APPL",                    /* 1 */
+    "CONTEXT",                 /* 2 */
+    "PRIVATE"                  /* 3 */
+};
+
+const char *type_names[] = {
+    "PRIM",                    /* 0 */
+    "CONS"                     /* 1 */
+};
+
+const char *tag_names[] = {
+    NULL,                      /* 0 */
+    NULL,                      /* 1 */
+    "Integer",                 /* 2 */
+    "BitString",               /* 3 */
+    "OctetString",             /* 4 */
+    "Null",                    /* 5 */
+    "ObjectID",                        /* 6 */
+    NULL,                      /* 7 */
+    NULL,                      /* 8 */
+    NULL,                      /* 9 */
+    "Enumerated",              /* 10 */
+    NULL,                      /* 11 */
+    NULL,                      /* 12 */
+    NULL,                      /* 13 */
+    NULL,                      /* 14 */
+    NULL,                      /* 15 */
+    "Sequence",                        /* 16 */
+    "Set",                     /* 17 */
+    NULL,                      /* 18 */
+    "PrintableString",         /* 19 */
+    NULL,                      /* 20 */
+    NULL,                      /* 21 */
+    "IA5String",               /* 22 */
+    "UTCTime",                 /* 23 */
+    "GeneralizedTime",         /* 24 */
+    NULL,                      /* 25 */
+    "VisibleString",           /* 26 */
+    "GeneralString"            /* 27 */
+};
+
+static int
+loop (unsigned char *buf, size_t len, int indent)
+{
+    while (len > 0) {
+       int ret;
+       Der_class class;
+       Der_type type;
+       int tag;
+       size_t sz;
+       size_t length;
+       int i;
+
+       ret = der_get_tag (buf, len, &class, &type, &tag, &sz);
+       if (ret)
+           errx (1, "der_get_tag: %s", error_message (ret));
+       if (sz > len)
+           errx (1, "unreasonable length (%u) > %u",
+                 (unsigned)sz, (unsigned)len);
+       buf += sz;
+       len -= sz;
+       for (i = 0; i < indent; ++i)
+           printf (" ");
+       printf ("%s %s ", class_names[class], type_names[type]);
+       if (tag_names[tag])
+           printf ("%s = ", tag_names[tag]);
+       else
+           printf ("tag %d = ", tag);
+       ret = der_get_length (buf, len, &length, &sz);
+       if (ret)
+           errx (1, "der_get_tag: %s", error_message (ret));
+       buf += sz;
+       len -= sz;
+
+       if (class == ASN1_C_CONTEXT) {
+           printf ("[%d]\n", tag);
+           loop (buf, length, indent);
+       } else if (class == ASN1_C_UNIV) {
+           switch (tag) {
+           case UT_Sequence :
+               printf ("{\n");
+               loop (buf, length, indent + 2);
+               for (i = 0; i < indent; ++i)
+                   printf (" ");
+               printf ("}\n");
+               break;
+           case UT_Integer : {
+               int val;
+
+               ret = der_get_int (buf, length, &val, NULL);
+               if (ret)
+                   errx (1, "der_get_int: %s", error_message (ret));
+               printf ("integer %d\n", val);
+               break;
+           }
+           case UT_OctetString : {
+               heim_octet_string str;
+               int i;
+               unsigned char *uc;
+
+               ret = der_get_octet_string (buf, length, &str, NULL);
+               if (ret)
+                   errx (1, "der_get_octet_string: %s", error_message (ret));
+               printf ("(length %lu)%s", (unsigned long)str.length,
+                       str.length > 0 ? ", " : "");
+               uc = (unsigned char *)str.data;
+               length = str.length;
+               if (length > 16)
+                   length = 16;
+               for (i = 0; i < length; ++i)
+                   printf ("%02x", uc[i]);
+               printf ("\n");
+               free (str.data);
+               break;
+           }
+           case UT_GeneralizedTime :
+           case UT_IA5String:
+           case UT_UTF8String :
+           case UT_GeneralString : {
+               heim_general_string str;
+
+               ret = der_get_general_string (buf, length, &str, NULL);
+               if (ret)
+                   errx (1, "der_get_general_string: %s",
+                         error_message (ret));
+               printf ("\"%s\"\n", str);
+               free (str);
+               break;
+           }
+           case UT_OID: {
+               heim_oid o;
+               int i;
+
+               ret = der_get_oid(buf, length, &o, NULL);
+               if (ret)
+                   errx (1, "der_get_oid: %s", error_message (ret));
+               
+               for (i = 0; i < o.length ; i++)
+                   printf("%d%s", o.components[i],
+                          i < o.length - 1 ? "." : "");
+               printf("\n");
+               free_oid(&o);
+               break;
+           }
+           case UT_Enumerated: {
+               unsigned num;
+
+               ret = der_get_int (buf, length, &num, NULL);
+               if (ret)
+                   errx (1, "der_get_enum: %s", error_message (ret));
+               
+               printf("%u\n", num);
+               break;
+           }
+           default :
+               printf ("%lu bytes\n", (unsigned long)length);
+               break;
+           }
+       }
+       buf += length;
+       len -= length;
+    }
+    return 0;
+}
+
+static int
+doit (const char *filename)
+{
+    int fd = open (filename, O_RDONLY);
+    struct stat sb;
+    unsigned char *buf;
+    size_t len;
+    int ret;
+
+    if(fd < 0)
+       err (1, "opening %s for read", filename);
+    if (fstat (fd, &sb) < 0)
+       err (1, "stat %s", filename);
+    len = sb.st_size;
+    buf = malloc (len);
+    if (buf == NULL)
+       err (1, "malloc %u", (unsigned)len);
+    if (read (fd, buf, len) != len)
+       errx (1, "read failed");
+    close (fd);
+    ret = loop (buf, len, 0);
+    free (buf);
+    return ret;
+}
+
+
+static int version_flag;
+static int help_flag;
+struct getargs args[] = {
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+    arg_printusage(args, num_args, NULL, "dump-file");
+    exit(code);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+
+    initialize_asn1_error_table_r (&et_list);
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    argv += optind;
+    argc -= optind;
+    if (argc != 1)
+       usage (1);
+    return doit (argv[0]);
+}
diff --git a/src/kerberosV/src/lib/asn1/check-common.c b/src/kerberosV/src/lib/asn1/check-common.c
new file mode 100644 (file)
index 0000000..676c22b
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1999 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <roken.h>
+
+#include "check-common.h"
+
+RCSID("$KTH: check-common.c,v 1.1 2003/01/23 10:21:36 lha Exp $");
+
+static void
+print_bytes (unsigned const char *buf, size_t len)
+{
+    int i;
+
+    for (i = 0; i < len; ++i)
+       printf ("%02x ", buf[i]);
+}
+
+int
+generic_test (const struct test_case *tests,
+             unsigned ntests,
+             size_t data_size,
+             int (*encode)(unsigned char *, size_t, void *, size_t *),
+             int (*length)(void *),
+             int (*decode)(unsigned char *, size_t, void *, size_t *),
+             int (*cmp)(void *a, void *b))
+{
+    unsigned char buf[4711];
+    int i;
+    int failures = 0;
+    void *val = malloc (data_size);
+
+    if (data_size != 0 && val == NULL)
+       err (1, "malloc");
+
+    for (i = 0; i < ntests; ++i) {
+       int ret;
+       size_t sz, consumed_sz, length_sz;
+       unsigned char *beg;
+
+       ret = (*encode) (buf + sizeof(buf) - 1, sizeof(buf),
+                        tests[i].val, &sz);
+       beg = buf + sizeof(buf) - sz;
+       if (ret != 0) {
+           printf ("encoding of %s failed\n", tests[i].name);
+           ++failures;
+       }
+       if (sz != tests[i].byte_len) {
+           printf ("encoding of %s has wrong len (%lu != %lu)\n",
+                   tests[i].name, 
+                   (unsigned long)sz, (unsigned long)tests[i].byte_len);
+           ++failures;
+       }
+
+       length_sz = (*length) (tests[i].val);
+       if (sz != length_sz) {
+           printf ("length for %s is bad (%lu != %lu)\n",
+                   tests[i].name, (unsigned long)length_sz, (unsigned long)sz);
+           ++failures;
+       }
+
+       if (memcmp (beg, tests[i].bytes, tests[i].byte_len) != 0) {
+           printf ("encoding of %s has bad bytes:\n"
+                   "correct: ", tests[i].name);
+           print_bytes (tests[i].bytes, tests[i].byte_len);
+           printf ("\nactual:  ");
+           print_bytes (beg, sz);
+           printf ("\n");
+           ++failures;
+       }
+       ret = (*decode) (beg, sz, val, &consumed_sz);
+       if (ret != 0) {
+           printf ("decoding of %s failed\n", tests[i].name);
+           ++failures;
+       }
+       if (sz != consumed_sz) {
+           printf ("different length decoding %s (%ld != %ld)\n",
+                   tests[i].name, 
+                   (unsigned long)sz, (unsigned long)consumed_sz);
+           ++failures;
+       }
+       if ((*cmp)(val, tests[i].val) != 0) {
+           printf ("%s: comparison failed\n", tests[i].name);
+           ++failures;
+       }
+    }
+    free (val);
+    return failures;
+}
diff --git a/src/kerberosV/src/lib/asn1/check-common.h b/src/kerberosV/src/lib/asn1/check-common.h
new file mode 100644 (file)
index 0000000..52d59cb
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1999 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+struct test_case {
+    void *val;
+    int byte_len;
+    const unsigned char *bytes;
+    char *name;
+};
+
+typedef int (*generic_encode)(unsigned char *, size_t, void *, size_t *);
+typedef int (*generic_length)(void *);
+typedef int (*generic_decode)(unsigned char *, size_t, void *, size_t *);
+
+int
+generic_test (const struct test_case *tests,
+             unsigned ntests,
+             size_t data_size,
+             int (*encode)(unsigned char *, size_t, void *, size_t *),
+             int (*length)(void *),
+             int (*decode)(unsigned char *, size_t, void *, size_t *),
+             int (*cmp)(void *a, void *b));
+
diff --git a/src/kerberosV/src/lib/asn1/check-der.c b/src/kerberosV/src/lib/asn1/check-der.c
new file mode 100644 (file)
index 0000000..a766afc
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 1999 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+#include <err.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+
+#include "check-common.h"
+
+RCSID("$KTH: check-der.c,v 1.13 2005/04/04 19:36:37 lha Exp $");
+
+static int
+cmp_integer (void *a, void *b)
+{
+    int *ia = (int *)a;
+    int *ib = (int *)b;
+
+    return *ib - *ia;
+}
+
+static int
+test_integer (void)
+{
+    struct test_case tests[] = {
+       {NULL, 3, "\x02\x01\x00"},
+       {NULL, 3, "\x02\x01\x7f"},
+       {NULL, 4, "\x02\x02\x00\x80"},
+       {NULL, 4, "\x02\x02\x01\x00"},
+       {NULL, 3, "\x02\x01\x80"},
+       {NULL, 4, "\x02\x02\xff\x7f"},
+       {NULL, 3, "\x02\x01\xff"},
+       {NULL, 4, "\x02\x02\xff\x01"},
+       {NULL, 4, "\x02\x02\x00\xff"},
+       {NULL, 6, "\x02\x04\x80\x00\x00\x00"},
+       {NULL, 6, "\x02\x04\x7f\xff\xff\xff"}
+    };
+
+    int values[] = {0, 127, 128, 256, -128, -129, -1, -255, 255,
+                   0x80000000, 0x7fffffff};
+    int i;
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    for (i = 0; i < ntests; ++i) {
+       tests[i].val = &values[i];
+       asprintf (&tests[i].name, "integer %d", values[i]);
+    }
+
+    return generic_test (tests, ntests, sizeof(int),
+                        (generic_encode)encode_integer,
+                        (generic_length) length_integer,
+                        (generic_decode)decode_integer,
+                        cmp_integer);
+}
+
+static int
+test_one_int(int val)
+{
+    int ret, dval;
+    unsigned char *buf;
+    size_t len_len, len;
+
+    len = _heim_len_int(val);
+
+    buf = emalloc(len + 2);
+
+    buf[0] = '\xff';
+    buf[len + 1] = '\xff';
+    memset(buf + 1, 0, len);
+
+    ret = der_put_int(buf + 1 + len - 1, len, val, &len_len);
+    if (ret) {
+       printf("integer %d encode failed %d\n", val, ret);
+       return 1;
+    }
+    if (len != len_len) {
+       printf("integer %d encode fail with %d len %lu, result len %lu\n",
+              val, ret, (unsigned long)len, (unsigned long)len_len);
+       return 1;
+    }
+
+    ret = der_get_int(buf + 1, len, &dval, &len_len);
+    if (ret) {
+       printf("integer %d decode failed %d\n", val, ret);
+       return 1;
+    }
+    if (len != len_len) {
+       printf("integer %d decoded diffrent len %lu != %lu",
+              val, (unsigned long)len, (unsigned long)len_len);
+       return 1;
+    }
+    if (val != dval) {
+       printf("decode decoded to diffrent value %d != %d",
+              val, dval);
+       return 1;
+    }
+
+    if (buf[0] != (unsigned char)'\xff') {
+       printf("precanary dead %d\n", val);
+       return 1;
+    }
+    if (buf[len + 1] != (unsigned char)'\xff') {
+       printf("postecanary dead %d\n", val);
+       return 1;
+    }
+    free(buf);
+    return 0;
+}
+
+static int
+test_integer_more (void)
+{
+    int i, n1, n2, n3, n4, n5, n6;
+
+    n2 = 0;
+    for (i = 0; i < (sizeof(int) * 8); i++) {
+       n1 = 0x01 << i;
+       n2 = n2 | n1;
+       n3 = ~n1;
+       n4 = ~n2;
+       n5 = (-1) & ~(0x3f << i);
+       n6 = (-1) & ~(0x7f << i);
+
+       test_one_int(n1);
+       test_one_int(n2);
+       test_one_int(n3);
+       test_one_int(n4);
+       test_one_int(n5);
+       test_one_int(n6);
+    }
+    return 0;
+}
+
+static int
+cmp_unsigned (void *a, void *b)
+{
+    return *(unsigned int*)b - *(unsigned int*)a;
+}
+
+static int
+test_unsigned (void)
+{
+    struct test_case tests[] = {
+       {NULL, 3, "\x02\x01\x00"},
+       {NULL, 3, "\x02\x01\x7f"},
+       {NULL, 4, "\x02\x02\x00\x80"},
+       {NULL, 4, "\x02\x02\x01\x00"},
+       {NULL, 4, "\x02\x02\x02\x00"},
+       {NULL, 5, "\x02\x03\x00\x80\x00"},
+       {NULL, 7, "\x02\x05\x00\x80\x00\x00\x00"},
+       {NULL, 6, "\x02\x04\x7f\xff\xff\xff"}
+    };
+
+    unsigned int values[] = {0, 127, 128, 256, 512, 32768, 
+                            0x80000000, 0x7fffffff};
+    int i;
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    for (i = 0; i < ntests; ++i) {
+       tests[i].val = &values[i];
+       asprintf (&tests[i].name, "unsigned %u", values[i]);
+    }
+
+    return generic_test (tests, ntests, sizeof(int),
+                        (generic_encode)encode_unsigned,
+                        (generic_length) length_unsigned,
+                        (generic_decode)decode_unsigned,
+                        cmp_unsigned);
+}
+
+static int
+cmp_octet_string (void *a, void *b)
+{
+    heim_octet_string *oa = (heim_octet_string *)a;
+    heim_octet_string *ob = (heim_octet_string *)b;
+
+    if (oa->length != ob->length)
+       return ob->length - oa->length;
+
+    return (memcmp (oa->data, ob->data, oa->length));
+}
+
+static int
+test_octet_string (void)
+{
+    heim_octet_string s1 = {8, "\x01\x23\x45\x67\x89\xab\xcd\xef"};
+
+    struct test_case tests[] = {
+       {NULL, 10, "\x04\x08\x01\x23\x45\x67\x89\xab\xcd\xef"}
+    };
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    tests[0].val = &s1;
+    asprintf (&tests[0].name, "a octet string");
+
+    return generic_test (tests, ntests, sizeof(heim_octet_string),
+                        (generic_encode)encode_octet_string,
+                        (generic_length)length_octet_string,
+                        (generic_decode)decode_octet_string,
+                        cmp_octet_string);
+}
+
+static int
+cmp_general_string (void *a, void *b)
+{
+    unsigned char **sa = (unsigned char **)a;
+    unsigned char **sb = (unsigned char **)b;
+
+    return strcmp (*sa, *sb);
+}
+
+static int
+test_general_string (void)
+{
+    unsigned char *s1 = "Test User 1";
+
+    struct test_case tests[] = {
+       {NULL, 13, "\x1b\x0b\x54\x65\x73\x74\x20\x55\x73\x65\x72\x20\x31"}
+    };
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    tests[0].val = &s1;
+    asprintf (&tests[0].name, "the string \"%s\"", s1);
+
+    return generic_test (tests, ntests, sizeof(unsigned char *),
+                        (generic_encode)encode_general_string,
+                        (generic_length)length_general_string,
+                        (generic_decode)decode_general_string,
+                        cmp_general_string);
+}
+
+static int
+cmp_generalized_time (void *a, void *b)
+{
+    time_t *ta = (time_t *)a;
+    time_t *tb = (time_t *)b;
+
+    return *tb - *ta;
+}
+
+static int
+test_generalized_time (void)
+{
+    struct test_case tests[] = {
+       {NULL, 17, "\x18\x0f""19700101000000Z"},
+       {NULL, 17, "\x18\x0f""19851106210627Z"}
+    };
+    time_t values[] = {0, 500159187};
+    int i;
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    for (i = 0; i < ntests; ++i) {
+       tests[i].val = &values[i];
+       asprintf (&tests[i].name, "time %d", (int)values[i]);
+    }
+
+    return generic_test (tests, ntests, sizeof(time_t),
+                        (generic_encode)encode_generalized_time,
+                        (generic_length)length_generalized_time,
+                        (generic_decode)decode_generalized_time,
+                        cmp_generalized_time);
+}
+
+int
+main(int argc, char **argv)
+{
+    int ret = 0;
+
+    ret += test_integer ();
+    ret += test_integer_more();
+    ret += test_unsigned ();
+    ret += test_octet_string ();
+    ret += test_general_string ();
+    ret += test_generalized_time ();
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/asn1/check-gen.c b/src/kerberosV/src/lib/asn1/check-gen.c
new file mode 100644 (file)
index 0000000..7c9cba3
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1999 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+#include <krb5_asn1.h>
+
+#include "check-common.h"
+
+RCSID("$KTH: check-gen.c,v 1.4 2004/02/03 22:15:42 lha Exp $");
+
+static char *lha_princ[] = { "lha" };
+static char *lharoot_princ[] = { "lha", "root" };
+static char *datan_princ[] = { "host", "nutcracker.e.kth.se" };
+
+
+#define COMPARE_STRING(ac,bc,e) \
+       do { if (strcmp((ac)->e, (bc)->e) != 0) return 1; } while(0)
+#define COMPARE_INTEGER(ac,bc,e) \
+       do { if ((ac)->e != (bc)->e) return 1; } while(0)
+#define COMPARE_MEM(ac,bc,e,len) \
+       do { if (memcmp((ac)->e, (bc)->e,len) != 0) return 1; } while(0)
+
+static int
+cmp_principal (void *a, void *b)
+{
+    Principal *pa = a;
+    Principal *pb = b;
+    int i;
+
+    COMPARE_STRING(pa,pb,realm);
+    COMPARE_INTEGER(pa,pb,name.name_type);
+    COMPARE_INTEGER(pa,pb,name.name_string.len);
+
+    for (i = 0; i < pa->name.name_string.len; i++)
+       COMPARE_STRING(pa,pb,name.name_string.val[i]);
+
+    return 0;
+}
+
+static int
+test_principal (void)
+{
+
+    struct test_case tests[] = {
+       { NULL, 29, 
+         (unsigned char*)"\x30\x1b\xa0\x10\x30\x0e\xa0\x03\x02\x01\x01\xa1\x07\x30\x05\x1b"
+         "\x03\x6c\x68\x61\xa1\x07\x1b\x05\x53\x55\x2e\x53\x45"
+       },
+       { NULL, 35,
+         (unsigned char*)"\x30\x21\xa0\x16\x30\x14\xa0\x03\x02\x01\x01\xa1\x0d\x30\x0b\x1b"
+         "\x03\x6c\x68\x61\x1b\x04\x72\x6f\x6f\x74\xa1\x07\x1b\x05\x53\x55"
+         "\x2e\x53\x45"
+       },
+       { NULL, 54, 
+         (unsigned char*)"\x30\x34\xa0\x26\x30\x24\xa0\x03\x02\x01\x03\xa1\x1d\x30\x1b\x1b"
+         "\x04\x68\x6f\x73\x74\x1b\x13\x6e\x75\x74\x63\x72\x61\x63\x6b\x65"
+         "\x72\x2e\x65\x2e\x6b\x74\x68\x2e\x73\x65\xa1\x0a\x1b\x08\x45\x2e"
+         "\x4b\x54\x48\x2e\x53\x45"
+       }
+    };
+
+
+    Principal values[] = { 
+       { { KRB5_NT_PRINCIPAL, { 1, lha_princ } },  "SU.SE" },
+       { { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } },  "SU.SE" },
+       { { KRB5_NT_SRV_HST, { 2, datan_princ } },  "E.KTH.SE" }
+    };
+    int i;
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    for (i = 0; i < ntests; ++i) {
+       tests[i].val = &values[i];
+       asprintf (&tests[i].name, "Principal %d", i);
+    }
+
+    return generic_test (tests, ntests, sizeof(Principal),
+                        (generic_encode)encode_Principal,
+                        (generic_length)length_Principal,
+                        (generic_decode)decode_Principal,
+                        cmp_principal);
+}
+
+static int
+cmp_authenticator (void *a, void *b)
+{
+    Authenticator *aa = a;
+    Authenticator *ab = b;
+    int i;
+
+    COMPARE_INTEGER(aa,ab,authenticator_vno);
+    COMPARE_STRING(aa,ab,crealm);
+
+    COMPARE_INTEGER(aa,ab,cname.name_type);
+    COMPARE_INTEGER(aa,ab,cname.name_string.len);
+
+    for (i = 0; i < aa->cname.name_string.len; i++)
+       COMPARE_STRING(aa,ab,cname.name_string.val[i]);
+
+    return 0;
+}
+
+static int
+test_authenticator (void)
+{
+    struct test_case tests[] = {
+       { NULL, 63, 
+         (unsigned char*)"\x62\x3d\x30\x3b\xa0\x03\x02\x01\x05\xa1\x0a\x1b\x08"
+         "\x45\x2e\x4b\x54\x48\x2e\x53\x45\xa2\x10\x30\x0e\xa0"
+         "\x03\x02\x01\x01\xa1\x07\x30\x05\x1b\x03\x6c\x68\x61"
+         "\xa4\x03\x02\x01\x0a\xa5\x11\x18\x0f\x31\x39\x37\x30"
+         "\x30\x31\x30\x31\x30\x30\x30\x31\x33\x39\x5a"
+       },
+       { NULL, 67, 
+         (unsigned char*)"\x62\x41\x30\x3f\xa0\x03\x02\x01\x05\xa1\x07\x1b\x05"
+         "\x53\x55\x2e\x53\x45\xa2\x16\x30\x14\xa0\x03\x02\x01"
+         "\x01\xa1\x0d\x30\x0b\x1b\x03\x6c\x68\x61\x1b\x04\x72"
+         "\x6f\x6f\x74\xa4\x04\x02\x02\x01\x24\xa5\x11\x18\x0f"
+         "\x31\x39\x37\x30\x30\x31\x30\x31\x30\x30\x31\x36\x33"
+         "\x39\x5a"
+       }
+    };
+
+    Authenticator values[] = {
+       { 5, "E.KTH.SE", { KRB5_NT_PRINCIPAL, { 1, lha_princ } },
+         NULL, 10, 99, NULL, NULL, NULL },
+       { 5, "SU.SE", { KRB5_NT_PRINCIPAL, { 2, lharoot_princ } },
+         NULL, 292, 999, NULL, NULL, NULL }
+    };
+    int i;
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    for (i = 0; i < ntests; ++i) {
+       tests[i].val = &values[i];
+       asprintf (&tests[i].name, "Authenticator %d", i);
+    }
+
+    return generic_test (tests, ntests, sizeof(Authenticator),
+                        (generic_encode)encode_Authenticator,
+                        (generic_length)length_Authenticator,
+                        (generic_decode)decode_Authenticator,
+                        cmp_authenticator);
+}
+
+static int
+cmp_AuthorizationData (void *a, void *b)
+{
+    AuthorizationData *aa = a;
+    AuthorizationData *ab = b;
+
+    COMPARE_INTEGER(aa,ab,len);
+
+    return 0;
+}
+
+static char static_buf512[512];
+
+static int
+test_AuthorizationData (void)
+{
+    struct test_case tests[] = {
+       { NULL, 14, 
+         (unsigned char*)
+         "\x30\x0c\x30\x0a\xa0\x03\x02\x01\x01\xa1\x03\x04\x01\x00"
+       },
+       { NULL, 142, 
+         (unsigned char*)
+         "\x30\x81\x8b\x30\x81\x88\xa0\x03\x02\x01\x01\xa1\x81\x80\x04\x7e"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+       },
+       { NULL, 132, 
+         (unsigned char*)
+         "\x30\x81\x81\x30\x73\xa0\x03\x02\x01\x01\xa1\x6c\x04\x6a\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x30\x0a\xa0\x03\x02\x01\x01\xa1"
+         "\x03\x04\x01\x00"
+       },
+       { NULL, 134, 
+         (unsigned char*)
+         "\x30\x81\x83\x30\x74\xa0\x03\x02\x01\x01\xa1\x6d\x04\x6b\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
+         "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x30\x0b\xa0\x03\x02\x01\x01"
+         "\xa1\x04\x04\x02\x00\x00"
+       }
+    };
+
+    AuthorizationData values[] = {
+       { 1, NULL },
+       { 1, NULL },
+       { 2, NULL },
+       { 2, NULL }
+    };
+    int i;
+    int ntests = sizeof(tests) / sizeof(*tests);
+
+    for (i = 0; i < ntests; ++i) {
+       tests[i].val = &values[i];
+       asprintf (&tests[i].name, "AuthorizationData %d", i);
+       values[i].val = emalloc(values[i].len * sizeof(values[i].val[0]));
+    }
+    values[0].val[0].ad_type = 1;
+    values[0].val[0].ad_data.length = 1;
+    values[0].val[0].ad_data.data = static_buf512;
+
+    values[1].val[0].ad_type = 1;
+    values[1].val[0].ad_data.length = 126;
+    values[1].val[0].ad_data.data = static_buf512;
+
+    values[2].val[0].ad_type = 1;
+    values[2].val[0].ad_data.length = 106;
+    values[2].val[0].ad_data.data = static_buf512;
+
+    values[2].val[1].ad_type = 1;
+    values[2].val[1].ad_data.length = 1;
+    values[2].val[1].ad_data.data = static_buf512;
+
+    values[3].val[0].ad_type = 1;
+    values[3].val[0].ad_data.length = 107;
+    values[3].val[0].ad_data.data = static_buf512;
+
+    values[3].val[1].ad_type = 1;
+    values[3].val[1].ad_data.length = 2;
+    values[3].val[1].ad_data.data = static_buf512;
+
+    return generic_test (tests, ntests, sizeof(AuthorizationData),
+                        (generic_encode)encode_AuthorizationData,
+                        (generic_length)length_AuthorizationData,
+                        (generic_decode)decode_AuthorizationData,
+                        cmp_AuthorizationData);
+}
+
+int
+main(int argc, char **argv)
+{
+    int ret = 0;
+
+    ret += test_principal ();
+    ret += test_authenticator();
+    ret += test_AuthorizationData();
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/asn1/der.h b/src/kerberosV/src/lib/asn1/der.h
new file mode 100644 (file)
index 0000000..f1856d6
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: der.h,v 1.28 2005/05/29 14:23:00 lha Exp $ */
+
+#ifndef __DER_H__
+#define __DER_H__
+
+#include <time.h>
+
+typedef enum {
+    ASN1_C_UNIV = 0,
+    ASN1_C_APPL = 1,
+    ASN1_C_CONTEXT = 2 ,
+    ASN1_C_PRIVATE = 3
+} Der_class;
+
+typedef enum {PRIM = 0, CONS = 1} Der_type;
+
+/* Universal tags */
+
+enum {
+     UT_Boolean                = 1,
+     UT_Integer                = 2,
+     UT_BitString      = 3,
+     UT_OctetString    = 4,
+     UT_Null           = 5,
+     UT_OID            = 6,
+     UT_Enumerated     = 10,
+     UT_UTF8String     = 12,
+     UT_Sequence       = 16,
+     UT_Set            = 17,
+     UT_PrintableString        = 19,
+     UT_IA5String      = 22,
+     UT_UTCTime                = 23,
+     UT_GeneralizedTime        = 24,
+     UT_VisibleString  = 26,
+     UT_GeneralString  = 27
+};
+
+#define ASN1_INDEFINITE 0xdce0deed
+
+#ifndef HAVE_TIMEGM
+time_t timegm (struct tm *);
+#endif
+
+int time2generalizedtime (time_t t, heim_octet_string *s);
+
+int der_get_int (const unsigned char *p, size_t len, int *ret, size_t *size);
+int der_get_length (const unsigned char *p, size_t len,
+                   size_t *val, size_t *size);
+int der_get_boolean (const unsigned char *p, size_t len,
+                    int *data, size_t *size);
+int der_get_general_string (const unsigned char *p, size_t len, 
+                           heim_general_string *str, size_t *size);
+int der_get_octet_string (const unsigned char *p, size_t len, 
+                         heim_octet_string *data, size_t *size);
+int der_get_oid (const unsigned char *p, size_t len,
+                heim_oid *data, size_t *size);
+int der_get_tag (const unsigned char *p, size_t len, 
+                Der_class *class, Der_type *type,
+                int *tag, size_t *size);
+
+int der_match_tag (const unsigned char *p, size_t len, 
+                  Der_class class, Der_type type,
+                  int tag, size_t *size);
+int der_match_tag_and_length (const unsigned char *p, size_t len,
+                             Der_class class, Der_type type, int tag,
+                             size_t *length_ret, size_t *size);
+
+int decode_boolean (const unsigned char*, size_t, int*, size_t*);
+int decode_integer (const unsigned char*, size_t, int*, size_t*);
+int decode_unsigned (const unsigned char*, size_t, unsigned*, size_t*);
+int decode_enumerated (const unsigned char*, size_t, unsigned*, size_t*);
+int decode_general_string (const unsigned char*, size_t,
+                          heim_general_string*, size_t*);
+int decode_oid (const unsigned char *p, size_t len, 
+               heim_oid *k, size_t *size);
+int decode_octet_string (const unsigned char*, size_t, 
+                        heim_octet_string*, size_t*);
+int decode_generalized_time (const unsigned char*, size_t, time_t*, size_t*);
+int decode_nulltype (const unsigned char*, size_t, size_t*);
+int decode_utf8string (const unsigned char*, size_t, 
+                      heim_utf8_string*, size_t*);
+
+int der_put_int (unsigned char *p, size_t len, int val, size_t*);
+int der_put_length (unsigned char *p, size_t len, size_t val, size_t*);
+int der_put_boolean (unsigned char *p, size_t len, const int *data, size_t*);
+int der_put_general_string (unsigned char *p, size_t len,
+                           const heim_general_string *str, size_t*);
+int der_put_octet_string (unsigned char *p, size_t len,
+                         const heim_octet_string *data, size_t*);
+int der_put_oid (unsigned char *p, size_t len,
+                const heim_oid *data, size_t *size);
+int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
+                int tag, size_t*);
+int der_put_length_and_tag (unsigned char*, size_t, size_t, 
+                           Der_class, Der_type, int, size_t*);
+
+int encode_boolean (unsigned char *p, size_t len,
+                   const int *data, size_t*);
+int encode_integer (unsigned char *p, size_t len,
+                   const int *data, size_t*);
+int encode_unsigned (unsigned char *p, size_t len,
+                    const unsigned *data, size_t*);
+int encode_enumerated (unsigned char *p, size_t len,
+                      const unsigned *data, size_t*);
+int encode_general_string (unsigned char *p, size_t len, 
+                          const heim_general_string *data, size_t*);
+int encode_octet_string (unsigned char *p, size_t len,
+                        const heim_octet_string *k, size_t*);
+int encode_oid (unsigned char *p, size_t len,
+               const heim_oid *k, size_t*);
+int encode_generalized_time (unsigned char *p, size_t len,
+                            const time_t *t, size_t*);
+int encode_nulltype (unsigned char*, size_t, size_t*);
+int encode_utf8string (unsigned char*, size_t, 
+                      const heim_utf8_string*, size_t*);
+
+void free_integer (int *num);
+void free_general_string (heim_general_string *str);
+void free_octet_string (heim_octet_string *k);
+void free_oid (heim_oid *k);
+void free_generalized_time (time_t *t);
+void free_utf8string (heim_utf8_string*);
+
+size_t length_len (size_t len);
+size_t length_boolean (const int *data);
+size_t length_integer (const int *data);
+size_t length_unsigned (const unsigned *data);
+size_t length_enumerated (const unsigned *data);
+size_t length_general_string (const heim_general_string *data);
+size_t length_octet_string (const heim_octet_string *k);
+size_t length_oid (const heim_oid *k);
+size_t length_generalized_time (const time_t *t);
+size_t length_nulltype (void);
+size_t length_utf8string (const heim_utf8_string*);
+
+int copy_general_string (const heim_general_string *, heim_general_string *);
+int copy_octet_string (const heim_octet_string *, heim_octet_string *);
+int copy_oid (const heim_oid *from, heim_oid *to);
+int copy_nulltype (void *, void *);
+int copy_utf8string (const heim_utf8_string*, heim_utf8_string*);
+
+int heim_oid_cmp(const heim_oid *, const heim_oid *);
+int heim_octet_string_cmp(const heim_octet_string *,const heim_octet_string *);
+
+int fix_dce(size_t reallen, size_t *len);
+
+#endif /* __DER_H__ */
diff --git a/src/kerberosV/src/lib/asn1/der_cmp.c b/src/kerberosV/src/lib/asn1/der_cmp.c
new file mode 100644 (file)
index 0000000..5aa0c4c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: der_cmp.c,v 1.2 2004/04/26 20:54:02 lha Exp $");
+
+int
+heim_oid_cmp(const heim_oid *p, const heim_oid *q)
+{
+    if (p->length != q->length)
+       return p->length - q->length;
+    return memcmp(p->components, 
+                 q->components,
+                 p->length * sizeof(*p->components));
+}
+
+int
+heim_octet_string_cmp(const heim_octet_string *p, const heim_octet_string *q)
+{
+    if (p->length != q->length)
+       return p->length - q->length;
+    return memcmp(p->data, q->data, p->length);
+}
diff --git a/src/kerberosV/src/lib/asn1/der_copy.c b/src/kerberosV/src/lib/asn1/der_copy.c
new file mode 100644 (file)
index 0000000..f548291
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: der_copy.c,v 1.12 2003/11/07 07:39:43 lha Exp $");
+
+int
+copy_general_string (const heim_general_string *from, heim_general_string *to)
+{
+    *to = strdup(*from);
+    if(*to == NULL)
+       return ENOMEM;
+    return 0;
+}
+
+int
+copy_octet_string (const heim_octet_string *from, heim_octet_string *to)
+{
+    to->length = from->length;
+    to->data   = malloc(to->length);
+    if(to->length != 0 && to->data == NULL)
+       return ENOMEM;
+    memcpy(to->data, from->data, to->length);
+    return 0;
+}
+
+int
+copy_oid (const heim_oid *from, heim_oid *to)
+{
+    to->length     = from->length;
+    to->components = malloc(to->length * sizeof(*to->components));
+    if (to->length != 0 && to->components == NULL)
+       return ENOMEM;
+    memcpy(to->components, from->components,
+          to->length * sizeof(*to->components));
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/asn1/der_free.c b/src/kerberosV/src/lib/asn1/der_free.c
new file mode 100644 (file)
index 0000000..e655a9e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: der_free.c,v 1.10 2003/08/20 16:18:49 joda Exp $");
+
+void
+free_general_string (heim_general_string *str)
+{
+    free(*str);
+    *str = NULL;
+}
+
+void
+free_octet_string (heim_octet_string *k)
+{
+    free(k->data);
+    k->data = NULL;
+}
+
+void
+free_oid (heim_oid *k)
+{
+    free(k->components);
+    k->components = NULL;
+}
diff --git a/src/kerberosV/src/lib/asn1/der_get.c b/src/kerberosV/src/lib/asn1/der_get.c
new file mode 100644 (file)
index 0000000..8ab4b8d
--- /dev/null
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: der_get.c,v 1.39 2005/05/29 14:23:00 lha Exp $");
+
+#include <version.h>
+
+/* 
+ * All decoding functions take a pointer `p' to first position in
+ * which to read, from the left, `len' which means the maximum number
+ * of characters we are able to read, `ret' were the value will be
+ * returned and `size' where the number of used bytes is stored.
+ * Either 0 or an error code is returned.
+ */
+
+static int
+der_get_unsigned (const unsigned char *p, size_t len,
+                 unsigned *ret, size_t *size)
+{
+    unsigned val = 0;
+    size_t oldlen = len;
+
+    while (len--)
+       val = val * 256 + *p++;
+    *ret = val;
+    if(size) *size = oldlen;
+    return 0;
+}
+
+int
+der_get_int (const unsigned char *p, size_t len,
+            int *ret, size_t *size)
+{
+    int val = 0;
+    size_t oldlen = len;
+
+    if (len > 0) {
+       val = (signed char)*p++;
+       while (--len)
+           val = val * 256 + *p++;
+    }
+    *ret = val;
+    if(size) *size = oldlen;
+    return 0;
+}
+
+int
+der_get_boolean(const unsigned char *p, size_t len, int *data, size_t *size)
+{
+    if(len < 1)
+       return ASN1_OVERRUN;
+    if(*p != 0)
+       *data = 1;
+    else
+       *data = 0;
+    *size = 1;
+    return 0;
+}
+
+int
+der_get_length (const unsigned char *p, size_t len,
+               size_t *val, size_t *size)
+{
+    size_t v;
+
+    if (len <= 0)
+       return ASN1_OVERRUN;
+    --len;
+    v = *p++;
+    if (v < 128) {
+       *val = v;
+       if(size) *size = 1;
+    } else {
+       int e;
+       size_t l;
+       unsigned tmp;
+
+       if(v == 0x80){
+           *val = ASN1_INDEFINITE;
+           if(size) *size = 1;
+           return 0;
+       }
+       v &= 0x7F;
+       if (len < v)
+           return ASN1_OVERRUN;
+       e = der_get_unsigned (p, v, &tmp, &l);
+       if(e) return e;
+       *val = tmp;
+       if(size) *size = l + 1;
+    }
+    return 0;
+}
+
+int
+der_get_general_string (const unsigned char *p, size_t len, 
+                       heim_general_string *str, size_t *size)
+{
+    char *s;
+
+    s = malloc (len + 1);
+    if (s == NULL)
+       return ENOMEM;
+    memcpy (s, p, len);
+    s[len] = '\0';
+    *str = s;
+    if(size) *size = len;
+    return 0;
+}
+
+int
+der_get_octet_string (const unsigned char *p, size_t len, 
+                     heim_octet_string *data, size_t *size)
+{
+    data->length = len;
+    data->data = malloc(len);
+    if (data->data == NULL && data->length != 0)
+       return ENOMEM;
+    memcpy (data->data, p, len);
+    if(size) *size = len;
+    return 0;
+}
+
+int
+der_get_oid (const unsigned char *p, size_t len,
+            heim_oid *data, size_t *size)
+{
+    int n;
+    size_t oldlen = len;
+
+    if (len < 1)
+       return ASN1_OVERRUN;
+
+    data->components = malloc((len + 1) * sizeof(*data->components));
+    if (data->components == NULL)
+       return ENOMEM;
+    data->components[0] = (*p) / 40;
+    data->components[1] = (*p) % 40;
+    --len;
+    ++p;
+    for (n = 2; len > 0; ++n) {
+       unsigned u = 0;
+
+       do {
+           --len;
+           u = u * 128 + (*p++ % 128);
+       } while (len > 0 && p[-1] & 0x80);
+       data->components[n] = u;
+    }
+    if (len > 0 && p[-1] & 0x80) {
+       free_oid (data);
+       return ASN1_OVERRUN;
+    }
+    data->length = n;
+    if (size)
+       *size = oldlen;
+    return 0;
+}
+
+int
+der_get_tag (const unsigned char *p, size_t len,
+            Der_class *class, Der_type *type,
+            int *tag, size_t *size)
+{
+    if (len < 1)
+       return ASN1_OVERRUN;
+    *class = (Der_class)(((*p) >> 6) & 0x03);
+    *type = (Der_type)(((*p) >> 5) & 0x01);
+    *tag = (*p) & 0x1F;
+    if(size) *size = 1;
+    return 0;
+}
+
+int
+der_match_tag (const unsigned char *p, size_t len,
+              Der_class class, Der_type type,
+              int tag, size_t *size)
+{
+    size_t l;
+    Der_class thisclass;
+    Der_type thistype;
+    int thistag;
+    int e;
+
+    e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
+    if (e) return e;
+    if (class != thisclass || type != thistype)
+       return ASN1_BAD_ID;
+    if(tag > thistag)
+       return ASN1_MISPLACED_FIELD;
+    if(tag < thistag)
+       return ASN1_MISSING_FIELD;
+    if(size) *size = l;
+    return 0;
+}
+
+int
+der_match_tag_and_length (const unsigned char *p, size_t len,
+                         Der_class class, Der_type type, int tag,
+                         size_t *length_ret, size_t *size)
+{
+    size_t l, ret = 0;
+    int e;
+
+    e = der_match_tag (p, len, class, type, tag, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, length_ret, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_boolean (const unsigned char *p, size_t len,
+               int *num, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Boolean, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (reallen > len)
+       return ASN1_OVERRUN;
+
+    e = der_get_boolean (p, reallen, num, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_integer (const unsigned char *p, size_t len,
+               int *num, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Integer, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (reallen > len)
+       return ASN1_OVERRUN;
+
+    e = der_get_int (p, reallen, num, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_unsigned (const unsigned char *p, size_t len,
+                unsigned *num, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Integer, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (reallen > len)
+       return ASN1_OVERRUN;
+
+    e = der_get_unsigned (p, reallen, num, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_enumerated (const unsigned char *p, size_t len,
+                  unsigned *num, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (reallen > len)
+       return ASN1_OVERRUN;
+
+    e = der_get_int (p, reallen, num, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_general_string (const unsigned char *p, size_t len, 
+                      heim_general_string *str, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_GeneralString, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (len < reallen)
+       return ASN1_OVERRUN;
+
+    e = der_get_general_string (p, reallen, str, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_octet_string (const unsigned char *p, size_t len, 
+                    heim_octet_string *k, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (len < reallen)
+       return ASN1_OVERRUN;
+
+    e = der_get_octet_string (p, reallen, k, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+int
+decode_oid (const unsigned char *p, size_t len, 
+           heim_oid *k, size_t *size)
+{
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_OID, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (len < reallen)
+       return ASN1_OVERRUN;
+
+    e = der_get_oid (p, reallen, k, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if(size) *size = ret;
+    return 0;
+}
+
+static void
+generalizedtime2time (const char *s, time_t *t)
+{
+    struct tm tm;
+
+    memset(&tm, 0, sizeof(tm));
+    sscanf (s, "%04d%02d%02d%02d%02d%02dZ",
+           &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour,
+           &tm.tm_min, &tm.tm_sec);
+    tm.tm_year -= 1900;
+    tm.tm_mon -= 1;
+    *t = timegm (&tm);
+}
+
+int
+decode_generalized_time (const unsigned char *p, size_t len,
+                        time_t *t, size_t *size)
+{
+    heim_octet_string k;
+    char *times;
+    size_t ret = 0;
+    size_t l, reallen;
+    int e;
+
+    e = der_match_tag (p, len, ASN1_C_UNIV, PRIM, UT_GeneralizedTime, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+
+    e = der_get_length (p, len, &reallen, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    if (len < reallen)
+       return ASN1_OVERRUN;
+
+    e = der_get_octet_string (p, reallen, &k, &l);
+    if (e) return e;
+    p += l;
+    len -= l;
+    ret += l;
+    times = realloc(k.data, k.length + 1);
+    if (times == NULL){
+       free(k.data);
+       return ENOMEM;
+    }
+    times[k.length] = 0;
+    generalizedtime2time (times, t);
+    free (times);
+    if(size) *size = ret;
+    return 0;
+}
+
+
+int
+fix_dce(size_t reallen, size_t *len)
+{
+    if(reallen == ASN1_INDEFINITE)
+       return 1;
+    if(*len < reallen)
+       return -1;
+    *len = reallen;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/asn1/der_length.c b/src/kerberosV/src/lib/asn1/der_length.c
new file mode 100644 (file)
index 0000000..575d1f2
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: der_length.c,v 1.16 2004/02/07 14:27:59 lha Exp $");
+
+size_t
+_heim_len_unsigned (unsigned val)
+{
+    size_t ret = 0;
+
+    do {
+       ++ret;
+       val /= 256;
+    } while (val);
+    return ret;
+}
+
+size_t
+_heim_len_int (int val)
+{
+    unsigned char q;
+    size_t ret = 0;
+
+    if (val >= 0) {
+       do {
+           q = val % 256;
+           ret++;
+           val /= 256;
+       } while(val);
+       if(q >= 128)
+           ret++;
+    } else {
+       val = ~val;
+       do {
+           q = ~(val % 256);
+           ret++;
+           val /= 256;
+       } while(val);
+       if(q < 128)
+           ret++;
+    }
+    return ret;
+}
+
+static size_t
+len_oid (const heim_oid *oid)
+{
+    size_t ret = 1;
+    int n;
+
+    for (n = 2; n < oid->length; ++n) {
+       unsigned u = oid->components[n];
+
+       ++ret;
+       u /= 128;
+       while (u > 0) {
+           ++ret;
+           u /= 128;
+       }
+    }
+    return ret;
+}
+
+size_t
+length_len (size_t len)
+{
+    if (len < 128)
+       return 1;
+    else
+       return _heim_len_unsigned (len) + 1;
+}
+
+size_t
+length_boolean (const int *data)
+{
+  return 1 + length_len(1) + 1;
+}
+
+size_t
+length_integer (const int *data)
+{
+    size_t len = _heim_len_int (*data);
+
+    return 1 + length_len(len) + len;
+}
+
+size_t
+length_unsigned (const unsigned *data)
+{
+    unsigned val = *data;
+    size_t len = 0;
+    while (val > 255) {
+       ++len;
+       val /= 256;
+    }
+    len++;
+    if (val >= 128)
+       len++;
+    return 1 + length_len(len) + len;
+}
+
+size_t
+length_enumerated (const unsigned *data)
+{
+    size_t len = _heim_len_int (*data);
+
+    return 1 + length_len(len) + len;
+}
+
+size_t
+length_general_string (const heim_general_string *data)
+{
+    char *str = *data;
+    size_t len = strlen(str);
+    return 1 + length_len(len) + len;
+}
+
+size_t
+length_octet_string (const heim_octet_string *k)
+{
+    return 1 + length_len(k->length) + k->length;
+}
+
+size_t
+length_oid (const heim_oid *k)
+{
+    size_t len = len_oid (k);
+
+    return 1 + length_len(len) + len;
+}
+
+size_t
+length_generalized_time (const time_t *t)
+{
+    heim_octet_string k;
+    size_t ret;
+
+    time2generalizedtime (*t, &k);
+    ret = 1 + length_len(k.length) + k.length;
+    free (k.data);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/asn1/der_locl.h b/src/kerberosV/src/lib/asn1/der_locl.h
new file mode 100644 (file)
index 0000000..123df4c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: der_locl.h,v 1.5 2004/02/07 14:16:53 lha Exp $ */
+
+#ifndef __DER_LOCL_H__
+#define __DER_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <roken.h>
+
+#include <asn1-common.h>
+#include <asn1_err.h>
+#include <der.h>
+
+size_t _heim_len_unsigned (unsigned);
+size_t _heim_len_int (int);
+
+#endif /* __DER_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/asn1/der_put.c b/src/kerberosV/src/lib/asn1/der_put.c
new file mode 100644 (file)
index 0000000..3388ed8
--- /dev/null
@@ -0,0 +1,468 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: der_put.c,v 1.32 2005/05/29 14:23:01 lha Exp $");
+
+/*
+ * All encoding functions take a pointer `p' to first position in
+ * which to write, from the right, `len' which means the maximum
+ * number of characters we are able to write.  The function returns
+ * the number of characters written in `size' (if non-NULL).
+ * The return value is 0 or an error.
+ */
+
+static int
+der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size)
+{
+    unsigned char *base = p;
+
+    if (val) {
+       while (len > 0 && val) {
+           *p-- = val % 256;
+           val /= 256;
+           --len;
+       }
+       if (val != 0)
+           return ASN1_OVERFLOW;
+       else {
+           *size = base - p;
+           return 0;
+       }
+    } else if (len < 1)
+       return ASN1_OVERFLOW;
+    else {
+       *p    = 0;
+       *size = 1;
+       return 0;
+    }
+}
+
+int
+der_put_int (unsigned char *p, size_t len, int val, size_t *size)
+{
+    unsigned char *base = p;
+
+    if(val >= 0) {
+       do {
+           if(len < 1)
+               return ASN1_OVERFLOW;
+           *p-- = val % 256;
+           len--;
+           val /= 256;
+       } while(val);
+       if(p[1] >= 128) {
+           if(len < 1)
+               return ASN1_OVERFLOW;
+           *p-- = 0;
+           len--;
+       }
+    } else {
+       val = ~val;
+       do {
+           if(len < 1)
+               return ASN1_OVERFLOW;
+           *p-- = ~(val % 256);
+           len--;
+           val /= 256;
+       } while(val);
+       if(p[1] < 128) {
+           if(len < 1)
+               return ASN1_OVERFLOW;
+           *p-- = 0xff;
+           len--;
+       }
+    }
+    *size = base - p;
+    return 0;
+}
+
+
+int
+der_put_length (unsigned char *p, size_t len, size_t val, size_t *size)
+{
+    if (len < 1)
+       return ASN1_OVERFLOW;
+    if (val < 128) {
+       *p = val;
+       *size = 1;
+       return 0;
+    } else {
+       size_t l;
+       int e;
+
+       e = der_put_unsigned (p, len - 1, val, &l);
+       if (e)
+           return e;
+       p -= l;
+       *p = 0x80 | l;
+       *size = l + 1;
+       return 0;
+    }
+}
+
+int
+der_put_boolean(unsigned char *p, size_t len, const int *data, size_t *size)
+{
+    if(len < 1)
+       return ASN1_OVERFLOW;
+    if(*data != 0)
+       *p = 0xff;
+    else
+       *p = 0;
+    *size = 1;
+    return 0;
+}
+
+int
+der_put_general_string (unsigned char *p, size_t len, 
+                       const heim_general_string *str, size_t *size)
+{
+    size_t slen = strlen(*str);
+
+    if (len < slen)
+       return ASN1_OVERFLOW;
+    p -= slen;
+    len -= slen;
+    memcpy (p+1, *str, slen);
+    *size = slen;
+    return 0;
+}
+
+int
+der_put_octet_string (unsigned char *p, size_t len, 
+                     const heim_octet_string *data, size_t *size)
+{
+    if (len < data->length)
+       return ASN1_OVERFLOW;
+    p -= data->length;
+    len -= data->length;
+    memcpy (p+1, data->data, data->length);
+    *size = data->length;
+    return 0;
+}
+
+int
+der_put_oid (unsigned char *p, size_t len,
+            const heim_oid *data, size_t *size)
+{
+    unsigned char *base = p;
+    int n;
+
+    for (n = data->length - 1; n >= 2; --n) {
+       unsigned u = data->components[n];
+
+       if (len < 1)
+           return ASN1_OVERFLOW;
+       *p-- = u % 128;
+       u /= 128;
+       --len;
+       while (u > 0) {
+           if (len < 1)
+               return ASN1_OVERFLOW;
+           *p-- = 128 + u % 128;
+           u /= 128;
+           --len;
+       }
+    }
+    if (len < 1)
+       return ASN1_OVERFLOW;
+    *p-- = 40 * data->components[0] + data->components[1];
+    *size = base - p;
+    return 0;
+}
+
+int
+der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
+            int tag, size_t *size)
+{
+    if (len < 1)
+       return ASN1_OVERFLOW;
+    *p = (class << 6) | (type << 5) | tag; /* XXX */
+    *size = 1;
+    return 0;
+}
+
+int
+der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
+                       Der_class class, Der_type type, int tag, size_t *size)
+{
+    size_t ret = 0;
+    size_t l;
+    int e;
+
+    e = der_put_length (p, len, len_val, &l);
+    if(e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_tag (p, len, class, type, tag, &l);
+    if(e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_boolean (unsigned char *p, size_t len, const int *data,
+               size_t *size)
+{
+    size_t ret = 0;
+    size_t l;
+    int e;
+    
+    e = der_put_boolean (p, len, data, &l);
+    if(e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Boolean, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_integer (unsigned char *p, size_t len, const int *data, size_t *size)
+{
+    int num = *data;
+    size_t ret = 0;
+    size_t l;
+    int e;
+    
+    e = der_put_int (p, len, num, &l);
+    if(e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Integer, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_unsigned (unsigned char *p, size_t len, const unsigned *data,
+                size_t *size)
+{
+    unsigned num = *data;
+    size_t ret = 0;
+    size_t l;
+    int e;
+    
+    e = der_put_unsigned (p, len, num, &l);
+    if(e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    /* if first octet has msb set, we need to pad with a zero byte */
+    if(p[1] >= 128) {
+       if(len == 0)
+           return ASN1_OVERFLOW;
+       *p-- = 0;
+       len--;
+       ret++;
+       l++;
+    }
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Integer, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_enumerated (unsigned char *p, size_t len, const unsigned *data,
+                  size_t *size)
+{
+    unsigned num = *data;
+    size_t ret = 0;
+    size_t l;
+    int e;
+    
+    e = der_put_int (p, len, num, &l);
+    if(e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_Enumerated, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_general_string (unsigned char *p, size_t len, 
+                      const heim_general_string *data, size_t *size)
+{
+    size_t ret = 0;
+    size_t l;
+    int e;
+
+    e = der_put_general_string (p, len, data, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_GeneralString, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_octet_string (unsigned char *p, size_t len, 
+                    const heim_octet_string *k, size_t *size)
+{
+    size_t ret = 0;
+    size_t l;
+    int e;
+
+    e = der_put_octet_string (p, len, k, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_OctetString, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+encode_oid(unsigned char *p, size_t len,
+          const heim_oid *k, size_t *size)
+{
+    size_t ret = 0;
+    size_t l;
+    int e;
+
+    e = der_put_oid (p, len, k, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, l, ASN1_C_UNIV, PRIM, UT_OID, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
+
+int
+time2generalizedtime (time_t t, heim_octet_string *s)
+{
+     struct tm *tm;
+     size_t len;
+
+     len = 15;
+
+     s->data = malloc(len + 1);
+     if (s->data == NULL)
+        return ENOMEM;
+     s->length = len;
+     tm = gmtime (&t);
+     snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ", 
+              tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, 
+              tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+     return 0;
+}
+
+int
+encode_generalized_time (unsigned char *p, size_t len,
+                        const time_t *t, size_t *size)
+{
+    size_t ret = 0;
+    size_t l;
+    heim_octet_string k;
+    int e;
+
+    e = time2generalizedtime (*t, &k);
+    if (e)
+       return e;
+    e = der_put_octet_string (p, len, &k, &l);
+    free (k.data);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    e = der_put_length_and_tag (p, len, k.length, ASN1_C_UNIV, PRIM, 
+                               UT_GeneralizedTime, &l);
+    if (e)
+       return e;
+    p -= l;
+    len -= l;
+    ret += l;
+    *size = ret;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/asn1/gen.c b/src/kerberosV/src/lib/asn1/gen.c
new file mode 100644 (file)
index 0000000..b08fe0f
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen.c,v 1.58 2005/03/31 00:08:58 lha Exp $");
+
+FILE *headerfile, *codefile, *logfile;
+
+#define STEM "asn1"
+
+static const char *orig_filename;
+static char *header;
+static char *headerbase;
+
+/*
+ * list of all IMPORTs
+ */
+
+struct import {
+    const char *module;
+    struct import *next;
+};
+
+static struct import *imports = NULL;
+
+void
+add_import (const char *module)
+{
+    struct import *tmp = emalloc (sizeof(*tmp));
+
+    tmp->module = module;
+    tmp->next   = imports;
+    imports     = tmp;
+}
+
+const char *
+filename (void)
+{
+    return orig_filename;
+}
+
+void
+init_generate (const char *filename, const char *base)
+{
+    orig_filename = filename;
+    if(base)
+       asprintf(&headerbase, "%s", base);
+    else
+       headerbase = strdup(STEM);
+    asprintf(&header, "%s.h", headerbase);
+    headerfile = fopen (header, "w");
+    if (headerfile == NULL)
+       err (1, "open %s", header);
+    fprintf (headerfile,
+            "/* Generated from %s */\n"
+            "/* Do not edit */\n\n",
+            filename);
+    fprintf (headerfile, 
+            "#ifndef __%s_h__\n"
+            "#define __%s_h__\n\n", headerbase, headerbase);
+    fprintf (headerfile, 
+            "#include <stddef.h>\n"
+            "#include <time.h>\n\n");
+#ifndef HAVE_TIMEGM
+    fprintf (headerfile, "time_t timegm (struct tm*);\n\n");
+#endif
+    fprintf (headerfile,
+            "#ifndef __asn1_common_definitions__\n"
+            "#define __asn1_common_definitions__\n\n");
+    fprintf (headerfile,
+            "typedef struct heim_octet_string {\n"
+            "  size_t length;\n"
+            "  void *data;\n"
+            "} heim_octet_string;\n\n");
+    fprintf (headerfile,
+            "typedef char *heim_general_string;\n\n"
+            );
+    fprintf (headerfile,
+            "typedef char *heim_utf8_string;\n\n"
+            );
+    fprintf (headerfile,
+            "typedef struct heim_oid {\n"
+            "  size_t length;\n"
+            "  unsigned *components;\n"
+            "} heim_oid;\n\n");
+    fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R)                  \\\n"
+         "  do {                                                         \\\n"
+         "    (BL) = length_##T((S));                                    \\\n"
+         "    (B) = malloc((BL));                                        \\\n"
+         "    if((B) == NULL) {                                          \\\n"
+         "      (R) = ENOMEM;                                            \\\n"
+         "    } else {                                                   \\\n"
+         "      (R) = encode_##T(((unsigned char*)(B)) + (BL) - 1, (BL), \\\n"
+         "                       (S), (L));                              \\\n"
+         "      if((R) != 0) {                                           \\\n"
+         "        free((B));                                             \\\n"
+         "        (B) = NULL;                                            \\\n"
+         "      }                                                        \\\n"
+         "    }                                                          \\\n"
+         "  } while (0)\n\n",
+         headerfile);
+    fprintf (headerfile, "#endif\n\n");
+    logfile = fopen(STEM "_files", "w");
+    if (logfile == NULL)
+       err (1, "open " STEM "_files");
+}
+
+void
+close_generate (void)
+{
+    fprintf (headerfile, "#endif /* __%s_h__ */\n", headerbase);
+
+    fclose (headerfile);
+    fprintf (logfile, "\n");
+    fclose (logfile);
+}
+
+void
+generate_constant (const Symbol *s)
+{
+  fprintf (headerfile, "enum { %s = %d };\n\n",
+          s->gen_name, s->constant);
+}
+
+static void
+space(int level)
+{
+    while(level-- > 0)
+       fprintf(headerfile, "  ");
+}
+
+static void
+define_asn1 (int level, Type *t)
+{
+    switch (t->type) {
+    case TType:
+       space(level);
+       fprintf (headerfile, "%s", t->symbol->name);
+       break;
+    case TInteger:
+       space(level);
+       fprintf (headerfile, "INTEGER");
+       break;
+    case TUInteger:
+       space(level);
+       fprintf (headerfile, "UNSIGNED INTEGER");
+       break;
+    case TOctetString:
+       space(level);
+       fprintf (headerfile, "OCTET STRING");
+       break;
+    case TOID :
+       space(level);
+       fprintf(headerfile, "OBJECT IDENTIFIER");
+       break;
+    case TBitString: {
+       Member *m;
+       int tag = -1;
+
+       space(level);
+       fprintf (headerfile, "BIT STRING {\n");
+       for (m = t->members; m && m->val != tag; m = m->next) {
+           if (tag == -1)
+               tag = m->val;
+           space(level + 1);
+           fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 
+                    m->next->val == tag?"":",");
+
+       }
+       space(level);
+       fprintf (headerfile, "}");
+       break;
+    }
+    case TEnumerated : {
+       Member *m;
+       int tag = -1;
+
+       space(level);
+       fprintf (headerfile, "ENUMERATED {\n");
+       for (m = t->members; m && m->val != tag; m = m->next) {
+           if (tag == -1)
+               tag = m->val;
+           space(level + 1);
+           fprintf (headerfile, "%s(%d)%s\n", m->name, m->val, 
+                    m->next->val == tag?"":",");
+
+       }
+       space(level);
+       fprintf (headerfile, "}");
+       break;
+    }
+    case TSequence: {
+       Member *m;
+       int tag;
+       int max_width = 0;
+
+       space(level);
+       fprintf (headerfile, "SEQUENCE {\n");
+       for (m = t->members, tag = -1; m && m->val != tag; m = m->next) {
+           if (tag == -1)
+               tag = m->val;
+           if(strlen(m->name) + (m->val > 9) > max_width)
+               max_width = strlen(m->name) + (m->val > 9);
+       }
+       max_width += 3 + 2;
+       if(max_width < 16) max_width = 16;
+       for (m = t->members, tag = -1 ; m && m->val != tag; m = m->next) {
+           int width;
+           if (tag == -1)
+               tag = m->val;
+           space(level + 1);
+           fprintf(headerfile, "%s[%d]", m->name, m->val);
+           width = max_width - strlen(m->name) - 3 - (m->val > 9) - 2;
+           fprintf(headerfile, "%*s", width, "");
+           define_asn1(level + 1, m->type);
+           if(m->optional)
+               fprintf(headerfile, " OPTIONAL");
+           if(m->next->val != tag)
+               fprintf (headerfile, ",");
+           fprintf (headerfile, "\n");
+       }
+       space(level);
+       fprintf (headerfile, "}");
+       break;
+    }
+    case TSequenceOf: {
+       space(level);
+       fprintf (headerfile, "SEQUENCE OF ");
+       define_asn1 (0, t->subtype);
+       break;
+    }
+    case TGeneralizedTime:
+       space(level);
+       fprintf (headerfile, "GeneralizedTime");
+       break;
+    case TGeneralString:
+       space(level);
+       fprintf (headerfile, "GeneralString");
+       break;
+    case TApplication:
+       fprintf (headerfile, "[APPLICATION %d] ", t->application);
+       define_asn1 (level, t->subtype);
+       break;
+    case TBoolean:
+       space(level);
+       fprintf (headerfile, "BOOLEAN");
+       break;
+    case TUTF8String:
+       space(level);
+       fprintf (headerfile, "UTF8String");
+       break;
+    case TNull:
+       space(level);
+       fprintf (headerfile, "NULL");
+       break;
+    default:
+       abort ();
+    }
+}
+
+static void
+define_type (int level, const char *name, Type *t, int typedefp)
+{
+    switch (t->type) {
+    case TType:
+       space(level);
+       fprintf (headerfile, "%s %s;\n", t->symbol->gen_name, name);
+       break;
+    case TInteger:
+       space(level);
+        if(t->members == NULL) {
+            fprintf (headerfile, "int %s;\n", name);
+        } else {
+            Member *m;
+            int tag = -1;
+            fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
+           for (m = t->members; m && m->val != tag; m = m->next) {
+                if(tag == -1)
+                    tag = m->val;
+                space (level + 1);
+                fprintf(headerfile, "%s = %d%s\n", m->gen_name, m->val, 
+                        m->next->val == tag ? "" : ",");
+            }
+            fprintf (headerfile, "} %s;\n", name);
+        }
+       break;
+    case TUInteger:
+       space(level);
+       fprintf (headerfile, "unsigned int %s;\n", name);
+       break;
+    case TOctetString:
+       space(level);
+       fprintf (headerfile, "heim_octet_string %s;\n", name);
+       break;
+    case TOID :
+       space(level);
+       fprintf (headerfile, "heim_oid %s;\n", name);
+       break;
+    case TBitString: {
+       Member *m;
+       Type i;
+       int tag = -1;
+
+       i.type = TUInteger;
+       space(level);
+       fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
+       for (m = t->members; m && m->val != tag; m = m->next) {
+           char *n;
+
+           asprintf (&n, "%s:1", m->gen_name);
+           define_type (level + 1, n, &i, FALSE);
+           free (n);
+           if (tag == -1)
+               tag = m->val;
+       }
+       space(level);
+       fprintf (headerfile, "} %s;\n\n", name);
+       break;
+    }
+    case TEnumerated: {
+       Member *m;
+       int tag = -1;
+
+       space(level);
+       fprintf (headerfile, "enum %s {\n", typedefp ? name : "");
+       for (m = t->members; m && m->val != tag; m = m->next) {
+           if (tag == -1)
+               tag = m->val;
+           space(level + 1);
+           fprintf (headerfile, "%s = %d%s\n", m->gen_name, m->val,
+                        m->next->val == tag ? "" : ",");
+       }
+       space(level);
+       fprintf (headerfile, "} %s;\n\n", name);
+       break;
+    }
+    case TSequence: {
+       Member *m;
+       int tag = -1;
+
+       space(level);
+       fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
+       for (m = t->members; m && m->val != tag; m = m->next) {
+           if (m->optional) {
+               char *n;
+
+               asprintf (&n, "*%s", m->gen_name);
+               define_type (level + 1, n, m->type, FALSE);
+               free (n);
+           } else
+               define_type (level + 1, m->gen_name, m->type, FALSE);
+           if (tag == -1)
+               tag = m->val;
+       }
+       space(level);
+       fprintf (headerfile, "} %s;\n", name);
+       break;
+    }
+    case TSequenceOf: {
+       Type i;
+
+       i.type = TUInteger;
+       i.application = 0;
+
+       space(level);
+       fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
+       define_type (level + 1, "len", &i, FALSE);
+       define_type (level + 1, "*val", t->subtype, FALSE);
+       space(level);
+       fprintf (headerfile, "} %s;\n", name);
+       break;
+    }
+    case TGeneralizedTime:
+       space(level);
+       fprintf (headerfile, "time_t %s;\n", name);
+       break;
+    case TGeneralString:
+       space(level);
+       fprintf (headerfile, "heim_general_string %s;\n", name);
+       break;
+    case TUTF8String:
+       space(level);
+       fprintf (headerfile, "heim_utf8_string %s;\n", name);
+       break;
+    case TBoolean:
+       space(level);
+       fprintf (headerfile, "int %s;\n", name);
+       break;
+    case TNull:
+       space(level);
+       fprintf (headerfile, "NULL %s;\n", name);
+       break;
+    case TApplication:
+       define_type (level, name, t->subtype, FALSE);
+       break;
+    default:
+       abort ();
+    }
+}
+
+static void
+generate_type_header (const Symbol *s)
+{
+    fprintf (headerfile, "/*\n");
+    fprintf (headerfile, "%s ::= ", s->name);
+    define_asn1 (0, s->type);
+    fprintf (headerfile, "\n*/\n\n");
+
+    fprintf (headerfile, "typedef ");
+    define_type (0, s->gen_name, s->type, TRUE);
+
+    fprintf (headerfile, "\n");
+}
+
+
+void
+generate_type (const Symbol *s)
+{
+    struct import *i;
+    char *filename;
+
+    asprintf (&filename, "%s_%s.x", STEM, s->gen_name);
+    codefile = fopen (filename, "w");
+    if (codefile == NULL)
+       err (1, "fopen %s", filename);
+    fprintf(logfile, "%s ", filename);
+    free(filename);
+    fprintf (codefile, 
+            "/* Generated from %s */\n"
+            "/* Do not edit */\n\n"
+            "#include <stdio.h>\n"
+            "#include <stdlib.h>\n"
+            "#include <time.h>\n"
+            "#include <string.h>\n"
+            "#include <errno.h>\n",
+            orig_filename);
+
+    for (i = imports; i != NULL; i = i->next)
+       fprintf (codefile,
+                "#include <%s_asn1.h>\n",
+                i->module);
+    fprintf (codefile,
+            "#include <%s.h>\n",
+            headerbase);
+    fprintf (codefile,
+            "#include <asn1_err.h>\n"
+            "#include <der.h>\n"
+            "#include <parse_units.h>\n\n");
+
+    if (s->stype == Stype && s->type->type == TChoice) {
+       fprintf(codefile,
+               "/* CHOICE */\n"
+               "int asn1_%s_dummy_holder = 1;\n", s->gen_name);
+    } else {
+       generate_type_header (s);
+       generate_type_encode (s);
+       generate_type_decode (s);
+       generate_type_free (s);
+       generate_type_length (s);
+       generate_type_copy (s);
+       generate_glue (s);
+    }
+    fprintf(headerfile, "\n\n");
+    fclose(codefile);
+}
diff --git a/src/kerberosV/src/lib/asn1/gen.h b/src/kerberosV/src/lib/asn1/gen.h
new file mode 100644 (file)
index 0000000..d427920
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: gen.h,v 1.4 1999/12/02 17:05:02 joda Exp $ */
+
+#include <stdio.h>
+#include "symbol.h"
+
diff --git a/src/kerberosV/src/lib/asn1/gen_copy.c b/src/kerberosV/src/lib/asn1/gen_copy.c
new file mode 100644 (file)
index 0000000..8b3cff9
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen_copy.c,v 1.14 2003/10/03 00:27:36 lha Exp $");
+
+static void
+copy_primitive (const char *typename, const char *from, const char *to)
+{
+    fprintf (codefile, "if(copy_%s(%s, %s)) return ENOMEM;\n", 
+            typename, from, to);
+}
+
+static void
+copy_type (const char *from, const char *to, const Type *t)
+{
+  switch (t->type) {
+  case TType:
+#if 0
+      copy_type (from, to, t->symbol->type);
+#endif
+      fprintf (codefile, "if(copy_%s(%s, %s)) return ENOMEM;\n", 
+              t->symbol->gen_name, from, to);
+      break;
+  case TInteger:
+  case TUInteger:
+  case TBoolean:
+  case TEnumerated :
+      fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+      break;
+  case TOctetString:
+      copy_primitive ("octet_string", from, to);
+      break;
+  case TOID:
+      copy_primitive ("oid", from, to);
+      break;
+  case TBitString: {
+      fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+      break;
+  }
+  case TSequence: {
+      Member *m;
+      int tag = -1;
+
+      if (t->members == NULL)
+         break;
+      
+      for (m = t->members; m && tag != m->val; m = m->next) {
+         char *f;
+         char *t;
+
+         asprintf (&f, "%s(%s)->%s",
+                   m->optional ? "" : "&", from, m->gen_name);
+         asprintf (&t, "%s(%s)->%s",
+                   m->optional ? "" : "&", to, m->gen_name);
+         if(m->optional){
+             fprintf(codefile, "if(%s) {\n", f);
+             fprintf(codefile, "%s = malloc(sizeof(*%s));\n", t, t);
+             fprintf(codefile, "if(%s == NULL) return ENOMEM;\n", t);
+         }
+         copy_type (f, t, m->type);
+         if(m->optional){
+             fprintf(codefile, "}else\n");
+             fprintf(codefile, "%s = NULL;\n", t);
+         }
+         if (tag == -1)
+             tag = m->val;
+         free (f);
+         free (t);
+      }
+      break;
+  }
+  case TSequenceOf: {
+      char *f;
+      char *T;
+
+      fprintf (codefile, "if(((%s)->val = "
+              "malloc((%s)->len * sizeof(*(%s)->val))) == NULL && (%s)->len != 0)\n", 
+              to, from, to, from);
+      fprintf (codefile, "return ENOMEM;\n");
+      fprintf(codefile,
+             "for((%s)->len = 0; (%s)->len < (%s)->len; (%s)->len++){\n",
+             to, to, from, to);
+      asprintf(&f, "&(%s)->val[(%s)->len]", from, to);
+      asprintf(&T, "&(%s)->val[(%s)->len]", to, to);
+      copy_type(f, T, t->subtype);
+      fprintf(codefile, "}\n");
+      free(f);
+      free(T);
+      break;
+  }
+  case TGeneralizedTime:
+      fprintf(codefile, "*(%s) = *(%s);\n", to, from);
+      break;
+  case TGeneralString:
+      copy_primitive ("general_string", from, to);
+      break;
+  case TUTF8String:
+      copy_primitive ("utf8string", from, to);
+      break;
+  case TNull:
+      break;
+  case TApplication:
+      copy_type (from, to, t->subtype);
+      break;
+  default :
+      abort ();
+  }
+}
+
+void
+generate_type_copy (const Symbol *s)
+{
+  fprintf (headerfile,
+          "int    copy_%s  (const %s *, %s *);\n",
+          s->gen_name, s->gen_name, s->gen_name);
+
+  fprintf (codefile, "int\n"
+          "copy_%s(const %s *from, %s *to)\n"
+          "{\n",
+          s->gen_name, s->gen_name, s->gen_name);
+
+  copy_type ("from", "to", s->type);
+  fprintf (codefile, "return 0;\n}\n\n");
+}
+
diff --git a/src/kerberosV/src/lib/asn1/gen_decode.c b/src/kerberosV/src/lib/asn1/gen_decode.c
new file mode 100644 (file)
index 0000000..4d8daf9
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen_decode.c,v 1.21 2005/05/29 14:23:01 lha Exp $");
+
+static void
+decode_primitive (const char *typename, const char *name)
+{
+    fprintf (codefile,
+            "e = decode_%s(p, len, %s, &l);\n"
+            "FORW;\n",
+            typename,
+            name);
+}
+
+static void
+decode_type (const char *name, const Type *t)
+{
+    switch (t->type) {
+    case TType:
+#if 0
+       decode_type (name, t->symbol->type);
+#endif
+       fprintf (codefile,
+                "e = decode_%s(p, len, %s, &l);\n"
+                "FORW;\n",
+                t->symbol->gen_name, name);
+       break;
+    case TInteger:
+       if(t->members == NULL)
+           decode_primitive ("integer", name);
+       else {
+           char *s;
+           asprintf(&s, "(int*)%s", name);
+           if(s == NULL)
+               errx (1, "out of memory");
+           decode_primitive ("integer", s);
+           free(s);
+       }
+       break;
+    case TUInteger:
+       decode_primitive ("unsigned", name);
+       break;
+    case TEnumerated:
+       decode_primitive ("enumerated", name);
+       break;
+    case TOctetString:
+       decode_primitive ("octet_string", name);
+       break;
+    case TOID :
+       decode_primitive ("oid", name);
+       break;
+    case TBitString: {
+       Member *m;
+       int tag = -1;
+       int pos;
+
+       fprintf (codefile,
+                "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, PRIM, UT_BitString,"
+                "&reallen, &l);\n"
+                "FORW;\n"
+                "if(len < reallen)\n"
+                "return ASN1_OVERRUN;\n"
+                "p++;\n"
+                "len--;\n"
+                "reallen--;\n"
+                "ret++;\n");
+       pos = 0;
+       for (m = t->members; m && tag != m->val; m = m->next) {
+           while (m->val / 8 > pos / 8) {
+               fprintf (codefile,
+                        "p++; len--; reallen--; ret++;\n");
+               pos += 8;
+           }
+           fprintf (codefile,
+                    "%s->%s = (*p >> %d) & 1;\n",
+                    name, m->gen_name, 7 - m->val % 8);
+           if (tag == -1)
+               tag = m->val;
+       }
+       fprintf (codefile,
+                "p += reallen; len -= reallen; ret += reallen;\n");
+       break;
+    }
+    case TSequence: {
+       Member *m;
+       int tag = -1;
+
+       if (t->members == NULL)
+           break;
+
+       fprintf (codefile,
+                "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,"
+                "&reallen, &l);\n"
+                "FORW;\n"
+                "{\n"
+                "int dce_fix;\n"
+                "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
+                "return ASN1_BAD_FORMAT;\n");
+
+       for (m = t->members; m && tag != m->val; m = m->next) {
+           char *s;
+
+           asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
+           if (0 && m->type->type == TType){
+               if(m->optional)
+                   fprintf (codefile,
+                            "%s = malloc(sizeof(*%s));\n"
+                            "if(%s == NULL) return ENOMEM;\n", s, s, s);
+               fprintf (codefile, 
+                        "e = decode_seq_%s(p, len, %d, %d, %s, &l);\n",
+                        m->type->symbol->gen_name,
+                        m->val, 
+                        m->optional,
+                        s);
+               if(m->optional)
+                   fprintf (codefile, 
+                            "if (e == ASN1_MISSING_FIELD) {\n"
+                            "free(%s);\n"
+                            "%s = NULL;\n"
+                            "e = l = 0;\n"
+                            "}\n",
+                            s, s);
+         
+               fprintf (codefile, "FORW;\n");
+         
+           }else{
+               fprintf (codefile, "{\n"
+                        "size_t newlen, oldlen;\n\n"
+                        "e = der_match_tag (p, len, ASN1_C_CONTEXT, CONS, %d, &l);\n",
+                        m->val);
+               fprintf (codefile,
+                        "if (e)\n");
+               if(m->optional)
+                   /* XXX should look at e */
+                   fprintf (codefile,
+                            "%s = NULL;\n", s);
+               else
+                   fprintf (codefile,
+                            "return e;\n");
+               fprintf (codefile, 
+                        "else {\n");
+               fprintf (codefile,
+                        "p += l;\n"
+                        "len -= l;\n"
+                        "ret += l;\n"
+                        "e = der_get_length (p, len, &newlen, &l);\n"
+                        "FORW;\n"
+                        "{\n"
+              
+                        "int dce_fix;\n"
+                        "oldlen = len;\n"
+                        "if((dce_fix = fix_dce(newlen, &len)) < 0)"
+                        "return ASN1_BAD_FORMAT;\n");
+               if (m->optional)
+                   fprintf (codefile,
+                            "%s = malloc(sizeof(*%s));\n"
+                            "if(%s == NULL) return ENOMEM;\n", s, s, s);
+               decode_type (s, m->type);
+               fprintf (codefile,
+                        "if(dce_fix){\n"
+                        "e = der_match_tag_and_length (p, len, "
+                        "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
+                        "FORW;\n"
+                        "}else \n"
+                        "len = oldlen - newlen;\n"
+                        "}\n"
+                        "}\n");
+               fprintf (codefile,
+                        "}\n");
+           }
+           if (tag == -1)
+               tag = m->val;
+           free (s);
+       }
+       fprintf(codefile,
+               "if(dce_fix){\n"
+               "e = der_match_tag_and_length (p, len, "
+               "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
+               "FORW;\n"
+               "}\n"
+               "}\n");
+
+       break;
+    }
+    case TSequenceOf: {
+       char *n;
+
+       fprintf (codefile,
+                "e = der_match_tag_and_length (p, len, ASN1_C_UNIV, CONS, UT_Sequence,"
+                "&reallen, &l);\n"
+                "FORW;\n"
+                "if(len < reallen)\n"
+                "return ASN1_OVERRUN;\n"
+                "len = reallen;\n");
+
+       fprintf (codefile,
+                "{\n"
+                "size_t origlen = len;\n"
+                "int oldret = ret;\n"
+                "ret = 0;\n"
+                "(%s)->len = 0;\n"
+                "(%s)->val = NULL;\n"
+                "while(ret < origlen) {\n"
+                "(%s)->len++;\n"
+                "(%s)->val = realloc((%s)->val, sizeof(*((%s)->val)) * (%s)->len);\n",
+                name, name, name, name, name, name, name);
+       asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name);
+       decode_type (n, t->subtype);
+       fprintf (codefile, 
+                "len = origlen - ret;\n"
+                "}\n"
+                "ret += oldret;\n"
+                "}\n");
+       free (n);
+       break;
+    }
+    case TGeneralizedTime:
+       decode_primitive ("generalized_time", name);
+       break;
+    case TGeneralString:
+       decode_primitive ("general_string", name);
+       break;
+    case TUTF8String:
+       decode_primitive ("utf8string", name);
+       break;
+    case TNull:
+       fprintf (codefile,
+                "e = decode_nulltype(p, len, &l);\n"
+                "FORW;\n");
+       break;
+    case TApplication:
+       fprintf (codefile,
+                "e = der_match_tag_and_length (p, len, ASN1_C_APPL, CONS, %d, "
+                "&reallen, &l);\n"
+                "FORW;\n"
+                "{\n"
+                "int dce_fix;\n"
+                "if((dce_fix = fix_dce(reallen, &len)) < 0)\n"
+                "return ASN1_BAD_FORMAT;\n", 
+                t->application);
+       decode_type (name, t->subtype);
+       fprintf(codefile,
+               "if(dce_fix){\n"
+               "e = der_match_tag_and_length (p, len, "
+               "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
+               "FORW;\n"
+               "}\n"
+               "}\n");
+
+       break;
+    case TBoolean:
+       decode_primitive ("boolean", name);
+       break;
+    default :
+       abort ();
+    }
+}
+
+void
+generate_type_decode (const Symbol *s)
+{
+  fprintf (headerfile,
+          "int    "
+          "decode_%s(const unsigned char *, size_t, %s *, size_t *);\n",
+          s->gen_name, s->gen_name);
+
+  fprintf (codefile, "#define FORW "
+          "if(e) goto fail; "
+          "p += l; "
+          "len -= l; "
+          "ret += l\n\n");
+
+
+  fprintf (codefile, "int\n"
+          "decode_%s(const unsigned char *p,"
+          " size_t len, %s *data, size_t *size)\n"
+          "{\n",
+          s->gen_name, s->gen_name);
+
+  switch (s->type->type) {
+  case TInteger:
+  case TUInteger:
+  case TBoolean:
+  case TOctetString:
+  case TOID:
+  case TGeneralizedTime:
+  case TGeneralString:
+  case TUTF8String:
+  case TNull:
+  case TEnumerated:
+  case TBitString:
+  case TSequence:
+  case TSequenceOf:
+  case TApplication:
+  case TType:
+    fprintf (codefile,
+            "size_t ret = 0, reallen;\n"
+            "size_t l;\n"
+            "int e;\n\n");
+    fprintf (codefile, "memset(data, 0, sizeof(*data));\n");
+    fprintf (codefile, "reallen = 0;\n"); /* hack to avoid `unused variable' */
+
+    decode_type ("data", s->type);
+    fprintf (codefile, 
+            "if(size) *size = ret;\n"
+            "return 0;\n");
+    fprintf (codefile,
+            "fail:\n"
+            "free_%s(data);\n"
+            "return e;\n",
+            s->gen_name);
+    break;
+  default:
+    abort ();
+  }
+  fprintf (codefile, "}\n\n");
+}
+
+void
+generate_seq_type_decode (const Symbol *s)
+{
+    fprintf (headerfile,
+            "int decode_seq_%s(const unsigned char *, size_t, int, int, "
+            "%s *, size_t *);\n",
+            s->gen_name, s->gen_name);
+
+    fprintf (codefile, "int\n"
+            "decode_seq_%s(const unsigned char *p, size_t len, int tag, "
+            "int optional, %s *data, size_t *size)\n"
+            "{\n",
+            s->gen_name, s->gen_name);
+
+    fprintf (codefile,
+            "size_t newlen, oldlen;\n"
+            "size_t l, ret = 0;\n"
+            "int e;\n"
+            "int dce_fix;\n");
+    
+    fprintf (codefile,
+            "e = der_match_tag(p, len, ASN1_C_CONTEXT, CONS, tag, &l);\n"
+            "if (e)\n"
+            "return e;\n");
+    fprintf (codefile, 
+            "p += l;\n"
+            "len -= l;\n"
+            "ret += l;\n"
+            "e = der_get_length(p, len, &newlen, &l);\n"
+            "if (e)\n"
+            "return e;\n"
+            "p += l;\n"
+            "len -= l;\n"
+            "ret += l;\n"
+            "oldlen = len;\n"
+            "if ((dce_fix = fix_dce(newlen, &len)) < 0)\n"
+            "return ASN1_BAD_FORMAT;\n"
+            "e = decode_%s(p, len, data, &l);\n"
+            "if (e)\n"
+            "return e;\n"
+            "p += l;\n"
+            "len -= l;\n"
+            "ret += l;\n"
+            "if (dce_fix) {\n"
+            "size_t reallen;\n\n"
+            "e = der_match_tag_and_length(p, len, "
+            "(Der_class)0, (Der_type)0, 0, &reallen, &l);\n"
+            "if (e)\n"
+            "return e;\n"
+            "ret += l;\n"
+            "}\n",
+            s->gen_name);
+    fprintf (codefile, 
+            "if(size) *size = ret;\n"
+            "return 0;\n");
+
+    fprintf (codefile, "}\n\n");
+}
diff --git a/src/kerberosV/src/lib/asn1/gen_encode.c b/src/kerberosV/src/lib/asn1/gen_encode.c
new file mode 100644 (file)
index 0000000..9db0b7b
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen_encode.c,v 1.15 2005/05/29 14:23:01 lha Exp $");
+
+static void
+encode_primitive (const char *typename, const char *name)
+{
+    fprintf (codefile,
+            "e = encode_%s(p, len, %s, &l);\n"
+            "BACK;\n",
+            typename,
+            name);
+}
+
+static void
+encode_type (const char *name, const Type *t)
+{
+    switch (t->type) {
+    case TType:
+#if 0
+       encode_type (name, t->symbol->type);
+#endif
+       fprintf (codefile,
+                "e = encode_%s(p, len, %s, &l);\n"
+                "BACK;\n",
+                t->symbol->gen_name, name);
+       break;
+    case TInteger:
+       if(t->members == NULL)
+           encode_primitive ("integer", name);
+       else {
+           char *s;
+           asprintf(&s, "(const int*)%s", name);
+           if(s == NULL)
+               errx(1, "out of memory");
+           encode_primitive ("integer", s);
+           free(s);
+       }
+       break;
+    case TUInteger:
+       encode_primitive ("unsigned", name);
+       break;
+    case TOctetString:
+       encode_primitive ("octet_string", name);
+       break;
+    case TOID :
+       encode_primitive ("oid", name);
+       break;
+    case TBitString: {
+       Member *m;
+       int pos;
+       int rest;
+       int tag = -1;
+
+       if (t->members == NULL)
+           break;
+
+       fprintf (codefile, "{\n"
+                "unsigned char c = 0;\n");
+       pos = t->members->prev->val;
+       /* fix for buggy MIT (and OSF?) code */
+       if (pos > 31)
+           abort ();
+       /*
+        * It seems that if we do not always set pos to 31 here, the MIT
+        * code will do the wrong thing.
+        *
+        * I hate ASN.1 (and DER), but I hate it even more when everybody
+        * has to screw it up differently.
+        */
+       pos = 31;
+       rest = 7 - (pos % 8);
+
+       for (m = t->members->prev; m && tag != m->val; m = m->prev) {
+           while (m->val / 8 < pos / 8) {
+               fprintf (codefile,
+                        "*p-- = c; len--; ret++;\n"
+                        "c = 0;\n");
+               pos -= 8;
+           }
+           fprintf (codefile,
+                    "if(%s->%s) c |= 1<<%d;\n", name, m->gen_name,
+                    7 - m->val % 8);
+
+           if (tag == -1)
+               tag = m->val;
+       }
+
+       fprintf (codefile, 
+                "*p-- = c;\n"
+                "*p-- = %d;\n"
+                "len -= 2;\n"
+                "ret += 2;\n"
+                "}\n\n"
+                "e = der_put_length_and_tag (p, len, ret, ASN1_C_UNIV, PRIM,"
+                "UT_BitString, &l);\n"
+                "BACK;\n",
+                rest);
+       break;
+    }
+    case TEnumerated : {
+       encode_primitive ("enumerated", name);
+       break;
+    }
+    case TSequence: {
+       Member *m;
+       int tag = -1;
+
+       if (t->members == NULL)
+           break;
+
+       for (m = t->members->prev; m && tag != m->val; m = m->prev) {
+           char *s;
+
+           asprintf (&s, "%s(%s)->%s", m->optional ? "" : "&", name, m->gen_name);
+           if (m->optional)
+               fprintf (codefile,
+                        "if(%s)\n",
+                        s);
+#if 1
+           fprintf (codefile, "{\n"
+                    "int oldret = ret;\n"
+                    "ret = 0;\n");
+#endif
+           encode_type (s, m->type);
+           fprintf (codefile,
+                    "e = der_put_length_and_tag (p, len, ret, ASN1_C_CONTEXT, CONS, "
+                    "%d, &l);\n"
+                    "BACK;\n",
+                    m->val);
+#if 1
+           fprintf (codefile,
+                    "ret += oldret;\n"
+                    "}\n");
+#endif
+           if (tag == -1)
+               tag = m->val;
+           free (s);
+       }
+       fprintf (codefile,
+                "e = der_put_length_and_tag (p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);\n"
+                "BACK;\n");
+       break;
+    }
+    case TSequenceOf: {
+       char *n;
+
+       fprintf (codefile,
+                "for(i = (%s)->len - 1; i >= 0; --i) {\n"
+#if 1
+                "int oldret = ret;\n"
+                "ret = 0;\n",
+#else
+                ,
+#endif
+                name);
+       asprintf (&n, "&(%s)->val[i]", name);
+       encode_type (n, t->subtype);
+       fprintf (codefile,
+#if 1
+                "ret += oldret;\n"
+#endif
+                "}\n"
+                "e = der_put_length_and_tag (p, len, ret, ASN1_C_UNIV, CONS, UT_Sequence, &l);\n"
+                "BACK;\n");
+       free (n);
+       break;
+    }
+    case TGeneralizedTime:
+       encode_primitive ("generalized_time", name);
+       break;
+    case TGeneralString:
+       encode_primitive ("general_string", name);
+       break;
+    case TUTF8String:
+       encode_primitive ("utf8string", name);
+       break;
+    case TNull:
+       fprintf (codefile,
+                "e = encode_nulltype(p, len, &l);\n"
+                "BACK;\n");
+       break;
+    case TApplication:
+       encode_type (name, t->subtype);
+       fprintf (codefile,
+                "e = der_put_length_and_tag (p, len, ret, ASN1_C_APPL, CONS, %d, &l);\n"
+                "BACK;\n",
+                t->application);
+       break;
+    case TBoolean:
+       encode_primitive ("boolean", name);
+       break;
+    default:
+       abort ();
+    }
+}
+
+void
+generate_type_encode (const Symbol *s)
+{
+  fprintf (headerfile,
+          "int    "
+          "encode_%s(unsigned char *, size_t, const %s *, size_t *);\n",
+          s->gen_name, s->gen_name);
+
+  fprintf (codefile, "#define BACK if (e) return e; p -= l; len -= l; ret += l\n\n");
+
+
+  fprintf (codefile, "int\n"
+          "encode_%s(unsigned char *p, size_t len,"
+          " const %s *data, size_t *size)\n"
+          "{\n",
+          s->gen_name, s->gen_name);
+
+  switch (s->type->type) {
+  case TInteger:
+  case TUInteger:
+  case TBoolean:
+  case TOctetString:
+  case TGeneralizedTime:
+  case TGeneralString:
+  case TUTF8String:
+  case TNull:
+  case TBitString:
+  case TEnumerated:
+  case TOID:
+  case TSequence:
+  case TSequenceOf:
+  case TApplication:
+  case TType:
+    fprintf (codefile,
+            "size_t ret = 0;\n"
+            "size_t l;\n"
+            "int i, e;\n\n");
+    fprintf(codefile, "i = 0;\n"); /* hack to avoid `unused variable' */
+    
+      encode_type("data", s->type);
+
+    fprintf (codefile, "*size = ret;\n"
+            "return 0;\n");
+    break;
+  default:
+    abort ();
+  }
+  fprintf (codefile, "}\n\n");
+}
diff --git a/src/kerberosV/src/lib/asn1/gen_free.c b/src/kerberosV/src/lib/asn1/gen_free.c
new file mode 100644 (file)
index 0000000..a471cf5
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen_free.c,v 1.12 2003/10/03 00:28:08 lha Exp $");
+
+static void
+free_primitive (const char *typename, const char *name)
+{
+    fprintf (codefile, "free_%s(%s);\n", typename, name);
+}
+
+static void
+free_type (const char *name, const Type *t)
+{
+  switch (t->type) {
+  case TType:
+#if 0
+      free_type (name, t->symbol->type);
+#endif
+      fprintf (codefile, "free_%s(%s);\n", t->symbol->gen_name, name);
+      break;
+  case TInteger:
+  case TUInteger:
+  case TBoolean:
+  case TEnumerated :
+      break;
+  case TOctetString:
+      free_primitive ("octet_string", name);
+      break;
+  case TOID :
+      free_primitive ("oid", name);
+      break;
+  case TBitString: {
+      break;
+  }
+  case TSequence: {
+      Member *m;
+      int tag = -1;
+
+      if (t->members == NULL)
+         break;
+      
+      for (m = t->members; m && tag != m->val; m = m->next) {
+         char *s;
+
+         asprintf (&s, "%s(%s)->%s",
+                   m->optional ? "" : "&", name, m->gen_name);
+         if(m->optional)
+             fprintf(codefile, "if(%s) {\n", s);
+         free_type (s, m->type);
+         if(m->optional)
+             fprintf(codefile, 
+                     "free(%s);\n"
+                     "%s = NULL;\n"
+                     "}\n", s, s);
+         if (tag == -1)
+             tag = m->val;
+         free (s);
+      }
+      break;
+  }
+  case TSequenceOf: {
+      char *n;
+
+      fprintf (codefile, "while((%s)->len){\n", name);
+      asprintf (&n, "&(%s)->val[(%s)->len-1]", name, name);
+      free_type(n, t->subtype);
+      fprintf(codefile, 
+             "(%s)->len--;\n"
+             "}\n",
+             name);
+      fprintf(codefile,
+             "free((%s)->val);\n"
+             "(%s)->val = NULL;\n", name, name);
+      free(n);
+      break;
+  }
+  case TGeneralizedTime:
+      break;
+  case TGeneralString:
+      free_primitive ("general_string", name);
+      break;
+  case TUTF8String:
+      free_primitive ("utf8string", name);
+      break;
+  case TNull:
+      break;
+  case TApplication:
+      free_type (name, t->subtype);
+      break;
+  default :
+      abort ();
+  }
+}
+
+void
+generate_type_free (const Symbol *s)
+{
+  fprintf (headerfile,
+          "void   free_%s  (%s *);\n",
+          s->gen_name, s->gen_name);
+
+  fprintf (codefile, "void\n"
+          "free_%s(%s *data)\n"
+          "{\n",
+          s->gen_name, s->gen_name);
+
+  free_type ("data", s->type);
+  fprintf (codefile, "}\n\n");
+}
+
diff --git a/src/kerberosV/src/lib/asn1/gen_glue.c b/src/kerberosV/src/lib/asn1/gen_glue.c
new file mode 100644 (file)
index 0000000..0d823c4
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 1997, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen_glue.c,v 1.8 2005/04/25 18:07:07 lha Exp $");
+
+static void
+generate_2int (const Symbol *s)
+{
+    Type *t = s->type;
+    Member *m;
+    int tag = -1;
+
+    fprintf (headerfile,
+            "unsigned %s2int(%s);\n",
+            s->gen_name, s->gen_name);
+
+    fprintf (codefile,
+            "unsigned %s2int(%s f)\n"
+            "{\n"
+            "unsigned r = 0;\n",
+            s->gen_name, s->gen_name);
+
+    for (m = t->members; m && m->val != tag; m = m->next) {
+       fprintf (codefile, "if(f.%s) r |= (1U << %d);\n",
+                m->gen_name, m->val);
+       
+       if (tag == -1)
+           tag = m->val;
+    }
+    fprintf (codefile, "return r;\n"
+            "}\n\n");
+}
+
+static void
+generate_int2 (const Symbol *s)
+{
+    Type *t = s->type;
+    Member *m;
+    int tag = -1;
+
+    fprintf (headerfile,
+            "%s int2%s(unsigned);\n",
+            s->gen_name, s->gen_name);
+
+    fprintf (codefile,
+            "%s int2%s(unsigned n)\n"
+            "{\n"
+            "\t%s flags;\n\n",
+            s->gen_name, s->gen_name, s->gen_name);
+
+    for (m = t->members; m && m->val != tag; m = m->next) {
+       fprintf (codefile, "\tflags.%s = (n >> %d) & 1;\n",
+                m->gen_name, m->val);
+       
+       if (tag == -1)
+           tag = m->val;
+    }
+    fprintf (codefile, "\treturn flags;\n"
+            "}\n\n");
+}
+
+/*
+ * This depends on the bit string being declared in increasing order
+ */
+
+static void
+generate_units (const Symbol *s)
+{
+    Type *t = s->type;
+    Member *m;
+    int tag = -1;
+
+    fprintf (headerfile,
+            "const struct units * asn1_%s_units(void);",
+            s->gen_name);
+
+    fprintf (codefile,
+            "static struct units %s_units[] = {\n",
+            s->gen_name);
+
+    if(t->members)
+       for (m = t->members->prev; m && m->val != tag; m = m->prev) {
+           fprintf (codefile,
+                    "\t{\"%s\",\t1U << %d},\n", m->gen_name, m->val);
+           
+           if (tag == -1)
+               tag = m->val;
+       }
+
+    fprintf (codefile,
+            "\t{NULL,\t0}\n"
+            "};\n\n");
+
+    fprintf (codefile,
+            "const struct units * asn1_%s_units(void){\n"
+            "return %s_units;\n"
+            "}\n\n",
+            s->gen_name, s->gen_name);
+
+
+}
+
+void
+generate_glue (const Symbol *s)
+{
+    switch(s->type->type) {
+    case TBitString :
+       generate_2int (s);
+       generate_int2 (s);
+       generate_units (s);
+       break;
+    default :
+       break;
+    }
+}
diff --git a/src/kerberosV/src/lib/asn1/gen_length.c b/src/kerberosV/src/lib/asn1/gen_length.c
new file mode 100644 (file)
index 0000000..38b39ef
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: gen_length.c,v 1.14 2004/01/19 17:54:33 lha Exp $");
+
+static void
+length_primitive (const char *typename,
+                 const char *name,
+                 const char *variable)
+{
+    fprintf (codefile, "%s += length_%s(%s);\n", variable, typename, name);
+}
+
+static void
+length_type (const char *name, const Type *t, const char *variable)
+{
+    switch (t->type) {
+    case TType:
+#if 0
+       length_type (name, t->symbol->type);
+#endif
+       fprintf (codefile, "%s += length_%s(%s);\n",
+                variable, t->symbol->gen_name, name);
+       break;
+    case TInteger:
+        if(t->members == NULL)
+            length_primitive ("integer", name, variable);
+        else {
+            char *s;
+            asprintf(&s, "(const int*)%s", name);
+            if(s == NULL)
+               errx (1, "out of memory");
+            length_primitive ("integer", s, variable);
+            free(s);
+        }
+       break;
+    case TUInteger:
+       length_primitive ("unsigned", name, variable);
+       break;
+    case TEnumerated :
+       length_primitive ("enumerated", name, variable);
+       break;
+    case TOctetString:
+       length_primitive ("octet_string", name, variable);
+       break;
+    case TOID :
+       length_primitive ("oid", name, variable);
+       break;
+    case TBitString: {
+       /*
+        * XXX - Hope this is correct
+        * look at TBitString case in `encode_type'
+        */
+       fprintf (codefile, "%s += 7;\n", variable);
+       break;
+    }
+    case TSequence: {
+       Member *m;
+       int tag = -1;
+
+       if (t->members == NULL)
+           break;
+      
+       for (m = t->members; m && tag != m->val; m = m->next) {
+           char *s;
+
+           asprintf (&s, "%s(%s)->%s",
+                     m->optional ? "" : "&", name, m->gen_name);
+           if (m->optional)
+               fprintf (codefile, "if(%s)", s);
+           fprintf (codefile, "{\n"
+                    "int oldret = %s;\n"
+                    "%s = 0;\n", variable, variable);
+           length_type (s, m->type, "ret");
+           fprintf (codefile, "%s += 1 + length_len(%s) + oldret;\n",
+                    variable, variable);
+           fprintf (codefile, "}\n");
+           if (tag == -1)
+               tag = m->val;
+           free (s);
+       }
+       fprintf (codefile,
+                "%s += 1 + length_len(%s);\n", variable, variable);
+       break;
+    }
+    case TSequenceOf: {
+       char *n;
+
+       fprintf (codefile,
+                "{\n"
+                "int oldret = %s;\n"
+                "int i;\n"
+                "%s = 0;\n",
+                variable, variable);
+
+       fprintf (codefile, "for(i = (%s)->len - 1; i >= 0; --i){\n", name);
+       fprintf (codefile, "int oldret = %s;\n"
+                "%s = 0;\n", variable, variable);
+       asprintf (&n, "&(%s)->val[i]", name);
+       length_type(n, t->subtype, variable);
+       fprintf (codefile, "%s += oldret;\n",
+                variable);
+       fprintf (codefile, "}\n");
+
+       fprintf (codefile,
+                "%s += 1 + length_len(%s) + oldret;\n"
+                "}\n", variable, variable);
+       free(n);
+       break;
+    }
+    case TGeneralizedTime:
+       length_primitive ("generalized_time", name, variable);
+       break;
+    case TGeneralString:
+       length_primitive ("general_string", name, variable);
+       break;
+    case TUTF8String:
+       length_primitive ("utf8string", name, variable);
+       break;
+    case TNull:
+       fprintf (codefile, "%s += length_nulltype();\n", variable);
+       break;
+    case TApplication:
+       length_type (name, t->subtype, variable);
+       fprintf (codefile, "ret += 1 + length_len (ret);\n");
+       break;
+    case TBoolean:
+       length_primitive ("boolean", name, variable);
+       break;
+    default :
+       abort ();
+    }
+}
+
+void
+generate_type_length (const Symbol *s)
+{
+  fprintf (headerfile,
+          "size_t length_%s(const %s *);\n",
+          s->gen_name, s->gen_name);
+
+  fprintf (codefile,
+          "size_t\n"
+          "length_%s(const %s *data)\n"
+          "{\n"
+          "size_t ret = 0;\n",
+          s->gen_name, s->gen_name);
+
+  length_type ("data", s->type, "ret");
+  fprintf (codefile, "return ret;\n}\n\n");
+}
+
diff --git a/src/kerberosV/src/lib/asn1/gen_locl.h b/src/kerberosV/src/lib/asn1/gen_locl.h
new file mode 100644 (file)
index 0000000..e39899f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: gen_locl.h,v 1.9 2001/09/27 16:21:47 assar Exp $ */
+
+#ifndef __GEN_LOCL_H__
+#define __GEN_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+#include <err.h>
+#include <roken.h>
+#include "hash.h"
+#include "symbol.h"
+
+void generate_type (const Symbol *);
+void generate_constant (const Symbol *);
+void generate_type_encode (const Symbol *s);
+void generate_type_decode (const Symbol *s);
+void generate_seq_type_decode (const Symbol *s);
+void generate_type_free (const Symbol *s);
+void generate_type_length (const Symbol *s);
+void generate_type_copy (const Symbol *s);
+void generate_type_maybe (const Symbol *s);
+void generate_glue (const Symbol *s);
+
+void init_generate (const char *filename, const char *basename);
+const char *filename (void);
+void close_generate(void);
+void add_import(const char *module);
+int yyparse(void);
+
+extern FILE *headerfile, *codefile, *logfile;
+
+#endif /* __GEN_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/asn1/hash.c b/src/kerberosV/src/lib/asn1/hash.c
new file mode 100644 (file)
index 0000000..9e29a7e
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * Hash table functions
+ */
+
+#include "gen_locl.h"
+
+RCSID("$KTH: hash.c,v 1.9 2005/01/08 22:55:26 lha Exp $");
+
+static Hashentry *_search(Hashtab * htab,      /* The hash table */
+                         void *ptr);   /* And key */
+
+Hashtab *
+hashtabnew(int sz,
+          int (*cmp) (void *, void *),
+          unsigned (*hash) (void *))
+{
+    Hashtab *htab;
+    int i;
+
+    assert(sz > 0);
+
+    htab = (Hashtab *) malloc(sizeof(Hashtab) + (sz - 1) * sizeof(Hashentry *));
+    if (htab == NULL)
+       return NULL;
+
+    for (i = 0; i < sz; ++i)
+       htab->tab[i] = NULL;
+
+    htab->cmp = cmp;
+    htab->hash = hash;
+    htab->sz = sz;
+    return htab;
+}
+
+/* Intern search function */
+
+static Hashentry *
+_search(Hashtab * htab, void *ptr)
+{
+    Hashentry *hptr;
+
+    assert(htab && ptr);
+
+    for (hptr = htab->tab[(*htab->hash) (ptr) % htab->sz];
+        hptr;
+        hptr = hptr->next)
+       if ((*htab->cmp) (ptr, hptr->ptr) == 0)
+           break;
+    return hptr;
+}
+
+/* Search for element in hash table */
+
+void *
+hashtabsearch(Hashtab * htab, void *ptr)
+{
+    Hashentry *tmp;
+
+    tmp = _search(htab, ptr);
+    return tmp ? tmp->ptr : tmp;
+}
+
+/* add element to hash table */
+/* if already there, set new value */
+/* !NULL if succesful */
+
+void *
+hashtabadd(Hashtab * htab, void *ptr)
+{
+    Hashentry *h = _search(htab, ptr);
+    Hashentry **tabptr;
+
+    assert(htab && ptr);
+
+    if (h)
+       free((void *) h->ptr);
+    else {
+       h = (Hashentry *) malloc(sizeof(Hashentry));
+       if (h == NULL) {
+           return NULL;
+       }
+       tabptr = &htab->tab[(*htab->hash) (ptr) % htab->sz];
+       h->next = *tabptr;
+       *tabptr = h;
+       h->prev = tabptr;
+       if (h->next)
+           h->next->prev = &h->next;
+    }
+    h->ptr = ptr;
+    return h;
+}
+
+/* delete element with key key. Iff freep, free Hashentry->ptr */
+
+int
+_hashtabdel(Hashtab * htab, void *ptr, int freep)
+{
+    Hashentry *h;
+
+    assert(htab && ptr);
+
+    h = _search(htab, ptr);
+    if (h) {
+       if (freep)
+           free(h->ptr);
+       if ((*(h->prev) = h->next))
+           h->next->prev = h->prev;
+       free(h);
+       return 0;
+    } else
+       return -1;
+}
+
+/* Do something for each element */
+
+void
+hashtabforeach(Hashtab * htab, int (*func) (void *ptr, void *arg),
+              void *arg)
+{
+    Hashentry **h, *g;
+
+    assert(htab);
+
+    for (h = htab->tab; h < &htab->tab[htab->sz]; ++h)
+       for (g = *h; g; g = g->next)
+           if ((*func) (g->ptr, arg))
+               return;
+}
+
+/* standard hash-functions for strings */
+
+unsigned
+hashadd(const char *s)
+{                              /* Standard hash function */
+    unsigned i;
+
+    assert(s);
+
+    for (i = 0; *s; ++s)
+       i += *s;
+    return i;
+}
+
+unsigned
+hashcaseadd(const char *s)
+{                              /* Standard hash function */
+    unsigned i;
+
+    assert(s);
+
+    for (i = 0; *s; ++s)
+       i += toupper((unsigned char)*s);
+    return i;
+}
+
+#define TWELVE (sizeof(unsigned))
+#define SEVENTYFIVE (6*sizeof(unsigned))
+#define HIGH_BITS (~((unsigned)(~0) >> TWELVE))
+
+unsigned
+hashjpw(const char *ss)
+{                              /* another hash function */
+    unsigned h = 0;
+    unsigned g;
+    const unsigned char *s = (const unsigned char *)ss;
+
+    for (; *s; ++s) {
+       h = (h << TWELVE) + *s;
+       if ((g = h & HIGH_BITS))
+           h = (h ^ (g >> SEVENTYFIVE)) & ~HIGH_BITS;
+    }
+    return h;
+}
diff --git a/src/kerberosV/src/lib/asn1/hash.h b/src/kerberosV/src/lib/asn1/hash.h
new file mode 100644 (file)
index 0000000..a9a9651
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/*
+ * hash.h. Header file for hash table functions
+ */
+
+/* $KTH: hash.h,v 1.3 1999/12/02 17:05:02 joda Exp $ */
+
+struct hashentry {             /* Entry in bucket */
+     struct hashentry **prev;
+     struct hashentry *next;
+     void *ptr;
+};
+
+typedef struct hashentry Hashentry;
+
+struct hashtab {               /* Hash table */
+     int (*cmp)(void *, void *); /* Compare function */
+     unsigned (*hash)(void *); /* hash function */
+     int sz;                   /* Size */
+     Hashentry *tab[1];                /* The table */
+};
+
+typedef struct hashtab Hashtab;
+
+/* prototypes */
+
+Hashtab *hashtabnew(int sz, 
+                   int (*cmp)(void *, void *),
+                   unsigned (*hash)(void *));  /* Make new hash table */
+
+void *hashtabsearch(Hashtab *htab, /* The hash table */
+                   void *ptr); /*  The key */
+
+
+void *hashtabadd(Hashtab *htab,        /* The hash table */
+              void *ptr);      /* The element */
+
+int _hashtabdel(Hashtab *htab, /* The table */
+               void *ptr,      /* Key */
+               int freep);     /* Free data part? */
+
+void hashtabforeach(Hashtab *htab,
+                   int (*func)(void *ptr, void *arg),
+                   void *arg);
+
+unsigned hashadd(const char *s);               /* Standard hash function */
+unsigned hashcaseadd(const char *s);           /* Standard hash function */
+unsigned hashjpw(const char *s);               /* another hash function */
+
+/* macros */
+
+ /* Don't free space */
+#define hashtabdel(htab,key)  _hashtabdel(htab,key,FALSE)
+
+#define hashtabfree(htab,key) _hashtabdel(htab,key,TRUE) /* Do! */
diff --git a/src/kerberosV/src/lib/asn1/k5.asn1 b/src/kerberosV/src/lib/asn1/k5.asn1
new file mode 100644 (file)
index 0000000..a6c951e
--- /dev/null
@@ -0,0 +1,590 @@
+-- $KTH: k5.asn1,v 1.42 2005/04/08 10:32:44 lha Exp $
+
+KERBEROS5 DEFINITIONS ::=
+BEGIN
+
+NAME-TYPE ::= INTEGER {
+       KRB5_NT_UNKNOWN(0),     -- Name type not known
+       KRB5_NT_PRINCIPAL(1),   -- Just the name of the principal as in
+       KRB5_NT_SRV_INST(2),    -- Service and other unique instance (krbtgt)
+       KRB5_NT_SRV_HST(3),     -- Service with host name as instance
+       KRB5_NT_SRV_XHST(4),    -- Service with host as remaining components
+       KRB5_NT_UID(5),         -- Unique ID
+       KRB5_NT_X500_PRINCIPAL(6), -- PKINIT
+       KRB5_NT_ENTERPRISE(10)  -- May be mapped to principal name
+}
+
+-- message types
+
+MESSAGE-TYPE ::= INTEGER {
+       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
+}
+
+
+-- pa-data types
+
+PADATA-TYPE ::= INTEGER {
+       KRB5-PADATA-NONE(0),
+       KRB5-PADATA-TGS-REQ(1),
+       KRB5-PADATA-AP-REQ(1),
+       KRB5-PADATA-ENC-TIMESTAMP(2),
+       KRB5-PADATA-PW-SALT(3),
+       KRB5-PADATA-ENC-UNIX-TIME(5),
+       KRB5-PADATA-SANDIA-SECUREID(6),
+       KRB5-PADATA-SESAME(7),
+       KRB5-PADATA-OSF-DCE(8),
+       KRB5-PADATA-CYBERSAFE-SECUREID(9),
+       KRB5-PADATA-AFS3-SALT(10),
+       KRB5-PADATA-ETYPE-INFO(11),
+       KRB5-PADATA-SAM-CHALLENGE(12), -- (sam/otp)
+       KRB5-PADATA-SAM-RESPONSE(13), -- (sam/otp)
+       KRB5-PADATA-PK-AS-REQ-19(14), -- (PKINIT-19)
+       KRB5-PADATA-PK-AS-REP-19(15), -- (PKINIT-19)
+       KRB5-PADATA-PK-AS-REQ(16), -- (PKINIT-25)
+       KRB5-PADATA-PK-AS-REP(17), -- (PKINIT-25)
+       KRB5-PADATA-ETYPE-INFO2(19),
+       KRB5-PADATA-USE-SPECIFIED-KVNO(20),
+       KRB5-PADATA-SAM-REDIRECT(21), -- (sam/otp)
+       KRB5-PADATA-GET-FROM-TYPED-DATA(22),
+       KRB5-PADATA-SAM-ETYPE-INFO(23),
+       KRB5-PADATA-SERVER-REFERRAL(25),
+       KRB5-PADATA-TD-KRB-PRINCIPAL(102),      -- PrincipalName
+       KRB5-PADATA-TD-KRB-REALM(103),          -- Realm
+       KRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS(104), -- PKINIT
+       KRB5-PADATA-PK-TD-CERTIFICATE-INDEX(105), -- PKINIT
+       KRB5-PADATA-TD-APP-DEFINED-ERROR(106),  -- application specific
+       KRB5-PADATA-TD-REQ-NONCE(107),          -- INTEGER
+       KRB5-PADATA-TD-REQ-SEQ(108),            -- INTEGER
+       KRB5-PADATA-PA-PAC-REQUEST(128)         -- jbrezak@exchange.microsoft.com
+}
+
+AUTHDATA-TYPE ::= INTEGER {
+       KRB5-AUTHDATA-IF-RELEVANT(1),
+       KRB5-AUTHDATA-INTENDED-FOR_SERVER(2),
+       KRB5-AUTHDATA-INTENDED-FOR-APPLICATION-CLASS(3),
+       KRB5-AUTHDATA-KDC-ISSUED(4),
+       KRB5-AUTHDATA-AND-OR(5),
+       KRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS(6),
+       KRB5-AUTHDATA-IN-TICKET-EXTENSIONS(7),
+       KRB5-AUTHDATA-MANDATORY-FOR-KDC(8),
+       KRB5-AUTHDATA-OSF-DCE(64),
+       KRB5-AUTHDATA-SESAME(65),
+       KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66),
+       KRB5-AUTHDATA-WIN2K-PAC(128),
+       KRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129) -- Authenticator only
+}
+
+-- checksumtypes
+
+CKSUMTYPE ::= INTEGER {
+       CKSUMTYPE_NONE(0),
+       CKSUMTYPE_CRC32(1),
+       CKSUMTYPE_RSA_MD4(2),
+       CKSUMTYPE_RSA_MD4_DES(3),
+       CKSUMTYPE_DES_MAC(4),
+       CKSUMTYPE_DES_MAC_K(5),
+       CKSUMTYPE_RSA_MD4_DES_K(6),
+       CKSUMTYPE_RSA_MD5(7),
+       CKSUMTYPE_RSA_MD5_DES(8),
+       CKSUMTYPE_RSA_MD5_DES3(9),
+       CKSUMTYPE_SHA1_OTHER(10),
+       CKSUMTYPE_HMAC_SHA1_DES3(12),
+       CKSUMTYPE_SHA1(14),
+       CKSUMTYPE_HMAC_SHA1_96_AES_128(15),
+       CKSUMTYPE_HMAC_SHA1_96_AES_256(16),
+       CKSUMTYPE_GSSAPI(0x8003),
+       CKSUMTYPE_HMAC_MD5(-138),       -- unofficial microsoft number
+       CKSUMTYPE_HMAC_MD5_ENC(-1138)   -- even more unofficial
+}
+
+--enctypes
+ENCTYPE ::= INTEGER {
+       ETYPE_NULL(0),
+       ETYPE_DES_CBC_CRC(1),
+       ETYPE_DES_CBC_MD4(2),
+       ETYPE_DES_CBC_MD5(3),
+       ETYPE_DES3_CBC_MD5(5),
+       ETYPE_OLD_DES3_CBC_SHA1(7),
+       ETYPE_SIGN_DSA_GENERATE(8),
+       ETYPE_ENCRYPT_RSA_PRIV(9),
+       ETYPE_ENCRYPT_RSA_PUB(10),
+       ETYPE_DES3_CBC_SHA1(16),        -- with key derivation
+       ETYPE_AES128_CTS_HMAC_SHA1_96(17),
+       ETYPE_AES256_CTS_HMAC_SHA1_96(18),
+       ETYPE_ARCFOUR_HMAC_MD5(23),
+       ETYPE_ARCFOUR_HMAC_MD5_56(24),
+       ETYPE_ENCTYPE_PK_CROSS(48),
+-- these are for Heimdal internal use
+       ETYPE_DES_CBC_NONE(-0x1000),
+       ETYPE_DES3_CBC_NONE(-0x1001),
+       ETYPE_DES_CFB64_NONE(-0x1002),
+       ETYPE_DES_PCBC_NONE(-0x1003),
+       ETYPE_DIGEST_MD5_NONE(-0x1004),         -- private use, lukeh@padl.com
+       ETYPE_CRAM_MD5_NONE(-0x1005),           -- private use, lukeh@padl.com
+       ETYPE_RC2_CBC_NONE(-0x1006),
+       ETYPE_AES128_CBC_NONE(-0x1007),
+       ETYPE_AES192_CBC_NONE(-0x1008),
+       ETYPE_AES256_CBC_NONE(-0x1009),
+       ETYPE_DES3_CBC_NONE_CMS(-0x100a)
+}
+
+-- this is sugar to make something ASN1 does not have: unsigned
+
+UNSIGNED ::= INTEGER (0..4294967295)
+
+KerberosString  ::= GeneralString
+
+Realm ::= GeneralString
+PrincipalName ::= SEQUENCE {
+       name-type[0]            NAME-TYPE,
+       name-string[1]          SEQUENCE OF GeneralString
+}
+
+-- this is not part of RFC1510
+Principal ::= SEQUENCE {
+       name[0]                 PrincipalName,
+       realm[1]                Realm
+}
+
+HostAddress ::= SEQUENCE  {
+       addr-type[0]            INTEGER,
+       address[1]              OCTET STRING
+}
+
+-- This is from RFC1510.
+--
+-- HostAddresses ::= SEQUENCE OF SEQUENCE {
+--     addr-type[0]            INTEGER,
+--     address[1]              OCTET STRING
+-- }
+
+-- This seems much better.
+HostAddresses ::= SEQUENCE OF HostAddress
+
+
+KerberosTime ::= GeneralizedTime -- Specifying UTC time zone (Z)
+
+AuthorizationData ::= SEQUENCE OF SEQUENCE {
+       ad-type[0]              INTEGER,
+       ad-data[1]              OCTET STRING
+}
+
+APOptions ::= BIT STRING {
+       reserved(0),
+       use-session-key(1),
+       mutual-required(2)
+}
+
+TicketFlags ::= BIT STRING {
+       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),
+       transited-policy-checked(12),
+       ok-as-delegate(13),
+       anonymous(14)
+}
+
+KDCOptions ::= BIT STRING {
+       reserved(0),
+       forwardable(1),
+       forwarded(2),
+       proxiable(3),
+       proxy(4),
+       allow-postdate(5),
+       postdated(6),
+       unused7(7),
+       renewable(8),
+       unused9(9),
+       unused10(10),
+       unused11(11),
+       request-anonymous(14),
+       canonicalize(15),
+       disable-transited-check(26),
+       renewable-ok(27),
+       enc-tkt-in-skey(28),
+       renew(30),
+       validate(31)
+}
+
+LR-TYPE ::= INTEGER {
+       LR_NONE(0),             -- no information
+       LR_INITIAL_TGT(1),      -- last initial TGT request
+       LR_INITIAL(2),          -- last initial request
+       LR_ISSUE_USE_TGT(3),    -- time of newest TGT used
+       LR_RENEWAL(4),          -- time of last renewal
+       LR_REQUEST(5),          -- time of last request (of any type)
+       LR_PW_EXPTIME(6),       -- expiration time of password
+       LR_ACCT_EXPTIME(7)      -- expiration time of account
+}
+
+LastReq ::= SEQUENCE OF SEQUENCE {
+       lr-type[0]              LR-TYPE,
+       lr-value[1]             KerberosTime
+}
+
+
+EncryptedData ::= SEQUENCE {
+       etype[0]                ENCTYPE, -- EncryptionType
+       kvno[1]                 INTEGER OPTIONAL,
+       cipher[2]               OCTET STRING -- ciphertext
+}
+
+EncryptionKey ::= SEQUENCE {
+       keytype[0]              INTEGER,
+       keyvalue[1]             OCTET STRING
+}
+
+-- encoded Transited field
+TransitedEncoding ::= SEQUENCE {
+       tr-type[0]              INTEGER, -- must be registered
+       contents[1]             OCTET STRING
+}
+
+Ticket ::= [APPLICATION 1] SEQUENCE {
+       tkt-vno[0]              INTEGER,
+       realm[1]                Realm,
+       sname[2]                PrincipalName,
+       enc-part[3]             EncryptedData
+}
+-- 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
+}
+
+Checksum ::= SEQUENCE {
+       cksumtype[0]            CKSUMTYPE,
+       checksum[1]             OCTET STRING
+}
+
+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]           UNSIGNED OPTIONAL,
+       authorization-data[8]   AuthorizationData OPTIONAL
+       }
+
+PA-DATA ::= SEQUENCE {
+       -- might be encoded AP-REQ
+       padata-type[1]          PADATA-TYPE,
+       padata-value[2]         OCTET STRING
+}
+
+ETYPE-INFO-ENTRY ::= SEQUENCE {
+       etype[0]                ENCTYPE,
+       salt[1]                 OCTET STRING OPTIONAL,
+       salttype[2]             INTEGER OPTIONAL
+}
+
+ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY
+
+ETYPE-INFO2-ENTRY ::= SEQUENCE {
+       etype[0]                ENCTYPE,
+       salt[1]                 KerberosString OPTIONAL,
+       s2kparams[2]            OCTET STRING OPTIONAL
+}
+
+ETYPE-INFO2 ::= SEQUENCE OF ETYPE-INFO2-ENTRY
+
+METHOD-DATA ::= SEQUENCE OF PA-DATA
+
+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 OPTIONAL,
+       rtime[6]                KerberosTime OPTIONAL,
+       nonce[7]                INTEGER,
+       etype[8]                SEQUENCE OF ENCTYPE, -- EncryptionType,
+                                       -- in preference order
+       addresses[9]            HostAddresses OPTIONAL,
+       enc-authorization-data[10] EncryptedData OPTIONAL,
+                                       -- Encrypted AuthorizationData encoding
+       additional-tickets[11]  SEQUENCE OF Ticket OPTIONAL
+}
+
+KDC-REQ ::= SEQUENCE {
+       pvno[1]                 INTEGER,
+       msg-type[2]             MESSAGE-TYPE,
+       padata[3]               METHOD-DATA OPTIONAL,
+       req-body[4]             KDC-REQ-BODY
+}
+
+AS-REQ ::= [APPLICATION 10] KDC-REQ
+TGS-REQ ::= [APPLICATION 12] KDC-REQ
+
+-- padata-type ::= PA-ENC-TIMESTAMP
+-- padata-value ::= EncryptedData - PA-ENC-TS-ENC
+
+PA-ENC-TS-ENC ::= SEQUENCE {
+       patimestamp[0]          KerberosTime, -- client's time
+       pausec[1]               INTEGER OPTIONAL
+}
+
+-- draft-brezak-win2k-krb-authz-01
+PA-PAC-REQUEST ::= SEQUENCE {
+       include-pac[0]          BOOLEAN -- Indicates whether a PAC 
+                                       -- should be included or not
+}
+
+KDC-REP ::= SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE,
+       padata[2]               METHOD-DATA OPTIONAL,
+       crealm[3]               Realm,
+       cname[4]                PrincipalName,
+       ticket[5]               Ticket,
+       enc-part[6]             EncryptedData
+}
+
+AS-REP ::= [APPLICATION 11] KDC-REP
+TGS-REP ::= [APPLICATION 13] KDC-REP
+
+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
+}
+
+EncASRepPart ::= [APPLICATION 25] EncKDCRepPart
+EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
+
+AP-REQ ::= [APPLICATION 14] SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE,
+       ap-options[2]           APOptions,
+       ticket[3]               Ticket,
+       authenticator[4]        EncryptedData
+}
+
+AP-REP ::= [APPLICATION 15] SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE,
+       enc-part[2]             EncryptedData
+}
+
+EncAPRepPart ::= [APPLICATION 27]     SEQUENCE {
+       ctime[0]                KerberosTime,
+       cusec[1]                INTEGER,
+       subkey[2]               EncryptionKey OPTIONAL,
+       seq-number[3]           UNSIGNED OPTIONAL
+}
+
+KRB-SAFE-BODY ::= SEQUENCE {
+       user-data[0]            OCTET STRING,
+       timestamp[1]            KerberosTime OPTIONAL,
+       usec[2]                 INTEGER OPTIONAL,
+       seq-number[3]           UNSIGNED OPTIONAL,
+       s-address[4]            HostAddress OPTIONAL,
+       r-address[5]            HostAddress OPTIONAL
+}
+
+KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE,
+       safe-body[2]            KRB-SAFE-BODY,
+       cksum[3]                Checksum
+}
+
+KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE,
+       enc-part[3]             EncryptedData
+}
+EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
+       user-data[0]            OCTET STRING,
+       timestamp[1]            KerberosTime OPTIONAL,
+       usec[2]                 INTEGER OPTIONAL,
+       seq-number[3]           UNSIGNED OPTIONAL,
+       s-address[4]            HostAddress OPTIONAL, -- sender's addr
+       r-address[5]            HostAddress OPTIONAL  -- recip's addr
+}
+
+KRB-CRED ::= [APPLICATION 22]   SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE, -- KRB_CRED
+       tickets[2]              SEQUENCE OF Ticket,
+       enc-part[3]             EncryptedData
+}
+
+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
+}
+
+EncKrbCredPart ::= [APPLICATION 29]   SEQUENCE {
+       ticket-info[0]          SEQUENCE OF KrbCredInfo,
+       nonce[1]                INTEGER OPTIONAL,
+       timestamp[2]            KerberosTime OPTIONAL,
+       usec[3]                 INTEGER OPTIONAL,
+       s-address[4]            HostAddress OPTIONAL,
+       r-address[5]            HostAddress OPTIONAL
+}
+
+KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
+       pvno[0]                 INTEGER,
+       msg-type[1]             MESSAGE-TYPE,
+       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
+}
+
+ChangePasswdDataMS ::= SEQUENCE {
+       newpasswd[0]            OCTET STRING,
+       targname[1]             PrincipalName OPTIONAL,
+       targrealm[2]            Realm OPTIONAL
+}
+
+EtypeList ::= SEQUENCE OF INTEGER
+       -- the client's proposed enctype list in
+       -- decreasing preference order, favorite choice first
+
+pvno INTEGER ::= 5 -- current Kerberos protocol version number
+
+-- transited encodings
+
+DOMAIN-X500-COMPRESS   INTEGER ::= 1
+
+-- authorization data primitives
+
+AD-IF-RELEVANT ::= AuthorizationData
+
+AD-KDCIssued ::= SEQUENCE {
+       ad-checksum[0]          Checksum,
+       i-realm[1]              Realm OPTIONAL,
+       i-sname[2]              PrincipalName OPTIONAL,
+       elements[3]             AuthorizationData
+}
+
+AD-AND-OR ::= SEQUENCE {
+       condition-count[0]      INTEGER,
+       elements[1]             AuthorizationData
+}
+
+AD-MANDATORY-FOR-KDC ::= AuthorizationData
+
+-- PA-SAM-RESPONSE-2/PA-SAM-RESPONSE-2
+
+PA-SAM-TYPE ::= INTEGER {
+       PA_SAM_TYPE_ENIGMA(1),          -- Enigma Logic
+       PA_SAM_TYPE_DIGI_PATH(2),       -- Digital Pathways
+       PA_SAM_TYPE_SKEY_K0(3),         -- S/key where  KDC has key 0
+       PA_SAM_TYPE_SKEY(4),            -- Traditional S/Key
+       PA_SAM_TYPE_SECURID(5),         -- Security Dynamics
+       PA_SAM_TYPE_CRYPTOCARD(6)       -- CRYPTOCard
+}
+
+PA-SAM-REDIRECT ::= HostAddresses
+
+SAMFlags ::= BIT STRING {
+       use-sad-as-key(0),
+       send-encrypted-sad(1),
+       must-pk-encrypt-sad(2)
+}
+
+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,
+       ...
+}
+
+PA-SAM-CHALLENGE-2 ::= SEQUENCE {
+       sam-body[0]             PA-SAM-CHALLENGE-2-BODY,
+       sam-cksum[1]            SEQUENCE OF Checksum, -- (1..MAX)
+       ...
+}
+
+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-RESPONSE-ENC ::= SEQUENCE {
+       sam-nonce[0]            INTEGER,
+       sam-sad[1]              GeneralString OPTIONAL,
+       ...
+}
+
+RC2CBCParameter ::= SEQUENCE {
+       rc2ParameterVersion     [0] INTEGER,
+       iv                      [1] OCTET STRING -- exactly 8 octets
+}
+
+CBCParameter ::= OCTET STRING
+
+END
+
+-- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' k5.asn1
diff --git a/src/kerberosV/src/lib/asn1/lex.h b/src/kerberosV/src/lib/asn1/lex.h
new file mode 100644 (file)
index 0000000..ae6bbbc
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: lex.h,v 1.5 2000/07/01 20:21:34 assar Exp $ */
+
+#include <roken.h>
+
+void error_message (const char *, ...)
+__attribute__ ((format (printf, 1, 2)));
+
+int yylex(void);
diff --git a/src/kerberosV/src/lib/asn1/lex.l b/src/kerberosV/src/lib/asn1/lex.l
new file mode 100644 (file)
index 0000000..59c4892
--- /dev/null
@@ -0,0 +1,186 @@
+%{
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: lex.l,v 1.24 2004/10/13 17:40:21 lha Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#undef ECHO
+#include "symbol.h"
+#include "parse.h"
+#include "lex.h"
+#include "gen_locl.h"
+
+static unsigned lineno = 1;
+
+#define YY_NO_UNPUT
+
+#undef ECHO
+
+static void handle_comment(int type);
+
+%}
+
+
+%%
+INTEGER                        { return INTEGER; }
+BOOLEAN                        { return BOOLEAN; }
+IMPORTS                        { return IMPORTS; }
+FROM                   { return FROM; }
+SEQUENCE               { return SEQUENCE; }
+CHOICE                 { return CHOICE; }
+OF                     { return OF; }
+OCTET                  { return OCTET; }
+STRING                 { return STRING; }
+GeneralizedTime                { return GeneralizedTime; }
+GeneralString          { return GeneralString; }
+UTF8String             { return UTF8String; }
+NULL                   { return NULLTYPE; }
+BIT                    { return BIT; }
+APPLICATION            { return APPLICATION; }
+OPTIONAL               { return OPTIONAL; }
+BEGIN                  { return TBEGIN; }
+END                    { return END; }
+DEFAULT                        { return DEFAULT; }
+DEFINITIONS            { return DEFINITIONS; }
+ENUMERATED             { return ENUMERATED; }
+EXTERNAL               { return EXTERNAL; }
+OBJECT                 { return OBJECT; }
+IDENTIFIER             { return IDENTIFIER; }
+[-,;{}()|\"]           { return *yytext; }
+"["                    { return *yytext; }
+"]"                    { return *yytext; }
+::=                    { return EEQUAL; }
+--                     { handle_comment(0); }
+\/\*                   { handle_comment(1); }
+0x[0-9A-Fa-f]+|[0-9]+  { char *e, *y = yytext;
+                         yylval.constant = strtol((const char *)yytext,
+                                                  &e, 0);
+                         if(e == y) 
+                           error_message("malformed constant (%s)", yytext); 
+                         else
+                           return CONSTANT;
+                       }
+[A-Za-z][-A-Za-z0-9_]* {
+                         yylval.name =  strdup ((const char *)yytext);
+                         return IDENT;
+                       }
+[ \t]                  ;
+\n                     { ++lineno; }
+\.\.\.                 { return DOTDOTDOT; }
+\.\.                   { return DOTDOT; }
+.                      { error_message("Ignoring char(%c)\n", *yytext); }
+%%
+
+#ifndef yywrap /* XXX */
+int
+yywrap () 
+{
+     return 1;
+}
+#endif
+
+void
+error_message (const char *format, ...)
+{
+     va_list args;
+
+     va_start (args, format);
+     fprintf (stderr, "%s:%d: ", filename(), lineno);
+     vfprintf (stderr, format, args);
+     va_end (args);
+}
+
+static void
+handle_comment(int type)
+{
+    int c;
+    int start_lineno = lineno;
+    if(type == 0) {
+       int f = 0;
+       while((c = input()) != EOF) {
+           if(f && c == '-')
+               return;
+           if(c == '-') {
+               f = 1;
+               continue;
+           }
+           if(c == '\n') {
+               lineno++;
+               return;
+           }
+           f = 0;
+       }
+    } else {
+       int level = 1;
+       int seen_star = 0;
+       int seen_slash = 0;
+       while((c = input()) != EOF) {
+           if(c == '/') {
+               if(seen_star) {
+                   if(--level == 0)
+                       return;
+                   seen_star = 0;
+                   continue;
+               }
+               seen_slash = 1;
+               continue;
+           }
+           if(c == '*') {
+               if(seen_slash) {
+                   level++;
+                   seen_star = seen_slash = 0;
+                   continue;
+               } 
+               seen_star = 1;
+               continue;
+           }
+           seen_star = seen_slash = 0;
+           if(c == '\n') {
+               lineno++;
+               continue;
+           }
+       }
+    }
+    if(c == EOF)
+       error_message("unterminated comment, possibly started on line %d\n", start_lineno);
+}
diff --git a/src/kerberosV/src/lib/asn1/libasn1.h b/src/kerberosV/src/lib/asn1/libasn1.h
new file mode 100644 (file)
index 0000000..8570b71
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: libasn1.h,v 1.9 2001/04/18 13:10:24 joda Exp $ */
+
+#ifndef __LIBASN1_H__
+#define __LIBASN1_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "krb5_asn1.h"
+#include "der.h"
+#include "asn1_err.h"
+#include <parse_units.h>
+
+#endif /* __LIBASN1_H__ */
diff --git a/src/kerberosV/src/lib/asn1/main.c b/src/kerberosV/src/lib/asn1/main.c
new file mode 100644 (file)
index 0000000..5bd4d20
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+#include <getarg.h>
+
+RCSID("$KTH: main.c,v 1.12 2005/03/31 00:37:42 lha Exp $");
+
+extern FILE *yyin;
+
+int version_flag;
+int help_flag;
+struct getargs args[] = {
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+    arg_printusage(args, num_args, NULL, "[asn1-file [name]]");
+    exit(code);
+}
+
+int
+main(int argc, char **argv)
+{
+    int ret;
+    const char *file;
+    const char *name = NULL;
+    int optind = 0;
+
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    if (argc == optind) {
+       file = "stdin";
+       name = "stdin";
+       yyin = stdin;
+    } else {
+       file = argv[optind];
+       yyin = fopen (file, "r");
+       if (yyin == NULL)
+           err (1, "open %s", file);
+       name = argv[optind + 1];
+    }
+
+    init_generate (file, name);
+    initsym ();
+    ret = yyparse ();
+    close_generate ();
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/asn1/parse.y b/src/kerberosV/src/lib/asn1/parse.y
new file mode 100644 (file)
index 0000000..daa4e4a
--- /dev/null
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: parse.y,v 1.23 2004/10/13 17:41:48 lha Exp $ */
+
+%{
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "symbol.h"
+#include "lex.h"
+#include "gen_locl.h"
+
+RCSID("$KTH: parse.y,v 1.23 2004/10/13 17:41:48 lha Exp $");
+
+static Type *new_type (Typetype t);
+void yyerror (char *);
+
+static void append (Member *l, Member *r);
+
+%}
+
+%union {
+  int constant;
+  char *name;
+  Type *type;
+  Member *member;
+  char *defval;
+}
+
+%token INTEGER SEQUENCE CHOICE OF OCTET STRING GeneralizedTime GeneralString 
+%token BIT APPLICATION OPTIONAL EEQUAL TBEGIN END DEFINITIONS ENUMERATED
+%token UTF8String NULLTYPE
+%token EXTERNAL DEFAULT
+%token DOTDOT DOTDOTDOT
+%token BOOLEAN
+%token IMPORTS FROM
+%token OBJECT IDENTIFIER
+%token <name> IDENT 
+%token <constant> CONSTANT
+
+%type <constant> constant optional2
+%type <type> type
+%type <member> memberdecls memberdecl memberdeclstart bitdecls bitdecl
+
+%type <defval> defvalue
+
+%start envelope
+
+%%
+
+envelope       : IDENT DEFINITIONS EEQUAL TBEGIN specification END {}
+               ;
+
+specification  :
+               | specification declaration
+               ;
+
+declaration    : imports_decl
+               | type_decl
+               | constant_decl
+               ;
+
+referencenames : IDENT ',' referencenames
+               {
+                       Symbol *s = addsym($1);
+                       s->stype = Stype;
+               }
+               | IDENT
+               {
+                       Symbol *s = addsym($1);
+                       s->stype = Stype;
+               }
+               ;
+
+imports_decl   : IMPORTS referencenames FROM IDENT ';'
+               { add_import($4); }
+               ;
+
+type_decl      : IDENT EEQUAL type
+               {
+                 Symbol *s = addsym ($1);
+                 s->stype = Stype;
+                 s->type = $3;
+                 generate_type (s);
+               }
+               ;
+
+constant_decl  : IDENT type EEQUAL constant
+               {
+                 Symbol *s = addsym ($1);
+                 s->stype = SConstant;
+                 s->constant = $4;
+                 generate_constant (s);
+               }
+               ;
+
+type           : INTEGER     { $$ = new_type(TInteger); }
+               | INTEGER '(' constant DOTDOT constant ')' {
+                   if($3 != 0)
+                       error_message("Only 0 supported as low range");
+                   if($5 != INT_MIN && $5 != UINT_MAX && $5 != INT_MAX)
+                       error_message("Only %u supported as high range",
+                                     UINT_MAX);
+                   $$ = new_type(TUInteger);
+               }
+                | INTEGER '{' bitdecls '}'
+                {
+                       $$ = new_type(TInteger);
+                       $$->members = $3;
+                }
+               | OBJECT IDENTIFIER { $$ = new_type(TOID); }
+               | ENUMERATED '{' bitdecls '}'
+               {
+                       $$ = new_type(TEnumerated);
+                       $$->members = $3;
+               }
+               | OCTET STRING { $$ = new_type(TOctetString); }
+               | GeneralString { $$ = new_type(TGeneralString); }
+               | UTF8String { $$ = new_type(TUTF8String); }
+                | NULLTYPE { $$ = new_type(TNull); }
+               | GeneralizedTime { $$ = new_type(TGeneralizedTime); }
+               | SEQUENCE OF type
+               {
+                 $$ = new_type(TSequenceOf);
+                 $$->subtype = $3;
+               }
+               | SEQUENCE '{' memberdecls '}'
+               {
+                 $$ = new_type(TSequence);
+                 $$->members = $3;
+               }
+               | CHOICE '{' memberdecls '}'
+               {
+                 $$ = new_type(TChoice);
+                 $$->members = $3;
+               }
+               | BIT STRING '{' bitdecls '}'
+               {
+                 $$ = new_type(TBitString);
+                 $$->members = $4;
+               }
+               | IDENT
+               {
+                 Symbol *s = addsym($1);
+                 $$ = new_type(TType);
+                 if(s->stype != Stype)
+                   error_message ("%s is not a type\n", $1);
+                 else
+                   $$->symbol = s;
+               }
+               | '[' APPLICATION constant ']' type
+               {
+                 $$ = new_type(TApplication);
+                 $$->subtype = $5;
+                 $$->application = $3;
+               }
+               | BOOLEAN     { $$ = new_type(TBoolean); }
+               ;
+
+memberdecls    : { $$ = NULL; }
+               | memberdecl    { $$ = $1; }
+               | memberdecls  ',' DOTDOTDOT { $$ = $1; }
+               | memberdecls ',' memberdecl { $$ = $1; append($$, $3); }
+               ;
+
+memberdeclstart : IDENT '[' constant ']' type
+               {
+                 $$ = malloc(sizeof(*$$));
+                 $$->name = $1;
+                 $$->gen_name = strdup($1);
+                 output_name ($$->gen_name);
+                 $$->val = $3;
+                 $$->optional = 0;
+                 $$->defval = NULL;
+                 $$->type = $5;
+                 $$->next = $$->prev = $$;
+               }
+               ;
+
+
+memberdecl     : memberdeclstart optional2
+               { $1->optional = $2 ; $$ = $1; }
+               | memberdeclstart defvalue
+               { $1->defval = $2 ; $$ = $1; }
+               | memberdeclstart
+               { $$ = $1; }
+               ;
+
+
+optional2      : OPTIONAL { $$ = 1; }
+               ;
+
+defvalue       : DEFAULT constant
+               { asprintf(&$$, "%d", $2); }
+               | DEFAULT '"' IDENT '"'
+               { $$ = strdup ($3); }
+               ;
+
+bitdecls       : { $$ = NULL; }
+               | bitdecl { $$ = $1; }
+               | bitdecls ',' DOTDOTDOT { $$ = $1; }
+               | bitdecls ',' bitdecl { $$ = $1; append($$, $3); }
+               ;
+
+bitdecl                : IDENT '(' constant ')'
+               {
+                 $$ = malloc(sizeof(*$$));
+                 $$->name = $1;
+                 $$->gen_name = strdup($1);
+                 output_name ($$->gen_name);
+                 $$->val = $3;
+                 $$->optional = 0;
+                 $$->type = NULL;
+                 $$->prev = $$->next = $$;
+               }
+               ;
+
+constant       : CONSTANT      { $$ = $1; }
+               | '-' CONSTANT  { $$ = -$2; }
+               | IDENT {
+                                 Symbol *s = addsym($1);
+                                 if(s->stype != SConstant)
+                                   error_message ("%s is not a constant\n",
+                                                  s->name);
+                                 else
+                                   $$ = s->constant;
+                               }
+               ;
+%%
+
+void
+yyerror (char *s)
+{
+     error_message ("%s\n", s);
+}
+
+static Type *
+new_type (Typetype tt)
+{
+  Type *t = malloc(sizeof(*t));
+  if (t == NULL) {
+      error_message ("out of memory in malloc(%lu)", 
+                    (unsigned long)sizeof(*t));
+      exit (1);
+  }
+  t->type = tt;
+  t->application = 0;
+  t->members = NULL;
+  t->subtype = NULL;
+  t->symbol  = NULL;
+  return t;
+}
+
+static void
+append (Member *l, Member *r)
+{
+  l->prev->next = r;
+  r->prev = l->prev;
+  l->prev = r;
+  r->next = l;
+}
diff --git a/src/kerberosV/src/lib/asn1/pkinit.asn1 b/src/kerberosV/src/lib/asn1/pkinit.asn1
new file mode 100644 (file)
index 0000000..92c5de7
--- /dev/null
@@ -0,0 +1,189 @@
+PKINIT DEFINITIONS ::= BEGIN
+
+IMPORTS  EncryptionKey, PrincipalName, Realm, KerberosTime, TypedData 
+       FROM krb5;
+IMPORTS SignedData, EnvelopedData FROM CMS;
+IMPORTS CertificateSerialNumber, AttributeTypeAndValue, Name FROM X509;
+
+
+-- 3.1
+
+CertPrincipalName ::= SEQUENCE {
+       name-type[0]            INTEGER,
+       name-string[1]          SEQUENCE OF UTF8String
+}
+
+
+-- 3.2.2
+
+
+TrustedCertifiers ::= SEQUENCE OF PrincipalName
+                               -- X.500 name encoded as a principal name
+                               -- see Section 3.1
+CertificateIndex  ::= INTEGER
+                               -- 0 = 1st certificate,
+                               --     (in order of encoding)
+                               -- 1 = 2nd certificate, etc
+
+PA-PK-AS-REP ::= CHOICE {
+                               -- PA TYPE 15
+       dhSignedData[0]         SignedData,
+                               -- Defined in CMS and used only with
+                               -- Diffie-Hellman key exchange (if the
+                               -- client public value was present in the
+                               -- request).
+                               -- 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.
+}
+
+
+
+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
+}
+
+-- subjectAltName EXTENSION ::= {
+--     SYNTAX GeneralNames
+--     IDENTIFIED BY id-ce-subjectAltName
+-- }
+
+OtherName ::= SEQUENCE {
+       type-id                 OBJECT IDENTIFIER,
+       value[0]                OCTET STRING
+--     value[0] EXPLICIT ANY DEFINED BY type-id
+}
+
+GeneralName ::= CHOICE {
+       otherName       [0] OtherName,
+       ...
+}
+
+GeneralNames ::= SEQUENCE -- SIZE(1..MAX)
+       OF GeneralName
+
+KerberosName ::= SEQUENCE {
+       realm[0]                Realm,
+                               -- as defined in RFC 1510
+       principalName[1]        CertPrincipalName
+                               -- defined above
+}
+
+
+-- krb5 OBJECT IDENTIFIER ::= {
+--     iso (1) org (3) dod (6) internet (1) security (5) kerberosv5 (2)
+-- }
+
+-- krb5PrincipalName OBJECT IDENTIFIER ::= { krb5 2 }
+
+-- 3.2.1
+
+
+IssuerAndSerialNumber ::= SEQUENCE {
+       issuer                  Name,
+       serialNumber            CertificateSerialNumber
+}
+
+TrustedCas ::= CHOICE {
+       principalName[0]        KerberosName,
+                               -- as defined below
+       caName[1]               Name,
+                               -- fully qualified X.500 name
+                               -- as defined by X.509
+       issuerAndSerial[2]      IssuerAndSerialNumber
+                               -- Since a CA may have a number of
+                               -- certificates, only one of which
+                               -- a client trusts
+}
+
+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;
+       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.
+}
+
+PKAuthenticator ::= SEQUENCE {
+       kdcName[0]              PrincipalName,
+       kdcRealm[1]             Realm,
+       cusec[2]                INTEGER,
+                               -- for replay prevention as in RFC1510
+       ctime[3]                KerberosTime,
+                               -- for replay prevention as in RFC1510
+       nonce[4]                INTEGER
+}
+
+-- This is the real definition of AlgorithmIdentifier
+-- AlgorithmIdentifier ::= SEQUENCE {
+--     algorithm               ALGORITHM.&id,
+--     parameters              ALGORITHM.&Type
+-- }   -- as specified by the X.509 recommendation[10]
+
+-- But we'll use this one instead:
+
+AlgorithmIdentifier ::= SEQUENCE {
+       algorithm               OBJECT IDENTIFIER,
+       parameters              CHOICE {
+                                       a 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]
+
+AuthPack ::= SEQUENCE {
+       pkAuthenticator[0]      PKAuthenticator,
+       clientPublicValue[1]    SubjectPublicKeyInfo OPTIONAL
+                               -- if client is using Diffie-Hellman
+                               -- (ephemeral-ephemeral only)
+}
+
+
+END
diff --git a/src/kerberosV/src/lib/asn1/rfc2459.asn1 b/src/kerberosV/src/lib/asn1/rfc2459.asn1
new file mode 100644 (file)
index 0000000..c9adec6
--- /dev/null
@@ -0,0 +1,21 @@
+RFC2459 DEFINITIONS ::= BEGIN
+
+AttributeType ::= OBJECT-IDENTIFIER
+
+AttributeValue ::= OCTET STRING --ANY DEFINED BY AttributeType
+
+AttributeTypeAndValue ::= SEQUENCE {
+       type AttributeType,
+       value AttributeValue
+}
+
+RelativeDistinguishedName ::= --SET
+SEQUENCE OF AttributeTypeAndValue
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+Name ::= CHOICE { -- RFC2459
+       x RDNSequence
+}
+
+END
\ No newline at end of file
diff --git a/src/kerberosV/src/lib/asn1/setchgpw2.asn1 b/src/kerberosV/src/lib/asn1/setchgpw2.asn1
new file mode 100644 (file)
index 0000000..d054edc
--- /dev/null
@@ -0,0 +1,195 @@
+-- $KTH: setchgpw2.asn1,v 1.3 2003/05/21 13:43:28 lha Exp $
+
+SETCHGPW2 DEFINITIONS ::=
+BEGIN
+
+IMPORTS PrincipalName, Realm FROM krb5;
+
+ProtocolErrorCode ::= ENUMERATED {
+       generic-error(0),
+       unsupported-major-version(1),
+       unsupported-minor-version(2),
+       unsupported-operation(3),
+       authorization-failed(4),
+       initial-ticket-required(5),
+       target-principal-unknown(6),
+       ...
+}
+
+Key    ::= SEQUENCE {
+       enc-type[0]     INTEGER,
+       key[1]          OCTET STRING,
+       ...
+}
+
+Etype ::= INTEGER
+
+Language-Tag   ::= UTF8String    -- Constrained by RFC3066
+
+LangTaggedText ::= SEQUENCE {
+       language[0]     Language-Tag OPTIONAL,
+       text[1]         UTF8String,
+       ...
+}
+
+-- NULL Op
+
+Req-null ::= NULL
+Rep-null ::= NULL
+Err-null ::= NULL
+
+-- Change password
+Req-change-pw ::= SEQUENCE {
+       old-pw[0]       UTF8String,
+       new-pw[1]       UTF8String OPTIONAL,
+       etypes[2]       SEQUENCE OF Etype OPTIONAL,
+       ...
+}
+
+Rep-change-pw ::= SEQUENCE {
+       info-text[0]    UTF8String OPTIONAL,
+       new-pw[1]       UTF8String OPTIONAL,
+       etypes[2]       SEQUENCE OF Etype OPTIONAL
+}
+
+Err-change-pw ::= SEQUENCE {
+       help-text[0]            UTF8String OPTIONAL,
+       code[1]                 ENUMERATED {
+               generic(0),
+               wont-generate-new-pw(1),
+               old-pw-incorrect(2),
+               new-pw-rejected-geneneric(3),
+               pw-change-too-short(4),
+               ...
+       },
+       suggested-new-pw[2]     UTF8String OPTIONAL,
+       ...
+}
+
+-- Change/Set keys
+Req-set-keys ::= SEQUENCE {
+       etypes[0]       SEQUENCE OF Etype,
+       entropy[1]      OCTET STRING,
+       ...
+}
+
+Rep-set-keys ::= SEQUENCE {
+       info-text[0]            UTF8String OPTIONAL,
+       kvno[1]                 INTEGER,
+       keys[2]                 SEQUENCE OF Key,
+       aliases[3]      SEQUENCE OF SEQUENCE {
+               name[0] PrincipalName,
+               realm[1] Realm OPTIONAL,
+               ...
+       },
+       ...
+}
+
+Err-set-keys ::= SEQUENCE {
+       help-text[0]            UTF8String OPTIONAL,
+       enctypes[1]             SEQUENCE OF Etype OPTIONAL,
+       code[1]         ENUMERATED {
+               etype-no-support(0),
+               ...
+       },
+       ...
+}
+
+-- Get password policy
+Req-get-pw-policy ::= NULL
+
+Rep-get-pw-policy ::= SEQUENCE {
+       help-text[0]            UTF8String OPTIONAL,
+       policy-name[1]          UTF8String OPTIONAL,
+       description[2]          UTF8String OPTIONAL,
+       ...
+}
+
+Err-get-pw-policy ::= NULL
+
+-- Get principal aliases
+Req-get-princ-aliases ::= NULL
+
+Rep-get-princ-aliases ::= SEQUENCE {
+       help-text[0]            UTF8String OPTIONAL,
+       aliases[1]      SEQUENCE OF SEQUENCE {
+               name[0]         PrincipalName,
+               realm[1]        Realm OPTIONAL,
+               ...
+       } OPTIONAL,
+       ...
+}
+
+Err-get-princ-aliases ::= NULL
+
+-- Get list of encryption types supported by KDC for new types
+Req-get-supported-etypes ::= NULL
+
+Rep-get-supported-etypes ::= SEQUENCE OF Etype
+
+Err-get-supported-etypes ::= NULL
+
+-- Choice switch
+
+Op-req ::= CHOICE {
+       null[0]                 Req-null,
+       change-pw[1]            Req-change-pw,
+       set-keys[2]             Req-set-keys,
+       get-pw-policy[3]        Req-get-pw-policy,
+       get-princ-aliases[4]    Req-get-princ-aliases,
+       get-supported-etypes[5] Req-get-supported-etypes,
+       ...
+}
+Op-rep ::= CHOICE {
+       null[0]                 Rep-null,
+       change-pw[1]            Rep-change-pw,
+       set-keys[2]             Rep-set-keys,
+       get-pw-policy[3]        Rep-get-pw-policy,
+       get-princ-aliases[4]    Rep-get-princ-aliases,
+       get-supported-etypes[5] Rep-get-supported-etypes,
+       ...
+}
+
+Op-error ::= CHOICE {
+       null[0]                 Err-null,
+       change-pw[1]            Err-change-pw,
+       set-keys[2]             Err-set-keys,
+       get-pw-policy[3]        Err-get-pw-policy,
+       get-princ-aliases[4]    Err-get-princ-aliases,
+       get-supported-etypes[5] Err-get-supported-etypes,
+       ...
+}
+
+
+Request ::= [ APPLICATION 0 ] SEQUENCE {
+       pvno-major[0]   INTEGER DEFAULT 2,
+       pvno-minor[1]   INTEGER DEFAULT 0,
+       languages[2]    SEQUENCE OF Language-Tag OPTIONAL,
+       targ-name[3]    PrincipalName OPTIONAL,
+       targ-realm[4]   Realm OPTIONAL,
+--     operation[5]    Op-Req,
+       ...
+}
+
+Responce ::= [ APPLICATION 1 ] SEQUENCE {
+       pvno-major[0]   INTEGER DEFAULT 2,
+       pvno-minor[1]   INTEGER DEFAULT 0,
+       language[2]     Language-Tag DEFAULT "i-default",
+--     result[3]       Op-rep OPTIONAL,
+       ...
+}
+
+Error-Responce ::= [ APPLICATION 2 ] SEQUENCE {
+       pvno-major[0]   INTEGER DEFAULT 2,
+       pvno-minor[1]   INTEGER DEFAULT 0,
+       language[2]     Language-Tag DEFAULT "i-default",
+       error-code[3]   ProtocolErrorCode,
+       help-text[4]    UTF8String OPTIONAL,
+--     op-error[5]     Op-error OP-ERROR,
+       ...
+}
+
+END
+
+-- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' setchgpw2.asn1
diff --git a/src/kerberosV/src/lib/asn1/symbol.c b/src/kerberosV/src/lib/asn1/symbol.c
new file mode 100644 (file)
index 0000000..d0c8fab
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gen_locl.h"
+
+RCSID("$KTH: symbol.c,v 1.9 2001/09/25 13:39:27 assar Exp $");
+
+static Hashtab *htab;
+
+static int
+cmp (void *a, void *b)
+{
+  Symbol *s1 = (Symbol *)a;
+  Symbol *s2 = (Symbol *)b;
+
+  return strcmp (s1->name, s2->name);
+}
+
+static unsigned
+hash (void *a)
+{
+  Symbol *s = (Symbol *)a;
+
+  return hashjpw (s->name);
+}
+
+void
+initsym (void)
+{
+  htab = hashtabnew (101, cmp, hash);
+}
+
+
+void
+output_name (char *s)
+{
+  char *p;
+
+  for (p = s; *p; ++p)
+    if (*p == '-')
+      *p = '_';
+}
+
+Symbol*
+addsym (char *name)
+{
+  Symbol key, *s;
+
+  key.name = name;
+  s = (Symbol *)hashtabsearch (htab, (void *)&key);
+  if (s == NULL) {
+    s = (Symbol *)malloc (sizeof (*s));
+    s->name = name;
+    s->gen_name = strdup(name);
+    output_name (s->gen_name);
+    s->stype = SUndefined;
+    hashtabadd (htab, s);
+  }
+  return s;
+}
diff --git a/src/kerberosV/src/lib/asn1/symbol.h b/src/kerberosV/src/lib/asn1/symbol.h
new file mode 100644 (file)
index 0000000..ceff7b2
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: symbol.h,v 1.11 2003/10/03 00:28:29 lha Exp $ */
+
+#ifndef _SYMBOL_H
+#define _SYMBOL_H
+
+enum typetype { 
+    TApplication,
+    TBitString,
+    TBoolean,
+    TChoice,
+    TEnumerated,
+    TGeneralString,
+    TGeneralizedTime,
+    TInteger, 
+    TNull,
+    TOID,
+    TOctetString,
+    TSequence,
+    TSequenceOf,
+    TType, 
+    TUInteger,
+    TUTF8String
+};
+
+typedef enum typetype Typetype;
+
+struct type;
+
+struct member {
+  char *name;
+  char *gen_name;
+  int val;
+  int optional;
+  struct type *type;
+  struct member *next, *prev;
+  char *defval;
+};
+
+typedef struct member Member;
+
+struct symbol;
+
+struct type {
+  Typetype type;
+  int application;
+  Member *members;
+  struct type *subtype;
+  struct symbol *symbol;
+};
+
+typedef struct type Type;
+
+struct symbol {
+  char *name;
+  char *gen_name;
+  enum { SUndefined, SConstant, Stype } stype;
+  int constant;
+  Type *type;
+};
+
+typedef struct symbol Symbol;
+
+void initsym (void);
+Symbol *addsym (char *);
+void output_name (char *);
+#endif
diff --git a/src/kerberosV/src/lib/asn1/timegm.c b/src/kerberosV/src/lib/asn1/timegm.c
new file mode 100644 (file)
index 0000000..b69fb6a
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "der_locl.h"
+
+RCSID("$KTH: timegm.c,v 1.7 1999/12/02 17:05:02 joda Exp $");
+
+#ifndef HAVE_TIMEGM
+
+static int
+is_leap(unsigned y)
+{
+    y += 1900;
+    return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
+}
+
+time_t
+timegm (struct tm *tm)
+{
+  static const unsigned ndays[2][12] ={
+    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
+  time_t res = 0;
+  unsigned i;
+
+  for (i = 70; i < tm->tm_year; ++i)
+    res += is_leap(i) ? 366 : 365;
+
+  for (i = 0; i < tm->tm_mon; ++i)
+    res += ndays[is_leap(tm->tm_year)][i];
+  res += tm->tm_mday - 1;
+  res *= 24;
+  res += tm->tm_hour;
+  res *= 60;
+  res += tm->tm_min;
+  res *= 60;
+  res += tm->tm_sec;
+  return res;
+}
+
+#endif /* HAVE_TIMEGM */
diff --git a/src/kerberosV/src/lib/asn1/x509.asn1 b/src/kerberosV/src/lib/asn1/x509.asn1
new file mode 100644 (file)
index 0000000..4a15844
--- /dev/null
@@ -0,0 +1,23 @@
+X509 DEFINITIONS ::= BEGIN
+
+CertificateSerialNumber ::= INTEGER -- X.509 '97
+
+AttributeType ::= OBJECT-IDENTIFIER
+
+AttributeValue ::= OCTET STRING --ANY DEFINED BY AttributeType
+
+AttributeTypeAndValue ::= SEQUENCE {
+       type AttributeType,
+       value AttributeValue
+}
+
+RelativeDistinguishedName ::= --SET
+SEQUENCE OF AttributeTypeAndValue
+
+RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
+
+Name ::= CHOICE { -- RFC2459
+       x RDNSequence
+}
+
+END
\ No newline at end of file
diff --git a/src/kerberosV/src/lib/com_err/CVS/Entries b/src/kerberosV/src/lib/com_err/CVS/Entries
new file mode 100644 (file)
index 0000000..59877b5
--- /dev/null
@@ -0,0 +1,5 @@
+/com_err.c/1.7/Fri Apr 14 08:15:04 2006//
+/com_err.h/1.5/Fri Apr 14 08:15:04 2006//
+/com_right.h/1.4/Fri Apr 14 08:15:04 2006//
+/error.c/1.3/Tue Jun  3 09:08:04 2003//
+D
diff --git a/src/kerberosV/src/lib/com_err/CVS/Repository b/src/kerberosV/src/lib/com_err/CVS/Repository
new file mode 100644 (file)
index 0000000..dc41aaf
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/com_err
diff --git a/src/kerberosV/src/lib/com_err/CVS/Root b/src/kerberosV/src/lib/com_err/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/com_err/com_err.c b/src/kerberosV/src/lib/com_err/com_err.c
new file mode 100644 (file)
index 0000000..ca39e64
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: com_err.c,v 1.19 2005/04/24 19:42:39 lha Exp $");
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <roken.h>
+#include "com_err.h"
+
+struct et_list *_et_list = NULL;
+
+
+const char *
+error_message (long code)
+{
+    static char msg[128];
+    const char *p = com_right(_et_list, code);
+    if (p == NULL) {
+       if (code < 0)
+           snprintf(msg, sizeof(msg), "Unknown error %ld", code);
+       else
+           p = strerror(code);
+    }
+    if (p != NULL && *p != '\0') {
+       strlcpy(msg, p, sizeof(msg));
+    } else 
+       snprintf(msg, sizeof(msg), "Unknown error %ld", code);
+    return msg;
+}
+
+int
+init_error_table(const char **msgs, long base, int count)
+{
+    initialize_error_table_r(&_et_list, msgs, count, base);
+    return 0;
+}
+
+static void
+default_proc (const char *whoami, long code, const char *fmt, va_list args)
+    __attribute__((__format__(__printf__, 3, 0)));
+static void
+default_proc (const char *whoami, long code, const char *fmt, va_list args)
+{
+    if (whoami)
+      fprintf(stderr, "%s: ", whoami);
+    if (code)
+      fprintf(stderr, "%s ", error_message(code));
+    if (fmt)
+      vfprintf(stderr, fmt, args);
+    fprintf(stderr, "\r\n");   /* ??? */
+}
+
+static errf com_err_hook = default_proc;
+
+void 
+com_err_va (const char *whoami, 
+           long code, 
+           const char *fmt, 
+           va_list args)
+{
+    (*com_err_hook) (whoami, code, fmt, args);
+}
+
+void
+com_err (const char *whoami,
+        long code,
+        const char *fmt, 
+        ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    com_err_va (whoami, code, fmt, ap);
+    va_end(ap);
+}
+
+errf
+set_com_err_hook (errf new)
+{
+    errf old = com_err_hook;
+
+    if (new)
+       com_err_hook = new;
+    else
+       com_err_hook = default_proc;
+    
+    return old;
+}
+
+errf
+reset_com_err_hook (void) 
+{
+    return set_com_err_hook(NULL);
+}
+
+#define ERRCODE_RANGE   8       /* # of bits to shift table number */
+#define BITS_PER_CHAR   6       /* # bits to shift per character in name */
+
+static const char char_set[] =
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
+
+static char buf[6];
+
+const char *
+error_table_name(int num)
+{
+    int ch;
+    int i;
+    char *p;
+
+    /* num = aa aaa abb bbb bcc ccc cdd ddd d?? ??? ??? */
+    p = buf;
+    num >>= ERRCODE_RANGE;
+    /* num = ?? ??? ??? aaa aaa bbb bbb ccc ccc ddd ddd */
+    num &= 077777777;
+    /* num = 00 000 000 aaa aaa bbb bbb ccc ccc ddd ddd */
+    for (i = 4; i >= 0; i--) {
+        ch = (num >> BITS_PER_CHAR * i) & ((1 << BITS_PER_CHAR) - 1);
+        if (ch != 0)
+            *p++ = char_set[ch-1];
+    }
+    *p = '\0';
+    return(buf);
+}
+
+void
+add_to_error_table(struct et_list *new_table)
+{
+    struct et_list *et;
+
+    for (et = _et_list; et; et = et->next) {
+       if (et->table->base == new_table->table->base)
+           return;
+    }
+
+    new_table->next = _et_list;
+    _et_list = new_table;
+}
diff --git a/src/kerberosV/src/lib/com_err/com_err.h b/src/kerberosV/src/lib/com_err/com_err.h
new file mode 100644 (file)
index 0000000..ccee437
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: com_err.h,v 1.10 2005/02/03 08:42:05 lha Exp $ */
+
+/* MIT compatible com_err library */
+
+#ifndef __COM_ERR_H__
+#define __COM_ERR_H__
+
+#include <kerberosV/com_right.h>
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(X)
+#endif
+
+typedef void (*errf) (const char *, long, const char *, va_list);
+
+const char * error_message (long);
+int init_error_table (const char**, long, int);
+
+void com_err_va (const char *, long, const char *, va_list)
+    __attribute__((format(printf, 3, 0)));
+
+void com_err (const char *, long, const char *, ...)
+    __attribute__((format(printf, 3, 4)));
+
+errf set_com_err_hook (errf);
+errf reset_com_err_hook (void);
+
+const char *error_table_name  (int num);
+
+void add_to_error_table (struct et_list *new_table);
+
+#endif /* __COM_ERR_H__ */
diff --git a/src/kerberosV/src/lib/com_err/com_right.h b/src/kerberosV/src/lib/com_err/com_right.h
new file mode 100644 (file)
index 0000000..9f70e26
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: com_right.h,v 1.12 2005/02/03 08:43:01 lha Exp $ */
+
+#ifndef __COM_RIGHT_H__
+#define __COM_RIGHT_H__
+
+#ifdef __STDC__
+#include <stdarg.h>
+#endif
+
+struct error_table {
+    char const * const * msgs;
+    long base;
+    int n_msgs;
+};
+struct et_list {
+    struct et_list *next;
+    struct error_table *table;
+};
+extern struct et_list *_et_list;
+
+const char *com_right (struct et_list *list, long code);
+void initialize_error_table_r (struct et_list **, const char **, int, long);
+void free_error_table (struct et_list *);
+
+#endif /* __COM_RIGHT_H__ */
diff --git a/src/kerberosV/src/lib/com_err/error.c b/src/kerberosV/src/lib/com_err/error.c
new file mode 100644 (file)
index 0000000..c91d4bc
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 1997, 1998, 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: error.c,v 1.15 2001/02/28 20:00:13 joda Exp $");
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <com_right.h>
+
+const char *
+com_right(struct et_list *list, long code)
+{
+    struct et_list *p;
+    for (p = list; p; p = p->next) {
+       if (code >= p->table->base && code < p->table->base + p->table->n_msgs)
+           return p->table->msgs[code - p->table->base];
+    }
+    return NULL;
+}
+
+struct foobar {
+    struct et_list etl;
+    struct error_table et;
+};
+
+void
+initialize_error_table_r(struct et_list **list, 
+                        const char **messages, 
+                        int num_errors,
+                        long base)
+{
+    struct et_list *et, **end;
+    struct foobar *f;
+    for (end = list, et = *list; et; end = &et->next, et = et->next)
+        if (et->table->msgs == messages)
+            return;
+    f = malloc(sizeof(*f));
+    if (f == NULL)
+        return;
+    et = &f->etl;
+    et->table = &f->et;
+    et->table->msgs = messages;
+    et->table->n_msgs = num_errors;
+    et->table->base = base;
+    et->next = NULL;
+    *end = et;
+}
+                       
+
+void
+free_error_table(struct et_list *et)
+{
+    while(et){
+       struct et_list *p = et;
+       et = et->next;
+       free(p);
+    }
+}
diff --git a/src/kerberosV/src/lib/des/CVS/Entries b/src/kerberosV/src/lib/des/CVS/Entries
new file mode 100644 (file)
index 0000000..5cd0d72
--- /dev/null
@@ -0,0 +1,14 @@
+/DESperate.txt/1.1.1.1/Fri Apr 14 07:33:47 2006//
+/aes.c/1.1.1.1/Fri Apr 14 07:33:47 2006//
+/aes.h/1.1.1.1/Fri Apr 14 07:33:47 2006//
+/des-tables.h/1.1.1.1/Fri Apr 14 07:33:47 2006//
+/gen-des.pl/1.1.1.1/Fri Apr 14 07:33:48 2006//
+/rc2.c/1.1.1.1/Fri Apr 14 07:33:49 2006//
+/rc2.h/1.1.1.1/Fri Apr 14 07:33:49 2006//
+/rc2test.c/1.1.1.1/Fri Apr 14 07:33:49 2006//
+/rc4.c/1.1.1.1/Fri Apr 14 07:33:49 2006//
+/rctest.c/1.1.1.1/Fri Apr 14 07:33:49 2006//
+/rijndael-alg-fst.c/1.1.1.1/Fri Apr 14 07:33:50 2006//
+/rijndael-alg-fst.h/1.1.1.1/Fri Apr 14 07:33:50 2006//
+/ui.c/1.1.1.1/Fri Apr 14 07:33:51 2006//
+D
diff --git a/src/kerberosV/src/lib/des/CVS/Repository b/src/kerberosV/src/lib/des/CVS/Repository
new file mode 100644 (file)
index 0000000..6112803
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/des
diff --git a/src/kerberosV/src/lib/des/CVS/Root b/src/kerberosV/src/lib/des/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/des/DESperate.txt b/src/kerberosV/src/lib/des/DESperate.txt
new file mode 100644 (file)
index 0000000..e36ade6
--- /dev/null
@@ -0,0 +1,108 @@
+The hunt for getting a DES with plain BSD license w/o advertisement clause
+==========================================================================
+
+$KTH: DESperate.txt,v 1.1 2005/02/23 15:26:49 lha Exp $
+
+This all feels very silly given that DES is about 30 years old and now
+is deprecated.
+
+Helpful documents on the way:
+
+Schider's crypto wasn't that useful since it only told how to do DES,
+not how to do des fast or how to not use DES. I find this to be a
+common thread in the book, it explain each tool in great detail, but
+not its limitations.
+
+Dag Arne Osvik: Efficient Implementation of the Data Encryption Standard
+
+Some threads on sci.crypto was also useful.
+
+PC1 transformations
+===================
+
+
+Getting the PC1 bit mangling working was hard, I never got it to work.
+
+Printning out the bit usage made me realize a lookup table could be
+used since only 12 bits are used from the first half and 16 from the
+second.
+
+01110000 01110000 01110000 01110000 01111000 01111000 01111000 01111000 
+00001111 00001111 00001111 00001111 00000111 00000111 00000111 00000111 
+
+The pattern is getting more obvious if its printed out where the bits
+are coming from.
+
+ 8 16 24  -  -  -  -  - 
+ 7 15 23  -  -  -  -  - 
+ 6 14 22  -  -  -  -  - 
+ 5 13 21  -  -  -  -  - 
+ 4 12 20 28  -  -  -  - 
+ 3 11 19 27  -  -  -  - 
+ 2 10 18 26  -  -  -  - 
+ 1  9 17 25  -  -  -  - 
+
+ -  -  - 60 56 48 40  - 
+ -  -  - 59 55 47 39  - 
+ -  -  - 58 54 46 38  - 
+ -  -  - 57 53 45 37  - 
+ -  -  -  - 52 44 36  - 
+ -  -  -  - 51 43 35  - 
+ -  -  -  - 50 42 34  - 
+ -  -  -  - 49 41 33  - 
+
+Only 3 bits-table is needed for the first half and 4 bits for the
+second half because they are on diffrent shift offsets.
+
+So to get the bitpattern bit-pattern
+
+gen_pattern("pc1_c_3", 7,  [ 5, 13, 21 ], 0, 0x1000000);
+gen_pattern("pc1_c_4", 15, [ 1, 9, 17, 25 ], 0, 0x1000000);
+gen_pattern("pc1_d_3", 7, [ 49, 41, 33 ], 32, 0x1000000);
+gen_pattern("pc1_d_4", 15, [ 57, 53, 45, 37 ], 32, 0x1000000);
+
+PC2 transformations
+===================
+
+PC2 is also a table lookup, since its a 24 bit field, I use 4 6-bit
+lookup tables. Printing the reverse of the PC2 table reveal that some
+of the bits are not used, namely (9, 18, 22, 25) from c and (7, 10,
+15, 26) from d.
+
+pc2 from c
+----------
+
+ 5 24  7 16  6 10 20 
+18  - 12  3 15 23  1 
+ 9 19  2  - 14 22 11 
+ - 13  4  - 17 21  8 
+
+pc2 from d
+----------
+
+51 35 31 52 39 45  - 
+50 32  - 43 36 29 48 
+ - 41 38 47 33 40 42 
+49 37 30 46  - 34 44 
+
+So we generate tables for that too.
+
+gen_pattern("pc2_c_1", 63, [  5, 24,  7, 16,  6, 10 ], 0, 0x800000);
+gen_pattern("pc2_c_2", 63, [ 20, 18, 12,  3, 15, 23 ], 0, 0x800000);
+gen_pattern("pc2_c_3", 63, [  1,  9, 19,  2, 14, 22 ], 0, 0x800000);
+gen_pattern("pc2_c_4", 63, [ 11, 13,  4, 17, 21,  8 ], 0, 0x800000);
+
+gen_pattern("pc2_d_1", 63, [ 51, 35, 31, 52, 39, 45 ], 28, 0x800000);
+gen_pattern("pc2_d_2", 63, [ 50, 32, 43, 36, 29, 48 ], 28, 0x800000);
+gen_pattern("pc2_d_3", 63, [ 41, 38, 47, 33, 40, 42 ], 28, 0x800000);
+gen_pattern("pc2_d_4", 63, [ 49, 37, 30, 46, 34, 44 ], 28, 0x800000);
+
+
+SBOX transformations
+====================
+
+The SBOX transformations are 6 bit to 4 bit transformations.
+
+Here I grew tired and used Richard Outerbridge SBOXes. Thank you
+Richard.
+
diff --git a/src/kerberosV/src/lib/des/aes.c b/src/kerberosV/src/lib/des/aes.c
new file mode 100644 (file)
index 0000000..39a38cb
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+
+RCSID("$KTH: aes.c,v 1.4 2005/05/13 08:00:09 lha Exp $");
+#endif
+
+#ifdef KRB5
+#include <krb5-types.h>
+#endif
+
+#include <string.h>
+
+#include "rijndael-alg-fst.h"
+#include "aes.h"
+
+int
+AES_set_encrypt_key(const unsigned char *userkey, const int bits, AES_KEY *key)
+{
+    key->rounds = rijndaelKeySetupEnc(key->key, userkey, bits);
+    if (key->rounds == 0)
+       return -1;
+    return 0;
+}
+
+int
+AES_set_decrypt_key(const unsigned char *userkey, const int bits, AES_KEY *key)
+{
+    key->rounds = rijndaelKeySetupDec(key->key, userkey, bits);
+    if (key->rounds == 0)
+       return -1;
+    return 0;
+}
+
+void
+AES_encrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key)
+{
+    rijndaelEncrypt(key->key, key->rounds, in, out);
+}
+
+void
+AES_decrypt(const unsigned char *in, unsigned char *out, const AES_KEY *key)
+{
+    rijndaelDecrypt(key->key, key->rounds, in, out);
+}
+
+void
+AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+               unsigned long size, const AES_KEY *key,
+               unsigned char *iv, int encrypt)
+{
+    unsigned char tmp[AES_BLOCK_SIZE];
+    int i;
+
+    if (encrypt) {
+       while (size >= AES_BLOCK_SIZE) {
+           for (i = 0; i < AES_BLOCK_SIZE; i++)
+               tmp[i] = in[i] ^ iv[i];
+           AES_encrypt(tmp, out, key);
+           memcpy(iv, out, AES_BLOCK_SIZE);
+           size -= AES_BLOCK_SIZE;
+           in += AES_BLOCK_SIZE;
+           out += AES_BLOCK_SIZE;
+       }
+       if (size) {
+           for (i = 0; i < size; i++)
+               tmp[i] = in[i] ^ iv[i];
+           for (i = size; i < AES_BLOCK_SIZE; i++)
+               tmp[i] = iv[i];
+           AES_encrypt(tmp, out, key);
+           memcpy(iv, out, AES_BLOCK_SIZE);
+       }
+    } else {
+       while (size >= AES_BLOCK_SIZE) {
+           memcpy(tmp, in, AES_BLOCK_SIZE);
+           AES_decrypt(tmp, out, key);
+           for (i = 0; i < AES_BLOCK_SIZE; i++)
+               out[i] ^= iv[i];
+           memcpy(iv, tmp, AES_BLOCK_SIZE);
+           size -= AES_BLOCK_SIZE;
+           in += AES_BLOCK_SIZE;
+           out += AES_BLOCK_SIZE;
+       }
+       if (size) {
+           memcpy(tmp, in, AES_BLOCK_SIZE);
+           AES_decrypt(tmp, out, key);
+           for (i = 0; i < size; i++)
+               out[i] ^= iv[i];
+           memcpy(iv, tmp, AES_BLOCK_SIZE);
+       }
+    }
+}
diff --git a/src/kerberosV/src/lib/des/aes.h b/src/kerberosV/src/lib/des/aes.h
new file mode 100644 (file)
index 0000000..8d40b29
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2003-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: aes.h,v 1.4 2005/04/10 19:09:47 lha Exp $ */
+
+#ifndef HEIM_AES_H
+#define HEIM_AES_H 1
+
+#define AES_BLOCK_SIZE 16
+#define AES_MAXNR 14
+
+#define AES_ENCRYPT 1
+#define AES_DECRYPT 0
+
+typedef struct aes_key {
+    u_int32_t key[(AES_MAXNR+1)*4];
+    int rounds;
+} AES_KEY;
+
+int AES_set_encrypt_key(const unsigned char *, const int, AES_KEY *);
+int AES_set_decrypt_key(const unsigned char *, const int, AES_KEY *);
+
+void AES_encrypt(const unsigned char *, unsigned char *, const AES_KEY *);
+void AES_decrypt(const unsigned char *, unsigned char *, const AES_KEY *);
+
+void AES_cbc_encrypt(const unsigned char *, unsigned char *,
+                    const unsigned long, const AES_KEY *,
+                    unsigned char *, int);
+
+#endif /* HEIM_AES_H */
diff --git a/src/kerberosV/src/lib/des/des-tables.h b/src/kerberosV/src/lib/des/des-tables.h
new file mode 100644 (file)
index 0000000..03854ec
--- /dev/null
@@ -0,0 +1,196 @@
+/* GENERATE FILE from gen-des.pl, do not edit */
+
+/* pc1_c_3 bit pattern 5 13 21 */
+static int pc1_c_3[8] = {
+    0x00000000, 0x00000010, 0x00001000, 0x00001010, 
+    0x00100000, 0x00100010, 0x00101000, 0x00101010
+};
+/* pc1_c_4 bit pattern 1 9 17 25 */
+static int pc1_c_4[16] = {
+    0x00000000, 0x00000001, 0x00000100, 0x00000101, 
+    0x00010000, 0x00010001, 0x00010100, 0x00010101, 
+    0x01000000, 0x01000001, 0x01000100, 0x01000101, 
+    0x01010000, 0x01010001, 0x01010100, 0x01010101
+};
+/* pc1_d_3 bit pattern 49 41 33 */
+static int pc1_d_3[8] = {
+    0x00000000, 0x01000000, 0x00010000, 0x01010000, 
+    0x00000100, 0x01000100, 0x00010100, 0x01010100
+};
+/* pc1_d_4 bit pattern 57 53 45 37 */
+static int pc1_d_4[16] = {
+    0x00000000, 0x00100000, 0x00001000, 0x00101000, 
+    0x00000010, 0x00100010, 0x00001010, 0x00101010, 
+    0x00000001, 0x00100001, 0x00001001, 0x00101001, 
+    0x00000011, 0x00100011, 0x00001011, 0x00101011
+};
+/* pc2_c_1 bit pattern 5 24 7 16 6 10 */
+static int pc2_c_1[64] = {
+    0x00000000, 0x00004000, 0x00040000, 0x00044000, 
+    0x00000100, 0x00004100, 0x00040100, 0x00044100, 
+    0x00020000, 0x00024000, 0x00060000, 0x00064000, 
+    0x00020100, 0x00024100, 0x00060100, 0x00064100, 
+    0x00000001, 0x00004001, 0x00040001, 0x00044001, 
+    0x00000101, 0x00004101, 0x00040101, 0x00044101, 
+    0x00020001, 0x00024001, 0x00060001, 0x00064001, 
+    0x00020101, 0x00024101, 0x00060101, 0x00064101, 
+    0x00080000, 0x00084000, 0x000c0000, 0x000c4000, 
+    0x00080100, 0x00084100, 0x000c0100, 0x000c4100, 
+    0x000a0000, 0x000a4000, 0x000e0000, 0x000e4000, 
+    0x000a0100, 0x000a4100, 0x000e0100, 0x000e4100, 
+    0x00080001, 0x00084001, 0x000c0001, 0x000c4001, 
+    0x00080101, 0x00084101, 0x000c0101, 0x000c4101, 
+    0x000a0001, 0x000a4001, 0x000e0001, 0x000e4001, 
+    0x000a0101, 0x000a4101, 0x000e0101, 0x000e4101
+};
+/* pc2_c_2 bit pattern 20 18 12 3 15 23 */
+static int pc2_c_2[64] = {
+    0x00000000, 0x00000002, 0x00000200, 0x00000202, 
+    0x00200000, 0x00200002, 0x00200200, 0x00200202, 
+    0x00001000, 0x00001002, 0x00001200, 0x00001202, 
+    0x00201000, 0x00201002, 0x00201200, 0x00201202, 
+    0x00000040, 0x00000042, 0x00000240, 0x00000242, 
+    0x00200040, 0x00200042, 0x00200240, 0x00200242, 
+    0x00001040, 0x00001042, 0x00001240, 0x00001242, 
+    0x00201040, 0x00201042, 0x00201240, 0x00201242, 
+    0x00000010, 0x00000012, 0x00000210, 0x00000212, 
+    0x00200010, 0x00200012, 0x00200210, 0x00200212, 
+    0x00001010, 0x00001012, 0x00001210, 0x00001212, 
+    0x00201010, 0x00201012, 0x00201210, 0x00201212, 
+    0x00000050, 0x00000052, 0x00000250, 0x00000252, 
+    0x00200050, 0x00200052, 0x00200250, 0x00200252, 
+    0x00001050, 0x00001052, 0x00001250, 0x00001252, 
+    0x00201050, 0x00201052, 0x00201250, 0x00201252
+};
+/* pc2_c_3 bit pattern 1 9 19 2 14 22 */
+static int pc2_c_3[64] = {
+    0x00000000, 0x00000004, 0x00000400, 0x00000404, 
+    0x00400000, 0x00400004, 0x00400400, 0x00400404, 
+    0x00000020, 0x00000024, 0x00000420, 0x00000424, 
+    0x00400020, 0x00400024, 0x00400420, 0x00400424, 
+    0x00008000, 0x00008004, 0x00008400, 0x00008404, 
+    0x00408000, 0x00408004, 0x00408400, 0x00408404, 
+    0x00008020, 0x00008024, 0x00008420, 0x00008424, 
+    0x00408020, 0x00408024, 0x00408420, 0x00408424, 
+    0x00800000, 0x00800004, 0x00800400, 0x00800404, 
+    0x00c00000, 0x00c00004, 0x00c00400, 0x00c00404, 
+    0x00800020, 0x00800024, 0x00800420, 0x00800424, 
+    0x00c00020, 0x00c00024, 0x00c00420, 0x00c00424, 
+    0x00808000, 0x00808004, 0x00808400, 0x00808404, 
+    0x00c08000, 0x00c08004, 0x00c08400, 0x00c08404, 
+    0x00808020, 0x00808024, 0x00808420, 0x00808424, 
+    0x00c08020, 0x00c08024, 0x00c08420, 0x00c08424
+};
+/* pc2_c_4 bit pattern 11 13 4 17 21 8 */
+static int pc2_c_4[64] = {
+    0x00000000, 0x00010000, 0x00000008, 0x00010008, 
+    0x00000080, 0x00010080, 0x00000088, 0x00010088, 
+    0x00100000, 0x00110000, 0x00100008, 0x00110008, 
+    0x00100080, 0x00110080, 0x00100088, 0x00110088, 
+    0x00000800, 0x00010800, 0x00000808, 0x00010808, 
+    0x00000880, 0x00010880, 0x00000888, 0x00010888, 
+    0x00100800, 0x00110800, 0x00100808, 0x00110808, 
+    0x00100880, 0x00110880, 0x00100888, 0x00110888, 
+    0x00002000, 0x00012000, 0x00002008, 0x00012008, 
+    0x00002080, 0x00012080, 0x00002088, 0x00012088, 
+    0x00102000, 0x00112000, 0x00102008, 0x00112008, 
+    0x00102080, 0x00112080, 0x00102088, 0x00112088, 
+    0x00002800, 0x00012800, 0x00002808, 0x00012808, 
+    0x00002880, 0x00012880, 0x00002888, 0x00012888, 
+    0x00102800, 0x00112800, 0x00102808, 0x00112808, 
+    0x00102880, 0x00112880, 0x00102888, 0x00112888
+};
+/* pc2_d_1 bit pattern 51 35 31 52 39 45 */
+static int pc2_d_1[64] = {
+    0x00000000, 0x00000080, 0x00002000, 0x00002080, 
+    0x00000001, 0x00000081, 0x00002001, 0x00002081, 
+    0x00200000, 0x00200080, 0x00202000, 0x00202080, 
+    0x00200001, 0x00200081, 0x00202001, 0x00202081, 
+    0x00020000, 0x00020080, 0x00022000, 0x00022080, 
+    0x00020001, 0x00020081, 0x00022001, 0x00022081, 
+    0x00220000, 0x00220080, 0x00222000, 0x00222080, 
+    0x00220001, 0x00220081, 0x00222001, 0x00222081, 
+    0x00000002, 0x00000082, 0x00002002, 0x00002082, 
+    0x00000003, 0x00000083, 0x00002003, 0x00002083, 
+    0x00200002, 0x00200082, 0x00202002, 0x00202082, 
+    0x00200003, 0x00200083, 0x00202003, 0x00202083, 
+    0x00020002, 0x00020082, 0x00022002, 0x00022082, 
+    0x00020003, 0x00020083, 0x00022003, 0x00022083, 
+    0x00220002, 0x00220082, 0x00222002, 0x00222082, 
+    0x00220003, 0x00220083, 0x00222003, 0x00222083
+};
+/* pc2_d_2 bit pattern 50 32 43 36 29 48 */
+static int pc2_d_2[64] = {
+    0x00000000, 0x00000010, 0x00800000, 0x00800010, 
+    0x00010000, 0x00010010, 0x00810000, 0x00810010, 
+    0x00000200, 0x00000210, 0x00800200, 0x00800210, 
+    0x00010200, 0x00010210, 0x00810200, 0x00810210, 
+    0x00100000, 0x00100010, 0x00900000, 0x00900010, 
+    0x00110000, 0x00110010, 0x00910000, 0x00910010, 
+    0x00100200, 0x00100210, 0x00900200, 0x00900210, 
+    0x00110200, 0x00110210, 0x00910200, 0x00910210, 
+    0x00000004, 0x00000014, 0x00800004, 0x00800014, 
+    0x00010004, 0x00010014, 0x00810004, 0x00810014, 
+    0x00000204, 0x00000214, 0x00800204, 0x00800214, 
+    0x00010204, 0x00010214, 0x00810204, 0x00810214, 
+    0x00100004, 0x00100014, 0x00900004, 0x00900014, 
+    0x00110004, 0x00110014, 0x00910004, 0x00910014, 
+    0x00100204, 0x00100214, 0x00900204, 0x00900214, 
+    0x00110204, 0x00110214, 0x00910204, 0x00910214
+};
+/* pc2_d_3 bit pattern 41 38 47 33 40 42 */
+static int pc2_d_3[64] = {
+    0x00000000, 0x00000400, 0x00001000, 0x00001400, 
+    0x00080000, 0x00080400, 0x00081000, 0x00081400, 
+    0x00000020, 0x00000420, 0x00001020, 0x00001420, 
+    0x00080020, 0x00080420, 0x00081020, 0x00081420, 
+    0x00004000, 0x00004400, 0x00005000, 0x00005400, 
+    0x00084000, 0x00084400, 0x00085000, 0x00085400, 
+    0x00004020, 0x00004420, 0x00005020, 0x00005420, 
+    0x00084020, 0x00084420, 0x00085020, 0x00085420, 
+    0x00000800, 0x00000c00, 0x00001800, 0x00001c00, 
+    0x00080800, 0x00080c00, 0x00081800, 0x00081c00, 
+    0x00000820, 0x00000c20, 0x00001820, 0x00001c20, 
+    0x00080820, 0x00080c20, 0x00081820, 0x00081c20, 
+    0x00004800, 0x00004c00, 0x00005800, 0x00005c00, 
+    0x00084800, 0x00084c00, 0x00085800, 0x00085c00, 
+    0x00004820, 0x00004c20, 0x00005820, 0x00005c20, 
+    0x00084820, 0x00084c20, 0x00085820, 0x00085c20
+};
+/* pc2_d_4 bit pattern 49 37 30 46 34 44 */
+static int pc2_d_4[64] = {
+    0x00000000, 0x00000100, 0x00040000, 0x00040100, 
+    0x00000040, 0x00000140, 0x00040040, 0x00040140, 
+    0x00400000, 0x00400100, 0x00440000, 0x00440100, 
+    0x00400040, 0x00400140, 0x00440040, 0x00440140, 
+    0x00008000, 0x00008100, 0x00048000, 0x00048100, 
+    0x00008040, 0x00008140, 0x00048040, 0x00048140, 
+    0x00408000, 0x00408100, 0x00448000, 0x00448100, 
+    0x00408040, 0x00408140, 0x00448040, 0x00448140, 
+    0x00000008, 0x00000108, 0x00040008, 0x00040108, 
+    0x00000048, 0x00000148, 0x00040048, 0x00040148, 
+    0x00400008, 0x00400108, 0x00440008, 0x00440108, 
+    0x00400048, 0x00400148, 0x00440048, 0x00440148, 
+    0x00008008, 0x00008108, 0x00048008, 0x00048108, 
+    0x00008048, 0x00008148, 0x00048048, 0x00048148, 
+    0x00408008, 0x00408108, 0x00448008, 0x00448108, 
+    0x00408048, 0x00408148, 0x00448048, 0x00448148
+};
+static unsigned char odd_parity[256] = { 
+  1,  1,  2,  2,  4,  4,  7,  7,  8,  8, 11, 11, 13, 13, 14, 14,
+ 16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
+ 32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
+ 49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
+ 64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
+ 81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
+ 97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
+112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
+128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
+145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
+161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
+176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
+193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
+208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
+224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
+241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254,
+ };
diff --git a/src/kerberosV/src/lib/des/gen-des.pl b/src/kerberosV/src/lib/des/gen-des.pl
new file mode 100644 (file)
index 0000000..20eb1df
--- /dev/null
@@ -0,0 +1,217 @@
+#!/usr/pkg/bin/perl
+#
+# $KTH: gen-des.pl,v 1.2 2005/03/01 11:43:01 lha Exp $
+
+use strict;
+
+print "/* GENERATE FILE from gen-des.pl, do not edit */\n\n";
+
+my $gen = 1;
+
+sub gen_pattern
+{
+    my $n = shift;
+    my $r = shift;
+    my $a = shift;
+    my $o = shift;
+    my $s = shift;
+    print "/* $n bit pattern ";
+    foreach my $k (@$a) {
+       print "$k ";
+    }
+    print "*/\n";
+    print "static int $n\[", $r + 1, "\] = {\n    ";
+    foreach my $i (0..$r) {
+       my $j = 0;
+       my $b = 1;
+       foreach my $k (reverse @$a) {
+           if ($i & $b) {
+               $j |= ($s >>($k - $o - 1));
+           }
+           $b = $b << 1;
+       }
+        printf "0x%08x", $j; 
+       print ", " if ($i != $r);
+        if (($i % 4) == 3) {
+               print "\n";
+               print "    " if ($i != $r);
+       }
+    }
+    print "};\n";
+}
+
+if ($gen) {
+    gen_pattern("pc1_c_3", 7,  [ 5, 13, 21 ], 0, 0x1000000);
+    gen_pattern("pc1_c_4", 15, [ 1, 9, 17, 25 ], 0, 0x1000000);
+    gen_pattern("pc1_d_3", 7, [ 49, 41, 33 ], 32, 0x1000000);
+    gen_pattern("pc1_d_4", 15, [ 57, 53, 45, 37 ], 32, 0x1000000);
+    
+    gen_pattern("pc2_c_1", 63, [  5, 24,  7, 16,  6, 10 ], 0, 0x800000);
+    gen_pattern("pc2_c_2", 63, [ 20, 18, 12,  3, 15, 23 ], 0, 0x800000);
+    gen_pattern("pc2_c_3", 63, [  1,  9, 19,  2, 14, 22 ], 0, 0x800000);
+    gen_pattern("pc2_c_4", 63, [ 11, 13,  4, 17, 21,  8 ], 0, 0x800000);
+    
+    gen_pattern("pc2_d_1", 63, [ 51, 35, 31, 52, 39, 45 ], 28, 0x800000);
+    gen_pattern("pc2_d_2", 63, [ 50, 32, 43, 36, 29, 48 ], 28, 0x800000);
+    gen_pattern("pc2_d_3", 63, [ 41, 38, 47, 33, 40, 42 ], 28, 0x800000);
+    gen_pattern("pc2_d_4", 63, [ 49, 37, 30, 46, 34, 44 ], 28, 0x800000);
+}
+
+sub
+pbox_mutation
+{
+    my $n = shift;
+    my $res = 0;
+    
+    my @pbox = (
+               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
+               );
+
+    foreach my $i (0..31) {
+       if ($n & (1 << ($pbox[$i] - 1))) {
+#          print "$i ", ($pbox[$i] - 1), "\n";
+           $res |= 1 << $i;
+       }
+    }
+
+    return $res;
+}
+
+
+my @S1 = (
+         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, 
+         );
+my @S2 = (
+         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, 
+         );
+my @S3 = (
+         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, 
+         );
+my @S4 = (
+         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, 
+         );
+my @S5 = (
+         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, 
+         );
+my @S6 = (
+         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, 
+         );
+my @S7 = (
+         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, 
+         );
+
+my @S8 = (
+         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, 
+         );
+
+my @SBox = ( \@S1, \@S2, \@S3, \@S4, \@S5, \@S6, \@S7, \@S8 );
+
+sub
+one_num_in_one_sbox
+{
+    my $i = shift;
+    my $n = shift;
+    my $r = shift;
+
+    my $index = (($n & 1) << 4) | (($n & 0x20)) |
+       (($n >> 1) & 0x1) << 0 |
+       (($n >> 2) & 0x1) << 1 |
+       (($n >> 3) & 0x1) << 2 |
+       (($n >> 4) & 0x1) << 3;
+
+    die "argh" if ($index > 63 || $index < 0);
+
+    my $S = $SBox[$i - 1];
+    my $val = $$S[$index];
+
+    my $res = $val << (($i - 1) * 4);
+
+    my $p = &pbox_mutation($res);
+
+    print " $r ";
+
+#    $p = ($p >> $r) | ($p << (32 - $r - 1));
+
+    printf "0x%08x", $p;
+    print ", " if ($n != 63 or 1);
+    if (($n % 4) == 3) {
+       print " /* $i */" if ($n == 3);
+       print "\n";
+       print "\t" if ($n != 63);
+    }
+}
+
+sub
+one_sbox
+{
+    my $i = shift;
+    my $s = 0;
+    
+#    print "static uint32_t sbox". $i ."[] = {\n\t";
+    print "\t";
+    foreach my $n (0..63) {
+       one_num_in_one_sbox($i, $n, $s);
+    }
+    print "\n";
+#    print "};\n";
+}
+
+if ($gen and 0) {
+    foreach my $sbox (7, 1, 3, 5, 4, 6, 8, 2) {
+       one_sbox($sbox, 1);
+    }
+}
+
+#my $num = 1;
+#printf "pbox: %d -> 0x%08x\n", $num, pbox_mutation($num);
+#$num = 0xc000000;
+#printf "pbox: 0x%08x -> 0x%08x\n", $num, pbox_mutation($num);
+
+print "static unsigned char odd_parity[256] = { \n";
+foreach my $i (0..255) {
+    my $num = 0;
+    foreach my $b (1..7) {
+       $num++ if (($i >> $b) & 1);
+    }
+    my $t;
+    if (($num & 1) == 0) {
+       $t = $i | 1;
+    } else {
+       $t = 0xfe & $i;
+    }
+    printf "%3d,", $t; 
+    printf "\n" if (($i % 16) == 15);
+       
+};
+print " };\n";
diff --git a/src/kerberosV/src/lib/des/rc2.c b/src/kerberosV/src/lib/des/rc2.c
new file mode 100644 (file)
index 0000000..afa7c48
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: rc2.c,v 1.5 2005/05/13 08:04:51 lha Exp $");
+#endif
+
+#include "rc2.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Implemented from Peter Gutmann's "Specification for Ron Rivests Cipher No.2"
+ * rfc2268 and "On the Design and Security of RC2" was also useful.
+ */
+
+static unsigned int Sbox[256] = {
+    0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 
+    0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 
+    0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 
+    0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 
+    0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 
+    0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32, 
+    0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b, 
+    0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 
+    0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 
+    0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 
+    0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 
+    0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 
+    0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57, 
+    0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03, 
+    0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 
+    0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 
+    0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 
+    0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 
+    0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 
+    0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec, 
+    0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc, 
+    0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 
+    0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 
+    0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 
+    0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 
+    0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 
+    0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 
+    0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 
+    0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 
+    0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 
+    0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 
+    0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
+};
+
+void
+RC2_set_key(RC2_KEY *key, int len, const unsigned char *data, int bits)
+{
+    unsigned char k[128];
+    int j, T8, TM;
+
+    if (len > 128)
+       len = 128;
+    if (bits <= 0 || bits > 1024)
+       bits = 1024;
+
+    for (j = 0; j < len; j++)
+       k[j] = data[j];
+    for (; j < 128; j++)
+       k[j] = Sbox[(k[j - len] + k[j - 1]) & 0xff];
+
+    T8 = (bits + 7) / 8;
+    j = (8*T8 - bits);
+    TM = 0xff >> j;
+
+    k[128 - T8] = Sbox[k[128 - T8] & TM];
+
+    for (j = 127 - T8; j >= 0; j--)
+       k[j] = Sbox[k[j + 1] ^ k[j + T8]];
+
+    for (j = 0; j < 64; j++)
+       key->data[j] = k[(j * 2) + 0] | (k[(j * 2) + 1] << 8);  
+    memset(k, 0, sizeof(k));
+}
+
+#define ROT16L(w,n)  ((w<<n)|(w>>(16-n)))
+#define ROT16R(w,n)  ((w>>n)|(w<<(16-n)))
+
+void
+RC2_encryptc(unsigned char *in, unsigned char *out, const RC2_KEY *key)
+{
+    int i, j;
+    int w0, w1, w2, w3;
+    int t0, t1, t2, t3;
+
+    w0 = in[0] | (in[1] << 8);
+    w1 = in[2] | (in[3] << 8);
+    w2 = in[4] | (in[5] << 8);
+    w3 = in[6] | (in[7] << 8);
+
+    for (i = 0; i < 16; i++) {
+       j = i * 4;
+       t0 = (w0 + (w1 & ~w3) + (w2 & w3) + key->data[j + 0]) & 0xffff;
+       w0 = ROT16L(t0, 1);
+       t1 = (w1 + (w2 & ~w0) + (w3 & w0) + key->data[j + 1]) & 0xffff;
+       w1 = ROT16L(t1, 2);
+       t2 = (w2 + (w3 & ~w1) + (w0 & w1) + key->data[j + 2]) & 0xffff;
+       w2 = ROT16L(t2, 3);
+       t3 = (w3 + (w0 & ~w2) + (w1 & w2) + key->data[j + 3]) & 0xffff;
+       w3 = ROT16L(t3, 5);
+       if(i == 4 || i == 10) {
+           w0 += key->data[w3 & 63];
+           w1 += key->data[w0 & 63];
+           w2 += key->data[w1 & 63];
+           w3 += key->data[w2 & 63];
+       }
+    }
+
+    out[0] = w0 & 0xff;
+    out[1] = (w0 >> 8) & 0xff;
+    out[2] = w1 & 0xff;
+    out[3] = (w1 >> 8) & 0xff;
+    out[4] = w2 & 0xff;
+    out[5] = (w2 >> 8) & 0xff;
+    out[6] = w3 & 0xff;
+    out[7] = (w3 >> 8) & 0xff;
+}
+
+void
+RC2_decryptc(unsigned char *in, unsigned char *out, const RC2_KEY *key)
+{
+    int i, j;
+    int w0, w1, w2, w3;
+    int t0, t1, t2, t3;
+
+    w0 = in[0] | (in[1] << 8);
+    w1 = in[2] | (in[3] << 8);
+    w2 = in[4] | (in[5] << 8);
+    w3 = in[6] | (in[7] << 8);
+
+    for (i = 15; i >= 0; i--) {
+       j = i * 4;
+
+       if(i == 4 || i == 10) {
+           w3 = (w3 - key->data[w2 & 63]) & 0xffff;
+           w2 = (w2 - key->data[w1 & 63]) & 0xffff;
+           w1 = (w1 - key->data[w0 & 63]) & 0xffff;
+           w0 = (w0 - key->data[w3 & 63]) & 0xffff;
+       }
+
+       t3 = ROT16R(w3, 5);
+       w3 = (t3 - (w0 & ~w2) - (w1 & w2) - key->data[j + 3]) & 0xffff;
+       t2 = ROT16R(w2, 3);
+       w2 = (t2 - (w3 & ~w1) - (w0 & w1) - key->data[j + 2]) & 0xffff;
+       t1 = ROT16R(w1, 2);
+       w1 = (t1 - (w2 & ~w0) - (w3 & w0) - key->data[j + 1]) & 0xffff;
+       t0 = ROT16R(w0, 1);
+       w0 = (t0 - (w1 & ~w3) - (w2 & w3) - key->data[j + 0]) & 0xffff;
+
+    }
+    out[0] = w0 & 0xff;
+    out[1] = (w0 >> 8) & 0xff;
+    out[2] = w1 & 0xff;
+    out[3] = (w1 >> 8) & 0xff;
+    out[4] = w2 & 0xff;
+    out[5] = (w2 >> 8) & 0xff;
+    out[6] = w3 & 0xff;
+    out[7] = (w3 >> 8) & 0xff;
+}
+
+void
+RC2_cbc_encrypt(const unsigned char *in, unsigned char *out, long size,
+               RC2_KEY *key, unsigned char *iv, int encrypt)
+{
+    unsigned char tmp[RC2_BLOCK_SIZE];
+    int i;
+
+    if (encrypt) {
+       while (size >= RC2_BLOCK_SIZE) {
+           for (i = 0; i < RC2_BLOCK_SIZE; i++)
+               tmp[i] = in[i] ^ iv[i];
+           RC2_encryptc(tmp, out, key);
+           memcpy(iv, out, RC2_BLOCK_SIZE);
+           size -= RC2_BLOCK_SIZE;
+           in += RC2_BLOCK_SIZE;
+           out += RC2_BLOCK_SIZE;
+       }
+       if (size) {
+           for (i = 0; i < size; i++)
+               tmp[i] = in[i] ^ iv[i];
+           for (i = size; i < RC2_BLOCK_SIZE; i++)
+               tmp[i] = iv[i];
+           RC2_encryptc(tmp, out, key);
+           memcpy(iv, out, RC2_BLOCK_SIZE);
+       }
+    } else {
+       while (size >= RC2_BLOCK_SIZE) {
+           memcpy(tmp, in, RC2_BLOCK_SIZE);
+           RC2_decryptc(tmp, out, key);
+           for (i = 0; i < RC2_BLOCK_SIZE; i++)
+               out[i] ^= iv[i];
+           memcpy(iv, tmp, RC2_BLOCK_SIZE);
+           size -= RC2_BLOCK_SIZE;
+           in += RC2_BLOCK_SIZE;
+           out += RC2_BLOCK_SIZE;
+       }
+       if (size) {
+           memcpy(tmp, in, RC2_BLOCK_SIZE);
+           RC2_decryptc(tmp, out, key);
+           for (i = 0; i < size; i++)
+               out[i] ^= iv[i];
+           memcpy(iv, tmp, RC2_BLOCK_SIZE);
+       }
+    }
+}
diff --git a/src/kerberosV/src/lib/des/rc2.h b/src/kerberosV/src/lib/des/rc2.h
new file mode 100644 (file)
index 0000000..a949009
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: rc2.h,v 1.1 2004/04/23 19:23:00 lha Exp $ */
+
+#define RC2_ENCRYPT    1
+#define RC2_DECRYPT    0
+
+#define RC2_BLOCK_SIZE 8
+#define RC2_BLOCK      RC2_BLOCK_SIZE
+#define RC2_KEY_LENGTH 16
+
+typedef struct rc2_key {
+    unsigned int data[64];
+} RC2_KEY;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void RC2_set_key(RC2_KEY *, int, const unsigned char *,int);
+
+void RC2_encryptc(unsigned char *, unsigned char *, const RC2_KEY *);
+void RC2_decryptc(unsigned char *, unsigned char *, const RC2_KEY *);
+
+void RC2_cbc_encrypt(const unsigned char *, unsigned char *, long,
+                    RC2_KEY *, unsigned char *, int);
+
+#ifdef  __cplusplus
+}
+#endif
diff --git a/src/kerberosV/src/lib/des/rc2test.c b/src/kerberosV/src/lib/des/rc2test.c
new file mode 100644 (file)
index 0000000..c6245c2
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: rc2test.c,v 1.2 2004/04/24 12:08:54 lha Exp $");
+#endif
+
+#include <rc2.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct {
+    const char *key;
+    const int keylen;
+    const int bitsize;
+    const char *plain;
+    const char *cipher;
+} tests[] = {
+    {
+       "\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       0,
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x1C\x19\x8A\x83\x8D\xF0\x28\xB7"
+    },
+    {
+       "\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x01",
+       16,
+       0,
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x21\x82\x9C\x78\xA9\xF9\xC0\x74"
+    },
+    { 
+       "\x00\x00\x00\x00\x00\x00\x00\x00"
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       16,
+       0,
+       "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
+       "\x13\xDB\x35\x17\xD3\x21\x86\x9E"
+    },
+    {
+       "\x00\x01\x02\x03\x04\x05\x06\x07"
+       "\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F",
+       16,
+       0,
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x50\xDC\x01\x62\xBD\x75\x7F\x31"
+    },
+    {
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       8,
+       63,
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\xeb\xb7\x73\xf9\x93\x27\x8e\xff"
+    },
+    {
+       "\xff\xff\xff\xff\xff\xff\xff\xff",
+       8,
+       64,
+       "\xff\xff\xff\xff\xff\xff\xff\xff",
+       "\x27\x8b\x27\xe4\x2e\x2f\x0d\x49"
+    },
+    {
+       "\x88",
+       1,
+       64,
+       "\x00\x00\x00\x00\x00\x00\x00\x00",
+       "\x61\xa8\xa2\x44\xad\xac\xcc\xf0"
+    }
+};
+
+const char cbc_key[16] = 
+"\x00\x00\x00\x00\x00\x00\x00\x00"
+"\x00\x00\x00\x00\x00\x00\x00\x00";
+const char cbc_iv[8] =
+"\x01\x01\x01\x01\x01\x01\x01\x01";
+const char cbc_in_data[32] = 
+"\x20\x20\x20\x20\x20\x20\x20\x20"
+"\x20\x20\x20\x20\x20\x20\x20\x20"
+"\x20\x20\x20\x20\x20\x20\x20\x20"
+"\x20\x20\x20\x20\x20\x20\x20\x20";
+
+const char out_iv[8] = "\x00\x78\x1b\x6\xff\xb9\xfa\xe";
+
+const char cbc_out_data[32] = 
+"\xb4\x3f\x89\x15\x69\x68\xda\x79"
+"\x29\xab\x5f\x78\xc5\xba\x15\x82"
+"\x80\x89\x57\x1b\xbe\x57\x2f\xdc"
+"\x00\x78\x1b\x06\xff\xb9\xfa\x0e";
+
+int
+main(int argc, char **argv)
+{
+    RC2_KEY key;
+    unsigned char t[8];
+    unsigned char out[40];
+    int i;
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
+       RC2_set_key(&key, tests[i].keylen, tests[i].key, tests[i].bitsize);
+
+       memcpy(t, tests[i].plain, 8);
+       RC2_encryptc(t, t, &key);
+       if (memcmp(t, tests[i].cipher, 8) != 0) {
+           printf("encrypt %d\n", i);
+           exit(1);
+       }
+       RC2_decryptc(t, t, &key);
+       if (memcmp(t, tests[i].plain, 8) != 0) {
+           printf("decrypt: %d\n", i);
+           exit(1);
+       }
+    }
+
+    /* cbc test */
+
+    RC2_set_key(&key, 16, cbc_key, 0);
+    memcpy(t, cbc_iv, 8);
+    RC2_cbc_encrypt(cbc_in_data, out, 32, &key, t, 1);
+
+    if (memcmp(out_iv, t, 8) != 0)
+       abort();
+
+    if (memcmp(out, cbc_out_data, 32) != 0) {
+       printf("cbc test encrypt\n");
+       exit(1);
+    }
+
+    memcpy(t, cbc_iv, 8);
+    RC2_cbc_encrypt(out, out, 32, &key, t, 0);
+
+    if (memcmp(cbc_in_data, out, 32) != 0) {
+       printf("cbc test decrypt \n");
+       exit(1);
+    }
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/des/rc4.c b/src/kerberosV/src/lib/des/rc4.c
new file mode 100644 (file)
index 0000000..334f263
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* implemented from description in draft-kaukonen-cipher-arcfour-03.txt */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+
+RCSID("$KTH: rc4.c,v 1.1 2004/03/25 16:40:59 lha Exp $");
+#endif
+
+#include <rc4.h>
+
+#define SWAP(k,x,y)                            \
+{ unsigned int _t;                             \
+  _t = k->state[x];                            \
+  k->state[x] = k->state[y];                   \
+  k->state[y] = _t;                            \
+}
+
+void
+RC4_set_key(RC4_KEY *key, const int len, unsigned char *data)
+{
+    int i, j;
+
+    for (i = 0; i < 256; i++)
+       key->state[i] = i;
+    for (i = 0, j = 0; i < 256; i++) {
+       j = (j + key->state[i] + data[i % len]) % 256;
+       SWAP(key, i, j);
+    }
+    key->x = key->y = 0;
+}
+
+void
+RC4(RC4_KEY *key, const int len, const unsigned char *in, unsigned char *out)
+{
+    int i, t;
+    unsigned x, y;
+
+    x = key->x;
+    y = key->y;
+    for (i = 0; i < len; i++) {
+       x = (x + 1) % 256;
+       y = (y + key->state[x]) % 256;
+       SWAP(key, x, y);
+       t = (key->state[x] + key->state[y]) % 256;
+       *out++ = key->state[t] ^ *in++;
+    }
+    key->x = x;
+    key->y = y;
+}
diff --git a/src/kerberosV/src/lib/des/rctest.c b/src/kerberosV/src/lib/des/rctest.c
new file mode 100644 (file)
index 0000000..3a70bc1
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: rctest.c,v 1.3 2005/05/27 13:50:05 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <rc4.h>
+
+static unsigned char plain1[8] =
+    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static unsigned char key1[8] =
+    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };
+static unsigned char cipher1[8] =
+    { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 };
+
+static unsigned char plain2[5] =
+    { 0xdc, 0xee, 0x4c, 0xf9, 0x2c };
+static unsigned char key2[5] =
+    { 0x61, 0x8a, 0x63, 0xd2, 0xfb };
+static unsigned char cipher2[5] =
+    { 0xf1, 0x38, 0x29, 0xc9, 0xde };
+
+static unsigned char plain3[] =
+    { 
+       0x52, 0x75, 0x69, 0x73, 0x6c, 0x69, 0x6e, 0x6e,
+       0x75, 0x6e, 0x20, 0x6c, 0x61, 0x75, 0x6c, 0x75,
+       0x20, 0x6b, 0x6f, 0x72, 0x76, 0x69, 0x73, 0x73,
+       0x73, 0x61, 0x6e, 0x69, 0x2c, 0x20, 0x74, 0xe4,
+       0x68, 0x6b, 0xe4, 0x70, 0xe4, 0x69, 0x64, 0x65,
+       0x6e, 0x20, 0x70, 0xe4, 0xe4, 0x6c, 0x6c, 0xe4,
+       0x20, 0x74, 0xe4, 0x79, 0x73, 0x69, 0x6b, 0x75,
+       0x75, 0x2e, 0x20, 0x4b, 0x65, 0x73, 0xe4, 0x79,
+       0xf6, 0x6e, 0x20, 0x6f, 0x6e, 0x20, 0x6f, 0x6e,
+       0x6e, 0x69, 0x20, 0x6f, 0x6d, 0x61, 0x6e, 0x61,
+       0x6e, 0x69, 0x2c, 0x20, 0x6b, 0x61, 0x73, 0x6b,
+       0x69, 0x73, 0x61, 0x76, 0x75, 0x75, 0x6e, 0x20,
+       0x6c, 0x61, 0x61, 0x6b, 0x73, 0x6f, 0x74, 0x20,
+       0x76, 0x65, 0x72, 0x68, 0x6f, 0x75, 0x75, 0x2e,
+       0x20, 0x45, 0x6e, 0x20, 0x6d, 0x61, 0x20, 0x69,
+       0x6c, 0x6f, 0x69, 0x74, 0x73, 0x65, 0x2c, 0x20,
+       0x73, 0x75, 0x72, 0x65, 0x20, 0x68, 0x75, 0x6f,
+       0x6b, 0x61, 0x61, 0x2c, 0x20, 0x6d, 0x75, 0x74,
+       0x74, 0x61, 0x20, 0x6d, 0x65, 0x74, 0x73, 0xe4,
+       0x6e, 0x20, 0x74, 0x75, 0x6d, 0x6d, 0x75, 0x75,
+       0x73, 0x20, 0x6d, 0x75, 0x6c, 0x6c, 0x65, 0x20,
+       0x74, 0x75, 0x6f, 0x6b, 0x61, 0x61, 0x2e, 0x20,
+       0x50, 0x75, 0x75, 0x6e, 0x74, 0x6f, 0x20, 0x70,
+       0x69, 0x6c, 0x76, 0x65, 0x6e, 0x2c, 0x20, 0x6d,
+       0x69, 0x20, 0x68, 0x75, 0x6b, 0x6b, 0x75, 0x75,
+       0x2c, 0x20, 0x73, 0x69, 0x69, 0x6e, 0x74, 0x6f,
+       0x20, 0x76, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x74,
+       0x75, 0x75, 0x6c, 0x69, 0x73, 0x65, 0x6e, 0x2c,
+       0x20, 0x6d, 0x69, 0x20, 0x6e, 0x75, 0x6b, 0x6b,
+       0x75, 0x75, 0x2e, 0x20, 0x54, 0x75, 0x6f, 0x6b,
+       0x73, 0x75, 0x74, 0x20, 0x76, 0x61, 0x6e, 0x61,
+       0x6d, 0x6f, 0x6e, 0x20, 0x6a, 0x61, 0x20, 0x76,
+       0x61, 0x72, 0x6a, 0x6f, 0x74, 0x20, 0x76, 0x65,
+       0x65, 0x6e, 0x2c, 0x20, 0x6e, 0x69, 0x69, 0x73,
+       0x74, 0xe4, 0x20, 0x73, 0x79, 0x64, 0xe4, 0x6d,
+       0x65, 0x6e, 0x69, 0x20, 0x6c, 0x61, 0x75, 0x6c,
+       0x75, 0x6e, 0x20, 0x74, 0x65, 0x65, 0x6e, 0x2e,
+       0x20, 0x2d, 0x20, 0x45, 0x69, 0x6e, 0x6f, 0x20,
+       0x4c, 0x65, 0x69, 0x6e, 0x6f };
+      
+static unsigned char key3[16] = 
+    { 0x29, 0x04, 0x19, 0x72, 0xfb, 0x42, 0xba, 0x5f,
+      0xc7, 0x12, 0x77, 0x12, 0xf1, 0x38, 0x29, 0xc9 };
+
+const unsigned char cipher3[] = 
+    { 0x35, 0x81, 0x86, 0x99, 0x90, 0x01, 0xe6, 0xb5,
+      0xda, 0xf0, 0x5e, 0xce, 0xeb, 0x7e, 0xee, 0x21,
+      0xe0, 0x68, 0x9c, 0x1f, 0x00, 0xee, 0xa8, 0x1f,
+      0x7d, 0xd2, 0xca, 0xae, 0xe1, 0xd2, 0x76, 0x3e,
+      0x68, 0xaf, 0x0e, 0xad, 0x33, 0xd6, 0x6c, 0x26,
+      0x8b, 0xc9, 0x46, 0xc4, 0x84, 0xfb, 0xe9, 0x4c,
+      0x5f, 0x5e, 0x0b, 0x86, 0xa5, 0x92, 0x79, 0xe4,
+      0xf8, 0x24, 0xe7, 0xa6, 0x40, 0xbd, 0x22, 0x32,
+      0x10, 0xb0, 0xa6, 0x11, 0x60, 0xb7, 0xbc, 0xe9,
+      0x86, 0xea, 0x65, 0x68, 0x80, 0x03, 0x59, 0x6b,
+      0x63, 0x0a, 0x6b, 0x90, 0xf8, 0xe0, 0xca, 0xf6,
+      0x91, 0x2a, 0x98, 0xeb, 0x87, 0x21, 0x76, 0xe8,
+      0x3c, 0x20, 0x2c, 0xaa, 0x64, 0x16, 0x6d, 0x2c,
+      0xce, 0x57, 0xff, 0x1b, 0xca, 0x57, 0xb2, 0x13,
+      0xf0, 0xed, 0x1a, 0xa7, 0x2f, 0xb8, 0xea, 0x52,
+      0xb0, 0xbe, 0x01, 0xcd, 0x1e, 0x41, 0x28, 0x67,
+      0x72, 0x0b, 0x32, 0x6e, 0xb3, 0x89, 0xd0, 0x11,
+      0xbd, 0x70, 0xd8, 0xaf, 0x03, 0x5f, 0xb0, 0xd8,
+      0x58, 0x9d, 0xbc, 0xe3, 0xc6, 0x66, 0xf5, 0xea,
+      0x8d, 0x4c, 0x79, 0x54, 0xc5, 0x0c, 0x3f, 0x34,
+      0x0b, 0x04, 0x67, 0xf8, 0x1b, 0x42, 0x59, 0x61,
+      0xc1, 0x18, 0x43, 0x07, 0x4d, 0xf6, 0x20, 0xf2,
+      0x08, 0x40, 0x4b, 0x39, 0x4c, 0xf9, 0xd3, 0x7f,
+      0xf5, 0x4b, 0x5f, 0x1a, 0xd8, 0xf6, 0xea, 0x7d,
+      0xa3, 0xc5, 0x61, 0xdf, 0xa7, 0x28, 0x1f, 0x96,
+      0x44, 0x63, 0xd2, 0xcc, 0x35, 0xa4, 0xd1, 0xb0,
+      0x34, 0x90, 0xde, 0xc5, 0x1b, 0x07, 0x11, 0xfb,
+      0xd6, 0xf5, 0x5f, 0x79, 0x23, 0x4d, 0x5b, 0x7c,
+      0x76, 0x66, 0x22, 0xa6, 0x6d, 0xe9, 0x2b, 0xe9,
+      0x96, 0x46, 0x1d, 0x5e, 0x4d, 0xc8, 0x78, 0xef,
+      0x9b, 0xca, 0x03, 0x05, 0x21, 0xe8, 0x35, 0x1e,
+      0x4b, 0xae, 0xd2, 0xfd, 0x04, 0xf9, 0x46, 0x73,
+      0x68, 0xc4, 0xad, 0x6a, 0xc1, 0x86, 0xd0, 0x82,
+      0x45, 0xb2, 0x63, 0xa2, 0x66, 0x6d, 0x1f, 0x6c,
+      0x54, 0x20, 0xf1, 0x59, 0x9d, 0xfd, 0x9f, 0x43,
+      0x89, 0x21, 0xc2, 0xf5, 0xa4, 0x63, 0x93, 0x8c,
+      0xe0, 0x98, 0x22, 0x65, 0xee, 0xf7, 0x01, 0x79,
+      0xbc, 0x55, 0x3f, 0x33, 0x9e, 0xb1, 0xa4, 0xc1,
+      0xaf, 0x5f, 0x6a, 0x54, 0x7f };
+      
+int
+main (void)
+{
+    char buf[1024];
+    RC4_KEY key;
+
+    RC4_set_key(&key, 8, key1);
+    RC4(&key, 8, plain1, buf);
+    if (memcmp(buf, cipher1, 8) != 0)
+       return 1;
+
+    RC4_set_key(&key, 5, key2);
+    RC4(&key, 5, plain2, buf);
+    if (memcmp(buf, cipher2, 5) != 0)
+       return 1;
+
+    RC4_set_key(&key, 16, key3);
+    RC4(&key, 309, plain3, buf);
+    if (memcmp(buf, cipher3, 309) != 0)
+       return 1;
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/des/rijndael-alg-fst.c b/src/kerberosV/src/lib/des/rijndael-alg-fst.c
new file mode 100644 (file)
index 0000000..896139e
--- /dev/null
@@ -0,0 +1,1231 @@
+/*     $NetBSD: rijndael-alg-fst.c,v 1.5 2001/11/13 01:40:10 lukem Exp $       */
+/*     $KAME: rijndael-alg-fst.c,v 1.10 2003/07/15 10:47:16 itojun Exp $       */
+/**
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/* "$NetBSD: rijndael-alg-fst.c,v 1.5 2001/11/13 01:40:10 lukem Exp $" */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+
+RCSID("$KTH: rijndael-alg-fst.c,v 1.2 2004/06/02 20:09:48 lha Exp $");
+#endif
+
+#ifdef KRB5
+#include <krb5-types.h>
+#endif
+
+#include <rijndael-alg-fst.h>
+
+/* the file should not be used from outside */
+typedef u_int8_t               u8;
+typedef u_int16_t              u16;    
+typedef u_int32_t              u32;
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+static const u32 Te0[256] = {
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+static const u32 Te1[256] = {
+    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+static const u32 Te2[256] = {
+    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+static const u32 Te3[256] = {
+
+    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+static const u32 Te4[256] = {
+    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+static const u32 Td0[256] = {
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+static const u32 Td1[256] = {
+    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+static const u32 Td2[256] = {
+    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+static const u32 Td3[256] = {
+    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+static const u32 Td4[256] = {
+    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+static const u32 rcon[] = {
+       0x01000000, 0x02000000, 0x04000000, 0x08000000,
+       0x10000000, 0x20000000, 0x40000000, 0x80000000,
+       0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
+
+#ifdef _MSC_VER
+#define GETU32(p) SWAP(*((u32 *)(p)))
+#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); }
+#else
+#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ ((u32)(pt)[2] <<  8) ^ ((u32)(pt)[3]))
+#define PUTU32(ct, st) { (ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); (ct)[2] = (u8)((st) >>  8); (ct)[3] = (u8)(st); }
+#endif
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return     the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+       int i = 0;
+       u32 temp;
+
+       rk[0] = GETU32(cipherKey     );
+       rk[1] = GETU32(cipherKey +  4);
+       rk[2] = GETU32(cipherKey +  8);
+       rk[3] = GETU32(cipherKey + 12);
+       if (keyBits == 128) {
+               for (;;) {
+                       temp  = rk[3];
+                       rk[4] = rk[0] ^
+                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+                               (Te4[(temp >> 24)       ] & 0x000000ff) ^
+                               rcon[i];
+                       rk[5] = rk[1] ^ rk[4];
+                       rk[6] = rk[2] ^ rk[5];
+                       rk[7] = rk[3] ^ rk[6];
+                       if (++i == 10) {
+                               return 10;
+                       }
+                       rk += 4;
+               }
+       }
+       rk[4] = GETU32(cipherKey + 16);
+       rk[5] = GETU32(cipherKey + 20);
+       if (keyBits == 192) {
+               for (;;) {
+                       temp = rk[ 5];
+                       rk[ 6] = rk[ 0] ^
+                               (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+                               (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+                               (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+                               (Te4[(temp >> 24)       ] & 0x000000ff) ^
+                               rcon[i];
+                       rk[ 7] = rk[ 1] ^ rk[ 6];
+                       rk[ 8] = rk[ 2] ^ rk[ 7];
+                       rk[ 9] = rk[ 3] ^ rk[ 8];
+                       if (++i == 8) {
+                               return 12;
+                       }
+                       rk[10] = rk[ 4] ^ rk[ 9];
+                       rk[11] = rk[ 5] ^ rk[10];
+                       rk += 6;
+               }
+       }
+       rk[6] = GETU32(cipherKey + 24);
+       rk[7] = GETU32(cipherKey + 28);
+       if (keyBits == 256) {
+        for (;;) {
+               temp = rk[ 7];
+               rk[ 8] = rk[ 0] ^
+                       (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+                       (Te4[(temp >>  8) & 0xff] & 0x00ff0000) ^
+                       (Te4[(temp      ) & 0xff] & 0x0000ff00) ^
+                       (Te4[(temp >> 24)       ] & 0x000000ff) ^
+                       rcon[i];
+               rk[ 9] = rk[ 1] ^ rk[ 8];
+               rk[10] = rk[ 2] ^ rk[ 9];
+               rk[11] = rk[ 3] ^ rk[10];
+                       if (++i == 7) {
+                               return 14;
+                       }
+               temp = rk[11];
+               rk[12] = rk[ 4] ^
+                       (Te4[(temp >> 24)       ] & 0xff000000) ^
+                       (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
+                       (Te4[(temp >>  8) & 0xff] & 0x0000ff00) ^
+                       (Te4[(temp      ) & 0xff] & 0x000000ff);
+               rk[13] = rk[ 5] ^ rk[12];
+               rk[14] = rk[ 6] ^ rk[13];
+               rk[15] = rk[ 7] ^ rk[14];
+
+                       rk += 8;
+        }
+       }
+       return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return     the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) {
+       int Nr, i, j;
+       u32 temp;
+
+       /* expand the cipher key: */
+       Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+       /* invert the order of the round keys: */
+       for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+               temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+               temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+               temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+               temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+       }
+       /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+       for (i = 1; i < Nr; i++) {
+               rk += 4;
+               rk[0] =
+                       Td0[Te4[(rk[0] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[0] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[0]      ) & 0xff] & 0xff];
+               rk[1] =
+                       Td0[Te4[(rk[1] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[1] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[1]      ) & 0xff] & 0xff];
+               rk[2] =
+                       Td0[Te4[(rk[2] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[2] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[2]      ) & 0xff] & 0xff];
+               rk[3] =
+                       Td0[Te4[(rk[3] >> 24)       ] & 0xff] ^
+                       Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
+                       Td2[Te4[(rk[3] >>  8) & 0xff] & 0xff] ^
+                       Td3[Te4[(rk[3]      ) & 0xff] & 0xff];
+       }
+       return Nr;
+}
+
+void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) {
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+       s0 = GETU32(pt     ) ^ rk[0];
+       s1 = GETU32(pt +  4) ^ rk[1];
+       s2 = GETU32(pt +  8) ^ rk[2];
+       s3 = GETU32(pt + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+       /* round 2: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+    /* round 3: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+       /* round 4: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+    /* round 5: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+       /* round 6: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+    /* round 7: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+       /* round 8: */
+       s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+       s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+       s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+       s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+    /* round 9: */
+       t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+       t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+       t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+       t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+        s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+        s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+        s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+        t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+        t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+        t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >>  8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+            s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >>  8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+            s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >>  8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+            s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >>  8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >>  8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+            t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >>  8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+            t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >>  8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+            t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >>  8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+        }
+    }
+    rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+        * Nr - 1 full rounds:
+        */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Te0[(s0 >> 24)       ] ^
+            Te1[(s1 >> 16) & 0xff] ^
+            Te2[(s2 >>  8) & 0xff] ^
+            Te3[(s3      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Te0[(s1 >> 24)       ] ^
+            Te1[(s2 >> 16) & 0xff] ^
+            Te2[(s3 >>  8) & 0xff] ^
+            Te3[(s0      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Te0[(s2 >> 24)       ] ^
+            Te1[(s3 >> 16) & 0xff] ^
+            Te2[(s0 >>  8) & 0xff] ^
+            Te3[(s1      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Te0[(s3 >> 24)       ] ^
+            Te1[(s0 >> 16) & 0xff] ^
+            Te2[(s1 >>  8) & 0xff] ^
+            Te3[(s2      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Te0[(t0 >> 24)       ] ^
+            Te1[(t1 >> 16) & 0xff] ^
+            Te2[(t2 >>  8) & 0xff] ^
+            Te3[(t3      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Te0[(t1 >> 24)       ] ^
+            Te1[(t2 >> 16) & 0xff] ^
+            Te2[(t3 >>  8) & 0xff] ^
+            Te3[(t0      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Te0[(t2 >> 24)       ] ^
+            Te1[(t3 >> 16) & 0xff] ^
+            Te2[(t0 >>  8) & 0xff] ^
+            Te3[(t1      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Te0[(t3 >> 24)       ] ^
+            Te1[(t0 >> 16) & 0xff] ^
+            Te2[(t1 >>  8) & 0xff] ^
+            Te3[(t2      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       s0 =
+               (Te4[(t0 >> 24)       ] & 0xff000000) ^
+               (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t3      ) & 0xff] & 0x000000ff) ^
+               rk[0];
+       PUTU32(ct     , s0);
+       s1 =
+               (Te4[(t1 >> 24)       ] & 0xff000000) ^
+               (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t0      ) & 0xff] & 0x000000ff) ^
+               rk[1];
+       PUTU32(ct +  4, s1);
+       s2 =
+               (Te4[(t2 >> 24)       ] & 0xff000000) ^
+               (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t1      ) & 0xff] & 0x000000ff) ^
+               rk[2];
+       PUTU32(ct +  8, s2);
+       s3 =
+               (Te4[(t3 >> 24)       ] & 0xff000000) ^
+               (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+               (Te4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+               (Te4[(t2      ) & 0xff] & 0x000000ff) ^
+               rk[3];
+       PUTU32(ct + 12, s3);
+}
+
+void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) {
+       u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+        * map byte array block to cipher state
+        * and add initial round key:
+        */
+    s0 = GETU32(ct     ) ^ rk[0];
+    s1 = GETU32(ct +  4) ^ rk[1];
+    s2 = GETU32(ct +  8) ^ rk[2];
+    s3 = GETU32(ct + 12) ^ rk[3];
+#ifdef FULL_UNROLL
+    /* round 1: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+    /* round 2: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+    /* round 3: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+    /* round 4: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+    /* round 5: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+    /* round 6: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+    /* round 7: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+    /* round 8: */
+    s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+    s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+    s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+    s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+    /* round 9: */
+    t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+    t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+    t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+    t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+    if (Nr > 10) {
+        /* round 10: */
+        s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+        s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+        s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+        s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+        /* round 11: */
+        t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+        t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+        t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+        t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+        if (Nr > 12) {
+            /* round 12: */
+            s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >>  8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+            s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >>  8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+            s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >>  8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+            s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >>  8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+            /* round 13: */
+            t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >>  8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+            t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >>  8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+            t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >>  8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+            t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >>  8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+        }
+    }
+       rk += Nr << 2;
+#else  /* !FULL_UNROLL */
+    /*
+     * Nr - 1 full rounds:
+     */
+    r = Nr >> 1;
+    for (;;) {
+        t0 =
+            Td0[(s0 >> 24)       ] ^
+            Td1[(s3 >> 16) & 0xff] ^
+            Td2[(s2 >>  8) & 0xff] ^
+            Td3[(s1      ) & 0xff] ^
+            rk[4];
+        t1 =
+            Td0[(s1 >> 24)       ] ^
+            Td1[(s0 >> 16) & 0xff] ^
+            Td2[(s3 >>  8) & 0xff] ^
+            Td3[(s2      ) & 0xff] ^
+            rk[5];
+        t2 =
+            Td0[(s2 >> 24)       ] ^
+            Td1[(s1 >> 16) & 0xff] ^
+            Td2[(s0 >>  8) & 0xff] ^
+            Td3[(s3      ) & 0xff] ^
+            rk[6];
+        t3 =
+            Td0[(s3 >> 24)       ] ^
+            Td1[(s2 >> 16) & 0xff] ^
+            Td2[(s1 >>  8) & 0xff] ^
+            Td3[(s0      ) & 0xff] ^
+            rk[7];
+
+        rk += 8;
+        if (--r == 0) {
+            break;
+        }
+
+        s0 =
+            Td0[(t0 >> 24)       ] ^
+            Td1[(t3 >> 16) & 0xff] ^
+            Td2[(t2 >>  8) & 0xff] ^
+            Td3[(t1      ) & 0xff] ^
+            rk[0];
+        s1 =
+            Td0[(t1 >> 24)       ] ^
+            Td1[(t0 >> 16) & 0xff] ^
+            Td2[(t3 >>  8) & 0xff] ^
+            Td3[(t2      ) & 0xff] ^
+            rk[1];
+        s2 =
+            Td0[(t2 >> 24)       ] ^
+            Td1[(t1 >> 16) & 0xff] ^
+            Td2[(t0 >>  8) & 0xff] ^
+            Td3[(t3      ) & 0xff] ^
+            rk[2];
+        s3 =
+            Td0[(t3 >> 24)       ] ^
+            Td1[(t2 >> 16) & 0xff] ^
+            Td2[(t1 >>  8) & 0xff] ^
+            Td3[(t0      ) & 0xff] ^
+            rk[3];
+    }
+#endif /* ?FULL_UNROLL */
+    /*
+        * apply last round and
+        * map cipher state to byte array block:
+        */
+       s0 =
+               (Td4[(t0 >> 24)       ] & 0xff000000) ^
+               (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t2 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t1      ) & 0xff] & 0x000000ff) ^
+               rk[0];
+       PUTU32(pt     , s0);
+       s1 =
+               (Td4[(t1 >> 24)       ] & 0xff000000) ^
+               (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t3 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t2      ) & 0xff] & 0x000000ff) ^
+               rk[1];
+       PUTU32(pt +  4, s1);
+       s2 =
+               (Td4[(t2 >> 24)       ] & 0xff000000) ^
+               (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t0 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t3      ) & 0xff] & 0x000000ff) ^
+               rk[2];
+       PUTU32(pt +  8, s2);
+       s3 =
+               (Td4[(t3 >> 24)       ] & 0xff000000) ^
+               (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+               (Td4[(t1 >>  8) & 0xff] & 0x0000ff00) ^
+               (Td4[(t0      ) & 0xff] & 0x000000ff) ^
+               rk[3];
+       PUTU32(pt + 12, s3);
+}
diff --git a/src/kerberosV/src/lib/des/rijndael-alg-fst.h b/src/kerberosV/src/lib/des/rijndael-alg-fst.h
new file mode 100644 (file)
index 0000000..0281110
--- /dev/null
@@ -0,0 +1,40 @@
+/*     $NetBSD: rijndael-alg-fst.h,v 1.2 2000/10/02 17:19:15 itojun Exp $      */
+/*     $KAME: rijndael-alg-fst.h,v 1.5 2003/07/15 10:47:16 itojun Exp $        */
+/**
+ * rijndael-alg-fst.h
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (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 __RIJNDAEL_ALG_FST_H
+#define __RIJNDAEL_ALG_FST_H
+
+#define RIJNDAEL_MAXKC (256/32)
+#define RIJNDAEL_MAXKB (256/8)
+#define RIJNDAEL_MAXNR 14
+
+int rijndaelKeySetupEnc(u_int32_t rk[/*4*(Nr + 1)*/], const u_int8_t cipherKey[], int keyBits);
+int rijndaelKeySetupDec(u_int32_t rk[/*4*(Nr + 1)*/], const u_int8_t cipherKey[], int keyBits);
+void rijndaelEncrypt(const u_int32_t rk[/*4*(Nr + 1)*/], int Nr, const u_int8_t pt[16], u_int8_t ct[16]);
+void rijndaelDecrypt(const u_int32_t rk[/*4*(Nr + 1)*/], int Nr, const u_int8_t ct[16], u_int8_t pt[16]);
+
+#endif /* __RIJNDAEL_ALG_FST_H */
diff --git a/src/kerberosV/src/lib/des/ui.c b/src/kerberosV/src/lib/des/ui.c
new file mode 100644 (file)
index 0000000..efbe534
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 1997 - 2000, 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: ui.c,v 1.4 2005/04/30 14:10:18 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <termios.h>
+#include <roken.h>
+
+#include <des.h>
+
+static sig_atomic_t intr_flag;
+
+static void
+intr(int sig)
+{
+    intr_flag++;
+}
+
+static int
+read_string(const char *preprompt, const char *prompt, 
+           char *buf, size_t len, int echo)
+{
+    struct sigaction sigs[47];
+    struct sigaction sa;
+    FILE *tty;
+    int ret = 0;
+    int of = 0;
+    int i;
+    int c;
+    char *p;
+
+    struct termios t_new, t_old;
+
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = intr;
+    sigemptyset(&sa.sa_mask);
+    sa.sa_flags = 0;
+    for(i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
+       if (i != SIGALRM) sigaction(i, &sa, &sigs[i]);
+
+    if((tty = fopen("/dev/tty", "r")) == NULL)
+       tty = stdin;
+       
+    fprintf(stderr, "%s%s", preprompt, prompt);
+    fflush(stderr);
+
+    if(echo == 0){
+       tcgetattr(fileno(tty), &t_old);
+       memcpy(&t_new, &t_old, sizeof(t_new));
+       t_new.c_lflag &= ~ECHO;
+       tcsetattr(fileno(tty), TCSANOW, &t_new);
+    }
+    intr_flag = 0;
+    p = buf;
+    while(intr_flag == 0){
+       c = getc(tty);
+       if(c == EOF){
+           if(!ferror(tty))
+               ret = 1;
+           break;
+       }
+       if(c == '\n')
+           break;
+       if(of == 0)
+           *p++ = c;
+       of = (p == buf + len);
+    }
+    if(of)
+       p--;
+    *p = 0;
+    
+    if(echo == 0){
+       printf("\n");
+       tcsetattr(fileno(tty), TCSANOW, &t_old);
+    }
+    
+    if(tty != stdin)
+       fclose(tty);
+
+    for(i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++)
+       if (i != SIGALRM) sigaction(i, &sigs[i], NULL);
+    
+    if(ret)
+       return -3;
+    if(intr_flag)
+       return -2;
+    if(of)
+       return -1;
+    return 0;
+}
+
+int
+UI_UTIL_read_pw_string(char *buf, int length, const char *prompt, int verify)
+{
+    int ret;
+
+    ret = read_string("", prompt, buf, length, 0);
+    if (ret)
+       return ret;
+
+    if (verify) {
+       char *buf2;
+       buf2 = malloc(length);
+       if (buf2 == NULL)
+           return 1;
+
+       ret = read_string("Verify password - ", prompt, buf2, length, 0);
+       if (ret) {
+           free(buf2);
+           return ret;
+       }
+       if (strcmp(buf2, buf) != 0)
+           ret = 1;
+       free(buf2);
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/editline/CVS/Entries b/src/kerberosV/src/lib/editline/CVS/Entries
new file mode 100644 (file)
index 0000000..6c9830b
--- /dev/null
@@ -0,0 +1,2 @@
+/edit_locl.h/1.1.1.1/Fri Apr 14 07:33:51 2006//
+D
diff --git a/src/kerberosV/src/lib/editline/CVS/Repository b/src/kerberosV/src/lib/editline/CVS/Repository
new file mode 100644 (file)
index 0000000..e41a47b
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/editline
diff --git a/src/kerberosV/src/lib/editline/CVS/Root b/src/kerberosV/src/lib/editline/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/editline/edit_locl.h b/src/kerberosV/src/lib/editline/edit_locl.h
new file mode 100644 (file)
index 0000000..a68b0aa
--- /dev/null
@@ -0,0 +1,61 @@
+/*  $Revision: 1.1.1.1 $
+**
+**  Internal header file for editline library.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CRLF           "\r\n"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+typedef struct dirent  DIRENTRY;
+#else
+#include <sys/dir.h>
+typedef struct direct  DIRENTRY;
+#endif
+
+#include <roken.h>
+
+#if    !defined(S_ISDIR)
+#define S_ISDIR(m)             (((m) & S_IFMT) == S_IFDIR)
+#endif /* !defined(S_ISDIR) */
+
+typedef unsigned char  CHAR;
+
+#define MEM_INC                64
+#define SCREEN_INC     256
+
+/*
+**  Variables and routines internal to this package.
+*/
+extern int     rl_eof;
+extern int     rl_erase;
+extern int     rl_intr;
+extern int     rl_kill;
+extern int     rl_quit;
+
+typedef char* (*rl_complete_func_t)(char*, int*);
+
+typedef int (*rl_list_possib_func_t)(char*, char***);
+
+void   rl_add_slash (char*, char*, size_t);
+int    rl_list_possib (char*, char***);
+void   rl_ttyset (int);
+rl_complete_func_t     rl_set_complete_func (rl_complete_func_t);
+rl_list_possib_func_t  rl_set_list_possib_func (rl_list_possib_func_t);
+#include "editline.h"
+
diff --git a/src/kerberosV/src/lib/gssapi/8003.c b/src/kerberosV/src/lib/gssapi/8003.c
new file mode 100644 (file)
index 0000000..62b0844
--- /dev/null
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: 8003.c,v 1.17 2005/04/01 08:55:36 lha Exp $");
+
+krb5_error_code
+gssapi_encode_om_uint32(OM_uint32 n, u_char *p)
+{
+  p[0] = (n >> 0)  & 0xFF;
+  p[1] = (n >> 8)  & 0xFF;
+  p[2] = (n >> 16) & 0xFF;
+  p[3] = (n >> 24) & 0xFF;
+  return 0;
+}
+
+krb5_error_code
+gssapi_encode_be_om_uint32(OM_uint32 n, u_char *p)
+{
+  p[0] = (n >> 24) & 0xFF;
+  p[1] = (n >> 16) & 0xFF;
+  p[2] = (n >> 8)  & 0xFF;
+  p[3] = (n >> 0)  & 0xFF;
+  return 0;
+}
+
+krb5_error_code
+gssapi_decode_om_uint32(u_char *p, OM_uint32 *n)
+{
+    *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+    return 0;
+}
+
+krb5_error_code
+gssapi_decode_be_om_uint32(u_char *p, OM_uint32 *n)
+{
+    *n = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
+    return 0;
+}
+
+static krb5_error_code
+hash_input_chan_bindings (const gss_channel_bindings_t b,
+                         u_char *p)
+{
+  u_char num[4];
+  MD5_CTX md5;
+
+  MD5_Init(&md5);
+  gssapi_encode_om_uint32 (b->initiator_addrtype, num);
+  MD5_Update (&md5, num, sizeof(num));
+  gssapi_encode_om_uint32 (b->initiator_address.length, num);
+  MD5_Update (&md5, num, sizeof(num));
+  if (b->initiator_address.length)
+    MD5_Update (&md5,
+               b->initiator_address.value,
+               b->initiator_address.length);
+  gssapi_encode_om_uint32 (b->acceptor_addrtype, num);
+  MD5_Update (&md5, num, sizeof(num));
+  gssapi_encode_om_uint32 (b->acceptor_address.length, num);
+  MD5_Update (&md5, num, sizeof(num));
+  if (b->acceptor_address.length)
+    MD5_Update (&md5,
+               b->acceptor_address.value,
+               b->acceptor_address.length);
+  gssapi_encode_om_uint32 (b->application_data.length, num);
+  MD5_Update (&md5, num, sizeof(num));
+  if (b->application_data.length)
+    MD5_Update (&md5,
+               b->application_data.value,
+               b->application_data.length);
+  MD5_Final (p, &md5);
+  return 0;
+}
+
+/*
+ * create a checksum over the chanel bindings in
+ * `input_chan_bindings', `flags' and `fwd_data' and return it in
+ * `result'
+ */
+
+OM_uint32
+gssapi_krb5_create_8003_checksum (
+                     OM_uint32 *minor_status,    
+                     const gss_channel_bindings_t input_chan_bindings,
+                     OM_uint32 flags,
+                     const krb5_data *fwd_data,
+                     Checksum *result)
+{
+    u_char *p;
+
+    /* 
+     * see rfc1964 (section 1.1.1 (Initial Token), and the checksum value 
+     * field's format) */
+    result->cksumtype = CKSUMTYPE_GSSAPI;
+    if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG))
+       result->checksum.length = 24 + 4 + fwd_data->length;
+    else 
+       result->checksum.length = 24;
+    result->checksum.data   = malloc (result->checksum.length);
+    if (result->checksum.data == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+  
+    p = result->checksum.data;
+    gssapi_encode_om_uint32 (16, p);
+    p += 4;
+    if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) {
+       memset (p, 0, 16);
+    } else {
+       hash_input_chan_bindings (input_chan_bindings, p);
+    }
+    p += 16;
+    gssapi_encode_om_uint32 (flags, p);
+    p += 4;
+
+    if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) {
+
+       *p++ = (1 >> 0) & 0xFF;                   /* DlgOpt */ /* == 1 */
+       *p++ = (1 >> 8) & 0xFF;                   /* DlgOpt */ /* == 0 */
+       *p++ = (fwd_data->length >> 0) & 0xFF;    /* Dlgth  */
+       *p++ = (fwd_data->length >> 8) & 0xFF;    /* Dlgth  */
+       memcpy(p, (unsigned char *) fwd_data->data, fwd_data->length);
+
+       p += fwd_data->length;
+    }
+     
+    return GSS_S_COMPLETE;
+}
+
+/*
+ * verify the checksum in `cksum' over `input_chan_bindings'
+ * returning  `flags' and `fwd_data'
+ */
+
+OM_uint32
+gssapi_krb5_verify_8003_checksum(
+                     OM_uint32 *minor_status,    
+                     const gss_channel_bindings_t input_chan_bindings,
+                     const Checksum *cksum,
+                     OM_uint32 *flags,
+                     krb5_data *fwd_data)
+{
+    unsigned char hash[16];
+    unsigned char *p;
+    OM_uint32 length;
+    int DlgOpt;
+    static unsigned char zeros[16];
+
+    if (cksum == NULL) {
+       *minor_status = 0;
+       return GSS_S_BAD_BINDINGS;
+    }
+
+    /* XXX should handle checksums > 24 bytes */
+    if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) {
+       *minor_status = 0;
+       return GSS_S_BAD_BINDINGS;
+    }
+    
+    p = cksum->checksum.data;
+    gssapi_decode_om_uint32(p, &length);
+    if(length != sizeof(hash)) {
+       *minor_status = 0;
+       return GSS_S_BAD_BINDINGS;
+    }
+    
+    p += 4;
+    
+    if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS
+       && memcmp(p, zeros, sizeof(zeros)) != 0) {
+       if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) {
+           *minor_status = 0;
+           return GSS_S_BAD_BINDINGS;
+       }
+       if(memcmp(hash, p, sizeof(hash)) != 0) {
+           *minor_status = 0;
+           return GSS_S_BAD_BINDINGS;
+       }
+    }
+    
+    p += sizeof(hash);
+    
+    gssapi_decode_om_uint32(p, flags);
+    p += 4;
+
+    if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) {
+       if(cksum->checksum.length < 28) {
+           *minor_status = 0;
+           return GSS_S_BAD_BINDINGS;
+       }
+    
+       DlgOpt = (p[0] << 0) | (p[1] << 8);
+       p += 2;
+       if (DlgOpt != 1) {
+           *minor_status = 0;
+           return GSS_S_BAD_BINDINGS;
+       }
+
+       fwd_data->length = (p[0] << 0) | (p[1] << 8);
+       p += 2;
+       if(cksum->checksum.length < 28 + fwd_data->length) {
+           *minor_status = 0;
+           return GSS_S_BAD_BINDINGS;
+       }
+       fwd_data->data = malloc(fwd_data->length);
+       if (fwd_data->data == NULL) {
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       memcpy(fwd_data->data, p, fwd_data->length);
+    }
+    
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/CVS/Entries b/src/kerberosV/src/lib/gssapi/CVS/Entries
new file mode 100644 (file)
index 0000000..1c71508
--- /dev/null
@@ -0,0 +1,60 @@
+/8003.c/1.1.1.5/Fri Apr 14 07:32:54 2006//
+/ChangeLog/1.1.1.7/Fri Apr 14 07:32:55 2006//
+/accept_sec_context.c/1.1.1.6/Fri Apr 14 07:32:55 2006//
+/acquire_cred.c/1.1.1.6/Fri Apr 14 07:32:55 2006//
+/add_cred.c/1.1.1.3/Fri Apr 14 07:32:56 2006//
+/add_oid_set_member.c/1.1.1.3/Sun May 11 02:15:38 2003//
+/address_to_krb5addr.c/1.1.1.3/Fri Apr 14 07:32:56 2006//
+/arcfour.c/1.1.1.2/Fri Apr 14 07:32:56 2006//
+/arcfour.h/1.1.1.2/Fri Apr 14 07:32:56 2006//
+/canonicalize_name.c/1.1.1.1/Fri May 25 07:50:01 2001//
+/ccache_name.c/1.1.1.1/Fri Apr 14 07:32:56 2006//
+/cfx.c/1.1.1.1/Fri Apr 14 07:32:56 2006//
+/cfx.h/1.1.1.1/Fri Apr 14 07:32:56 2006//
+/compare_name.c/1.1.1.2/Sun May 11 02:15:38 2003//
+/compat.c/1.1.1.3/Fri Apr 14 07:32:56 2006//
+/context_time.c/1.1.1.5/Fri Apr 14 07:32:56 2006//
+/copy_ccache.c/1.1.1.4/Fri Apr 14 07:32:56 2006//
+/create_emtpy_oid_set.c/1.1.1.3/Sun May 11 02:15:39 2003//
+/decapsulate.c/1.1.1.4/Fri Apr 14 07:32:57 2006//
+/delete_sec_context.c/1.1.1.4/Fri Apr 14 07:32:57 2006//
+/display_name.c/1.1.1.3/Sun May 11 02:15:39 2003//
+/display_status.c/1.1.1.5/Fri Apr 14 07:32:57 2006//
+/duplicate_name.c/1.1.1.3/Sun May 11 02:15:39 2003//
+/encapsulate.c/1.1.1.4/Fri Apr 14 07:32:57 2006//
+/export_name.c/1.1.1.2/Sun May 11 02:15:39 2003//
+/export_sec_context.c/1.1.1.4/Fri Apr 14 07:32:57 2006//
+/external.c/1.1.1.2/Fri Apr 14 07:32:57 2006//
+/get_mic.c/1.1.1.6/Fri Apr 14 07:32:57 2006//
+/gss_acquire_cred.3/1.3/Fri Apr 14 08:15:04 2006//
+/gssapi.3/1.3/Fri Apr 14 08:15:04 2006//
+/gssapi.h/1.1.1.5/Fri Apr 14 07:32:58 2006//
+/gssapi_locl.h/1.1.1.6/Fri Apr 14 07:32:58 2006//
+/import_name.c/1.1.1.3/Sun May 11 02:15:40 2003//
+/import_sec_context.c/1.1.1.4/Fri Apr 14 07:32:58 2006//
+/indicate_mechs.c/1.1.1.4/Fri Apr 14 07:32:58 2006//
+/init.c/1.1.1.3/Fri Apr 14 07:32:58 2006//
+/init_sec_context.c/1.1.1.6/Fri Apr 14 07:32:59 2006//
+/inquire_context.c/1.1.1.3/Fri Apr 14 07:32:59 2006//
+/inquire_cred.c/1.1.1.3/Fri Apr 14 07:32:59 2006//
+/inquire_cred_by_mech.c/1.1.1.2/Fri Apr 14 07:32:59 2006//
+/inquire_mechs_for_name.c/1.1.1.1/Sun May 11 02:15:41 2003//
+/inquire_names_for_mech.c/1.1.1.1/Sun May 11 02:15:41 2003//
+/process_context_token.c/1.1.1.1/Sun May 11 02:15:41 2003//
+/release_buffer.c/1.1.1.2/Sun May 11 02:15:41 2003//
+/release_cred.c/1.1.1.4/Fri Apr 14 07:32:59 2006//
+/release_name.c/1.1.1.2/Sun May 11 02:15:41 2003//
+/release_oid_set.c/1.1.1.2/Sun May 11 02:15:41 2003//
+/sequence.c/1.1.1.1/Fri Apr 14 07:32:59 2006//
+/spkm.asn1/1.1.1.1/Fri Apr 14 07:32:59 2006//
+/spnego.asn1/1.1.1.1/Fri Apr 14 07:32:59 2006//
+/test_acquire_cred.c/1.1.1.2/Fri Apr 14 07:32:59 2006//
+/test_cred.c/1.1.1.1/Fri Apr 14 07:33:00 2006//
+/test_oid_set_member.c/1.1.1.2/Sun May 11 02:15:41 2003//
+/test_sequence.c/1.1.1.1/Fri Apr 14 07:33:00 2006//
+/ticket_flags.c/1.1.1.1/Fri Apr 14 07:33:00 2006//
+/unwrap.c/1.1.1.6/Fri Apr 14 07:33:00 2006//
+/v1.c/1.1.1.1/Fri May 25 07:50:10 2001//
+/verify_mic.c/1.1.1.7/Fri Apr 14 07:33:00 2006//
+/wrap.c/1.1.1.6/Fri Apr 14 07:33:00 2006//
+D
diff --git a/src/kerberosV/src/lib/gssapi/CVS/Repository b/src/kerberosV/src/lib/gssapi/CVS/Repository
new file mode 100644 (file)
index 0000000..9e58064
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/gssapi
diff --git a/src/kerberosV/src/lib/gssapi/CVS/Root b/src/kerberosV/src/lib/gssapi/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/gssapi/ChangeLog b/src/kerberosV/src/lib/gssapi/ChangeLog
new file mode 100644 (file)
index 0000000..66084c4
--- /dev/null
@@ -0,0 +1,1337 @@
+2005-12-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * acquire_cred.c: 1.27: (acquire_acceptor_cred): only check if
+       principal exists if we got called with principal as an argument.
+       1.26: (acquire_acceptor_cred): check that the acceptor exists in
+       the keytab before returning ok.
+       
+2005-05-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_sec_context.c (init_auth): honor ok-as-delegate if local
+       configuration approves
+
+       * gssapi_locl.h: prototype for _gss_check_compat
+
+       * compat.c: export check_compat as _gss_check_compat
+
+2005-05-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_sec_context.c: Prefix Der_class with ASN1_C_ to avoid
+       problems with system headerfiles that pollute the name space.
+
+       * accept_sec_context.c: Prefix Der_class with ASN1_C_ to avoid
+       problems with system headerfiles that pollute the name space.
+
+2005-05-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_sec_context.c (init_auth): set
+       KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED (for java compatibility),
+       also while here, use krb5_auth_con_addflags
+
+2005-05-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * arcfour.c (_gssapi_wrap_arcfour): fix calculating the encap
+       length. From: Tom Maher <tmaher@eecs.berkeley.edu>
+
+2005-05-02  Dave Love  <fx@gnu.org>
+
+       * test_cred.c (main): Call setprogname.
+
+2005-04-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * prefix all sequence symbols with _, they are not part of the
+       GSS-API api. By comment from Wynn Wilkes <wynnw@vintela.com>
+
+2005-04-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * accept_sec_context.c: break out the processing of the delegated
+       credential to a separate function to make error handling easier,
+       move the credential handling to after other setup is done
+       
+       * test_sequence.c: make less verbose in case of success
+
+       * Makefile.am: add test_sequence to TESTS
+
+2005-04-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * 8003.c (gssapi_krb5_verify_8003_checksum): check that cksum
+       isn't NULL From: Nicolas Pouvesle <npouvesle@tenablesecurity.com>
+
+2005-03-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: use $(LIB_roken)
+
+2005-03-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * display_status.c (gssapi_krb5_set_error_string): pass in the
+       krb5_context to krb5_free_error_string
+       
+2005-03-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * display_status.c (gssapi_krb5_set_error_string): don't misuse
+       the krb5_get_error_string api
+
+2005-03-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * compat.c (_gss_DES3_get_mic_compat): don't unlock mutex
+       here. Bug reported by Stefan Metzmacher <metze@samba.org>
+
+2005-02-21  Luke Howard  <lukeh@padl.com>
+
+       * init_sec_context.c: don't call krb5_get_credentials() with
+         KRB5_TC_MATCH_KEYTYPE, it can lead to the credentials cache
+         growing indefinitely as no key is found with KEYTYPE_NULL
+
+       * compat.c: remove GSS_C_EXPECTING_MECH_LIST_MIC_FLAG, it is
+         no longer used (however the mechListMIC behaviour is broken,
+         rfc2478bis support requires the code in the mechglue branch)
+
+       * init_sec_context.c: remove GSS_C_EXPECTING_MECH_LIST_MIC_FLAG
+
+       * gssapi.h: remove GSS_C_EXPECTING_MECH_LIST_MIC_FLAG
+
+2005-01-05  Luke Howard  <lukeh@padl.com>
+
+       * 8003.c: use symbolic name for checksum type
+
+       * accept_sec_context.c: allow client to indicate
+         that subkey should be used
+
+       * acquire_cred.c: plug leak
+
+       * get_mic.c: use gss_krb5_get_subkey() instead
+         of gss_krb5_get_{local,remote}key(), support
+         KEYTYPE_ARCFOUR_56
+
+       * gssapi_local.c: use gss_krb5_get_subkey(),
+         support KEYTYPE_ARCFOUR_56
+
+       * import_sec_context.c: plug leak
+
+       * unwrap.c: use gss_krb5_get_subkey(),
+         support KEYTYPE_ARCFOUR_56
+
+       * verify_mic.c: use gss_krb5_get_subkey(),
+         support KEYTYPE_ARCFOUR_56
+
+       * wrap.c: use gss_krb5_get_subkey(),
+         support KEYTYPE_ARCFOUR_56
+
+2004-11-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * inquire_cred.c: Reverse order of HEIMDAL_MUTEX_unlock and
+       gss_release_cred to avoid deadlock, from Luke Howard
+       <lukeh@padl.com>.
+
+2004-09-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: gss_krb5_extract_authz_data_from_sec_context
+       was renamed to gsskrb5_extract_authz_data_from_sec_context
+       
+2004-08-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * unwrap.c: mutex buglet, From: Luke Howard <lukeh@PADL.COM>
+       
+       * arcfour.c: mutex buglet, From: Luke Howard <lukeh@PADL.COM>
+       
+2004-05-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.3: spelling from Josef El-Rayes <josef@FreeBSD.org> while
+       here, write some text about the SPNEGO situation
+       
+2004-04-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: s/CTXAcceptorSubkey/CFXAcceptorSubkey/
+       
+2004-04-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.h: add GSS_C_EXPECTING_MECH_LIST_MIC_FLAG From: Luke
+       Howard <lukeh@padl.com>
+       
+       * init_sec_context.c (spnego_reply): use
+       _gss_spnego_require_mechlist_mic to figure out if we need to check
+       MechListMIC; From: Luke Howard <lukeh@padl.com>
+
+       * accept_sec_context.c (send_accept): use
+       _gss_spnego_require_mechlist_mic to figure out if we need to send
+       MechListMIC; From: Luke Howard <lukeh@padl.com>
+
+       * gssapi_locl.h: add _gss_spnego_require_mechlist_mic
+       From: Luke Howard <lukeh@padl.com>
+
+       * compat.c: add _gss_spnego_require_mechlist_mic for compatibility
+       with MS SPNEGO, From: Luke Howard <lukeh@padl.com>
+       
+2004-04-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * accept_sec_context.c (gsskrb5_is_cfx): krb5_keyblock->keytype is
+       an enctype, not keytype
+
+       * accept_sec_context.c: use ASN1_MALLOC_ENCODE
+       
+       * init_sec_context.c: avoid the malloc loop and just allocate the
+       propper amount of data
+
+       * init_sec_context.c (spnego_initial): handle mech_token better
+       
+2004-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.h: add gss_krb5_get_tkt_flags
+       
+       * Makefile.am: add ticket_flags.c
+       
+       * ticket_flags.c: Get ticket-flags from acceptor ticket From: Luke
+       Howard <lukeh@PADL.COM>
+       
+       * gss_acquire_cred.3: document gss_krb5_get_tkt_flags
+       
+2004-03-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * acquire_cred.c (gss_acquire_cred): check usage before even
+       bothering to process it, add both keytab and initial tgt if
+       requested
+
+       * wrap.c: support cfx, try to handle acceptor asserted subkey
+       
+       * unwrap.c: support cfx, try to handle acceptor asserted subkey
+       
+       * verify_mic.c: support cfx
+       
+       * get_mic.c: support cfx
+       
+       * test_sequence.c: handle changed signature of
+       gssapi_msg_order_create
+
+       * import_sec_context.c: handle acceptor asserted subkey
+       
+       * init_sec_context.c: handle acceptor asserted subkey
+       
+       * accept_sec_context.c: handle acceptor asserted subkey
+       
+       * sequence.c: add dummy use_64 argument to gssapi_msg_order_create
+       
+       * gssapi_locl.h: add partial support for CFX
+       
+       * Makefile.am (noinst_PROGRAMS) += test_cred
+       
+       * test_cred.c: gssapi credential testing
+
+       * test_acquire_cred.c: fix comment
+       
+2004-03-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * arcfour.h: drop structures for message formats, no longer used
+       
+       * arcfour.c: comment describing message formats
+
+       * accept_sec_context.c (spnego_accept_sec_context): make sure the
+       length of the choice element doesn't overrun us
+       
+       * init_sec_context.c (spnego_reply): make sure the length of the
+       choice element doesn't overrun us
+       
+       * spnego.asn1: move NegotiationToken to avoid warning
+       
+       * spnego.asn1: uncomment NegotiationToken
+       
+       * Makefile.am: spnego_files += asn1_NegotiationToken.x
+       
+2004-01-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.h: add gss_krb5_ccache_name
+       
+       * Makefile.am (libgssapi_la_SOURCES): += ccache_name.c
+       
+       * ccache_name.c (gss_krb5_ccache_name): help function enable to
+       set krb5 name, using out_name argument makes function no longer
+       thread-safe
+
+       * gssapi.3: add missing gss_krb5_ references
+       
+       * gss_acquire_cred.3: document gss_krb5_ccache_name
+       
+2003-12-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: make rrc a modulus operation if its longer then the
+       length of the message, noticed by Sam Hartman
+
+2003-12-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * accept_sec_context.c: use krb5_auth_con_addflags
+       
+2003-12-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: Wrap token id was in wrong order, found by Sam Hartman
+       
+2003-12-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: add AcceptorSubkey (but no code understand it yet) ignore
+       unknown token flags
+       
+2003-11-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * accept_sec_context.c: Don't require timestamp to be set on
+       delegated token, its already protected by the outer token (and
+       windows doesn't alway send it) Pointed out by Zi-Bin Yang
+       <zbyang@decru.com> on heimdal-discuss
+
+2003-11-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: fix {} error, pointed out by Liqiang Zhu
+       
+2003-11-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: Sequence number should be stored in bigendian order From:
+       Luke Howard <lukeh@padl.com>
+       
+2003-11-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * delete_sec_context.c (gss_delete_sec_context): don't free
+       ticket, krb5_free_ticket does that now
+
+2003-11-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: checksum the header last in MIC token, update to -03
+       From: Luke Howard <lukeh@padl.com>
+       
+2003-10-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * add_cred.c: If its a MEMORY cc, make a copy. We need to do this
+       since now gss_release_cred will destroy the cred. This should be
+       really be solved a better way.
+
+       * acquire_cred.c (gss_release_cred): if its a mcc, destroy it
+       rather the just release it Found by: "Zi-Bin Yang"
+       <zbyang@decru.com>
+
+       * acquire_cred.c (acquire_initiator_cred): use kret instead of ret
+       where appropriate
+
+2003-09-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: spelling
+       From: jmc <jmc@prioris.mini.pw.edu.pl>
+       
+2003-09-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: - EC and RRC are big-endian, not little-endian - The
+       default is now to rotate regardless of GSS_C_DCE_STYLE. There are
+       no longer any references to GSS_C_DCE_STYLE.  - rrc_rotate()
+       avoids allocating memory on the heap if rrc <= 256
+       From: Luke Howard <lukeh@padl.com>
+       
+2003-09-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.[ch]: rrc_rotate() was untested and broken, fix it.
+       Set and verify wrap Token->Filler.
+       Correct token ID for wrap tokens, 
+       were accidentally swapped with delete tokens.
+       From: Luke Howard <lukeh@PADL.COM>
+
+2003-09-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.[ch]: no ASN.1-ish header on per-message tokens
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-09-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * arcfour.h: remove depenency on gss_arcfour_mic_token and
+       gss_arcfour_warp_token
+
+       * arcfour.c: remove depenency on gss_arcfour_mic_token and
+       gss_arcfour_warp_token
+
+2003-09-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * 8003.c: remove #if 0'ed code
+       
+2003-09-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * accept_sec_context.c (gsskrb5_accept_sec_context): set sequence
+       number when not requesting mutual auth From: Luke Howard
+       <lukeh@PADL.COM>
+
+       * init_sec_context.c (init_auth): set sequence number when not
+       requesting mutual auth From: Luke Howard <lukeh@PADL.COM>
+       
+2003-09-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * arcfour.c (*): set minor_status
+       (gss_wrap): set conf_state to conf_req_flags on success
+       From: Luke Howard <lukeh@PADL.COM>
+       
+       * wrap.c (gss_wrap_size_limit): use existing function From: Luke
+       Howard <lukeh@PADL.COM>
+       
+2003-09-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * indicate_mechs.c (gss_indicate_mechs): in case of error, free
+       mech_set
+
+       * indicate_mechs.c (gss_indicate_mechs): add SPNEGO
+
+2003-09-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_sec_context.c (spnego_initial): catch errors and return
+       them
+
+       * init_sec_context.c (spnego_initial): add #if 0 out version of
+       the CHOICE branch encoding, also where here, free no longer used
+       memory
+
+2003-09-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: support GSS_SPNEGO_MECHANISM
+       
+       * accept_sec_context.c: SPNEGO doesn't include gss wrapping on
+       SubsequentContextToken like the Kerberos 5 mech does.
+       
+       * init_sec_context.c (spnego_reply): SPNEGO doesn't include gss
+       wrapping on SubsequentContextToken like the Kerberos 5 mech
+       does. Lets check for it anyway.
+       
+       * accept_sec_context.c: Add support for SPNEGO on the initator
+       side.  Implementation initially from Assar Westerlund, passes
+       though quite a lot of hands before I commited it.
+       
+       * init_sec_context.c: Add support for SPNEGO on the initator side.
+       Tested with ldap server on a Windows 2000 DC. Implementation
+       initially from Assar Westerlund, passes though quite a lot of
+       hands before I commited it.
+       
+       * gssapi.h: export GSS_SPNEGO_MECHANISM
+       
+       * gssapi_locl.h: include spnego_as.h add prototype for
+       gssapi_krb5_get_mech
+       
+       * decapsulate.c (gssapi_krb5_get_mech): make non static
+       
+       * Makefile.am: build SPNEGO file
+       
+2003-09-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * external.c: SPENGO and IAKERB oids
+       
+       * spnego.asn1: SPENGO ASN1
+       
+2003-09-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.c: RRC also need to be zero before wraping them
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-09-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * encapsulate.c (gssapi_krb5_encap_length): don't return void
+       
+2003-09-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * verify_mic.c: switch from the des_ to the DES_ api
+       
+       * get_mic.c: switch from the des_ to the DES_ api
+       
+       * unwrap.c: switch from the des_ to the DES_ api
+       
+       * wrap.c: switch from the des_ to the DES_ api
+       
+       * cfx.c: EC is not included in the checksum since the length might
+       change depending on the data.  From: Luke Howard <lukeh@PADL.COM>
+       
+       * acquire_cred.c: use
+       krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free
+
+2003-09-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * copy_ccache.c: rename
+       gss_krb5_extract_authz_data_from_sec_context to
+       gsskrb5_extract_authz_data_from_sec_context
+
+       * gssapi.h: rename gss_krb5_extract_authz_data_from_sec_context to
+       gsskrb5_extract_authz_data_from_sec_context
+       
+2003-08-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * copy_ccache.c (gss_krb5_extract_authz_data_from_sec_context):
+       check that we have a ticket before we start to use it
+       
+       * gss_acquire_cred.3: document
+       gss_krb5_extract_authz_data_from_sec_context
+       
+       * gssapi.h (gss_krb5_extract_authz_data_from_sec_context):
+       return the kerberos authorizationdata, from idea of Luke Howard
+
+       * copy_ccache.c (gss_krb5_extract_authz_data_from_sec_context):
+       return the kerberos authorizationdata, from idea of Luke Howard
+       
+       * verify_mic.c (gss_verify_mic_internal): switch type and key
+       argument
+
+2003-08-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * cfx.[ch]: draft-ietf-krb-wg-gssapi-cfx-01.txt implemetation
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-08-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * arcfour.c (arcfour_mic_cksum): use free_Checksum to free the
+       checksum
+
+       * arcfour.h: swap two last arguments to verify_mic for consistency
+       with des3
+
+       * wrap.c,unwrap.c,get_mic.c,verify_mic.c,cfx.c,cfx.h:
+       prefix cfx symbols with _gssapi_
+
+       * arcfour.c: release the right buffer
+       
+       * arcfour.c: rename token structure in consistency with rest of
+       GSS-API From: Luke Howard <lukeh@PADL.COM>
+       
+       * unwrap.c (unwrap_des3): use _gssapi_verify_pad
+       (unwrap_des): use _gssapi_verify_pad
+
+       * arcfour.c (_gssapi_wrap_arcfour): set the correct padding
+       (_gssapi_unwrap_arcfour): verify and strip padding
+
+       * gssapi_locl.h: added _gssapi_verify_pad
+       
+       * decapsulate.c (_gssapi_verify_pad): verify padding of a gss
+       wrapped message and return its length
+       
+       * arcfour.c: support KEYTYPE_ARCFOUR_56 keys, from Luke Howard
+       <lukeh@PADL.COM>
+       
+       * arcfour.c: use right seal alg, inherit keytype from parent key
+       
+       * arcfour.c: include the confounder in the checksum use the right
+       key usage number for warped/unwraped tokens
+       
+       * gssapi.h: add gss_krb5_nt_general_name as an mit compat glue
+       (same as GSS_KRB5_NT_PRINCIPAL_NAME)
+
+       * unwrap.c: hook in arcfour unwrap
+       
+       * wrap.c: hook in arcfour wrap
+       
+       * verify_mic.c: hook in arcfour verify_mic
+       
+       * get_mic.c: hook in arcfour get_mic
+       
+       * arcfour.c: implement wrap/unwarp
+       
+       * gssapi_locl.h: add gssapi_{en,de}code_be_om_uint32
+       
+       * 8003.c: add gssapi_{en,de}code_be_om_uint32
+       
+2003-08-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * arcfour.c (_gssapi_verify_mic_arcfour): Do the checksum on right
+       area. Swap filler check, it was reversed.
+       
+       * Makefile.am (libgssapi_la_SOURCES): += arcfour.c
+       
+       * gssapi_locl.h: include "arcfour.h"
+       
+       * arcfour.c: arcfour gss-api mech, get_mic/verify_mic working
+
+       * arcfour.h: arcfour gss-api mech, get_mic/verify_mic working
+       
+2003-08-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi_locl.h: always include cfx.h add prototype for
+       _gssapi_decapsulate
+
+       * cfx.[ch]: Implementation of draft-ietf-krb-wg-gssapi-cfx-00.txt
+       from Luke Howard <lukeh@PADL.COM>
+
+       * decapsulate.c: add _gssapi_decapsulate, from Luke Howard
+       <lukeh@PADL.COM>
+       
+2003-08-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * unwrap.c: encap/decap now takes a oid if the enctype/keytype is
+       arcfour, return error add hook for cfx
+       
+       * verify_mic.c: encap/decap now takes a oid if the enctype/keytype
+       is arcfour, return error add hook for cfx
+       
+       * get_mic.c: encap/decap now takes a oid if the enctype/keytype is
+       arcfour, return error add hook for cfx
+       
+       * accept_sec_context.c: encap/decap now takes a oid
+       
+       * init_sec_context.c: encap/decap now takes a oid
+       
+       * gssapi_locl.h: include cfx.h if we need it lifetime is a
+       OM_uint32, depend on gssapi interface add all new encap/decap
+       functions
+       
+       * decapsulate.c: add decap functions that doesn't take the token
+       type also make all decap function take the oid mech that they
+       should use
+
+       * encapsulate.c: add encap functions that doesn't take the token
+       type also make all encap function take the oid mech that they
+       should use
+
+       * sequence.c (elem_insert): fix a off by one index counter
+       
+       * inquire_cred.c (gss_inquire_cred): handle cred_handle beeing
+       GSS_C_NO_CREDENTIAL and use the default cred then.
+       
+2003-08-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: break out extensions and document
+       gsskrb5_register_acceptor_identity
+
+2003-08-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * test_acquire_cred.c (print_time): time is returned in seconds
+       from now, not unix time
+
+2003-08-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * compat.c (check_compat): avoid leaking principal when finding a
+       match
+
+       * address_to_krb5addr.c: sa_size argument to krb5_addr2sockaddr is
+       a krb5_socklen_t
+
+       * acquire_cred.c (gss_acquire_cred): 4th argument to
+       gss_test_oid_set_member is a int
+
+2003-07-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_sec_context.c (repl_mutual): don't set kerberos error where
+       there was no kerberos error
+
+       * gssapi_locl.h: Add destruction/creation prototypes and structure
+       for the thread specific storage.
+
+       * display_status.c: use thread specific storage to set/get the
+       kerberos error message
+
+       * init.c: Provide locking around the creation of the global
+       krb5_context. Add destruction/creation functions for the thread
+       specific storage that the error string handling is using.
+       
+2003-07-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: add missing prototype and missing .Ft
+       arguments
+
+2003-06-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * verify_mic.c: reorder code so sequence numbers can can be used
+       
+       * unwrap.c: reorder code so sequence numbers can can be used
+       
+       * sequence.c: remove unused function, indent, add
+       gssapi_msg_order_f that filter gss flags to gss_msg_order flags
+       
+       * gssapi_locl.h: prototypes for
+       gssapi_{encode_om_uint32,decode_om_uint32} add sequence number
+       verifier prototypes
+
+       * delete_sec_context.c: destroy sequence number verifier
+       
+       * init_sec_context.c: remember to free data use sequence number
+       verifier
+       
+       * accept_sec_context.c: don't clear output_token twice remember to
+       free data use sequence number verifier
+       
+       * 8003.c: export and rename encode_om_uint32/decode_om_uint32 and
+       start to use them
+
+2003-06-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: can't have sequence.c in two different places
+
+2003-06-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * test_sequence.c: check rollover, print summery
+       
+       * wrap.c (sub_wrap_size): gss_wrap_size_limit() has
+       req_output_size and max_input_size around the wrong way -- it
+       returns the output token size for a given input size, rather than
+       the maximum input size for a given output token size.
+       
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-06-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi_locl.h: add prototypes for sequence.c
+       
+       * Makefile.am (libgssapi_la_SOURCES): add sequence.c
+       (test_sequence): build
+
+       * sequence.c: sequence number checks, order and replay
+       * test_sequence.c: sequence number checks, order and replay
+
+2003-06-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * accept_sec_context.c (gss_accept_sec_context): make sure time is
+       returned in seconds from now, not in kerberos time
+       
+       * acquire_cred.c (gss_aquire_cred): make sure time is returned in
+       seconds from now, not in kerberos time
+       
+       * init_sec_context.c (init_auth): if the cred is expired before we
+       tries to create a token, fail so the peer doesn't need reject us
+       (*): make sure time is returned in seconds from now, 
+       not in kerberos time
+       (repl_mutual): remember to unlock the context mutex
+
+       * context_time.c (gss_context_time): remove unused variable
+       
+       * verify_mic.c: make sure minor_status is always set, pointed out
+       by Luke Howard <lukeh@PADL.COM>
+
+2003-05-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * *.[ch]: do some basic locking (no reference counting so contexts 
+         can be removed while still used)
+       - don't export gss_ctx_id_t_desc_struct and gss_cred_id_t_desc_struct
+       - make sure all lifetime are returned in seconds left until expired,
+         not in unix epoch
+
+       * gss_acquire_cred.3: document argument lifetime_rec to function
+       gss_inquire_context
+
+2003-05-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * test_acquire_cred.c: test gss_add_cred more then once
+       
+2003-05-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.h: if __cplusplus, wrap the extern variable (just to be
+       safe) and functions in extern "C" { }
+       
+2003-04-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.3: more about the des3 mic mess
+       
+       * verify_mic.c (verify_mic_des3): always check if the mic is the
+       correct mic or the mic that old heimdal would have generated
+       
+2003-04-28  Jacques Vidrine  <nectar@kth.se>
+
+       * verify_mic.c (verify_mic_des3): If MIC verification fails,
+       retry using the `old' MIC computation (with zero IV).
+
+2003-04-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: more about difference between comparing IN
+       and MN
+
+       * gss_acquire_cred.3: more about name type and access control
+       
+2003-04-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: document gss_context_time
+       
+       * context_time.c: if lifetime of context have expired, set
+       time_rec to 0 and return GSS_S_CONTEXT_EXPIRED
+       
+       * gssapi.3: document [gssapi]correct_des3_mic
+       [gssapi]broken_des3_mic
+
+       * gss_acquire_cred.3: document gss_krb5_compat_des3_mic
+       
+       * compat.c (gss_krb5_compat_des3_mic): enable turning on/off des3
+       mic compat
+       (_gss_DES3_get_mic_compat): handle [gssapi]correct_des3_mic too
+
+       * gssapi.h (gss_krb5_compat_des3_mic): new function, turn on/off
+       des3 mic compat
+       (GSS_C_KRB5_COMPAT_DES3_MIC): cpp symbol that exists if
+       gss_krb5_compat_des3_mic exists
+       
+2003-04-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am:  (libgssapi_la_LDFLAGS): update major
+       version of gssapi for incompatiblity in 3des getmic support
+       
+2003-04-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: test_acquire_cred_LDADD: use libgssapi.la not
+       ./libgssapi.la (make make -jN work)
+
+2003-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.3: spelling
+       
+       * gss_acquire_cred.3: Change .Fd #include <header.h> to .In
+       header.h, from Thomas Klausner <wiz@netbsd.org>
+
+       
+2003-04-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: spelling
+       
+       * Makefile.am: remove stuff that sneaked in with last commit
+       
+       * acquire_cred.c (acquire_initiator_cred): if the requested name
+       isn't in the ccache, also check keytab.  Extact the krbtgt for the
+       default realm to check how long the credentials will last.
+       
+       * add_cred.c (gss_add_cred): don't create a new ccache, just open
+       the old one; better check if output handle is compatible with new
+       (copied) handle
+
+       * test_acquire_cred.c: test gss_add_cred too
+       
+2003-04-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: build test_acquire_cred
+       
+       * test_acquire_cred.c: simple gss_acquire_cred test
+       
+2003-04-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: s/gssapi/GSS-API/
+       
+2003-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: document v1 interface (and that they are
+       obsolete)
+
+2003-03-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_acquire_cred.3: list supported mechanism and nametypes
+       
+2003-03-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * gss_acquire_cred.3: text about gss_display_name
+
+       * Makefile.am (libgssapi_la_LDFLAGS): bump to 3:6:2
+       (libgssapi_la_SOURCES): add all new functions
+
+       * gssapi.3: now that we have a functions, uncomment the missing
+       ones
+
+       * gss_acquire_cred.3: now that we have a functions, uncomment the
+       missing ones
+
+       * process_context_token.c: implement gss_process_context_token
+       
+       * inquire_names_for_mech.c: implement gss_inquire_names_for_mech
+       
+       * inquire_mechs_for_name.c: implement gss_inquire_mechs_for_name
+       
+       * inquire_cred_by_mech.c: implement gss_inquire_cred_by_mech
+       
+       * add_cred.c: implement gss_add_cred
+       
+       * acquire_cred.c (gss_acquire_cred): more testing of input
+       argument, make sure output arguments are ok, since we don't know
+       the time_rec (for now), set it to time_req
+       
+       * export_sec_context.c: send lifetime, also set minor_status
+       
+       * get_mic.c: set minor_status
+       
+       * import_sec_context.c (gss_import_sec_context): add error
+       checking, pick up lifetime (if there is no lifetime, use
+       GSS_C_INDEFINITE)
+
+       * init_sec_context.c: take care to set export value to something
+       sane before we start so caller will have harmless values in them
+       if then function fails
+
+       * release_buffer.c (gss_release_buffer): set minor_status
+       
+       * wrap.c: make sure minor_status get set
+       
+       * verify_mic.c (gss_verify_mic_internal): rename verify_mic to
+       gss_verify_mic_internal and let it take the type as an argument,
+       (gss_verify_mic): call gss_verify_mic_internal
+       set minor_status
+       
+       * unwrap.c: set minor_status
+       
+       * test_oid_set_member.c (gss_test_oid_set_member): use
+       gss_oid_equal
+
+       * release_oid_set.c (gss_release_oid_set): set minor_status
+       
+       * release_name.c (gss_release_name): set minor_status
+       
+       * release_cred.c (gss_release_cred): set minor_status
+       
+       * add_oid_set_member.c (gss_add_oid_set_member): set minor_status
+       
+       * compare_name.c (gss_compare_name): set minor_status
+       
+       * compat.c (check_compat): make sure ret have a defined value
+       
+       * context_time.c (gss_context_time): set minor_status
+       
+       * copy_ccache.c (gss_krb5_copy_ccache): set minor_status
+       
+       * create_emtpy_oid_set.c (gss_create_empty_oid_set): set
+       minor_status
+
+       * delete_sec_context.c (gss_delete_sec_context): set minor_status
+       
+       * display_name.c (gss_display_name): set minor_status
+       
+       * display_status.c (gss_display_status): use gss_oid_equal, handle
+       supplementary errors
+
+       * duplicate_name.c (gss_duplicate_name): set minor_status
+       
+       * inquire_context.c (gss_inquire_context): set lifetime_rec now
+       when we know it, set minor_status
+
+       * inquire_cred.c (gss_inquire_cred): take care to set export value
+       to something sane before we start so caller will have harmless
+       values in them if the function fails
+       
+       * accept_sec_context.c (gss_accept_sec_context): take care to set
+       export value to something sane before we start so caller will have
+       harmless values in them if then function fails, set lifetime from
+       ticket expiration date
+
+       * indicate_mechs.c (gss_indicate_mechs): use
+       gss_create_empty_oid_set and gss_add_oid_set_member
+
+       * gssapi.h (gss_ctx_id_t_desc): store the lifetime in the cred,
+       since there is no ticket transfered in the exported context
+       
+       * export_name.c (gss_export_name): export name with
+       GSS_C_NT_EXPORT_NAME wrapping, not just the principal
+       
+       * import_name.c (import_export_name): new function, parses a
+       GSS_C_NT_EXPORT_NAME
+       (import_krb5_name): factor out common code of parsing krb5 name
+       (gss_oid_equal): rename from oid_equal
+
+       * gssapi_locl.h: add prototypes for gss_oid_equal and
+       gss_verify_mic_internal
+
+       * gssapi.h: comment out the argument names
+       
+2003-03-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gssapi.3: add LIST OF FUNCTIONS and copyright/license
+
+       * Makefile.am: s/gss_aquire_cred.3/gss_acquire_cred.3/
+       
+       * Makefile.am: man_MANS += gss_aquire_cred.3
+       
+2003-03-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gss_aquire_cred.3: the gssapi api manpage
+       
+2003-03-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * inquire_context.c: (gss_inquire_context): rename argument open
+       to open_context
+
+       * gssapi.h (gss_inquire_context): rename argument open to open_context
+
+2003-02-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_sec_context.c (do_delegation): remove unused variable
+       subkey
+
+       * gssapi.3: all 0.5.x version had broken token delegation
+       
+2003-02-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * (init_auth): only generate one subkey
+
+2003-01-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * verify_mic.c (verify_mic_des3): fix 3des verify_mic to conform
+       to rfc (and mit kerberos), provide backward compat hook
+       
+       * get_mic.c (mic_des3): fix 3des get_mic to conform to rfc (and
+       mit kerberos), provide backward compat hook
+       
+       * init_sec_context.c (init_auth): check if we need compat for
+       older get_mic/verify_mic
+
+       * gssapi_locl.h: add prototype for _gss_DES3_get_mic_compat
+       
+       * gssapi.h (more_flags): add COMPAT_OLD_DES3
+       
+       * Makefile.am: add gssapi.3 and compat.c
+       
+       * gssapi.3: add gssapi COMPATIBILITY documentation
+       
+       * accept_sec_context.c (gss_accept_sec_context): check if we need
+       compat for older get_mic/verify_mic
+
+       * compat.c: check for compatiblity with other heimdal's 3des
+       get_mic/verify_mic
+
+2002-10-31  Johan Danielsson  <joda@pdc.kth.se>
+
+       * check return value from gssapi_krb5_init
+       
+       * 8003.c (gssapi_krb5_verify_8003_checksum): check size of input
+
+2002-09-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * wrap.c (wrap_des3): use ETYPE_DES3_CBC_NONE
+
+       * unwrap.c (unwrap_des3): use ETYPE_DES3_CBC_NONE
+
+2002-09-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * init_sec_context.c: we need to generate a local subkey here
+
+2002-08-20  Jacques Vidrine <n@nectar.com>
+
+       * acquire_cred.c, inquire_cred.c, release_cred.c: Use default
+         credential resolution if gss_acquire_cred is called with
+         GSS_C_NO_NAME.
+
+2002-06-20  Jacques Vidrine <n@nectar.com>
+
+       * import_name.c: Compare name types by value if pointers do
+         not match.  Reported by: "Douglas E. Engert" <deengert@anl.gov>
+
+2002-05-20  Jacques Vidrine <n@nectar.com>
+
+       * verify_mic.c (gss_verify_mic), unwrap.c (gss_unwrap): initialize
+         the qop_state parameter.  from Doug Rabson <dfr@nlsystems.com>
+
+2002-05-09  Jacques Vidrine <n@nectar.com>
+
+       * acquire_cred.c: handle GSS_C_INITIATE/GSS_C_ACCEPT/GSS_C_BOTH
+
+2002-05-08  Jacques Vidrine <n@nectar.com>
+
+       * acquire_cred.c: initialize gssapi; handle null desired_name
+
+2002-03-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: remove non-functional stuff accidentally committed
+
+2002-03-11  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): bump version to 3:5:2
+       * 8003.c (gssapi_krb5_verify_8003_checksum): handle zero channel
+       bindings
+
+2001-10-31  Jacques Vidrine <n@nectar.com>
+
+       * get_mic.c (mic_des3): MIC computation using DES3/SHA1
+       was bogusly appending the message buffer to the result,
+       overwriting a heap buffer in the process.
+
+2001-08-29  Assar Westerlund  <assar@sics.se>
+
+       * 8003.c (gssapi_krb5_verify_8003_checksum,
+       gssapi_krb5_create_8003_checksum): make more consistent by always
+       returning an gssapi error and setting minor status.  update
+       callers
+
+2001-08-28  Jacques Vidrine  <n@nectar.com>
+
+       * accept_sec_context.c: Create a cache for delegated credentials
+         when needed.
+
+2001-08-28  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): set version to 3:4:2
+
+2001-08-23  Assar Westerlund  <assar@sics.se>
+
+       *  *.c: handle minor_status more consistently
+
+       * display_status.c (gss_display_status): handle krb5_get_err_text
+       failing
+
+2001-08-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * gssapi_locl.h: fix prototype for gssapi_krb5_init
+
+2001-08-13  Johan Danielsson  <joda@pdc.kth.se>
+
+       * accept_sec_context.c (gsskrb5_register_acceptor_identity): init
+       context and check return value from kt_resolve
+
+       * init.c: return error code
+
+2001-07-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): update to 3:3:2
+
+2001-07-12  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LIBADD): add required library
+       dependencies
+
+2001-07-06  Assar Westerlund  <assar@sics.se>
+
+       * accept_sec_context.c (gsskrb5_register_acceptor_identity): set
+       the keytab to be used for gss_acquire_cred too'
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): set version to 3:2:2
+
+2001-06-18  Assar Westerlund  <assar@sics.se>
+
+       * wrap.c: replace gss_krb5_getsomekey with gss_krb5_get_localkey
+       and gss_krb5_get_remotekey
+       * verify_mic.c: update krb5_auth_con function names use
+       gss_krb5_get_remotekey
+       * unwrap.c: replace gss_krb5_getsomekey with gss_krb5_get_localkey
+       and gss_krb5_get_remotekey
+       * gssapi_locl.h (gss_krb5_get_remotekey, gss_krb5_get_localkey):
+       add prototypes
+       * get_mic.c: update krb5_auth_con function names. use
+       gss_krb5_get_localkey
+       * accept_sec_context.c: update krb5_auth_con function names
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 3:1:2
+
+2001-05-14  Assar Westerlund  <assar@sics.se>
+
+       * address_to_krb5addr.c: adapt to new address functions
+
+2001-05-11  Assar Westerlund  <assar@sics.se>
+
+       * try to return the error string from libkrb5 where applicable
+
+2001-05-08  Assar Westerlund  <assar@sics.se>
+
+       * delete_sec_context.c (gss_delete_sec_context): remember to free
+       the memory used by the ticket itself. from <tmartin@mirapoint.com>
+
+2001-05-04  Assar Westerlund  <assar@sics.se>
+
+       * gssapi_locl.h: add config.h for completeness
+       * gssapi.h: remove config.h, this is an installed header file
+       sys/types.h is not needed either
+       
+2001-03-12  Assar Westerlund  <assar@sics.se>
+
+       * acquire_cred.c (gss_acquire_cred): remove memory leaks.  from
+       Jason R Thorpe <thorpej@zembu.com>
+
+2001-02-18  Assar Westerlund  <assar@sics.se>
+
+       * accept_sec_context.c (gss_accept_sec_context): either return
+       gss_name NULL-ed or set
+
+       * import_name.c: set minor_status in some cases where it was not
+       done
+
+2001-02-15  Assar Westerlund  <assar@sics.se>
+
+       * wrap.c: use krb5_generate_random_block for the confounders
+
+2001-01-30  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): bump version to 3:0:2
+       * acquire_cred.c, init_sec_context.c, release_cred.c: add support
+       for getting creds from a keytab, from fvdl@netbsd.org
+
+       * copy_ccache.c: add gss_krb5_copy_ccache
+
+2001-01-27  Assar Westerlund  <assar@sics.se>
+
+       * get_mic.c: cast parameters to des function to non-const pointers
+       to handle the case where these functions actually take non-const
+       des_cblock *
+
+2001-01-09  Assar Westerlund  <assar@sics.se>
+
+       * accept_sec_context.c (gss_accept_sec_context): use krb5_rd_cred2
+       instead of krb5_rd_cred
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): bump to 2:3:1
+
+2000-12-08  Assar Westerlund  <assar@sics.se>
+
+       * wrap.c (wrap_des3): use the checksum as ivec when encrypting the
+       sequence number
+       * unwrap.c (unwrap_des3): use the checksum as ivec when encrypting
+       the sequence number
+       * init_sec_context.c (init_auth): always zero fwd_data
+
+2000-12-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * accept_sec_context.c: de-pointerise auth_context parameter to
+       krb5_mk_rep
+
+2000-11-15  Assar Westerlund  <assar@sics.se>
+
+       * init_sec_context.c (init_auth): update to new
+       krb5_build_authenticator
+
+2000-09-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): bump to 2:2:1
+
+2000-08-27  Assar Westerlund  <assar@sics.se>
+
+       * init_sec_context.c: actually pay attention to `time_req'
+       * init_sec_context.c: re-organize.  leak less memory.
+       * gssapi_locl.h (gssapi_krb5_encapsulate, gss_krb5_getsomekey):
+       update prototypes add assert.h
+       * gssapi.h (GSS_KRB5_CONF_C_QOP_DES, GSS_KRB5_CONF_C_QOP_DES3_KD):
+       add
+       * verify_mic.c: re-organize and add 3DES code
+       * wrap.c: re-organize and add 3DES code
+       * unwrap.c: re-organize and add 3DES code
+       * get_mic.c: re-organize and add 3DES code
+       * encapsulate.c (gssapi_krb5_encapsulate): do not free `in_data',
+       let the caller do that.  fix the callers.
+
+2000-08-16  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 2:1:1
+
+2000-07-29  Assar Westerlund  <assar@sics.se>
+
+       * decapsulate.c (gssapi_krb5_verify_header): sanity-check length
+
+2000-07-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: bump version to 2:0:1
+
+2000-07-22  Assar Westerlund  <assar@sics.se>
+
+       * gssapi.h: update OID for GSS_C_NT_HOSTBASED_SERVICE and other
+       details from rfc2744
+
+2000-06-29  Assar Westerlund  <assar@sics.se>
+
+       * address_to_krb5addr.c (gss_address_to_krb5addr): actually use
+       `int' instead of `sa_family_t' for the address family.
+
+2000-06-21  Assar Westerlund  <assar@sics.se>
+
+       * add support for token delegation.  From Daniel Kouril
+       <kouril@ics.muni.cz> and Miroslav Ruda <ruda@ics.muni.cz>
+
+2000-05-15  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libgssapi_la_LDFLAGS): set version to 1:1:1
+
+2000-04-12  Assar Westerlund  <assar@sics.se>
+
+       * release_oid_set.c (gss_release_oid_set): clear set for
+       robustness.  From GOMBAS Gabor <gombasg@inf.elte.hu>
+       * release_name.c (gss_release_name): reset input_name for
+       robustness.  From GOMBAS Gabor <gombasg@inf.elte.hu>
+       * release_buffer.c (gss_release_buffer): set value to NULL to be
+       more robust.  From GOMBAS Gabor <gombasg@inf.elte.hu>
+       * add_oid_set_member.c (gss_add_oid_set_member): actually check if
+       the oid is a member first.  leave the oid_set unchanged if realloc
+       fails.
+
+2000-02-13  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 1:0:1
+
+2000-02-12  Assar Westerlund  <assar@sics.se>
+
+       * gssapi_locl.h: add flags for import/export
+       * import_sec_context.c (import_sec_context: add flags for what
+       fields are included.  do not include the authenticator for now.
+       * export_sec_context.c (export_sec_context: add flags for what
+       fields are included.  do not include the authenticator for now.
+       * accept_sec_context.c (gss_accept_sec_context): set target in
+       context_handle
+
+2000-02-11  Assar Westerlund  <assar@sics.se>
+
+       * delete_sec_context.c (gss_delete_sec_context): set context to
+       GSS_C_NO_CONTEXT
+
+       * Makefile.am: add {export,import}_sec_context.c
+       * export_sec_context.c: new file
+       * import_sec_context.c: new file
+       * accept_sec_context.c (gss_accept_sec_context): set trans flag
+
+2000-02-07  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 0:5:0
+
+2000-01-26  Assar Westerlund  <assar@sics.se>
+
+       * delete_sec_context.c (gss_delete_sec_context): handle a NULL
+       output_token
+
+       * wrap.c: update to pseudo-standard APIs for md4,md5,sha.  some
+       changes to libdes calls to make them more portable.
+       * verify_mic.c: update to pseudo-standard APIs for md4,md5,sha.
+       some changes to libdes calls to make them more portable.
+       * unwrap.c: update to pseudo-standard APIs for md4,md5,sha.  some
+       changes to libdes calls to make them more portable.
+       * get_mic.c: update to pseudo-standard APIs for md4,md5,sha.  some
+       changes to libdes calls to make them more portable.
+       * 8003.c: update to pseudo-standard APIs for md4,md5,sha.
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 0:4:0
+
+1999-12-26  Assar Westerlund  <assar@sics.se>
+
+       * accept_sec_context.c (gss_accept_sec_context): always set
+       `output_token'
+       * init_sec_context.c (init_auth): always initialize `output_token'
+       * delete_sec_context.c (gss_delete_sec_context): always set
+       `output_token'
+
+1999-12-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 0:3:0
+
+1999-10-20  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 0:2:0
+
+1999-09-21  Assar Westerlund  <assar@sics.se>
+
+       * init_sec_context.c (gss_init_sec_context): initialize `ticket'
+
+       * gssapi.h (gss_ctx_id_t_desc): add ticket in here.  ick.
+
+       * delete_sec_context.c (gss_delete_sec_context): free ticket
+
+       * accept_sec_context.c (gss_accept_sec_context): stove away
+       `krb5_ticket' in context so that ugly programs such as
+       gss_nt_server can get at it.  uck.
+
+1999-09-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * accept_sec_context.c: set minor_status
+
+1999-08-04  Assar Westerlund  <assar@sics.se>
+
+       * display_status.c (calling_error, routine_error): right shift the
+       code to make it possible to index into the arrays
+
+1999-07-28  Assar Westerlund  <assar@sics.se>
+
+       * gssapi.h (GSS_C_AF_INET6): add
+
+       * import_name.c (import_hostbased_name): set minor_status
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 0:1:0
+
+Wed Apr  7 14:05:15 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * display_status.c: set minor_status
+
+       * init_sec_context.c: set minor_status
+
+       * lib/gssapi/init.c: remove donep (check gssapi_krb5_context
+       directly)
+
diff --git a/src/kerberosV/src/lib/gssapi/accept_sec_context.c b/src/kerberosV/src/lib/gssapi/accept_sec_context.c
new file mode 100644 (file)
index 0000000..8a84b69
--- /dev/null
@@ -0,0 +1,974 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: accept_sec_context.c,v 1.53 2005/05/29 15:12:41 lha Exp $");
+
+HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;
+krb5_keytab gssapi_krb5_keytab;
+
+OM_uint32
+gsskrb5_register_acceptor_identity (const char *identity)
+{
+    krb5_error_code ret;
+
+    ret = gssapi_krb5_init();
+    if(ret)
+       return GSS_S_FAILURE;
+    
+    HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);
+
+    if(gssapi_krb5_keytab != NULL) {
+       krb5_kt_close(gssapi_krb5_context, gssapi_krb5_keytab);
+       gssapi_krb5_keytab = NULL;
+    }
+    if (identity == NULL) {
+       ret = krb5_kt_default(gssapi_krb5_context, &gssapi_krb5_keytab);
+    } else {
+       char *p;
+
+       asprintf(&p, "FILE:%s", identity);
+       if(p == NULL) {
+           HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
+           return GSS_S_FAILURE;
+       }
+       ret = krb5_kt_resolve(gssapi_krb5_context, p, &gssapi_krb5_keytab);
+       free(p);
+    }
+    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
+    if(ret)
+       return GSS_S_FAILURE;
+    return GSS_S_COMPLETE;
+}
+
+void
+gsskrb5_is_cfx(gss_ctx_id_t context_handle, int *is_cfx)
+{
+    krb5_keyblock *key;
+    int acceptor = (context_handle->more_flags & LOCAL) == 0;
+
+    if (acceptor) {
+       if (context_handle->auth_context->local_subkey)
+           key = context_handle->auth_context->local_subkey;
+       else
+           key = context_handle->auth_context->remote_subkey;
+    } else {
+       if (context_handle->auth_context->remote_subkey)
+           key = context_handle->auth_context->remote_subkey;
+       else
+           key = context_handle->auth_context->local_subkey;
+    }
+    if (key == NULL)
+       key = context_handle->auth_context->keyblock;
+
+    if (key == NULL)
+       return;
+           
+    switch (key->keytype) {
+    case ETYPE_DES_CBC_CRC:
+    case ETYPE_DES_CBC_MD4:
+    case ETYPE_DES_CBC_MD5:
+    case ETYPE_DES3_CBC_MD5:
+    case ETYPE_DES3_CBC_SHA1:
+    case ETYPE_ARCFOUR_HMAC_MD5:
+    case ETYPE_ARCFOUR_HMAC_MD5_56:
+       break;
+    default :
+       *is_cfx = 1;
+       if ((acceptor && context_handle->auth_context->local_subkey) ||
+           (!acceptor && context_handle->auth_context->remote_subkey))
+           context_handle->more_flags |= ACCEPTOR_SUBKEY;
+       break;
+    }
+}
+
+
+static OM_uint32
+gsskrb5_accept_delegated_token
+           (OM_uint32 * minor_status,
+            gss_ctx_id_t * context_handle,
+           krb5_data *fwd_data,
+           OM_uint32 *flags,
+           krb5_principal principal,
+            gss_cred_id_t * delegated_cred_handle
+          )
+{
+    krb5_ccache ccache = NULL;
+    krb5_error_code kret;
+    int32_t ac_flags, ret;
+    gss_cred_id_t handle = NULL;
+      
+    if (delegated_cred_handle == NULL) {
+       /* XXX Create a new delegated_cred_handle? */
+
+       ret = 0;
+
+       kret = krb5_cc_default (gssapi_krb5_context, &ccache);
+       if (kret) {
+           *flags &= ~GSS_C_DELEG_FLAG;
+           goto end_fwd;
+       }
+    } else {
+
+       *delegated_cred_handle = NULL;
+       
+       handle = calloc(1, sizeof(*handle));
+       if (handle == NULL) {
+           ret = GSS_S_FAILURE;
+           *minor_status = ENOMEM;
+           krb5_set_error_string(gssapi_krb5_context, "out of memory");
+           gssapi_krb5_set_error_string();
+           *flags &= ~GSS_C_DELEG_FLAG;
+           goto end_fwd;
+       }
+       if ((ret = gss_duplicate_name(minor_status, principal,
+                                     &handle->principal)) != 0) {
+           *flags &= ~GSS_C_DELEG_FLAG;
+           ret = 0;
+           goto end_fwd;
+       }
+       kret = krb5_cc_gen_new (gssapi_krb5_context,
+                               &krb5_mcc_ops,
+                               &handle->ccache);
+       if (kret) {
+           *flags &= ~GSS_C_DELEG_FLAG;
+           ret = 0;
+           goto end_fwd;
+       }
+       ccache = handle->ccache;
+
+       ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
+       if (ret) {
+           *flags &= ~GSS_C_DELEG_FLAG;
+           goto end_fwd;
+       }
+       ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
+                                    &handle->mechanisms);
+       if (ret) {
+           *flags &= ~GSS_C_DELEG_FLAG;
+           goto end_fwd;
+       }
+    }
+
+    kret = krb5_cc_initialize(gssapi_krb5_context, ccache, principal);
+    if (kret) {
+       *flags &= ~GSS_C_DELEG_FLAG;
+       ret = 0;
+       goto end_fwd;
+    }
+      
+    krb5_auth_con_removeflags(gssapi_krb5_context,
+                             (*context_handle)->auth_context,
+                             KRB5_AUTH_CONTEXT_DO_TIME,
+                             &ac_flags);
+    kret = krb5_rd_cred2(gssapi_krb5_context,
+                        (*context_handle)->auth_context,
+                        ccache,
+                        fwd_data);
+    if (kret)
+       gssapi_krb5_set_error_string();
+    krb5_auth_con_setflags(gssapi_krb5_context,
+                          (*context_handle)->auth_context,
+                          ac_flags);
+    if (kret) {
+       *flags &= ~GSS_C_DELEG_FLAG;
+       ret = GSS_S_FAILURE;
+       *minor_status = kret;
+       goto end_fwd;
+    }
+ end_fwd:
+    /* if there was some kind of failure, clean up internal structures */
+    if ((*flags & GSS_C_DELEG_FLAG) == 0) {
+       if (handle) {
+           if (handle->principal)
+               gss_release_name(minor_status, &handle->principal);
+           if (handle->mechanisms)
+               gss_release_oid_set(NULL, &handle->mechanisms);
+           if (handle->ccache)
+               krb5_cc_destroy(gssapi_krb5_context, handle->ccache);
+           free(handle);
+           handle = NULL;
+       }
+    }
+    if (delegated_cred_handle == NULL) {
+       if (ccache)
+           krb5_cc_close(gssapi_krb5_context, ccache);
+    }
+    if (handle)
+       *delegated_cred_handle = handle;
+
+    return ret;
+}
+
+
+static OM_uint32
+gsskrb5_accept_sec_context
+           (OM_uint32 * minor_status,
+            gss_ctx_id_t * context_handle,
+            const gss_cred_id_t acceptor_cred_handle,
+            const gss_buffer_t input_token_buffer,
+            const 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 kret;
+    OM_uint32 ret = GSS_S_COMPLETE;
+    krb5_data indata;
+    krb5_flags ap_options;
+    OM_uint32 flags;
+    krb5_ticket *ticket = NULL;
+    krb5_keytab keytab = NULL;
+    krb5_data fwd_data;
+    OM_uint32 minor;
+    int is_cfx = 0;
+
+    GSSAPI_KRB5_INIT();
+
+    krb5_data_zero (&fwd_data);
+    output_token->length = 0;
+    output_token->value = NULL;
+
+    if (src_name != NULL)
+       *src_name = NULL;
+    if (mech_type)
+       *mech_type = GSS_KRB5_MECHANISM;
+
+    if (*context_handle == GSS_C_NO_CONTEXT) {
+       *context_handle = malloc(sizeof(**context_handle));
+       if (*context_handle == GSS_C_NO_CONTEXT) {
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+    }
+
+    HEIMDAL_MUTEX_init(&(*context_handle)->ctx_id_mutex);
+    (*context_handle)->auth_context =  NULL;
+    (*context_handle)->source = NULL;
+    (*context_handle)->target = NULL;
+    (*context_handle)->flags = 0;
+    (*context_handle)->more_flags = 0;
+    (*context_handle)->ticket = NULL;
+    (*context_handle)->lifetime = GSS_C_INDEFINITE;
+    (*context_handle)->order = NULL;
+
+    kret = krb5_auth_con_init (gssapi_krb5_context,
+                              &(*context_handle)->auth_context);
+    if (kret) {
+       ret = GSS_S_FAILURE;
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       goto failure;
+    }
+
+    if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS
+       && input_chan_bindings->application_data.length ==
+       2 * sizeof((*context_handle)->auth_context->local_port)
+       ) {
+     
+       /* Port numbers are expected to be in application_data.value,
+        * initator's port first */
+     
+       krb5_address initiator_addr, acceptor_addr;
+     
+       memset(&initiator_addr, 0, sizeof(initiator_addr));
+       memset(&acceptor_addr, 0, sizeof(acceptor_addr));
+
+       (*context_handle)->auth_context->remote_port = 
+           *(int16_t *) input_chan_bindings->application_data.value; 
+     
+       (*context_handle)->auth_context->local_port =
+           *((int16_t *) input_chan_bindings->application_data.value + 1);
+
+     
+       kret = gss_address_to_krb5addr(input_chan_bindings->acceptor_addrtype,
+                                      &input_chan_bindings->acceptor_address,
+                                      (*context_handle)->auth_context->local_port,
+                                      &acceptor_addr); 
+       if (kret) {
+           gssapi_krb5_set_error_string ();
+           ret = GSS_S_BAD_BINDINGS;
+           *minor_status = kret;
+           goto failure;
+       }
+                             
+       kret = gss_address_to_krb5addr(input_chan_bindings->initiator_addrtype,
+                                      &input_chan_bindings->initiator_address, 
+                                      (*context_handle)->auth_context->remote_port,
+                                      &initiator_addr); 
+       if (kret) {
+           krb5_free_address (gssapi_krb5_context, &acceptor_addr);
+           gssapi_krb5_set_error_string ();
+           ret = GSS_S_BAD_BINDINGS;
+           *minor_status = kret;
+           goto failure;
+       }
+     
+       kret = krb5_auth_con_setaddrs(gssapi_krb5_context,
+                                     (*context_handle)->auth_context,
+                                     &acceptor_addr,    /* local address */
+                                     &initiator_addr);  /* remote address */
+     
+       krb5_free_address (gssapi_krb5_context, &initiator_addr);
+       krb5_free_address (gssapi_krb5_context, &acceptor_addr);
+     
+#if 0
+       free(input_chan_bindings->application_data.value);
+       input_chan_bindings->application_data.value = NULL;
+       input_chan_bindings->application_data.length = 0;
+#endif
+     
+       if (kret) {
+           gssapi_krb5_set_error_string ();
+           ret = GSS_S_BAD_BINDINGS;
+           *minor_status = kret;
+           goto failure;
+       }
+    }
+  
+    krb5_auth_con_addflags(gssapi_krb5_context,
+                          (*context_handle)->auth_context,
+                          KRB5_AUTH_CONTEXT_DO_SEQUENCE,
+                          NULL);
+
+    ret = gssapi_krb5_decapsulate (minor_status,
+                                  input_token_buffer,
+                                  &indata,
+                                  "\x01\x00",
+                                  GSS_KRB5_MECHANISM);
+    if (ret)
+       goto failure;
+
+    HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);
+
+    if (acceptor_cred_handle == GSS_C_NO_CREDENTIAL) {
+       if (gssapi_krb5_keytab != NULL) {
+           keytab = gssapi_krb5_keytab;
+       }
+    } else if (acceptor_cred_handle->keytab != NULL) {
+       keytab = acceptor_cred_handle->keytab;
+    }
+
+    kret = krb5_rd_req (gssapi_krb5_context,
+                       &(*context_handle)->auth_context,
+                       &indata,
+                       (acceptor_cred_handle == GSS_C_NO_CREDENTIAL) ? NULL 
+                       : acceptor_cred_handle->principal,
+                       keytab,
+                       &ap_options,
+                       &ticket);
+
+    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
+
+    if (kret) {
+       ret = GSS_S_FAILURE;
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       goto failure;
+    }
+
+    kret = krb5_copy_principal (gssapi_krb5_context,
+                               ticket->client,
+                               &(*context_handle)->source);
+    if (kret) {
+       ret = GSS_S_FAILURE;
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       goto failure;
+    }
+
+    kret = krb5_copy_principal (gssapi_krb5_context,
+                               ticket->server,
+                               &(*context_handle)->target);
+    if (kret) {
+       ret = GSS_S_FAILURE;
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       goto failure;
+    }
+
+    ret = _gss_DES3_get_mic_compat(minor_status, *context_handle);
+    if (ret)
+       goto failure;
+
+    if (src_name != NULL) {
+       kret = krb5_copy_principal (gssapi_krb5_context,
+                                   ticket->client,
+                                   src_name);
+       if (kret) {
+           ret = GSS_S_FAILURE;
+           *minor_status = kret;
+           gssapi_krb5_set_error_string ();
+           goto failure;
+       }
+    }
+
+    {
+       krb5_authenticator authenticator;
+      
+       kret = krb5_auth_con_getauthenticator(gssapi_krb5_context,
+                                             (*context_handle)->auth_context,
+                                             &authenticator);
+       if(kret) {
+           ret = GSS_S_FAILURE;
+           *minor_status = kret;
+           gssapi_krb5_set_error_string ();
+           goto failure;
+       }
+
+       ret = gssapi_krb5_verify_8003_checksum(minor_status,
+                                              input_chan_bindings,
+                                              authenticator->cksum,
+                                              &flags,
+                                              &fwd_data);
+       krb5_free_authenticator(gssapi_krb5_context, &authenticator);
+       if (ret)
+           goto failure;
+    }
+
+    flags |= GSS_C_TRANS_FLAG;
+
+    if (ret_flags)
+       *ret_flags = flags;
+    (*context_handle)->lifetime = ticket->ticket.endtime;
+    (*context_handle)->flags = flags;
+    (*context_handle)->more_flags |= OPEN;
+
+    if (mech_type)
+       *mech_type = GSS_KRB5_MECHANISM;
+
+    if (time_rec) {
+       ret = gssapi_lifetime_left(minor_status,
+                                  (*context_handle)->lifetime,
+                                  time_rec);
+       if (ret)
+           goto failure;
+    }
+
+    gsskrb5_is_cfx(*context_handle, &is_cfx);
+
+    if(flags & GSS_C_MUTUAL_FLAG) {
+       krb5_data outbuf;
+
+       if (is_cfx != 0
+           || (ap_options & AP_OPTS_USE_SUBKEY)) {
+           kret = krb5_auth_con_addflags(gssapi_krb5_context,
+                                         (*context_handle)->auth_context,
+                                         KRB5_AUTH_CONTEXT_USE_SUBKEY,
+                                         NULL);
+           (*context_handle)->more_flags |= ACCEPTOR_SUBKEY;
+       }
+
+       kret = krb5_mk_rep (gssapi_krb5_context,
+                           (*context_handle)->auth_context,
+                           &outbuf);
+       if (kret) {
+           ret = GSS_S_FAILURE;
+           *minor_status = kret;
+           gssapi_krb5_set_error_string ();
+           goto failure;
+       }
+       ret = gssapi_krb5_encapsulate (minor_status,
+                                      &outbuf,
+                                      output_token,
+                                      "\x02\x00",
+                                      GSS_KRB5_MECHANISM);
+       krb5_data_free (&outbuf);
+       if (ret)
+           goto failure;
+    }
+
+    (*context_handle)->ticket = ticket;
+
+    {
+       int32_t seq_number;
+       
+       krb5_auth_getremoteseqnumber (gssapi_krb5_context,
+                                     (*context_handle)->auth_context,
+                                     &seq_number);
+       ret = _gssapi_msg_order_create(minor_status,
+                                      &(*context_handle)->order,
+                                      _gssapi_msg_order_f(flags),
+                                      seq_number, 0, is_cfx);
+       if (ret)
+           goto failure;
+       
+       if ((flags & GSS_C_MUTUAL_FLAG) == 0 && _gssapi_msg_order_f(flags)) {
+           krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                                            (*context_handle)->auth_context,
+                                            seq_number);
+       }
+    }
+
+    if (fwd_data.length > 0) {
+
+       if (flags & GSS_C_DELEG_FLAG) {
+           ret = gsskrb5_accept_delegated_token(minor_status,
+                                                context_handle,
+                                                &fwd_data,
+                                                &flags,
+                                                ticket->client,
+                                                delegated_cred_handle);
+           if (ret)
+               goto failure;
+       }
+       free(fwd_data.data);
+       krb5_data_zero(&fwd_data);
+    }
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+
+ failure:
+    if (fwd_data.length > 0)
+       free(fwd_data.data);
+    if (ticket != NULL)
+       krb5_free_ticket (gssapi_krb5_context, ticket);
+    krb5_auth_con_free (gssapi_krb5_context,
+                       (*context_handle)->auth_context);
+    if((*context_handle)->source)
+       krb5_free_principal (gssapi_krb5_context,
+                            (*context_handle)->source);
+    if((*context_handle)->target)
+       krb5_free_principal (gssapi_krb5_context,
+                            (*context_handle)->target);
+    if((*context_handle)->order)
+       _gssapi_msg_order_destroy(&(*context_handle)->order);
+    HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex);
+    free (*context_handle);
+    if (src_name != NULL) {
+       gss_release_name (&minor, src_name);
+       *src_name = NULL;
+    }
+    *context_handle = GSS_C_NO_CONTEXT;
+    return ret;
+}
+
+static OM_uint32
+code_NegTokenArg(OM_uint32 *minor_status,
+                const NegTokenTarg *targ,
+                krb5_data *data,
+                u_char **ret_buf)
+{
+    OM_uint32 ret;
+    u_char *buf;
+    size_t buf_size, buf_len;
+
+    buf_size = 1024;
+    buf = malloc(buf_size);
+    if (buf == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    do {
+       ret = encode_NegTokenTarg(buf + buf_size - 1,
+                                 buf_size,
+                                 targ, &buf_len);
+       if (ret == 0) {
+           size_t tmp;
+
+           ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
+                                        buf_size - buf_len,
+                                        buf_len,
+                                        ASN1_C_CONTEXT,
+                                        CONS,
+                                        1,
+                                        &tmp);
+           if (ret == 0)
+               buf_len += tmp;
+       }
+       if (ret) {
+           if (ret == ASN1_OVERFLOW) {
+               u_char *tmp;
+
+               buf_size *= 2;
+               tmp = realloc (buf, buf_size);
+               if (tmp == NULL) {
+                   *minor_status = ENOMEM;
+                   free(buf);
+                   return GSS_S_FAILURE;
+               }
+               buf = tmp;
+           } else {
+               *minor_status = ret;
+               free(buf);
+               return GSS_S_FAILURE;
+           }
+       }
+    } while (ret == ASN1_OVERFLOW);
+
+    data->data   = buf + buf_size - buf_len;
+    data->length = buf_len;
+    *ret_buf     = buf;
+    return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+send_reject (OM_uint32 *minor_status,
+            gss_buffer_t output_token)
+{
+    NegTokenTarg targ;
+    krb5_data data;
+    u_char *buf;
+    OM_uint32 ret;
+
+    ALLOC(targ.negResult, 1);
+    if (targ.negResult == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    *(targ.negResult) = reject;
+    targ.supportedMech = NULL;
+    targ.responseToken = NULL;
+    targ.mechListMIC   = NULL;
+    
+    ret = code_NegTokenArg (minor_status, &targ, &data, &buf);
+    free_NegTokenTarg(&targ);
+    if (ret)
+       return ret;
+
+#if 0
+    ret = _gssapi_encapsulate(minor_status,
+                             &data,
+                             output_token,
+                             GSS_SPNEGO_MECHANISM);
+#else
+    output_token->value = malloc(data.length);
+    if (output_token->value == NULL) {
+       *minor_status = ENOMEM;
+       ret = GSS_S_FAILURE;
+    } else {
+       output_token->length = data.length;
+       memcpy(output_token->value, data.data, output_token->length);
+    }
+#endif
+    free(buf);
+    if (ret)
+       return ret;
+    return GSS_S_BAD_MECH;
+}
+
+static OM_uint32
+send_accept (OM_uint32 *minor_status,
+            OM_uint32 major_status,
+            gss_buffer_t output_token,
+            gss_buffer_t mech_token,
+            gss_ctx_id_t context_handle,
+            const MechTypeList *mechtypelist)
+{
+    NegTokenTarg targ;
+    krb5_data data;
+    u_char *buf;
+    OM_uint32 ret;
+    gss_buffer_desc mech_buf, mech_mic_buf;
+    krb5_boolean require_mic;
+
+    memset(&targ, 0, sizeof(targ));
+    ALLOC(targ.negResult, 1);
+    if (targ.negResult == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    *(targ.negResult) = accept_completed;
+
+    ALLOC(targ.supportedMech, 1);
+    if (targ.supportedMech == NULL) {
+       free_NegTokenTarg(&targ);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    ret = der_get_oid(GSS_KRB5_MECHANISM->elements,
+                     GSS_KRB5_MECHANISM->length,
+                     targ.supportedMech,
+                     NULL);
+    if (ret) {
+       free_NegTokenTarg(&targ);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    if (mech_token != NULL && mech_token->length != 0) {
+       ALLOC(targ.responseToken, 1);
+       if (targ.responseToken == NULL) {
+           free_NegTokenTarg(&targ);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       targ.responseToken->length = mech_token->length;
+       targ.responseToken->data   = mech_token->value;
+       mech_token->length = 0;
+       mech_token->value  = NULL;
+    } else {
+       targ.responseToken = NULL;
+    }
+
+    ret = _gss_spnego_require_mechlist_mic(minor_status, context_handle,
+                                          &require_mic);
+    if (ret) {
+       free_NegTokenTarg(&targ);
+       return ret;
+    }
+
+    if (major_status == GSS_S_COMPLETE && require_mic) {
+       size_t buf_len;
+
+       ALLOC(targ.mechListMIC, 1);
+       if (targ.mechListMIC == NULL) {
+           free_NegTokenTarg(&targ);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       
+       ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length,
+                          mechtypelist, &buf_len, ret);
+       if (ret) {
+           free_NegTokenTarg(&targ);
+           return ret;
+       }
+       if (mech_buf.length != buf_len)
+           abort();
+
+       ret = gss_get_mic(minor_status, context_handle, 0, &mech_buf,
+                         &mech_mic_buf);
+       free (mech_buf.value);
+       if (ret) {
+           free_NegTokenTarg(&targ);
+           return ret;
+       }
+
+       targ.mechListMIC->length = mech_mic_buf.length;
+       targ.mechListMIC->data   = mech_mic_buf.value;
+    } else
+       targ.mechListMIC = NULL;
+
+    ret = code_NegTokenArg (minor_status, &targ, &data, &buf);
+    free_NegTokenTarg(&targ);
+    if (ret)
+       return ret;
+
+#if 0
+    ret = _gssapi_encapsulate(minor_status,
+                             &data,
+                             output_token,
+                             GSS_SPNEGO_MECHANISM);
+#else
+    output_token->value = malloc(data.length);
+    if (output_token->value == NULL) {
+       *minor_status = ENOMEM;
+       ret = GSS_S_FAILURE;
+    } else {
+       output_token->length = data.length;
+       memcpy(output_token->value, data.data, output_token->length);
+    }
+#endif
+    free(buf);
+    if (ret)
+       return ret;
+    return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+spnego_accept_sec_context
+           (OM_uint32 * minor_status,
+            gss_ctx_id_t * context_handle,
+            const gss_cred_id_t acceptor_cred_handle,
+            const gss_buffer_t input_token_buffer,
+            const 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, ret2;
+    NegTokenInit ni;
+    size_t ni_len;
+    int i;
+    int found = 0;
+    krb5_data data;
+    size_t len, taglen;
+
+    output_token->length = 0;
+    output_token->value  = NULL;
+
+    ret = _gssapi_decapsulate (minor_status,
+                              input_token_buffer,
+                              &data,
+                              GSS_SPNEGO_MECHANISM);
+    if (ret)
+       return ret;
+
+    ret = der_match_tag_and_length(data.data, data.length,
+                                  ASN1_C_CONTEXT, CONS, 0, &len, &taglen);
+    if (ret)
+       return ret;
+
+    if(len > data.length - taglen)
+       return ASN1_OVERRUN;
+
+    ret = decode_NegTokenInit((const char *)data.data + taglen, len,
+                             &ni, &ni_len);
+    if (ret)
+       return GSS_S_DEFECTIVE_TOKEN;
+
+    if (ni.mechTypes == NULL) {
+       free_NegTokenInit(&ni);
+       return send_reject (minor_status, output_token);
+    }
+
+    for (i = 0; !found && i < ni.mechTypes->len; ++i) {
+       char mechbuf[17];
+       size_t mech_len;
+
+       ret = der_put_oid (mechbuf + sizeof(mechbuf) - 1,
+                          sizeof(mechbuf),
+                          &ni.mechTypes->val[i],
+                          &mech_len);
+       if (ret) {
+           free_NegTokenInit(&ni);
+           return GSS_S_DEFECTIVE_TOKEN;
+       }
+       if (mech_len == GSS_KRB5_MECHANISM->length
+           && memcmp(GSS_KRB5_MECHANISM->elements,
+                     mechbuf + sizeof(mechbuf) - mech_len,
+                     mech_len) == 0)
+           found = 1;
+    }
+    if (found) {
+       gss_buffer_desc ibuf, obuf;
+       gss_buffer_t ot = NULL;
+       OM_uint32 minor;
+
+       if (ni.mechToken != NULL) {
+           ibuf.length = ni.mechToken->length;
+           ibuf.value  = ni.mechToken->data;
+
+           ret = gsskrb5_accept_sec_context(&minor,
+                                            context_handle,
+                                            acceptor_cred_handle,
+                                            &ibuf,
+                                            input_chan_bindings,
+                                            src_name,
+                                            mech_type,
+                                            &obuf,
+                                            ret_flags,
+                                            time_rec,
+                                            delegated_cred_handle);
+           if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) {
+               ot = &obuf;
+           } else {
+               free_NegTokenInit(&ni);
+               send_reject (minor_status, output_token);
+               return ret;
+           }
+       }
+       ret2 = send_accept (minor_status, ret, output_token, ot,
+                          *context_handle, ni.mechTypes);
+       if (ret2 != GSS_S_COMPLETE)
+           ret = ret2;
+       if (ot != NULL)
+           gss_release_buffer(&minor, ot);
+       free_NegTokenInit(&ni);
+       return ret;
+    } else {
+       free_NegTokenInit(&ni);
+       return send_reject (minor_status, output_token);
+    }
+}
+
+OM_uint32
+gss_accept_sec_context
+           (OM_uint32 * minor_status,
+            gss_ctx_id_t * context_handle,
+            const gss_cred_id_t acceptor_cred_handle,
+            const gss_buffer_t input_token_buffer,
+            const 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;
+    ssize_t mech_len;
+    const u_char *p;
+
+    *minor_status = 0;
+
+    mech_len = gssapi_krb5_get_mech (input_token_buffer->value,
+                                    input_token_buffer->length,
+                                    &p);
+    if (mech_len < 0)
+       return GSS_S_DEFECTIVE_TOKEN;
+    if (mech_len == GSS_KRB5_MECHANISM->length
+       && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_len) == 0)
+       ret = gsskrb5_accept_sec_context(minor_status,
+                                        context_handle,
+                                        acceptor_cred_handle,
+                                        input_token_buffer,
+                                        input_chan_bindings,
+                                        src_name,
+                                        mech_type,
+                                        output_token,
+                                        ret_flags,
+                                        time_rec,
+                                        delegated_cred_handle);
+    else if (mech_len == GSS_SPNEGO_MECHANISM->length
+            && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_len) == 0)
+       ret = spnego_accept_sec_context(minor_status,
+                                       context_handle,
+                                       acceptor_cred_handle,
+                                       input_token_buffer,
+                                       input_chan_bindings,
+                                       src_name,
+                                       mech_type,
+                                       output_token,
+                                       ret_flags,
+                                       time_rec,
+                                       delegated_cred_handle);
+    else
+       return GSS_S_BAD_MECH;
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/acquire_cred.c b/src/kerberosV/src/lib/gssapi/acquire_cred.c
new file mode 100644 (file)
index 0000000..59a016d
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: acquire_cred.c,v 1.22.4.1 2005/12/01 18:53:56 lha Exp $");
+
+static krb5_error_code
+get_keytab(krb5_keytab *keytab)
+{
+    char kt_name[256];
+    krb5_error_code kret;
+
+    HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex);
+
+    if (gssapi_krb5_keytab != NULL) {
+       kret = krb5_kt_get_name(gssapi_krb5_context,
+                               gssapi_krb5_keytab,
+                               kt_name, sizeof(kt_name));
+       if (kret == 0)
+           kret = krb5_kt_resolve(gssapi_krb5_context, kt_name, keytab);
+    } else
+       kret = krb5_kt_default(gssapi_krb5_context, keytab);
+
+    HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex);
+
+    return (kret);
+}
+
+static OM_uint32 acquire_initiator_cred
+                 (OM_uint32 * minor_status,
+                  const gss_name_t desired_name,
+                  OM_uint32 time_req,
+                  const gss_OID_set desired_mechs,
+                  gss_cred_usage_t cred_usage,
+                  gss_cred_id_t handle,
+                  gss_OID_set * actual_mechs,
+                  OM_uint32 * time_rec
+                 )
+{
+    OM_uint32 ret;
+    krb5_creds cred;
+    krb5_principal def_princ;
+    krb5_get_init_creds_opt *opt;
+    krb5_ccache ccache;
+    krb5_keytab keytab;
+    krb5_error_code kret;
+
+    keytab = NULL;
+    ccache = NULL;
+    def_princ = NULL;
+    ret = GSS_S_FAILURE;
+    memset(&cred, 0, sizeof(cred));
+
+    kret = krb5_cc_default(gssapi_krb5_context, &ccache);
+    if (kret)
+       goto end;
+    kret = krb5_cc_get_principal(gssapi_krb5_context, ccache,
+       &def_princ);
+    if (kret != 0) {
+       /* we'll try to use a keytab below */
+       krb5_cc_destroy(gssapi_krb5_context, ccache);
+       ccache = NULL;
+       kret = 0;
+    } else if (handle->principal == NULL)  {
+       kret = krb5_copy_principal(gssapi_krb5_context, def_princ,
+           &handle->principal);
+       if (kret)
+           goto end;
+    } else if (handle->principal != NULL &&
+       krb5_principal_compare(gssapi_krb5_context, handle->principal,
+       def_princ) == FALSE) {
+       /* Before failing, lets check the keytab */
+       krb5_free_principal(gssapi_krb5_context, def_princ);
+       def_princ = NULL;
+    }
+    if (def_princ == NULL) {
+       /* We have no existing credentials cache,
+        * so attempt to get a TGT using a keytab.
+        */
+       if (handle->principal == NULL) {
+           kret = krb5_get_default_principal(gssapi_krb5_context,
+               &handle->principal);
+           if (kret)
+               goto end;
+       }
+       kret = get_keytab(&keytab);
+       if (kret)
+           goto end;
+       kret = krb5_get_init_creds_opt_alloc(gssapi_krb5_context, &opt);
+       if (kret)
+           goto end;
+       kret = krb5_get_init_creds_keytab(gssapi_krb5_context, &cred,
+           handle->principal, keytab, 0, NULL, opt);
+       krb5_get_init_creds_opt_free(opt);
+       if (kret)
+           goto end;
+       kret = krb5_cc_gen_new(gssapi_krb5_context, &krb5_mcc_ops,
+               &ccache);
+       if (kret)
+           goto end;
+       kret = krb5_cc_initialize(gssapi_krb5_context, ccache, cred.client);
+       if (kret)
+           goto end;
+       kret = krb5_cc_store_cred(gssapi_krb5_context, ccache, &cred);
+       if (kret)
+           goto end;
+       handle->lifetime = cred.times.endtime;
+    } else {
+       krb5_creds in_cred, *out_cred;
+       krb5_const_realm realm;
+
+       memset(&in_cred, 0, sizeof(in_cred));
+       in_cred.client = handle->principal;
+       
+       realm = krb5_principal_get_realm(gssapi_krb5_context, 
+                                        handle->principal);
+       if (realm == NULL) {
+           kret = KRB5_PRINC_NOMATCH; /* XXX */
+           goto end;
+       }
+
+       kret = krb5_make_principal(gssapi_krb5_context, &in_cred.server, 
+                                  realm, KRB5_TGS_NAME, realm, NULL);
+       if (kret)
+           goto end;
+
+       kret = krb5_get_credentials(gssapi_krb5_context, 0, 
+                                   ccache, &in_cred, &out_cred);
+       krb5_free_principal(gssapi_krb5_context, in_cred.server);
+       if (kret)
+           goto end;
+
+       handle->lifetime = out_cred->times.endtime;
+       krb5_free_creds(gssapi_krb5_context, out_cred);
+    }
+
+    handle->ccache = ccache;
+    ret = GSS_S_COMPLETE;
+
+end:
+    if (cred.client != NULL)
+       krb5_free_cred_contents(gssapi_krb5_context, &cred);
+    if (def_princ != NULL)
+       krb5_free_principal(gssapi_krb5_context, def_princ);
+    if (keytab != NULL)
+       krb5_kt_close(gssapi_krb5_context, keytab);
+    if (ret != GSS_S_COMPLETE) {
+       if (ccache != NULL)
+           krb5_cc_close(gssapi_krb5_context, ccache);
+       if (kret != 0) {
+           *minor_status = kret;
+           gssapi_krb5_set_error_string ();
+       }
+    }
+    return (ret);
+}
+
+static OM_uint32 acquire_acceptor_cred
+                 (OM_uint32 * minor_status,
+                  const gss_name_t desired_name,
+                  OM_uint32 time_req,
+                  const gss_OID_set desired_mechs,
+                  gss_cred_usage_t cred_usage,
+                  gss_cred_id_t handle,
+                  gss_OID_set * actual_mechs,
+                  OM_uint32 * time_rec
+                 )
+{
+    OM_uint32 ret;
+    krb5_error_code kret;
+
+    kret = 0;
+    ret = GSS_S_FAILURE;
+    kret = get_keytab(&handle->keytab);
+    if (kret)
+       goto end;
+    
+    /* check that the requested principal exists in the keytab */
+    if (handle->principal) {
+       krb5_keytab_entry entry;
+
+       kret = krb5_kt_get_entry(gssapi_krb5_context, handle->keytab, 
+                                handle->principal, 0, 0, &entry);
+       if (kret)
+           goto end;
+       krb5_kt_free_entry(gssapi_krb5_context, &entry);
+    }
+    ret = GSS_S_COMPLETE;
+end:
+    if (ret != GSS_S_COMPLETE) {
+       if (handle->keytab != NULL)
+           krb5_kt_close(gssapi_krb5_context, handle->keytab);
+       if (kret != 0) {
+           *minor_status = kret;
+           gssapi_krb5_set_error_string ();
+       }
+    }
+    return (ret);
+}
+
+OM_uint32 gss_acquire_cred
+           (OM_uint32 * minor_status,
+            const gss_name_t desired_name,
+            OM_uint32 time_req,
+            const 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
+           )
+{
+    gss_cred_id_t handle;
+    OM_uint32 ret;
+
+    if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) {
+       *minor_status = GSS_KRB5_S_G_BAD_USAGE;
+       return GSS_S_FAILURE;
+    }
+
+    GSSAPI_KRB5_INIT ();
+
+    *output_cred_handle = NULL;
+    if (time_rec)
+       *time_rec = 0;
+    if (actual_mechs)
+       *actual_mechs = GSS_C_NO_OID_SET;
+
+    if (desired_mechs) {
+       int present = 0;
+
+       ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
+                                     desired_mechs, &present); 
+       if (ret)
+           return ret;
+       if (!present) {
+           *minor_status = 0;
+           return GSS_S_BAD_MECH;
+       }
+    }
+
+    handle = (gss_cred_id_t)malloc(sizeof(*handle));
+    if (handle == GSS_C_NO_CREDENTIAL) {
+       *minor_status = ENOMEM;
+        return (GSS_S_FAILURE);
+    }
+
+    memset(handle, 0, sizeof (*handle));
+    HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
+
+    if (desired_name != GSS_C_NO_NAME) {
+       ret = gss_duplicate_name(minor_status, desired_name,
+           &handle->principal);
+       if (ret != GSS_S_COMPLETE) {
+           HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
+           free(handle);
+           return (ret);
+       }
+    }
+    if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) {
+       ret = acquire_initiator_cred(minor_status, desired_name, time_req,
+           desired_mechs, cred_usage, handle, actual_mechs, time_rec);
+       if (ret != GSS_S_COMPLETE) {
+           HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
+           krb5_free_principal(gssapi_krb5_context, handle->principal);
+           free(handle);
+           return (ret);
+       }
+    }
+    if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) {
+       ret = acquire_acceptor_cred(minor_status, desired_name, time_req,
+           desired_mechs, cred_usage, handle, actual_mechs, time_rec);
+       if (ret != GSS_S_COMPLETE) {
+           HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
+           krb5_free_principal(gssapi_krb5_context, handle->principal);
+           free(handle);
+           return (ret);
+       }
+    }
+    ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
+    if (ret == GSS_S_COMPLETE)
+       ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
+                                &handle->mechanisms);
+    if (ret == GSS_S_COMPLETE)
+       ret = gss_inquire_cred(minor_status, handle, NULL, time_rec, NULL,
+                          actual_mechs);
+    if (ret != GSS_S_COMPLETE) {
+       if (handle->mechanisms != NULL)
+           gss_release_oid_set(NULL, &handle->mechanisms);
+       HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex);
+       krb5_free_principal(gssapi_krb5_context, handle->principal);
+       free(handle);
+       return (ret);
+    } 
+    *minor_status = 0;
+    if (time_rec) {
+       ret = gssapi_lifetime_left(minor_status,
+                                  handle->lifetime,
+                                  time_rec);
+
+       if (ret)
+           return ret;
+    }
+    handle->usage = cred_usage;
+    *output_cred_handle = handle;
+    return (GSS_S_COMPLETE);
+}
diff --git a/src/kerberosV/src/lib/gssapi/add_cred.c b/src/kerberosV/src/lib/gssapi/add_cred.c
new file mode 100644 (file)
index 0000000..d6043c3
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: add_cred.c,v 1.4 2003/10/07 04:08:57 lha Exp $");
+
+OM_uint32 gss_add_cred (
+     OM_uint32           *minor_status,
+     const gss_cred_id_t input_cred_handle,
+     const gss_name_t    desired_name,
+     const 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 ret, lifetime;
+    gss_cred_id_t cred, handle;
+
+    handle = NULL;
+    cred = input_cred_handle;
+
+    if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) {
+       *minor_status = 0;
+       return GSS_S_BAD_MECH;
+    }
+
+    if (cred == GSS_C_NO_CREDENTIAL && output_cred_handle == NULL) {
+       *minor_status = 0;
+       return GSS_S_NO_CRED;
+    }
+
+    /* check if requested output usage is compatible with output usage */ 
+    if (output_cred_handle != NULL) {
+       HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
+       if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) {
+           HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+           *minor_status = GSS_KRB5_S_G_BAD_USAGE;
+           return(GSS_S_FAILURE);
+       }
+    }
+       
+    /* check that we have the same name */
+    if (desired_name != GSS_C_NO_NAME &&
+       krb5_principal_compare(gssapi_krb5_context, desired_name,
+                              cred->principal) != FALSE) {
+       if (output_cred_handle)
+           HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+       *minor_status = 0;
+       return GSS_S_BAD_NAME;
+    }
+
+    /* make a copy */
+    if (output_cred_handle) {
+
+       handle = (gss_cred_id_t)malloc(sizeof(*handle));
+       if (handle == GSS_C_NO_CREDENTIAL) {
+           HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+           *minor_status = ENOMEM;
+           return (GSS_S_FAILURE);
+       }
+
+       memset(handle, 0, sizeof (*handle));
+
+       handle->usage = cred_usage;
+       handle->lifetime = cred->lifetime;
+       handle->principal = NULL;
+       handle->keytab = NULL;
+       handle->ccache = NULL;
+       handle->mechanisms = NULL;
+       HEIMDAL_MUTEX_init(&handle->cred_id_mutex);
+       
+       ret = GSS_S_FAILURE;
+
+       ret = gss_duplicate_name(minor_status, cred->principal,
+                                &handle->principal);
+       if (ret) {
+           HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+           free(handle);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+
+       if (cred->keytab) {
+           krb5_error_code kret;
+           char name[KRB5_KT_PREFIX_MAX_LEN + MAXPATHLEN];
+           int len;
+           
+           ret = GSS_S_FAILURE;
+
+           kret = krb5_kt_get_type(gssapi_krb5_context, cred->keytab,
+                                   name, KRB5_KT_PREFIX_MAX_LEN);
+           if (kret) {
+               *minor_status = kret;
+               goto failure;
+           }
+           len = strlen(name);
+           name[len++] = ':';
+
+           kret = krb5_kt_get_name(gssapi_krb5_context, cred->keytab,
+                                   name + len, 
+                                   sizeof(name) - len);
+           if (kret) {
+               *minor_status = kret;
+               goto failure;
+           }
+
+           kret = krb5_kt_resolve(gssapi_krb5_context, name,
+                                  &handle->keytab);
+           if (kret){
+               *minor_status = kret;
+               goto failure;
+           }
+       }
+
+       if (cred->ccache) {
+           krb5_error_code kret;
+           const char *type, *name;
+           char *type_name;
+
+           ret = GSS_S_FAILURE;
+
+           type = krb5_cc_get_type(gssapi_krb5_context, cred->ccache);
+           if (type == NULL){
+               *minor_status = ENOMEM;
+               goto failure;
+           }
+
+           if (strcmp(type, "MEMORY") == 0) {
+               ret = krb5_cc_gen_new(gssapi_krb5_context, &krb5_mcc_ops,
+                                     &handle->ccache);
+               if (ret) {
+                   *minor_status = ret;
+                   goto failure;
+               }
+
+               ret = krb5_cc_copy_cache(gssapi_krb5_context, cred->ccache,
+                                        handle->ccache);
+               if (ret) {
+                   *minor_status = ret;
+                   goto failure;
+               }
+
+           } else {
+               name = krb5_cc_get_name(gssapi_krb5_context, cred->ccache);
+               if (name == NULL) {
+                   *minor_status = ENOMEM;
+                   goto failure;
+               }
+               
+               asprintf(&type_name, "%s:%s", type, name);
+               if (type_name == NULL) {
+                   *minor_status = ENOMEM;
+                   goto failure;
+               }
+               
+               kret = krb5_cc_resolve(gssapi_krb5_context, type_name,
+                                      &handle->ccache);
+               free(type_name);
+               if (kret) {
+                   *minor_status = kret;
+                   goto failure;
+               }           
+           }
+       }
+       ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms);
+       if (ret)
+           goto failure;
+
+       ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM,
+                                    &handle->mechanisms);
+       if (ret)
+           goto failure;
+    }
+
+    ret = gss_inquire_cred(minor_status, cred, NULL, &lifetime,
+                          NULL, actual_mechs);
+    if (ret)
+       goto failure;
+
+    if (initiator_time_rec)
+       *initiator_time_rec = lifetime;
+    if (acceptor_time_rec)
+       *acceptor_time_rec = lifetime;
+
+    if (output_cred_handle) {
+       *output_cred_handle = handle;
+       HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+    }
+
+    *minor_status = 0;
+    return ret;
+
+ failure:
+
+    if (handle) {
+       if (handle->principal)
+           gss_release_name(NULL, &handle->principal);
+       if (handle->keytab)
+           krb5_kt_close(gssapi_krb5_context, handle->keytab);
+       if (handle->ccache)
+           krb5_cc_destroy(gssapi_krb5_context, handle->ccache);
+       if (handle->mechanisms)
+           gss_release_oid_set(NULL, &handle->mechanisms);
+       free(handle);
+    }
+    if (output_cred_handle)
+       HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/add_oid_set_member.c b/src/kerberosV/src/lib/gssapi/add_oid_set_member.c
new file mode 100644 (file)
index 0000000..a9e88e0
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: add_oid_set_member.c,v 1.8 2003/03/16 17:50:49 lha Exp $");
+
+OM_uint32 gss_add_oid_set_member (
+            OM_uint32 * minor_status,
+            const gss_OID member_oid,
+            gss_OID_set * oid_set
+           )
+{
+  gss_OID tmp;
+  size_t n;
+  OM_uint32 res;
+  int present;
+
+  res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present);
+  if (res != GSS_S_COMPLETE)
+    return res;
+
+  if (present) {
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+  }
+
+  n = (*oid_set)->count + 1;
+  tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc));
+  if (tmp == NULL) {
+    *minor_status = ENOMEM;
+    return GSS_S_FAILURE;
+  }
+  (*oid_set)->elements = tmp;
+  (*oid_set)->count = n;
+  (*oid_set)->elements[n-1] = *member_oid;
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/address_to_krb5addr.c b/src/kerberosV/src/lib/gssapi/address_to_krb5addr.c
new file mode 100644 (file)
index 0000000..13a6825
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2000 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+#include <roken.h>
+
+krb5_error_code
+gss_address_to_krb5addr(OM_uint32 gss_addr_type,
+                        gss_buffer_desc *gss_addr,
+                        int16_t port,
+                        krb5_address *address)
+{
+   int addr_type;
+   struct sockaddr sa;
+   krb5_socklen_t sa_size = sizeof(sa);
+   krb5_error_code problem;
+   
+   if (gss_addr == NULL)
+      return GSS_S_FAILURE; 
+   
+   switch (gss_addr_type) {
+#ifdef HAVE_IPV6
+      case GSS_C_AF_INET6: addr_type = AF_INET6;
+                           break;
+#endif /* HAVE_IPV6 */
+                           
+      case GSS_C_AF_INET:  addr_type = AF_INET;
+                           break;
+      default:
+                           return GSS_S_FAILURE;
+   }
+                      
+   problem = krb5_h_addr2sockaddr (gssapi_krb5_context,
+                                  addr_type,
+                                   gss_addr->value, 
+                                   &sa, 
+                                   &sa_size, 
+                                   port);
+   if (problem)
+      return GSS_S_FAILURE;
+
+   problem = krb5_sockaddr2address (gssapi_krb5_context, &sa, address);
+
+   return problem;  
+}
diff --git a/src/kerberosV/src/lib/gssapi/arcfour.c b/src/kerberosV/src/lib/gssapi/arcfour.c
new file mode 100644 (file)
index 0000000..4d25ee7
--- /dev/null
@@ -0,0 +1,636 @@
+/*
+ * Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: arcfour.c,v 1.17 2005/05/06 07:13:32 lha Exp $");
+
+/*
+ * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
+ *
+ * The arcfour message have the following formats:
+ *
+ * MIC token
+ *     TOK_ID[2] = 01 01
+ *     SGN_ALG[2] = 11 00
+ *     Filler[4]
+ *     SND_SEQ[8]
+ *     SGN_CKSUM[8]
+ *
+ * WRAP token
+ *     TOK_ID[2] = 02 01
+ *     SGN_ALG[2];
+ *     SEAL_ALG[2]
+ *     Filler[2]
+ *     SND_SEQ[2]
+ *     SGN_CKSUM[8]
+ *     Confounder[8]
+ */
+
+
+static krb5_error_code
+arcfour_mic_key(krb5_context context, krb5_keyblock *key,
+               void *cksum_data, size_t cksum_size,
+               void *key6_data, size_t key6_size)
+{
+    krb5_error_code ret;
+    
+    Checksum cksum_k5;
+    krb5_keyblock key5;
+    char k5_data[16];
+    
+    Checksum cksum_k6;
+    
+    char T[4];
+
+    memset(T, 0, 4);
+    cksum_k5.checksum.data = k5_data;
+    cksum_k5.checksum.length = sizeof(k5_data);
+
+    if (key->keytype == KEYTYPE_ARCFOUR_56) {
+       char L40[14] = "fortybits";
+
+       memcpy(L40 + 10, T, sizeof(T));
+       ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
+                       L40, 14, 0, key, &cksum_k5);
+       memset(&k5_data[7], 0xAB, 9);
+    } else {
+       ret = krb5_hmac(context, CKSUMTYPE_RSA_MD5,
+                       T, 4, 0, key, &cksum_k5);
+    }
+    if (ret)
+       return ret;
+
+    key5.keytype = KEYTYPE_ARCFOUR;
+    key5.keyvalue = cksum_k5.checksum;
+
+    cksum_k6.checksum.data = key6_data;
+    cksum_k6.checksum.length = key6_size;
+
+    return krb5_hmac(context, CKSUMTYPE_RSA_MD5,
+                    cksum_data, cksum_size, 0, &key5, &cksum_k6);
+}
+
+
+static krb5_error_code
+arcfour_mic_cksum(krb5_keyblock *key, unsigned usage,
+                 u_char *sgn_cksum, size_t sgn_cksum_sz,
+                 const char *v1, size_t l1,
+                 const void *v2, size_t l2,
+                 const void *v3, size_t l3)
+{
+    Checksum CKSUM;
+    u_char *ptr;
+    size_t len;
+    krb5_crypto crypto;
+    krb5_error_code ret;
+    
+    assert(sgn_cksum_sz == 8);
+
+    len = l1 + l2 + l3;
+
+    ptr = malloc(len);
+    if (ptr == NULL)
+       return ENOMEM;
+
+    memcpy(ptr, v1, l1);
+    memcpy(ptr + l1, v2, l2);
+    memcpy(ptr + l1 + l2, v3, l3);
+    
+    ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+    if (ret) {
+       free(ptr);
+       return ret;
+    }
+    
+    ret = krb5_create_checksum(gssapi_krb5_context,
+                              crypto,
+                              usage,
+                              0,
+                              ptr, len,
+                              &CKSUM);
+    free(ptr);
+    if (ret == 0) {
+       memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz);
+       free_Checksum(&CKSUM);
+    }
+    krb5_crypto_destroy(gssapi_krb5_context, crypto);
+
+    return ret;
+}
+
+
+OM_uint32
+_gssapi_get_mic_arcfour(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,
+                       krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    int32_t seq_number;
+    size_t len, total_len;
+    u_char k6_data[16], *p0, *p;
+    RC4_KEY rc4_key;
+    
+    gssapi_krb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
+    
+    message_token->length = total_len;
+    message_token->value  = malloc (total_len);
+    if (message_token->value == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    
+    p0 = _gssapi_make_mech_header(message_token->value,
+                                 len,
+                                 GSS_KRB5_MECHANISM);
+    p = p0;
+    
+    *p++ = 0x01; /* TOK_ID */
+    *p++ = 0x01;
+    *p++ = 0x11; /* SGN_ALG */
+    *p++ = 0x00;
+    *p++ = 0xff; /* Filler */
+    *p++ = 0xff;
+    *p++ = 0xff;
+    *p++ = 0xff;
+
+    p = NULL;
+
+    ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SIGN,
+                           p0 + 16, 8,  /* SGN_CKSUM */
+                           p0, 8, /* TOK_ID, SGN_ALG, Filer */
+                           message_buffer->value, message_buffer->length,
+                           NULL, 0);
+    if (ret) {
+       gss_release_buffer(minor_status, message_token);
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    ret = arcfour_mic_key(gssapi_krb5_context, key,
+                         p0 + 16, 8, /* SGN_CKSUM */
+                         k6_data, sizeof(k6_data));
+    if (ret) {
+       gss_release_buffer(minor_status, message_token);
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
+                                    context_handle->auth_context,
+                                    &seq_number);
+    p = p0 + 8; /* SND_SEQ */
+    gssapi_encode_be_om_uint32(seq_number, p);
+    
+    krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                                    context_handle->auth_context,
+                                    ++seq_number);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    
+    memset (p + 4, (context_handle->more_flags & LOCAL) ? 0 : 0xff, 4);
+
+    RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
+    RC4 (&rc4_key, 8, p, p);
+       
+    memset(&rc4_key, 0, sizeof(rc4_key));
+    memset(k6_data, 0, sizeof(k6_data));
+    
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+
+OM_uint32
+_gssapi_verify_mic_arcfour(OM_uint32 * minor_status,
+                          const gss_ctx_id_t context_handle,
+                          const gss_buffer_t message_buffer,
+                          const gss_buffer_t token_buffer,
+                          gss_qop_t * qop_state,
+                          krb5_keyblock *key,
+                          char *type)
+{
+    krb5_error_code ret;
+    int32_t seq_number;
+    OM_uint32 omret;
+    char cksum_data[8], k6_data[16], SND_SEQ[8];
+    u_char *p;
+    int cmp;
+    
+    if (qop_state)
+       *qop_state = 0;
+
+    p = token_buffer->value;
+    omret = gssapi_krb5_verify_header (&p,
+                                      token_buffer->length,
+                                      type,
+                                      GSS_KRB5_MECHANISM);
+    if (omret)
+       return omret;
+    
+    if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
+       return GSS_S_BAD_SIG;
+    p += 2;
+    if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
+       return GSS_S_BAD_MIC;
+    p += 4;
+
+    ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SIGN,
+                           cksum_data, sizeof(cksum_data),
+                           p - 8, 8,
+                           message_buffer->value, message_buffer->length,
+                           NULL, 0);
+    if (ret) {
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    ret = arcfour_mic_key(gssapi_krb5_context, key,
+                         cksum_data, sizeof(cksum_data),
+                         k6_data, sizeof(k6_data));
+    if (ret) {
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    cmp = memcmp(cksum_data, p + 8, 8);
+    if (cmp) {
+       *minor_status = 0;
+       return GSS_S_BAD_MIC;
+    }
+
+    {
+       RC4_KEY rc4_key;
+       
+       RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
+       RC4 (&rc4_key, 8, p, SND_SEQ);
+       
+       memset(&rc4_key, 0, sizeof(rc4_key));
+       memset(k6_data, 0, sizeof(k6_data));
+    }
+
+    gssapi_decode_be_om_uint32(SND_SEQ, &seq_number);
+
+    if (context_handle->more_flags & LOCAL)
+       cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
+    else
+       cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
+
+    memset(SND_SEQ, 0, sizeof(SND_SEQ));
+    if (cmp != 0) {
+       *minor_status = 0;
+       return GSS_S_BAD_MIC;
+    }
+    
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    omret = _gssapi_msg_order_check(context_handle->order, seq_number);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    if (omret)
+       return omret;
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+_gssapi_wrap_arcfour(OM_uint32 * minor_status,
+                    const gss_ctx_id_t context_handle,
+                    int conf_req_flag,
+                    gss_qop_t qop_req,
+                    const gss_buffer_t input_message_buffer,
+                    int * conf_state,
+                    gss_buffer_t output_message_buffer,
+                    krb5_keyblock *key)
+{
+    u_char Klocaldata[16], k6_data[16], *p, *p0;
+    size_t len, total_len, datalen;
+    krb5_keyblock Klocal;
+    krb5_error_code ret;
+    int32_t seq_number;
+
+    if (conf_state)
+       *conf_state = 0;
+
+    datalen = input_message_buffer->length + 1 /* padding */;
+    len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
+     _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
+
+    output_message_buffer->length = total_len;
+    output_message_buffer->value  = malloc (total_len);
+    if (output_message_buffer->value == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    
+    p0 = _gssapi_make_mech_header(output_message_buffer->value,
+                                 len,
+                                 GSS_KRB5_MECHANISM);
+    p = p0;
+
+    *p++ = 0x02; /* TOK_ID */
+    *p++ = 0x01;
+    *p++ = 0x11; /* SGN_ALG */
+    *p++ = 0x00;
+    if (conf_req_flag) {
+       *p++ = 0x10; /* SEAL_ALG */
+       *p++ = 0x00;
+    } else {
+       *p++ = 0xff; /* SEAL_ALG */
+       *p++ = 0xff;
+    }
+    *p++ = 0xff; /* Filler */
+    *p++ = 0xff;
+
+    p = NULL;
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
+                                    context_handle->auth_context,
+                                    &seq_number);
+
+    gssapi_encode_be_om_uint32(seq_number, p0 + 8);
+
+    krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                                    context_handle->auth_context,
+                                    ++seq_number);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    memset (p0 + 8 + 4,
+           (context_handle->more_flags & LOCAL) ? 0 : 0xff,
+           4);
+
+    krb5_generate_random_block(p0 + 24, 8); /* fill in Confounder */
+    
+    /* p points to data */
+    p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE;
+    memcpy(p, input_message_buffer->value, input_message_buffer->length);
+    p[input_message_buffer->length] = 1; /* PADDING */
+
+    ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SEAL,
+                           p0 + 16, 8, /* SGN_CKSUM */ 
+                           p0, 8, /* TOK_ID, SGN_ALG, SEAL_ALG, Filler */
+                           p0 + 24, 8, /* Confounder */
+                           p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE, 
+                           datalen);
+    if (ret) {
+       *minor_status = ret;
+       gss_release_buffer(minor_status, output_message_buffer);
+       return GSS_S_FAILURE;
+    }
+
+    {
+       int i;
+
+       Klocal.keytype = key->keytype;
+       Klocal.keyvalue.data = Klocaldata;
+       Klocal.keyvalue.length = sizeof(Klocaldata);
+
+       for (i = 0; i < 16; i++)
+           Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
+    }
+    ret = arcfour_mic_key(gssapi_krb5_context, &Klocal,
+                         p0 + 8, 4, /* SND_SEQ */
+                         k6_data, sizeof(k6_data));
+    memset(Klocaldata, 0, sizeof(Klocaldata));
+    if (ret) {
+       gss_release_buffer(minor_status, output_message_buffer);
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+
+    if(conf_req_flag) {
+       RC4_KEY rc4_key;
+
+       RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
+       /* XXX ? */
+       RC4 (&rc4_key, 8 + datalen, p0 + 24, p0 + 24); /* Confounder + data */
+       memset(&rc4_key, 0, sizeof(rc4_key));
+    }
+    memset(k6_data, 0, sizeof(k6_data));
+
+    ret = arcfour_mic_key(gssapi_krb5_context, key,
+                         p0 + 16, 8, /* SGN_CKSUM */
+                         k6_data, sizeof(k6_data));
+    if (ret) {
+       gss_release_buffer(minor_status, output_message_buffer);
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    {
+       RC4_KEY rc4_key;
+       
+       RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
+       RC4 (&rc4_key, 8, p0 + 8, p0 + 8); /* SND_SEQ */
+       memset(&rc4_key, 0, sizeof(rc4_key));
+       memset(k6_data, 0, sizeof(k6_data));
+    }
+
+    if (conf_state)
+       *conf_state = conf_req_flag;
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
+                                const gss_ctx_id_t context_handle,
+                                const gss_buffer_t input_message_buffer,
+                                gss_buffer_t output_message_buffer,
+                                int *conf_state,
+                                gss_qop_t *qop_state,
+                                krb5_keyblock *key)
+{
+    u_char Klocaldata[16];
+    krb5_keyblock Klocal;
+    krb5_error_code ret;
+    int32_t seq_number;
+    size_t datalen;
+    OM_uint32 omret;
+    char k6_data[16], SND_SEQ[8], Confounder[8];
+    char cksum_data[8];
+    u_char *p, *p0;
+    int cmp;
+    int conf_flag;
+    size_t padlen;
+    
+    if (conf_state)
+       *conf_state = 0;
+    if (qop_state)
+       *qop_state = 0;
+
+    p0 = input_message_buffer->value;
+    omret = _gssapi_verify_mech_header(&p0,
+                                      input_message_buffer->length,
+                                      GSS_KRB5_MECHANISM);
+    if (omret)
+       return omret;
+    p = p0;
+
+    datalen = input_message_buffer->length -
+       (p - ((u_char *)input_message_buffer->value)) - 
+       GSS_ARCFOUR_WRAP_TOKEN_SIZE;
+
+    if (memcmp(p, "\x02\x01", 2) != 0)
+       return GSS_S_BAD_SIG;
+    p += 2;
+    if (memcmp(p, "\x11\x00", 2) != 0) /* SGN_ALG = HMAC MD5 ARCFOUR */
+       return GSS_S_BAD_SIG;
+    p += 2;
+
+    if (memcmp (p, "\x10\x00", 2) == 0)
+       conf_flag = 1;
+    else if (memcmp (p, "\xff\xff", 2) == 0)
+       conf_flag = 0;
+    else
+       return GSS_S_BAD_SIG;
+
+    p += 2;
+    if (memcmp (p, "\xff\xff", 2) != 0)
+       return GSS_S_BAD_MIC;
+    p = NULL;
+
+    ret = arcfour_mic_key(gssapi_krb5_context, key,
+                         p0 + 16, 8, /* SGN_CKSUM */
+                         k6_data, sizeof(k6_data));
+    if (ret) {
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    {
+       RC4_KEY rc4_key;
+       
+       RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
+       RC4 (&rc4_key, 8, p0 + 8, SND_SEQ); /* SND_SEQ */
+       memset(&rc4_key, 0, sizeof(rc4_key));
+       memset(k6_data, 0, sizeof(k6_data));
+    }
+
+    gssapi_decode_be_om_uint32(SND_SEQ, &seq_number);
+
+    if (context_handle->more_flags & LOCAL)
+       cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4);
+    else
+       cmp = memcmp(&SND_SEQ[4], "\x00\x00\x00\x00", 4);
+
+    if (cmp != 0) {
+       *minor_status = 0;
+       return GSS_S_BAD_MIC;
+    }
+
+    {
+       int i;
+
+       Klocal.keytype = key->keytype;
+       Klocal.keyvalue.data = Klocaldata;
+       Klocal.keyvalue.length = sizeof(Klocaldata);
+
+       for (i = 0; i < 16; i++)
+           Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0;
+    }
+    ret = arcfour_mic_key(gssapi_krb5_context, &Klocal,
+                         SND_SEQ, 4,
+                         k6_data, sizeof(k6_data));
+    memset(Klocaldata, 0, sizeof(Klocaldata));
+    if (ret) {
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    output_message_buffer->value = malloc(datalen);
+    if (output_message_buffer->value == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    output_message_buffer->length = datalen;
+
+    if(conf_flag) {
+       RC4_KEY rc4_key;
+
+       RC4_set_key (&rc4_key, sizeof(k6_data), k6_data);
+       RC4 (&rc4_key, 8, p0 + 24, Confounder); /* Confounder */
+       RC4 (&rc4_key, datalen, p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
+            output_message_buffer->value);
+       memset(&rc4_key, 0, sizeof(rc4_key));
+    } else {
+       memcpy(Confounder, p0 + 24, 8); /* Confounder */
+       memcpy(output_message_buffer->value, 
+              p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE,
+              datalen);
+    }
+    memset(k6_data, 0, sizeof(k6_data));
+
+    ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen);
+    if (ret) {
+       gss_release_buffer(minor_status, output_message_buffer);
+       *minor_status = 0;
+       return ret;
+    }
+    output_message_buffer->length -= padlen;
+
+    ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SEAL,
+                           cksum_data, sizeof(cksum_data),
+                           p0, 8, 
+                           Confounder, sizeof(Confounder),
+                           output_message_buffer->value, 
+                           output_message_buffer->length + padlen);
+    if (ret) {
+       gss_release_buffer(minor_status, output_message_buffer);
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */
+    if (cmp) {
+       gss_release_buffer(minor_status, output_message_buffer);
+       *minor_status = 0;
+       return GSS_S_BAD_MIC;
+    }
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    omret = _gssapi_msg_order_check(context_handle->order, seq_number);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    if (omret)
+       return omret;
+
+    if (conf_state)
+       *conf_state = conf_flag;
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/arcfour.h b/src/kerberosV/src/lib/gssapi/arcfour.h
new file mode 100644 (file)
index 0000000..b9be096
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: arcfour.h,v 1.5 2004/03/07 22:30:57 lha Exp $ */
+
+#ifndef GSSAPI_ARCFOUR_H_
+#define GSSAPI_ARCFOUR_H_ 1
+
+#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32
+
+OM_uint32 _gssapi_wrap_arcfour(OM_uint32 *minor_status,
+                              const gss_ctx_id_t context_handle,
+                              int conf_req_flag,
+                              gss_qop_t qop_req,
+                              const gss_buffer_t input_message_buffer,
+                              int *conf_state,
+                              gss_buffer_t output_message_buffer,
+                              krb5_keyblock *key);
+
+OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status,
+                                const gss_ctx_id_t context_handle,
+                                const gss_buffer_t input_message_buffer,
+                                gss_buffer_t output_message_buffer,
+                                int *conf_state,
+                                gss_qop_t *qop_state,
+                                krb5_keyblock *key);
+
+OM_uint32 _gssapi_get_mic_arcfour(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,
+                                 krb5_keyblock *key);
+
+OM_uint32 _gssapi_verify_mic_arcfour(OM_uint32 *minor_status,
+                                    const gss_ctx_id_t context_handle,
+                                    const gss_buffer_t message_buffer,
+                                    const gss_buffer_t token_buffer,
+                                    gss_qop_t *qop_state,
+                                    krb5_keyblock *key,
+                                    char *type);
+
+#endif /* GSSAPI_ARCFOUR_H_ */
diff --git a/src/kerberosV/src/lib/gssapi/canonicalize_name.c b/src/kerberosV/src/lib/gssapi/canonicalize_name.c
new file mode 100644 (file)
index 0000000..bcc5a03
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: canonicalize_name.c,v 1.2 1999/12/02 17:05:03 joda Exp $");
+
+OM_uint32 gss_canonicalize_name (
+            OM_uint32 * minor_status,
+            const gss_name_t input_name,
+            const gss_OID mech_type,
+            gss_name_t * output_name
+           )
+{
+    return gss_duplicate_name (minor_status, input_name, output_name);
+}
diff --git a/src/kerberosV/src/lib/gssapi/ccache_name.c b/src/kerberosV/src/lib/gssapi/ccache_name.c
new file mode 100644 (file)
index 0000000..85f480b
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: ccache_name.c,v 1.1 2004/01/25 19:08:57 lha Exp $");
+
+char *last_out_name;
+
+OM_uint32
+gss_krb5_ccache_name(OM_uint32 *minor_status, 
+                    const char *name,
+                    const char **out_name)
+{
+    krb5_error_code kret;
+
+    *minor_status = 0;
+
+    GSSAPI_KRB5_INIT();
+
+    if (out_name) {
+       const char *name;
+
+       if (last_out_name) {
+           free(last_out_name);
+           last_out_name = NULL;
+       }
+
+       name = krb5_cc_default_name(gssapi_krb5_context);
+       if (name == NULL) {
+           *minor_status = ENOMEM;
+           gssapi_krb5_set_error_string ();
+           return GSS_S_FAILURE;
+       }
+       last_out_name = strdup(name);
+       if (last_out_name == NULL) {
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       *out_name = last_out_name;
+    }
+
+    kret = krb5_cc_set_default_name(gssapi_krb5_context, name);
+    if (kret) {
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       return GSS_S_FAILURE;
+    }
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/cfx.c b/src/kerberosV/src/lib/gssapi/cfx.c
new file mode 100644 (file)
index 0000000..63c5fa3
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2003, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: cfx.c,v 1.17 2005/04/27 17:47:32 lha Exp $");
+
+/*
+ * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt
+ */
+
+#define CFXSentByAcceptor      (1 << 0)
+#define CFXSealed              (1 << 1)
+#define CFXAcceptorSubkey      (1 << 2)
+
+static krb5_error_code
+wrap_length_cfx(krb5_crypto crypto,
+               int conf_req_flag,
+               size_t input_length,
+               size_t *output_length,
+               size_t *cksumsize,
+               u_int16_t *padlength)
+{
+    krb5_error_code ret;
+    krb5_cksumtype type;
+
+    /* 16-byte header is always first */
+    *output_length = sizeof(gss_cfx_wrap_token_desc);
+    *padlength = 0;
+
+    ret = krb5_crypto_get_checksum_type(gssapi_krb5_context, crypto, &type);
+    if (ret) {
+       return ret;
+    }
+
+    ret = krb5_checksumsize(gssapi_krb5_context, type, cksumsize);
+    if (ret) {
+       return ret;
+    }
+
+    if (conf_req_flag) {
+       size_t padsize;
+
+       /* Header is concatenated with data before encryption */
+       input_length += sizeof(gss_cfx_wrap_token_desc);
+
+       ret = krb5_crypto_getpadsize(gssapi_krb5_context, crypto, &padsize);
+       if (ret) {
+           return ret;
+       }
+       if (padsize > 1) {
+           /* XXX check this */
+           *padlength = padsize - (input_length % padsize);
+       }
+
+       /* We add the pad ourselves (noted here for completeness only) */
+       input_length += *padlength;
+
+       *output_length += krb5_get_wrapped_length(gssapi_krb5_context,
+                                                 crypto, input_length);
+    } else {
+       /* Checksum is concatenated with data */
+       *output_length += input_length + *cksumsize;
+    }
+
+    assert(*output_length > input_length);
+
+    return 0;
+}
+
+OM_uint32 _gssapi_wrap_size_cfx(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,
+                               krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    u_int16_t padlength;
+    size_t output_length, cksumsize;
+
+    ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    ret = wrap_length_cfx(crypto, conf_req_flag, 
+                         req_output_size,
+                         &output_length, &cksumsize, &padlength);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+
+    if (output_length < req_output_size) {
+       *max_input_size = (req_output_size - output_length);
+       *max_input_size -= padlength;
+    } else {
+       /* Should this return an error? */
+       *max_input_size = 0;
+    }
+
+    krb5_crypto_destroy(gssapi_krb5_context, crypto);
+
+    return GSS_S_COMPLETE;
+}
+
+/*
+ * Rotate "rrc" bytes to the front or back
+ */
+
+static krb5_error_code
+rrc_rotate(void *data, size_t len, u_int16_t rrc, krb5_boolean unrotate)
+{
+    u_char *tmp;
+    size_t left;
+    char buf[256];
+
+    if (len == 0)
+       return 0;
+
+    rrc %= len;
+
+    if (rrc == 0)
+       return 0;
+
+    left = len - rrc;
+
+    if (rrc <= sizeof(buf)) {
+       tmp = buf;
+    } else {
+       tmp = malloc(rrc);
+       if (tmp == NULL) 
+           return ENOMEM;
+    }
+    if (unrotate) {
+       memcpy(tmp, data, rrc);
+       memmove(data, (u_char *)data + rrc, left);
+       memcpy((u_char *)data + left, tmp, rrc);
+    } else {
+       memcpy(tmp, (u_char *)data + left, rrc);
+       memmove((u_char *)data + rrc, data, left);
+       memcpy(data, tmp, rrc);
+    }
+
+    if (rrc > sizeof(buf)) 
+       free(tmp);
+
+    return 0;
+}
+
+OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
+                          const gss_ctx_id_t context_handle,
+                          int conf_req_flag,
+                          gss_qop_t qop_req,
+                          const gss_buffer_t input_message_buffer,
+                          int *conf_state,
+                          gss_buffer_t output_message_buffer,
+                          krb5_keyblock *key)
+{
+    krb5_crypto crypto;
+    gss_cfx_wrap_token token;
+    krb5_error_code ret;
+    unsigned usage;
+    krb5_data cipher;
+    size_t wrapped_len, cksumsize;
+    u_int16_t padlength, rrc = 0;
+    OM_uint32 seq_number;
+    u_char *p;
+
+    ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    ret = wrap_length_cfx(crypto, conf_req_flag, 
+                         input_message_buffer->length,
+                         &wrapped_len, &cksumsize, &padlength);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+
+    /* Always rotate encrypted token (if any) and checksum to header */
+    rrc = (conf_req_flag ? sizeof(*token) : 0) + (u_int16_t)cksumsize;
+
+    output_message_buffer->length = wrapped_len;
+    output_message_buffer->value = malloc(output_message_buffer->length);
+    if (output_message_buffer->value == NULL) {
+       *minor_status = ENOMEM;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+
+    p = output_message_buffer->value;
+    token = (gss_cfx_wrap_token)p;
+    token->TOK_ID[0] = 0x05;
+    token->TOK_ID[1] = 0x04;
+    token->Flags     = 0;
+    token->Filler    = 0xFF;
+    if ((context_handle->more_flags & LOCAL) == 0)
+       token->Flags |= CFXSentByAcceptor;
+    if (context_handle->more_flags & ACCEPTOR_SUBKEY)
+       token->Flags |= CFXAcceptorSubkey;
+    if (conf_req_flag) {
+       /*
+        * In Wrap tokens with confidentiality, the EC field is
+        * used to encode the size (in bytes) of the random filler.
+        */
+       token->Flags |= CFXSealed;
+       token->EC[0] = (padlength >> 8) & 0xFF;
+       token->EC[1] = (padlength >> 0) & 0xFF;
+    } else {
+       /*
+        * In Wrap tokens without confidentiality, the EC field is
+        * used to encode the size (in bytes) of the trailing
+        * checksum.
+        *
+        * This is not used in the checksum calcuation itself,
+        * because the checksum length could potentially vary
+        * depending on the data length.
+        */
+       token->EC[0] = 0;
+       token->EC[1] = 0;
+    }
+
+    /*
+     * In Wrap tokens that provide for confidentiality, the RRC
+     * field in the header contains the hex value 00 00 before
+     * encryption.
+     *
+     * In Wrap tokens that do not provide for confidentiality,
+     * both the EC and RRC fields in the appended checksum
+     * contain the hex value 00 00 for the purpose of calculating
+     * the checksum.
+     */
+    token->RRC[0] = 0;
+    token->RRC[1] = 0;
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    krb5_auth_con_getlocalseqnumber(gssapi_krb5_context,
+                                   context_handle->auth_context,
+                                   &seq_number);
+    gssapi_encode_be_om_uint32(0,          &token->SND_SEQ[0]);
+    gssapi_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
+    krb5_auth_con_setlocalseqnumber(gssapi_krb5_context,
+                                   context_handle->auth_context,
+                                   ++seq_number);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    /*
+     * If confidentiality is requested, the token header is
+     * appended to the plaintext before encryption; the resulting
+     * token is {"header" | encrypt(plaintext | pad | "header")}.
+     *
+     * If no confidentiality is requested, the checksum is
+     * calculated over the plaintext concatenated with the
+     * token header.
+     */
+    if (context_handle->more_flags & LOCAL) {
+       usage = KRB5_KU_USAGE_INITIATOR_SEAL;
+    } else {
+       usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;
+    }
+
+    if (conf_req_flag) {
+       /*
+        * Any necessary padding is added here to ensure that the
+        * encrypted token header is always at the end of the
+        * ciphertext.
+        *
+        * The specification does not require that the padding
+        * bytes are initialized.
+        */
+       p += sizeof(*token);
+       memcpy(p, input_message_buffer->value, input_message_buffer->length);
+       memset(p + input_message_buffer->length, 0xFF, padlength);
+       memcpy(p + input_message_buffer->length + padlength,
+              token, sizeof(*token));
+
+       ret = krb5_encrypt(gssapi_krb5_context, crypto,
+                          usage, p,
+                          input_message_buffer->length + padlength +
+                               sizeof(*token),
+                          &cipher);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           gss_release_buffer(minor_status, output_message_buffer);
+           return GSS_S_FAILURE;
+       }
+       assert(sizeof(*token) + cipher.length == wrapped_len);
+       token->RRC[0] = (rrc >> 8) & 0xFF;  
+       token->RRC[1] = (rrc >> 0) & 0xFF;
+
+       ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           gss_release_buffer(minor_status, output_message_buffer);
+           return GSS_S_FAILURE;
+       }
+       memcpy(p, cipher.data, cipher.length);
+       krb5_data_free(&cipher);
+    } else {
+       char *buf;
+       Checksum cksum;
+
+       buf = malloc(input_message_buffer->length + sizeof(*token));
+       if (buf == NULL) {
+           *minor_status = ENOMEM;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           gss_release_buffer(minor_status, output_message_buffer);
+           return GSS_S_FAILURE;
+       }
+       memcpy(buf, input_message_buffer->value, input_message_buffer->length);
+       memcpy(buf + input_message_buffer->length, token, sizeof(*token));
+
+       ret = krb5_create_checksum(gssapi_krb5_context, crypto,
+                                  usage, 0, buf, 
+                                  input_message_buffer->length +
+                                       sizeof(*token), 
+                                  &cksum);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           gss_release_buffer(minor_status, output_message_buffer);
+           free(buf);
+           return GSS_S_FAILURE;
+       }
+
+       free(buf);
+
+       assert(cksum.checksum.length == cksumsize);
+       token->EC[0] =  (cksum.checksum.length >> 8) & 0xFF;
+       token->EC[1] =  (cksum.checksum.length >> 0) & 0xFF;
+       token->RRC[0] = (rrc >> 8) & 0xFF;  
+       token->RRC[1] = (rrc >> 0) & 0xFF;
+
+       p += sizeof(*token);
+       memcpy(p, input_message_buffer->value, input_message_buffer->length);
+       memcpy(p + input_message_buffer->length,
+              cksum.checksum.data, cksum.checksum.length);
+
+       ret = rrc_rotate(p,
+           input_message_buffer->length + cksum.checksum.length, rrc, FALSE);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           gss_release_buffer(minor_status, output_message_buffer);
+           free_Checksum(&cksum);
+           return GSS_S_FAILURE;
+       }
+       free_Checksum(&cksum);
+    }
+
+    krb5_crypto_destroy(gssapi_krb5_context, crypto);
+
+    if (conf_state != NULL) {
+       *conf_state = conf_req_flag;
+    }
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
+                            const gss_ctx_id_t context_handle,
+                            const gss_buffer_t input_message_buffer,
+                            gss_buffer_t output_message_buffer,
+                            int *conf_state,
+                            gss_qop_t *qop_state,
+                            krb5_keyblock *key)
+{
+    krb5_crypto crypto;
+    gss_cfx_wrap_token token;
+    u_char token_flags;
+    krb5_error_code ret;
+    unsigned usage;
+    krb5_data data;
+    u_int16_t ec, rrc;
+    OM_uint32 seq_number_lo, seq_number_hi;
+    size_t len;
+    u_char *p;
+
+    *minor_status = 0;
+
+    if (input_message_buffer->length < sizeof(*token)) {
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    p = input_message_buffer->value;
+
+    token = (gss_cfx_wrap_token)p;
+
+    if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04) {
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /* Ignore unknown flags */
+    token_flags = token->Flags &
+       (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey);
+
+    if (token_flags & CFXSentByAcceptor) {
+       if ((context_handle->more_flags & LOCAL) == 0)
+           return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (context_handle->more_flags & ACCEPTOR_SUBKEY) {
+       if ((token_flags & CFXAcceptorSubkey) == 0)
+           return GSS_S_DEFECTIVE_TOKEN;
+    } else {
+       if (token_flags & CFXAcceptorSubkey)
+           return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (token->Filler != 0xFF) {
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (conf_state != NULL) {
+       *conf_state = (token_flags & CFXSealed) ? 1 : 0;
+    }
+
+    ec  = (token->EC[0]  << 8) | token->EC[1];
+    rrc = (token->RRC[0] << 8) | token->RRC[1];
+
+    /*
+     * Check sequence number
+     */
+    gssapi_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);
+    gssapi_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);
+    if (seq_number_hi) {
+       /* no support for 64-bit sequence numbers */
+       *minor_status = ERANGE;
+       return GSS_S_UNSEQ_TOKEN;
+    }
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo);
+    if (ret != 0) {
+       *minor_status = 0;
+       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+       gss_release_buffer(minor_status, output_message_buffer);
+       return ret;
+    }
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    /*
+     * Decrypt and/or verify checksum
+     */
+    ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    if (context_handle->more_flags & LOCAL) {
+       usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;
+    } else {
+       usage = KRB5_KU_USAGE_INITIATOR_SEAL;
+    }
+
+    p += sizeof(*token);
+    len = input_message_buffer->length;
+    len -= (p - (u_char *)input_message_buffer->value);
+
+    /* Rotate by RRC; bogus to do this in-place XXX */
+    *minor_status = rrc_rotate(p, len, rrc, TRUE);
+    if (*minor_status != 0) {
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+
+    if (token_flags & CFXSealed) {
+       ret = krb5_decrypt(gssapi_krb5_context, crypto, usage,
+           p, len, &data);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           return GSS_S_BAD_MIC;
+       }
+
+       /* Check that there is room for the pad and token header */
+       if (data.length < ec + sizeof(*token)) {
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           krb5_data_free(&data);
+           return GSS_S_DEFECTIVE_TOKEN;
+       }
+       p = data.data;
+       p += data.length - sizeof(*token);
+
+       /* RRC is unprotected; don't modify input buffer */
+       ((gss_cfx_wrap_token)p)->RRC[0] = token->RRC[0];
+       ((gss_cfx_wrap_token)p)->RRC[1] = token->RRC[1];
+
+       /* Check the integrity of the header */
+       if (memcmp(p, token, sizeof(*token)) != 0) {
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           krb5_data_free(&data);
+           return GSS_S_BAD_MIC;
+       }
+
+       output_message_buffer->value = data.data;
+       output_message_buffer->length = data.length - ec - sizeof(*token);
+    } else {
+       Checksum cksum;
+
+       /* Determine checksum type */
+       ret = krb5_crypto_get_checksum_type(gssapi_krb5_context,
+                                           crypto, &cksum.cksumtype);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           return GSS_S_FAILURE;
+       }
+
+       cksum.checksum.length = ec;
+
+       /* Check we have at least as much data as the checksum */
+       if (len < cksum.checksum.length) {
+           *minor_status = ERANGE;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           return GSS_S_BAD_MIC;
+       }
+
+       /* Length now is of the plaintext only, no checksum */
+       len -= cksum.checksum.length;
+       cksum.checksum.data = p + len;
+
+       output_message_buffer->length = len; /* for later */
+       output_message_buffer->value = malloc(len + sizeof(*token));
+       if (output_message_buffer->value == NULL) {
+           *minor_status = ENOMEM;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           return GSS_S_FAILURE;
+       }
+
+       /* Checksum is over (plaintext-data | "header") */
+       memcpy(output_message_buffer->value, p, len);
+       memcpy((u_char *)output_message_buffer->value + len, 
+              token, sizeof(*token));
+
+       /* EC is not included in checksum calculation */
+       token = (gss_cfx_wrap_token)((u_char *)output_message_buffer->value +
+                                    len);
+       token->EC[0]  = 0;
+       token->EC[1]  = 0;
+       token->RRC[0] = 0;
+       token->RRC[1] = 0;
+
+       ret = krb5_verify_checksum(gssapi_krb5_context, crypto,
+                                  usage,
+                                  output_message_buffer->value,
+                                  len + sizeof(*token),
+                                  &cksum);
+       if (ret != 0) {
+           gssapi_krb5_set_error_string();
+           *minor_status = ret;
+           krb5_crypto_destroy(gssapi_krb5_context, crypto);
+           gss_release_buffer(minor_status, output_message_buffer);
+           return GSS_S_BAD_MIC;
+       }
+    }
+
+    krb5_crypto_destroy(gssapi_krb5_context, crypto);
+
+    if (qop_state != NULL) {
+       *qop_state = GSS_C_QOP_DEFAULT;
+    }
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 _gssapi_mic_cfx(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,
+                         krb5_keyblock *key)
+{
+    krb5_crypto crypto;
+    gss_cfx_mic_token token;
+    krb5_error_code ret;
+    unsigned usage;
+    Checksum cksum;
+    u_char *buf;
+    size_t len;
+    OM_uint32 seq_number;
+
+    ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    len = message_buffer->length + sizeof(*token);
+    buf = malloc(len);
+    if (buf == NULL) {
+       *minor_status = ENOMEM;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+
+    memcpy(buf, message_buffer->value, message_buffer->length);
+
+    token = (gss_cfx_mic_token)(buf + message_buffer->length);
+    token->TOK_ID[0] = 0x04;
+    token->TOK_ID[1] = 0x04;
+    token->Flags = 0;
+    if ((context_handle->more_flags & LOCAL) == 0)
+       token->Flags |= CFXSentByAcceptor;
+    if (context_handle->more_flags & ACCEPTOR_SUBKEY)
+       token->Flags |= CFXAcceptorSubkey;
+    memset(token->Filler, 0xFF, 5);
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    krb5_auth_con_getlocalseqnumber(gssapi_krb5_context,
+                                   context_handle->auth_context,
+                                   &seq_number);
+    gssapi_encode_be_om_uint32(0,          &token->SND_SEQ[0]);
+    gssapi_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
+    krb5_auth_con_setlocalseqnumber(gssapi_krb5_context,
+                                   context_handle->auth_context,
+                                   ++seq_number);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    if (context_handle->more_flags & LOCAL) {
+       usage = KRB5_KU_USAGE_INITIATOR_SIGN;
+    } else {
+       usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
+    }
+
+    ret = krb5_create_checksum(gssapi_krb5_context, crypto,
+       usage, 0, buf, len, &cksum);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       free(buf);
+       return GSS_S_FAILURE;
+    }
+    krb5_crypto_destroy(gssapi_krb5_context, crypto);
+
+    /* Determine MIC length */
+    message_token->length = sizeof(*token) + cksum.checksum.length;
+    message_token->value = malloc(message_token->length);
+    if (message_token->value == NULL) {
+       *minor_status = ENOMEM;
+       free_Checksum(&cksum);
+       free(buf);
+       return GSS_S_FAILURE;
+    }
+
+    /* Token is { "header" | get_mic("header" | plaintext-data) } */
+    memcpy(message_token->value, token, sizeof(*token));
+    memcpy((u_char *)message_token->value + sizeof(*token),
+          cksum.checksum.data, cksum.checksum.length);
+
+    free_Checksum(&cksum);
+    free(buf);
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
+                                const gss_ctx_id_t context_handle,
+                                const gss_buffer_t message_buffer,
+                                const gss_buffer_t token_buffer,
+                                gss_qop_t *qop_state,
+                                krb5_keyblock *key)
+{
+    krb5_crypto crypto;
+    gss_cfx_mic_token token;
+    u_char token_flags;
+    krb5_error_code ret;
+    unsigned usage;
+    OM_uint32 seq_number_lo, seq_number_hi;
+    u_char *buf, *p;
+    Checksum cksum;
+
+    *minor_status = 0;
+
+    if (token_buffer->length < sizeof(*token)) {
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    p = token_buffer->value;
+
+    token = (gss_cfx_mic_token)p;
+
+    if (token->TOK_ID[0] != 0x04 || token->TOK_ID[1] != 0x04) {
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /* Ignore unknown flags */
+    token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey);
+
+    if (token_flags & CFXSentByAcceptor) {
+       if ((context_handle->more_flags & LOCAL) == 0)
+           return GSS_S_DEFECTIVE_TOKEN;
+    }
+    if (context_handle->more_flags & ACCEPTOR_SUBKEY) {
+       if ((token_flags & CFXAcceptorSubkey) == 0)
+           return GSS_S_DEFECTIVE_TOKEN;
+    } else {
+       if (token_flags & CFXAcceptorSubkey)
+           return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (memcmp(token->Filler, "\xff\xff\xff\xff\xff", 5) != 0) {
+       return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    /*
+     * Check sequence number
+     */
+    gssapi_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);
+    gssapi_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);
+    if (seq_number_hi) {
+       *minor_status = ERANGE;
+       return GSS_S_UNSEQ_TOKEN;
+    }
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo);
+    if (ret != 0) {
+       *minor_status = 0;
+       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+       return ret;
+    }
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    /*
+     * Verify checksum
+     */
+    ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    ret = krb5_crypto_get_checksum_type(gssapi_krb5_context, crypto,
+                                       &cksum.cksumtype);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+
+    cksum.checksum.data = p + sizeof(*token);
+    cksum.checksum.length = token_buffer->length - sizeof(*token);
+
+    if (context_handle->more_flags & LOCAL) {
+       usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
+    } else {
+       usage = KRB5_KU_USAGE_INITIATOR_SIGN;
+    }
+
+    buf = malloc(message_buffer->length + sizeof(*token));
+    if (buf == NULL) {
+       *minor_status = ENOMEM;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       return GSS_S_FAILURE;
+    }
+    memcpy(buf, message_buffer->value, message_buffer->length);
+    memcpy(buf + message_buffer->length, token, sizeof(*token));
+
+    ret = krb5_verify_checksum(gssapi_krb5_context, crypto,
+                              usage,
+                              buf,
+                              sizeof(*token) + message_buffer->length,
+                              &cksum);
+    if (ret != 0) {
+       gssapi_krb5_set_error_string();
+       *minor_status = ret;
+       krb5_crypto_destroy(gssapi_krb5_context, crypto);
+       free(buf);
+       return GSS_S_BAD_MIC;
+    }
+
+    free(buf);
+
+    if (qop_state != NULL) {
+       *qop_state = GSS_C_QOP_DEFAULT;
+    }
+
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/cfx.h b/src/kerberosV/src/lib/gssapi/cfx.h
new file mode 100644 (file)
index 0000000..cd6a333
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2003, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: cfx.h,v 1.5 2003/09/22 21:48:35 lha Exp $ */
+
+#ifndef GSSAPI_CFX_H_
+#define GSSAPI_CFX_H_ 1
+
+/*
+ * Implementation of draft-ietf-krb-wg-gssapi-cfx-01.txt
+ */
+
+typedef struct gss_cfx_mic_token_desc_struct {
+       u_char TOK_ID[2]; /* 04 04 */
+       u_char Flags;
+       u_char Filler[5];
+       u_char SND_SEQ[8];
+} gss_cfx_mic_token_desc, *gss_cfx_mic_token;
+
+typedef struct gss_cfx_wrap_token_desc_struct {
+       u_char TOK_ID[2]; /* 04 05 */
+       u_char Flags;
+       u_char Filler;
+       u_char EC[2];
+       u_char RRC[2];
+       u_char SND_SEQ[8];
+} gss_cfx_wrap_token_desc, *gss_cfx_wrap_token;
+
+typedef struct gss_cfx_delete_token_desc_struct {
+       u_char TOK_ID[2]; /* 05 04 */
+       u_char Flags;
+       u_char Filler[5];
+       u_char SND_SEQ[8];
+} gss_cfx_delete_token_desc, *gss_cfx_delete_token;
+
+OM_uint32 _gssapi_wrap_size_cfx(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,
+                               krb5_keyblock *key);
+
+OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
+                          const gss_ctx_id_t context_handle,
+                          int conf_req_flag,
+                          gss_qop_t qop_req,
+                          const gss_buffer_t input_message_buffer,
+                          int *conf_state,
+                          gss_buffer_t output_message_buffer,
+                          krb5_keyblock *key);
+
+OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
+                            const gss_ctx_id_t context_handle,
+                            const gss_buffer_t input_message_buffer,
+                            gss_buffer_t output_message_buffer,
+                            int *conf_state,
+                            gss_qop_t *qop_state,
+                            krb5_keyblock *key);
+
+OM_uint32 _gssapi_mic_cfx(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,
+                         krb5_keyblock *key);
+
+OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
+                                const gss_ctx_id_t context_handle,
+                                const gss_buffer_t message_buffer,
+                                const gss_buffer_t token_buffer,
+                                gss_qop_t *qop_state,
+                                krb5_keyblock *key);
+
+#endif /* GSSAPI_CFX_H_ */
diff --git a/src/kerberosV/src/lib/gssapi/compare_name.c b/src/kerberosV/src/lib/gssapi/compare_name.c
new file mode 100644 (file)
index 0000000..98d875d
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: compare_name.c,v 1.4 2003/03/16 17:50:07 lha Exp $");
+
+OM_uint32 gss_compare_name
+           (OM_uint32 * minor_status,
+            const gss_name_t name1,
+            const gss_name_t name2,
+            int * name_equal
+           )
+{
+    GSSAPI_KRB5_INIT();
+
+    *name_equal = krb5_principal_compare (gssapi_krb5_context,
+                                         name1, name2);
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/compat.c b/src/kerberosV/src/lib/gssapi/compat.c
new file mode 100644 (file)
index 0000000..bce7797
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: compat.c,v 1.10 2005/05/30 20:51:51 lha Exp $");
+
+
+krb5_error_code
+_gss_check_compat(OM_uint32 *minor_status, gss_name_t name, 
+                 const char *option, krb5_boolean *compat, 
+                 krb5_boolean match_val)
+{
+    krb5_error_code ret = 0;
+    char **p, **q;
+    krb5_principal match;
+
+
+    p = krb5_config_get_strings(gssapi_krb5_context, NULL, "gssapi",
+                               option, NULL);
+    if(p == NULL)
+       return 0;
+
+    match = NULL;
+    for(q = p; *q; q++) {
+       ret = krb5_parse_name(gssapi_krb5_context, *q, &match);
+       if (ret)
+           break;
+
+       if (krb5_principal_match(gssapi_krb5_context, name, match)) {
+           *compat = match_val;
+           break;
+       }
+       
+       krb5_free_principal(gssapi_krb5_context, match);
+       match = NULL;
+    }
+    if (match)
+       krb5_free_principal(gssapi_krb5_context, match);
+    krb5_config_free_strings(p);
+
+    if (ret) {
+       if (minor_status)
+           *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+
+    return 0;
+}
+
+/*
+ * ctx->ctx_id_mutex is assumed to be locked
+ */
+
+OM_uint32
+_gss_DES3_get_mic_compat(OM_uint32 *minor_status, gss_ctx_id_t ctx)
+{
+    krb5_boolean use_compat = FALSE;
+    OM_uint32 ret;
+
+    if ((ctx->more_flags & COMPAT_OLD_DES3_SELECTED) == 0) {
+       ret = _gss_check_compat(minor_status, ctx->target, 
+                               "broken_des3_mic", &use_compat, TRUE);
+       if (ret)
+           return ret;
+       ret = _gss_check_compat(minor_status, ctx->target, 
+                               "correct_des3_mic", &use_compat, FALSE);
+       if (ret)
+           return ret;
+
+       if (use_compat)
+           ctx->more_flags |= COMPAT_OLD_DES3;
+       ctx->more_flags |= COMPAT_OLD_DES3_SELECTED;
+    }
+    return 0;
+}
+
+OM_uint32
+gss_krb5_compat_des3_mic(OM_uint32 *minor_status, gss_ctx_id_t ctx, int on)
+{
+    *minor_status = 0;
+
+    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+    if (on) {
+       ctx->more_flags |= COMPAT_OLD_DES3;
+    } else {
+       ctx->more_flags &= ~COMPAT_OLD_DES3;
+    }
+    ctx->more_flags |= COMPAT_OLD_DES3_SELECTED;
+    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
+
+    return 0;
+}
+
+/*
+ * For compatability with the Windows SPNEGO implementation, the
+ * default is to ignore the mechListMIC unless the initiator specified
+ * CFX or configured in krb5.conf with the option
+ *     [gssapi]require_mechlist_mic=target-principal-pattern.
+ * The option is valid for both initiator and acceptor.
+ */
+OM_uint32
+_gss_spnego_require_mechlist_mic(OM_uint32 *minor_status,
+                                gss_ctx_id_t ctx,
+                                krb5_boolean *require_mic)
+{
+    OM_uint32 ret;
+    int is_cfx = 0;
+
+    gsskrb5_is_cfx(ctx, &is_cfx);
+    if (is_cfx) {
+       /* CFX session key was used */
+       *require_mic = TRUE;
+    } else {
+       *require_mic = FALSE;
+       ret = _gss_check_compat(minor_status, ctx->target, 
+                               "require_mechlist_mic",
+                               require_mic, TRUE);
+       if (ret)
+           return ret;
+    }
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/context_time.c b/src/kerberosV/src/lib/gssapi/context_time.c
new file mode 100644 (file)
index 0000000..a683b83
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: context_time.c,v 1.10 2003/06/03 15:08:00 lha Exp $");
+
+OM_uint32
+gssapi_lifetime_left(OM_uint32 *minor_status, 
+                    OM_uint32 lifetime,
+                    OM_uint32 *lifetime_rec)
+{
+    krb5_timestamp timeret;
+    krb5_error_code kret;
+
+    kret = krb5_timeofday(gssapi_krb5_context, &timeret);
+    if (kret) {
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       return GSS_S_FAILURE;
+    }
+
+    if (lifetime < timeret) 
+       *lifetime_rec = 0;
+    else
+       *lifetime_rec = lifetime - timeret;
+
+    return GSS_S_COMPLETE;
+}
+
+
+OM_uint32 gss_context_time
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            OM_uint32 * time_rec
+           )
+{
+    OM_uint32 lifetime;
+    OM_uint32 major_status;
+
+    GSSAPI_KRB5_INIT ();
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    lifetime = context_handle->lifetime;
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    major_status = gssapi_lifetime_left(minor_status, lifetime, time_rec);
+    if (major_status != GSS_S_COMPLETE)
+       return major_status;
+
+    *minor_status = 0;
+
+    if (*time_rec == 0)
+       return GSS_S_CONTEXT_EXPIRED;
+       
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/copy_ccache.c b/src/kerberosV/src/lib/gssapi/copy_ccache.c
new file mode 100644 (file)
index 0000000..b0838db
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2000 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: copy_ccache.c,v 1.7 2003/09/01 15:11:09 lha Exp $");
+
+OM_uint32
+gss_krb5_copy_ccache(OM_uint32 *minor_status,
+                    gss_cred_id_t cred,
+                    krb5_ccache out)
+{
+    krb5_error_code kret;
+
+    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
+
+    if (cred->ccache == NULL) {
+       HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+       *minor_status = EINVAL;
+       return GSS_S_FAILURE;
+    }
+
+    kret = krb5_cc_copy_cache(gssapi_krb5_context, cred->ccache, out);
+    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+    if (kret) {
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       return GSS_S_FAILURE;
+    }
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+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)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    
+    ad_data->value = NULL;
+    ad_data->length = 0;
+    
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    if (context_handle->ticket == NULL) {
+       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+       *minor_status = EINVAL;
+       return GSS_S_FAILURE;
+    }
+
+    ret = krb5_ticket_get_authorization_data_type(gssapi_krb5_context,
+                                                 context_handle->ticket,
+                                                 ad_type,
+                                                 &data);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    if (ret) {
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+    
+    ad_data->value = malloc(data.length);
+    if (ad_data->value == NULL) {
+       krb5_data_free(&data);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    ad_data->length = data.length;
+    memcpy(ad_data->value, data.data, ad_data->length);
+    krb5_data_free(&data);
+           
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/create_emtpy_oid_set.c b/src/kerberosV/src/lib/gssapi/create_emtpy_oid_set.c
new file mode 100644 (file)
index 0000000..2641f4b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: create_emtpy_oid_set.c,v 1.5 2003/03/16 17:47:07 lha Exp $");
+
+OM_uint32 gss_create_empty_oid_set (
+            OM_uint32 * minor_status,
+            gss_OID_set * oid_set
+           )
+{
+  *oid_set = malloc(sizeof(**oid_set));
+  if (*oid_set == NULL) {
+    *minor_status = ENOMEM;
+    return GSS_S_FAILURE;
+  }
+  (*oid_set)->count = 0;
+  (*oid_set)->elements = NULL;
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/decapsulate.c b/src/kerberosV/src/lib/gssapi/decapsulate.c
new file mode 100644 (file)
index 0000000..ead743b
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: decapsulate.c,v 1.11 2003/09/09 02:09:03 lha Exp $");
+
+/*
+ * return the length of the mechanism in token or -1
+ * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
+ */
+
+ssize_t
+gssapi_krb5_get_mech (const u_char *ptr,
+                     size_t total_len,
+                     const u_char **mech_ret)
+{
+    size_t len, len_len, mech_len, foo;
+    const u_char *p = ptr;
+    int e;
+
+    if (total_len < 1)
+       return -1;
+    if (*p++ != 0x60)
+       return -1;
+    e = der_get_length (p, total_len - 1, &len, &len_len);
+    if (e || 1 + len_len + len != total_len)
+       return -1;
+    p += len_len;
+    if (*p++ != 0x06)
+       return -1;
+    e = der_get_length (p, total_len - 1 - len_len - 1,
+                       &mech_len, &foo);
+    if (e)
+       return -1;
+    p += foo;
+    *mech_ret = p;
+    return mech_len;
+}
+
+OM_uint32
+_gssapi_verify_mech_header(u_char **str,
+                          size_t total_len,
+                          gss_OID mech)
+{
+    const u_char *p;
+    ssize_t mech_len;
+
+    mech_len = gssapi_krb5_get_mech (*str, total_len, &p);
+    if (mech_len < 0)
+       return GSS_S_DEFECTIVE_TOKEN;
+
+    if (mech_len != mech->length)
+       return GSS_S_BAD_MECH;
+    if (memcmp(p,
+              mech->elements,
+              mech->length) != 0)
+       return GSS_S_BAD_MECH;
+    p += mech_len;
+    *str = (char *)p;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+gssapi_krb5_verify_header(u_char **str,
+                         size_t total_len,
+                         u_char *type,
+                         gss_OID oid)
+{
+    OM_uint32 ret;
+    size_t len;
+    u_char *p = *str;
+
+    ret = _gssapi_verify_mech_header(str, total_len, oid);
+    if (ret)
+       return ret;
+
+    len = total_len - (*str - p);
+
+    if (len < 2)
+       return GSS_S_DEFECTIVE_TOKEN;
+
+    if (memcmp (*str, type, 2) != 0)
+       return GSS_S_DEFECTIVE_TOKEN;
+    *str += 2;
+
+    return 0;
+}
+
+/*
+ * Remove the GSS-API wrapping from `in_token' giving `out_data.
+ * Does not copy data, so just free `in_token'.
+ */
+
+OM_uint32
+_gssapi_decapsulate(
+    OM_uint32 *minor_status,
+    gss_buffer_t input_token_buffer,
+    krb5_data *out_data,
+    const gss_OID mech
+)
+{
+    u_char *p;
+    OM_uint32 ret;
+
+    p = input_token_buffer->value;
+    ret = _gssapi_verify_mech_header(&p,
+                                   input_token_buffer->length,
+                                   mech);
+    if (ret) {
+       *minor_status = 0;
+       return ret;
+    }
+
+    out_data->length = input_token_buffer->length -
+       (p - (u_char *)input_token_buffer->value);
+    out_data->data   = p;
+    return GSS_S_COMPLETE;
+}
+
+/*
+ * Remove the GSS-API wrapping from `in_token' giving `out_data.
+ * Does not copy data, so just free `in_token'.
+ */
+
+OM_uint32
+gssapi_krb5_decapsulate(OM_uint32 *minor_status,    
+                       gss_buffer_t input_token_buffer,
+                       krb5_data *out_data,
+                       char *type,
+                       gss_OID oid)
+{
+    u_char *p;
+    OM_uint32 ret;
+
+    p = input_token_buffer->value;
+    ret = gssapi_krb5_verify_header(&p,
+                                   input_token_buffer->length,
+                                   type,
+                                   oid);
+    if (ret) {
+       *minor_status = 0;
+       return ret;
+    }
+
+    out_data->length = input_token_buffer->length -
+       (p - (u_char *)input_token_buffer->value);
+    out_data->data   = p;
+    return GSS_S_COMPLETE;
+}
+
+/*
+ * Verify padding of a gss wrapped message and return its length.
+ */
+
+OM_uint32
+_gssapi_verify_pad(gss_buffer_t wrapped_token, 
+                  size_t datalen,
+                  size_t *padlen)
+{
+    u_char *pad;
+    size_t padlength;
+    int i;
+
+    pad = (u_char *)wrapped_token->value + wrapped_token->length - 1;
+    padlength = *pad;
+
+    if (padlength > datalen)
+       return GSS_S_BAD_MECH;
+
+    for (i = padlength; i > 0 && *pad == padlength; i--, pad--)
+       ;
+    if (i != 0)
+       return GSS_S_BAD_MIC;
+
+    *padlen = padlength;
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/gssapi/delete_sec_context.c b/src/kerberosV/src/lib/gssapi/delete_sec_context.c
new file mode 100644 (file)
index 0000000..f0c6135
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: delete_sec_context.c,v 1.15 2005/04/27 17:48:17 lha Exp $");
+
+OM_uint32 gss_delete_sec_context
+           (OM_uint32 * minor_status,
+            gss_ctx_id_t * context_handle,
+            gss_buffer_t output_token
+           )
+{
+    GSSAPI_KRB5_INIT ();
+
+    if (output_token) {
+       output_token->length = 0;
+       output_token->value  = NULL;
+    }
+
+    HEIMDAL_MUTEX_lock(&(*context_handle)->ctx_id_mutex);
+
+    krb5_auth_con_free (gssapi_krb5_context,
+                       (*context_handle)->auth_context);
+    if((*context_handle)->source)
+       krb5_free_principal (gssapi_krb5_context,
+                            (*context_handle)->source);
+    if((*context_handle)->target)
+       krb5_free_principal (gssapi_krb5_context,
+                            (*context_handle)->target);
+    if ((*context_handle)->ticket)
+       krb5_free_ticket (gssapi_krb5_context,
+                         (*context_handle)->ticket);
+    if((*context_handle)->order)
+       _gssapi_msg_order_destroy(&(*context_handle)->order);
+
+    HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+    HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex);
+    memset(*context_handle, 0, sizeof(**context_handle));
+    free (*context_handle);
+    *context_handle = GSS_C_NO_CONTEXT;
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/display_name.c b/src/kerberosV/src/lib/gssapi/display_name.c
new file mode 100644 (file)
index 0000000..15f6ad2
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: display_name.c,v 1.9 2003/03/16 17:46:11 lha Exp $");
+
+OM_uint32 gss_display_name
+           (OM_uint32 * minor_status,
+            const gss_name_t input_name,
+            gss_buffer_t output_name_buffer,
+            gss_OID * output_name_type
+           )
+{
+    krb5_error_code kret;
+    char *buf;
+    size_t len;
+
+    GSSAPI_KRB5_INIT ();
+    kret = krb5_unparse_name (gssapi_krb5_context,
+                             input_name,
+                             &buf);
+    if (kret) {
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       return GSS_S_FAILURE;
+    }
+    len = strlen (buf);
+    output_name_buffer->length = len;
+    output_name_buffer->value  = malloc(len + 1);
+    if (output_name_buffer->value == NULL) {
+       free (buf);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    memcpy (output_name_buffer->value, buf, len);
+    ((char *)output_name_buffer->value)[len] = '\0';
+    free (buf);
+    if (output_name_type)
+       *output_name_type = GSS_KRB5_NT_PRINCIPAL_NAME;
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/display_status.c b/src/kerberosV/src/lib/gssapi/display_status.c
new file mode 100644 (file)
index 0000000..bd12bc9
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 1998 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: display_status.c,v 1.12 2005/03/16 13:15:03 lha Exp $");
+
+static char *
+calling_error(OM_uint32 v)
+{
+    static char *msgs[] = {
+       NULL,                   /* 0 */
+       "A required input parameter could not be read.", /*  */
+       "A required output parameter could not be written.", /*  */
+       "A parameter was malformed"
+    };
+
+    v >>= GSS_C_CALLING_ERROR_OFFSET;
+
+    if (v == 0)
+       return "";
+    else if (v >= sizeof(msgs)/sizeof(*msgs))
+       return "unknown calling error";
+    else
+       return msgs[v];
+}
+
+static char *
+routine_error(OM_uint32 v)
+{
+    static char *msgs[] = {
+       NULL,                   /* 0 */
+       "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 MIC",
+       "No credentials were supplied, "
+       "or the credentials were unavailable or inaccessible.",
+       "No context has been established",
+       "A token was invalid",
+       "A credential was invalid",
+       "The referenced credentials have expired",
+       "The context has expired",
+       "Miscellaneous failure (see text)",
+       "The quality-of-protection requested could not be provide",
+       "The operation is forbidden by local security policy",
+       "The operation or option is not available",
+       "The requested credential element already exists",
+       "The provided name was not a mechanism name.",
+    };
+
+    v >>= GSS_C_ROUTINE_ERROR_OFFSET;
+
+    if (v == 0)
+       return "";
+    else if (v >= sizeof(msgs)/sizeof(*msgs))
+       return "unknown routine error";
+    else
+       return msgs[v];
+}
+
+static char *
+supplementary_error(OM_uint32 v)
+{
+    static char *msgs[] = {
+       "normal completion",
+       "continuation call to routine required",
+       "duplicate per-message token detected",
+       "timed-out per-message token detected",
+       "reordered (early) per-message token detected",
+       "skipped predecessor token(s) detected"
+    };
+
+    v >>= GSS_C_SUPPLEMENTARY_OFFSET;
+
+    if (v >= sizeof(msgs)/sizeof(*msgs))
+       return "unknown routine error";
+    else
+       return msgs[v];
+}
+
+void
+gssapi_krb5_set_error_string (void)
+{
+    struct gssapi_thr_context *ctx = gssapi_get_thread_context(1);
+    char *e;
+
+    if (ctx == NULL)
+       return;
+    HEIMDAL_MUTEX_lock(&ctx->mutex);
+    if (ctx->error_string)
+       free(ctx->error_string);
+    e = krb5_get_error_string(gssapi_krb5_context);
+    if (e == NULL)
+       ctx->error_string = NULL;
+    else {
+       /* ignore failures, will use status code instead */
+       ctx->error_string = strdup(e); 
+       krb5_free_error_string(gssapi_krb5_context, e);
+    }
+    HEIMDAL_MUTEX_unlock(&ctx->mutex);
+}
+
+char *
+gssapi_krb5_get_error_string (void)
+{
+    struct gssapi_thr_context *ctx = gssapi_get_thread_context(0);
+    char *ret;
+
+    if (ctx == NULL)
+       return NULL;
+    HEIMDAL_MUTEX_lock(&ctx->mutex);
+    ret = ctx->error_string;
+    ctx->error_string = NULL;
+    HEIMDAL_MUTEX_unlock(&ctx->mutex);
+    return ret;
+}
+
+OM_uint32 gss_display_status
+           (OM_uint32          *minor_status,
+           OM_uint32            status_value,
+           int                  status_type,
+           const gss_OID        mech_type,
+           OM_uint32           *message_context,
+           gss_buffer_t         status_string)
+{
+  char *buf;
+
+  GSSAPI_KRB5_INIT ();
+
+  status_string->length = 0;
+  status_string->value = NULL;
+
+  if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 &&
+      gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) {
+      *minor_status = 0;
+      return GSS_C_GSS_CODE;
+  }
+
+  if (status_type == GSS_C_GSS_CODE) {
+      if (GSS_SUPPLEMENTARY_INFO(status_value))
+         asprintf(&buf, "%s", 
+                  supplementary_error(GSS_SUPPLEMENTARY_INFO(status_value)));
+      else
+         asprintf (&buf, "%s %s",
+                   calling_error(GSS_CALLING_ERROR(status_value)),
+                   routine_error(GSS_ROUTINE_ERROR(status_value)));
+  } else if (status_type == GSS_C_MECH_CODE) {
+      buf = gssapi_krb5_get_error_string ();
+      if (buf == NULL) {
+         const char *tmp = krb5_get_err_text (gssapi_krb5_context,
+                                              status_value);
+         if (tmp == NULL)
+             asprintf(&buf, "unknown mech error-code %u",
+                      (unsigned)status_value);
+         else
+             buf = strdup(tmp);
+      }
+  } else {
+      *minor_status = EINVAL;
+      return GSS_S_BAD_STATUS;
+  }
+
+  if (buf == NULL) {
+      *minor_status = ENOMEM;
+      return GSS_S_FAILURE;
+  }
+
+  *message_context = 0;
+  *minor_status = 0;
+
+  status_string->length = strlen(buf);
+  status_string->value  = buf;
+  
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/duplicate_name.c b/src/kerberosV/src/lib/gssapi/duplicate_name.c
new file mode 100644 (file)
index 0000000..09f7ffa
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: duplicate_name.c,v 1.7 2003/03/16 17:44:26 lha Exp $");
+
+OM_uint32 gss_duplicate_name (
+            OM_uint32 * minor_status,
+            const gss_name_t src_name,
+            gss_name_t * dest_name
+           )
+{
+    krb5_error_code kret;
+
+    GSSAPI_KRB5_INIT ();
+
+    kret = krb5_copy_principal (gssapi_krb5_context,
+                               src_name,
+                               dest_name);
+    if (kret) {
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       return GSS_S_FAILURE;
+    } else {
+       *minor_status = 0;
+       return GSS_S_COMPLETE;
+    }
+}
diff --git a/src/kerberosV/src/lib/gssapi/encapsulate.c b/src/kerberosV/src/lib/gssapi/encapsulate.c
new file mode 100644 (file)
index 0000000..fcdb548
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: encapsulate.c,v 1.8 2003/09/04 18:08:55 lha Exp $");
+
+void
+_gssapi_encap_length (size_t data_len,
+                     size_t *len,
+                     size_t *total_len,
+                     const gss_OID mech)
+{
+    size_t len_len;
+
+    *len = 1 + 1 + mech->length + data_len;
+
+    len_len = length_len(*len);
+
+    *total_len = 1 + len_len + *len;
+}
+
+void
+gssapi_krb5_encap_length (size_t data_len,
+                         size_t *len,
+                         size_t *total_len,
+                         const gss_OID mech)
+{
+    _gssapi_encap_length(data_len + 2, len, total_len, mech);
+}
+
+u_char *
+gssapi_krb5_make_header (u_char *p,
+                        size_t len,
+                        const u_char *type,
+                        const gss_OID mech)
+{
+    p = _gssapi_make_mech_header(p, len, mech);
+    memcpy (p, type, 2);
+    p += 2;
+    return p;
+}
+
+u_char *
+_gssapi_make_mech_header(u_char *p,
+                        size_t len,
+                        const gss_OID mech)
+{
+    int e;
+    size_t len_len, foo;
+
+    *p++ = 0x60;
+    len_len = length_len(len);
+    e = der_put_length (p + len_len - 1, len_len, len, &foo);
+    if(e || foo != len_len)
+       abort ();
+    p += len_len;
+    *p++ = 0x06;
+    *p++ = mech->length;
+    memcpy (p, mech->elements, mech->length);
+    p += mech->length;
+    return p;
+}
+
+/*
+ * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings.
+ */
+
+OM_uint32
+_gssapi_encapsulate(
+    OM_uint32 *minor_status,
+    const krb5_data *in_data,
+    gss_buffer_t output_token,
+    const gss_OID mech
+)
+{
+    size_t len, outer_len;
+    u_char *p;
+
+    _gssapi_encap_length (in_data->length, &len, &outer_len, mech);
+    
+    output_token->length = outer_len;
+    output_token->value  = malloc (outer_len);
+    if (output_token->value == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }  
+
+    p = _gssapi_make_mech_header (output_token->value, len, mech);
+    memcpy (p, in_data->data, in_data->length);
+    return GSS_S_COMPLETE;
+}
+
+/*
+ * Give it a krb5_data and it will encapsulate with extra GSS-API krb5
+ * wrappings.
+ */
+
+OM_uint32
+gssapi_krb5_encapsulate(
+                       OM_uint32 *minor_status,    
+                       const krb5_data *in_data,
+                       gss_buffer_t output_token,
+                       const u_char *type,
+                       const gss_OID mech
+)
+{
+    size_t len, outer_len;
+    u_char *p;
+
+    gssapi_krb5_encap_length (in_data->length, &len, &outer_len, mech);
+    
+    output_token->length = outer_len;
+    output_token->value  = malloc (outer_len);
+    if (output_token->value == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }  
+
+    p = gssapi_krb5_make_header (output_token->value, len, type, mech);
+    memcpy (p, in_data->data, in_data->length);
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/export_name.c b/src/kerberosV/src/lib/gssapi/export_name.c
new file mode 100644 (file)
index 0000000..d5eecdd
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1997, 1999, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: export_name.c,v 1.5 2003/03/16 17:34:46 lha Exp $");
+
+OM_uint32 gss_export_name
+           (OM_uint32  * minor_status,
+            const gss_name_t input_name,
+            gss_buffer_t exported_name
+           )
+{
+    krb5_error_code kret;
+    char *buf, *name;
+    size_t len;
+
+    GSSAPI_KRB5_INIT ();
+    kret = krb5_unparse_name (gssapi_krb5_context,
+                             input_name,
+                             &name);
+    if (kret) {
+       *minor_status = kret;
+       gssapi_krb5_set_error_string ();
+       return GSS_S_FAILURE;
+    }
+    len = strlen (name);
+
+    exported_name->length = 10 + len + GSS_KRB5_MECHANISM->length;
+    exported_name->value  = malloc(exported_name->length);
+    if (exported_name->value == NULL) {
+       free (name);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
+
+    buf = exported_name->value;
+    memcpy(buf, "\x04\x01", 2);
+    buf += 2;
+    buf[0] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff;
+    buf[1] = (GSS_KRB5_MECHANISM->length + 2) & 0xff;
+    buf+= 2;
+    buf[0] = 0x06;
+    buf[1] = (GSS_KRB5_MECHANISM->length) & 0xFF;
+    buf+= 2;
+
+    memcpy(buf, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length);
+    buf += GSS_KRB5_MECHANISM->length;
+
+    buf[0] = (len >> 24) & 0xff;
+    buf[1] = (len >> 16) & 0xff;
+    buf[2] = (len >> 8) & 0xff;
+    buf[3] = (len) & 0xff;
+    buf += 4;
+
+    memcpy (buf, name, len);
+
+    free (name);
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/export_sec_context.c b/src/kerberosV/src/lib/gssapi/export_sec_context.c
new file mode 100644 (file)
index 0000000..68af266
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 1999 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: export_sec_context.c,v 1.7 2003/05/21 14:52:13 lha Exp $");
+
+OM_uint32
+gss_export_sec_context (
+    OM_uint32 * minor_status,
+    gss_ctx_id_t * context_handle,
+    gss_buffer_t interprocess_token
+    )
+{
+    krb5_storage *sp;
+    krb5_auth_context ac;
+    OM_uint32 ret = GSS_S_COMPLETE;
+    krb5_data data;
+    gss_buffer_desc buffer;
+    int flags;
+    OM_uint32 minor;
+    krb5_error_code kret;
+
+    GSSAPI_KRB5_INIT ();
+
+    HEIMDAL_MUTEX_lock(&(*context_handle)->ctx_id_mutex);
+
+    if (!((*context_handle)->flags & GSS_C_TRANS_FLAG)) {
+       HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+       *minor_status = 0;
+       return GSS_S_UNAVAILABLE;
+    }
+
+    sp = krb5_storage_emem ();
+    if (sp == NULL) {
+       HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    ac = (*context_handle)->auth_context;
+
+    /* flagging included fields */
+
+    flags = 0;
+    if (ac->local_address)
+       flags |= SC_LOCAL_ADDRESS;
+    if (ac->remote_address)
+       flags |= SC_REMOTE_ADDRESS;
+    if (ac->keyblock)
+       flags |= SC_KEYBLOCK;
+    if (ac->local_subkey)
+       flags |= SC_LOCAL_SUBKEY;
+    if (ac->remote_subkey)
+       flags |= SC_REMOTE_SUBKEY;
+
+    kret = krb5_store_int32 (sp, flags);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+
+    /* marshall auth context */
+
+    kret = krb5_store_int32 (sp, ac->flags);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+    if (ac->local_address) {
+       kret = krb5_store_address (sp, *ac->local_address);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+    }
+    if (ac->remote_address) {
+       kret = krb5_store_address (sp, *ac->remote_address);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+    }
+    kret = krb5_store_int16 (sp, ac->local_port);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+    kret = krb5_store_int16 (sp, ac->remote_port);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+    if (ac->keyblock) {
+       kret = krb5_store_keyblock (sp, *ac->keyblock);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+    }
+    if (ac->local_subkey) {
+       kret = krb5_store_keyblock (sp, *ac->local_subkey);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+    }
+    if (ac->remote_subkey) {
+       kret = krb5_store_keyblock (sp, *ac->remote_subkey);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+    }
+    kret = krb5_store_int32 (sp, ac->local_seqnumber);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+    kret = krb5_store_int32 (sp, ac->remote_seqnumber);
+       if (kret) {
+           *minor_status = kret;
+           goto failure;
+       }
+
+    kret = krb5_store_int32 (sp, ac->keytype);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+    kret = krb5_store_int32 (sp, ac->cksumtype);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+
+    /* names */
+
+    ret = gss_export_name (minor_status, (*context_handle)->source, &buffer);
+    if (ret)
+       goto failure;
+    data.data   = buffer.value;
+    data.length = buffer.length;
+    kret = krb5_store_data (sp, data);
+    gss_release_buffer (&minor, &buffer);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+
+    ret = gss_export_name (minor_status, (*context_handle)->target, &buffer);
+    if (ret)
+       goto failure;
+    data.data   = buffer.value;
+    data.length = buffer.length;
+
+    ret = GSS_S_FAILURE;
+
+    kret = krb5_store_data (sp, data);
+    gss_release_buffer (&minor, &buffer);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+
+    kret = krb5_store_int32 (sp, (*context_handle)->flags);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+    kret = krb5_store_int32 (sp, (*context_handle)->more_flags);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+    kret = krb5_store_int32 (sp, (*context_handle)->lifetime);
+    if (kret) {
+       *minor_status = kret;
+       goto failure;
+    }
+
+    kret = krb5_storage_to_data (sp, &data);
+    krb5_storage_free (sp);
+    if (kret) {
+       HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+       *minor_status = kret;
+       return GSS_S_FAILURE;
+    }
+    interprocess_token->length = data.length;
+    interprocess_token->value  = data.data;
+    HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+    ret = gss_delete_sec_context (minor_status, context_handle,
+                                 GSS_C_NO_BUFFER);
+    if (ret != GSS_S_COMPLETE)
+       gss_release_buffer (NULL, interprocess_token);
+    *minor_status = 0;
+    return ret;
+ failure:
+    HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+    krb5_storage_free (sp);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/external.c b/src/kerberosV/src/lib/gssapi/external.c
new file mode 100644 (file)
index 0000000..71ef452
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: external.c,v 1.6 2003/09/08 15:34:19 lha Exp $");
+
+/*
+ * 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.
+ */
+
+static gss_OID_desc gss_c_nt_user_name_oid_desc =
+{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
+ "\x01\x02\x01\x01"};
+
+gss_OID GSS_C_NT_USER_NAME = &gss_c_nt_user_name_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.
+ */
+
+static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc =
+{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
+ "\x01\x02\x01\x02"};
+
+gss_OID GSS_C_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_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.
+ */
+
+static gss_OID_desc gss_c_nt_string_uid_name_oid_desc =
+{10, (void *)"\x2a\x86\x48\x86\xf7\x12"
+ "\x01\x02\x01\x03"};
+
+gss_OID GSS_C_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_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
+ */
+
+static gss_OID_desc gss_c_nt_hostbased_service_x_oid_desc =
+{6, (void *)"\x2b\x06\x01\x05\x06\x02"};
+
+gss_OID GSS_C_NT_HOSTBASED_SERVICE_X = &gss_c_nt_hostbased_service_x_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\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.
+ */
+static gss_OID_desc gss_c_nt_hostbased_service_oid_desc =
+{10, (void *)"\x2a\x86\x48\x86\xf7\x12" "\x01\x02\x01\x04"};
+
+gss_OID GSS_C_NT_HOSTBASED_SERVICE = &gss_c_nt_hostbased_service_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.
+ */
+
+static gss_OID_desc gss_c_nt_anonymous_oid_desc =
+{6, (void *)"\x2b\x06\01\x05\x06\x03"};
+
+gss_OID GSS_C_NT_ANONYMOUS = &gss_c_nt_anonymous_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.
+ */
+
+static gss_OID_desc gss_c_nt_export_name_oid_desc =
+{6, (void *)"\x2b\x06\x01\x05\x06\x04"};
+
+gss_OID GSS_C_NT_EXPORT_NAME = &gss_c_nt_export_name_oid_desc;
+
+/*
+ *   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".
+ */
+
+static gss_OID_desc gss_krb5_nt_principal_name_oid_desc =
+{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"};
+
+gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &gss_krb5_nt_principal_name_oid_desc;
+
+/*
+ *   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".
+ */
+
+gss_OID GSS_KRB5_NT_USER_NAME = &gss_c_nt_user_name_oid_desc;
+
+/*
+ *   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".
+ */
+
+gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc;
+
+/*
+ *   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_OID GSS_KRB5_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc;
+
+/*
+ *   To support ongoing experimentation, testing, and evolution of the
+ *   specification, the Kerberos V5 GSS-API mechanism as defined in this
+ *   and any successor memos will be identified with the following Object
+ *   Identifier, as defined in RFC-1510, until the specification is
+ *   advanced to the level of Proposed Standard RFC:
+ *
+ *   {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)}
+ *
+ *   Upon advancement to the level of Proposed Standard RFC, the Kerberos
+ *   V5 GSS-API mechanism will be identified by an Object Identifier
+ *   having the value:
+ *
+ *   {iso(1) member-body(2) United States(840) mit(113554) infosys(1)
+ *   gssapi(2) krb5(2)}
+ */
+
+#if 0 /* This is the old OID */
+
+static gss_OID_desc gss_krb5_mechanism_oid_desc =
+{5, (void *)"\x2b\x05\x01\x05\x02"};
+
+#endif
+
+static gss_OID_desc gss_krb5_mechanism_oid_desc =
+{9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"};
+
+gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc;
+
+/*
+ * RFC2478, SPNEGO:
+ *  The security mechanism of the initial
+ *  negotiation token is identified by the Object Identifier
+ *  iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2).
+ */
+
+static gss_OID_desc gss_spnego_mechanism_oid_desc =
+{6, (void *)"\x2b\x06\x01\x05\x05\x02"};
+
+gss_OID GSS_SPNEGO_MECHANISM = &gss_spnego_mechanism_oid_desc;
+
+/*
+ * draft-ietf-cat-iakerb-09, IAKERB:
+ *   The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance
+ *   with the mechanism proposed by SPNEGO [7] for negotiating protocol
+ *   variations, is:  {iso(1) org(3) dod(6) internet(1) security(5)
+ *   mechanisms(5) iakerb(10) iakerbProxyProtocol(1)}.  The proposed
+ *   mechanism ID for IAKERB minimum messages GSS-API Kerberos, in
+ *   accordance with the mechanism proposed by SPNEGO for negotiating
+ *   protocol variations, is: {iso(1) org(3) dod(6) internet(1)
+ *   security(5) mechanisms(5) iakerb(10)
+ *   iakerbMinimumMessagesProtocol(2)}.
+ */
+
+static gss_OID_desc gss_iakerb_proxy_mechanism_oid_desc =
+{7, (void *)"\x2b\x06\x01\x05\x05\x0a\x01"};
+
+gss_OID GSS_IAKERB_PROXY_MECHANISM = &gss_iakerb_proxy_mechanism_oid_desc;
+
+static gss_OID_desc gss_iakerb_min_msg_mechanism_oid_desc =
+{7, (void *)"\x2b\x06\x01\x05\x05\x0a\x02"};
+
+gss_OID GSS_IAKERB_MIN_MSG_MECHANISM = &gss_iakerb_min_msg_mechanism_oid_desc;
+
+/*
+ * Context for krb5 calls.
+ */
+
+krb5_context gssapi_krb5_context;
diff --git a/src/kerberosV/src/lib/gssapi/get_mic.c b/src/kerberosV/src/lib/gssapi/get_mic.c
new file mode 100644 (file)
index 0000000..fc5666e
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: get_mic.c,v 1.29 2005/01/05 02:52:12 lukeh Exp $");
+
+static OM_uint32
+mic_des
+           (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,
+           krb5_keyblock *key
+           )
+{
+  u_char *p;
+  MD5_CTX md5;
+  u_char hash[16];
+  DES_key_schedule schedule;
+  DES_cblock deskey;
+  DES_cblock zero;
+  int32_t seq_number;
+  size_t len, total_len;
+
+  gssapi_krb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM);
+
+  message_token->length = total_len;
+  message_token->value  = malloc (total_len);
+  if (message_token->value == NULL) {
+    *minor_status = ENOMEM;
+    return GSS_S_FAILURE;
+  }
+
+  p = gssapi_krb5_make_header(message_token->value,
+                             len,
+                             "\x01\x01", /* TOK_ID */
+                             GSS_KRB5_MECHANISM); 
+
+  memcpy (p, "\x00\x00", 2);   /* SGN_ALG = DES MAC MD5 */
+  p += 2;
+
+  memcpy (p, "\xff\xff\xff\xff", 4); /* Filler */
+  p += 4;
+
+  /* Fill in later (SND-SEQ) */
+  memset (p, 0, 16);
+  p += 16;
+
+  /* checksum */
+  MD5_Init (&md5);
+  MD5_Update (&md5, p - 24, 8);
+  MD5_Update (&md5, message_buffer->value, message_buffer->length);
+  MD5_Final (hash, &md5);
+
+  memset (&zero, 0, sizeof(zero));
+  memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
+                &schedule, &zero);
+  memcpy (p - 8, hash, 8);     /* SGN_CKSUM */
+
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+  /* sequence number */
+  krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              &seq_number);
+
+  p -= 16;                     /* SND_SEQ */
+  p[0] = (seq_number >> 0)  & 0xFF;
+  p[1] = (seq_number >> 8)  & 0xFF;
+  p[2] = (seq_number >> 16) & 0xFF;
+  p[3] = (seq_number >> 24) & 0xFF;
+  memset (p + 4,
+         (context_handle->more_flags & LOCAL) ? 0 : 0xFF,
+         4);
+
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_encrypt ((void *)p, (void *)p, 8,
+                  &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT);
+
+  krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              ++seq_number);
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+  
+  memset (deskey, 0, sizeof(deskey));
+  memset (&schedule, 0, sizeof(schedule));
+  
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+mic_des3
+           (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,
+           krb5_keyblock *key
+           )
+{
+  u_char *p;
+  Checksum cksum;
+  u_char seq[8];
+
+  int32_t seq_number;
+  size_t len, total_len;
+
+  krb5_crypto crypto;
+  krb5_error_code kret;
+  krb5_data encdata;
+  char *tmp;
+  char ivec[8];
+
+  gssapi_krb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM);
+
+  message_token->length = total_len;
+  message_token->value  = malloc (total_len);
+  if (message_token->value == NULL) {
+      *minor_status = ENOMEM;
+      return GSS_S_FAILURE;
+  }
+
+  p = gssapi_krb5_make_header(message_token->value,
+                             len,
+                             "\x01\x01", /* TOK-ID */
+                             GSS_KRB5_MECHANISM);
+
+  memcpy (p, "\x04\x00", 2);   /* SGN_ALG = HMAC SHA1 DES3-KD */
+  p += 2;
+
+  memcpy (p, "\xff\xff\xff\xff", 4); /* filler */
+  p += 4;
+
+  /* this should be done in parts */
+
+  tmp = malloc (message_buffer->length + 8);
+  if (tmp == NULL) {
+      free (message_token->value);
+      *minor_status = ENOMEM;
+      return GSS_S_FAILURE;
+  }
+  memcpy (tmp, p - 8, 8);
+  memcpy (tmp + 8, message_buffer->value, message_buffer->length);
+
+  kret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+  if (kret) {
+      free (message_token->value);
+      free (tmp);
+      gssapi_krb5_set_error_string ();
+      *minor_status = kret;
+      return GSS_S_FAILURE;
+  }
+
+  kret = krb5_create_checksum (gssapi_krb5_context,
+                              crypto,
+                              KRB5_KU_USAGE_SIGN,
+                              0,
+                              tmp,
+                              message_buffer->length + 8,
+                              &cksum);
+  free (tmp);
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  if (kret) {
+      free (message_token->value);
+      gssapi_krb5_set_error_string ();
+      *minor_status = kret;
+      return GSS_S_FAILURE;
+  }
+
+  memcpy (p + 8, cksum.checksum.data, cksum.checksum.length);
+
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+  /* sequence number */
+  krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              &seq_number);
+
+  seq[0] = (seq_number >> 0)  & 0xFF;
+  seq[1] = (seq_number >> 8)  & 0xFF;
+  seq[2] = (seq_number >> 16) & 0xFF;
+  seq[3] = (seq_number >> 24) & 0xFF;
+  memset (seq + 4,
+         (context_handle->more_flags & LOCAL) ? 0 : 0xFF,
+         4);
+
+  kret = krb5_crypto_init(gssapi_krb5_context, key,
+                         ETYPE_DES3_CBC_NONE, &crypto);
+  if (kret) {
+      free (message_token->value);
+      gssapi_krb5_set_error_string ();
+      *minor_status = kret;
+      return GSS_S_FAILURE;
+  }
+
+  if (context_handle->more_flags & COMPAT_OLD_DES3)
+      memset(ivec, 0, 8);
+  else
+      memcpy(ivec, p + 8, 8);
+
+  kret = krb5_encrypt_ivec (gssapi_krb5_context,
+                           crypto,
+                           KRB5_KU_USAGE_SEQ,
+                           seq, 8, &encdata, ivec);
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  if (kret) {
+      free (message_token->value);
+      gssapi_krb5_set_error_string ();
+      *minor_status = kret;
+      return GSS_S_FAILURE;
+  }
+  
+  assert (encdata.length == 8);
+
+  memcpy (p, encdata.data, encdata.length);
+  krb5_data_free (&encdata);
+
+  krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              ++seq_number);
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+  
+  free_Checksum (&cksum);
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 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
+           )
+{
+  krb5_keyblock *key;
+  OM_uint32 ret;
+  krb5_keytype keytype;
+
+  ret = gss_krb5_get_subkey(context_handle, &key);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+  krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
+
+  switch (keytype) {
+  case KEYTYPE_DES :
+      ret = mic_des (minor_status, context_handle, qop_req,
+                    message_buffer, message_token, key);
+      break;
+  case KEYTYPE_DES3 :
+      ret = mic_des3 (minor_status, context_handle, qop_req,
+                     message_buffer, message_token, key);
+      break;
+  case KEYTYPE_ARCFOUR:
+  case KEYTYPE_ARCFOUR_56:
+      ret = _gssapi_get_mic_arcfour (minor_status, context_handle, qop_req,
+                                    message_buffer, message_token, key);
+      break;
+  default :
+      ret = _gssapi_mic_cfx (minor_status, context_handle, qop_req,
+                            message_buffer, message_token, key);
+      break;
+  }
+  krb5_free_keyblock (gssapi_krb5_context, key);
+  return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/gss_acquire_cred.3 b/src/kerberosV/src/lib/gssapi/gss_acquire_cred.3
new file mode 100644 (file)
index 0000000..7b58e04
--- /dev/null
@@ -0,0 +1,649 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: gss_acquire_cred.3,v 1.23 2004/09/06 07:08:58 lha Exp $
+.\"
+.Dd September  9, 2003
+.Dt GSS_ACQUIRE_CRED 3
+.Os HEIMDAL
+.Sh NAME
+.Nm gss_accept_sec_context ,
+.Nm gss_acquire_cred ,
+.Nm gss_add_cred ,
+.Nm gss_add_oid_set_member ,
+.Nm gss_canonicalize_name ,
+.Nm gss_compare_name ,
+.Nm gss_context_time ,
+.Nm gss_create_empty_oid_set ,
+.Nm gss_delete_sec_context ,
+.Nm gss_display_name ,
+.Nm gss_display_status ,
+.Nm gss_duplicate_name ,
+.Nm gss_export_name ,
+.Nm gss_export_sec_context ,
+.Nm gss_get_mic ,
+.Nm gss_import_name ,
+.Nm gss_import_sec_context ,
+.Nm gss_indicate_mechs ,
+.Nm gss_init_sec_context ,
+.Nm gss_inquire_context ,
+.Nm gss_inquire_cred ,
+.Nm gss_inquire_cred_by_mech ,
+.Nm gss_inquire_mechs_for_name ,
+.Nm gss_inquire_names_for_mech ,
+.Nm gss_krb5_ccache_name ,
+.Nm gss_krb5_compat_des3_mic ,
+.Nm gss_krb5_copy_ccache ,
+.Nm gsskrb5_extract_authz_data_from_sec_context ,
+.Nm gss_krb5_get_tkt_flags ,
+.Nm gss_process_context_token ,
+.Nm gss_release_buffer ,
+.Nm gss_release_cred ,
+.Nm gss_release_name ,
+.Nm gss_release_oid_set ,
+.Nm gss_seal ,
+.Nm gss_sign ,
+.Nm gss_test_oid_set_member ,
+.Nm gss_unseal ,
+.Nm gss_unwrap ,
+.Nm gss_verify ,
+.Nm gss_verify_mic ,
+.Nm gss_wrap ,
+.Nm gss_wrap_size_limit
+.Nd Generic Security Service Application Program Interface library
+.Sh LIBRARY
+GSS-API library (libgssapi, -lgssapi)
+.Sh SYNOPSIS
+.In gssapi.h
+.Pp
+.Ft OM_uint32
+.Fo gss_accept_sec_context
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t * context_handle"
+.Fa "const gss_cred_id_t acceptor_cred_handle"
+.Fa "const gss_buffer_t input_token_buffer"
+.Fa "const gss_channel_bindings_t input_chan_bindings"
+.Fa "gss_name_t * src_name"
+.Fa "gss_OID * mech_type"
+.Fa "gss_buffer_t output_token"
+.Fa "OM_uint32 * ret_flags"
+.Fa "OM_uint32 * time_rec"
+.Fa "gss_cred_id_t * delegated_cred_handle"
+.Fc
+.Pp
+.Ft OM_uint32
+.Fo gss_acquire_cred
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t desired_name"
+.Fa "OM_uint32 time_req"
+.Fa "const gss_OID_set desired_mechs"
+.Fa "gss_cred_usage_t cred_usage"
+.Fa "gss_cred_id_t * output_cred_handle"
+.Fa "gss_OID_set * actual_mechs"
+.Fa "OM_uint32 * time_rec"
+.Fc
+.Ft OM_uint32
+.Fo gss_add_cred
+.Fa "OM_uint32 *minor_status"
+.Fa "const gss_cred_id_t input_cred_handle"
+.Fa "const gss_name_t desired_name"
+.Fa "const gss_OID desired_mech"
+.Fa "gss_cred_usage_t cred_usage"
+.Fa "OM_uint32 initiator_time_req"
+.Fa "OM_uint32 acceptor_time_req"
+.Fa "gss_cred_id_t *output_cred_handle"
+.Fa "gss_OID_set *actual_mechs"
+.Fa "OM_uint32 *initiator_time_rec"
+.Fa "OM_uint32 *acceptor_time_rec"
+.Fc
+.Ft OM_uint32
+.Fo gss_add_oid_set_member
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_OID member_oid"
+.Fa "gss_OID_set * oid_set"
+.Fc
+.Ft OM_uint32
+.Fo gss_canonicalize_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t input_name"
+.Fa "const gss_OID mech_type"
+.Fa "gss_name_t * output_name"
+.Fc
+.Ft OM_uint32
+.Fo gss_compare_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t name1"
+.Fa "const gss_name_t name2"
+.Fa "int * name_equal"
+.Fc
+.Ft OM_uint32
+.Fo gss_context_time
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "OM_uint32 * time_rec"
+.Fc
+.Ft OM_uint32
+.Fo gss_create_empty_oid_set
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_OID_set * oid_set"
+.Fc
+.Ft OM_uint32
+.Fo gss_delete_sec_context
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t * context_handle"
+.Fa "gss_buffer_t output_token"
+.Fc
+.Ft OM_uint32
+.Fo gss_display_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t input_name"
+.Fa "gss_buffer_t output_name_buffer"
+.Fa "gss_OID * output_name_type"
+.Fc
+.Ft OM_uint32
+.Fo gss_display_status
+.Fa "OM_uint32 *minor_status"
+.Fa "OM_uint32 status_value"
+.Fa "int status_type"
+.Fa "const gss_OID mech_type"
+.Fa "OM_uint32 *message_context"
+.Fa "gss_buffer_t status_string"
+.Fc
+.Ft OM_uint32
+.Fo gss_duplicate_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t src_name"
+.Fa "gss_name_t * dest_name"
+.Fc
+.Ft OM_uint32
+.Fo gss_export_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t input_name"
+.Fa "gss_buffer_t exported_name"
+.Fc
+.Ft OM_uint32
+.Fo gss_export_sec_context
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t * context_handle"
+.Fa "gss_buffer_t interprocess_token"
+.Fc
+.Ft OM_uint32
+.Fo gss_get_mic
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "gss_qop_t qop_req"
+.Fa "const gss_buffer_t message_buffer"
+.Fa "gss_buffer_t message_token"
+.Fc
+.Ft OM_uint32
+.Fo gss_import_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_buffer_t input_name_buffer"
+.Fa "const gss_OID input_name_type"
+.Fa "gss_name_t * output_name"
+.Fc
+.Ft OM_uint32
+.Fo gss_import_sec_context
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_buffer_t interprocess_token"
+.Fa "gss_ctx_id_t * context_handle"
+.Fc
+.Ft OM_uint32
+.Fo gss_indicate_mechs
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_OID_set * mech_set"
+.Fc
+.Ft OM_uint32
+.Fo gss_init_sec_context
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_cred_id_t initiator_cred_handle"
+.Fa "gss_ctx_id_t * context_handle"
+.Fa "const gss_name_t target_name"
+.Fa "const gss_OID mech_type"
+.Fa "OM_uint32 req_flags"
+.Fa "OM_uint32 time_req"
+.Fa "const gss_channel_bindings_t input_chan_bindings"
+.Fa "const gss_buffer_t input_token"
+.Fa "gss_OID * actual_mech_type"
+.Fa "gss_buffer_t output_token"
+.Fa "OM_uint32 * ret_flags"
+.Fa "OM_uint32 * time_rec"
+.Fc
+.Ft OM_uint32
+.Fo gss_inquire_context
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "gss_name_t * src_name"
+.Fa "gss_name_t * targ_name"
+.Fa "OM_uint32 * lifetime_rec"
+.Fa "gss_OID * mech_type"
+.Fa "OM_uint32 * ctx_flags"
+.Fa "int * locally_initiated"
+.Fa "int * open_context"
+.Fc
+.Ft OM_uint32
+.Fo gss_inquire_cred
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_cred_id_t cred_handle"
+.Fa "gss_name_t * name"
+.Fa "OM_uint32 * lifetime"
+.Fa "gss_cred_usage_t * cred_usage"
+.Fa "gss_OID_set * mechanisms"
+.Fc
+.Ft OM_uint32
+.Fo gss_inquire_cred_by_mech
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_cred_id_t cred_handle"
+.Fa "const gss_OID mech_type"
+.Fa "gss_name_t * name"
+.Fa "OM_uint32 * initiator_lifetime"
+.Fa "OM_uint32 * acceptor_lifetime"
+.Fa "gss_cred_usage_t * cred_usage"
+.Fc
+.Ft OM_uint32
+.Fo gss_inquire_mechs_for_name
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_name_t input_name"
+.Fa "gss_OID_set * mech_types"
+.Fc
+.Ft OM_uint32
+.Fo gss_inquire_names_for_mech
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_OID mechanism"
+.Fa "gss_OID_set * name_types"
+.Fc
+.Ft OM_uint32
+.Fo gss_krb5_ccache_name
+.Fa "OM_uint32 *minor"
+.Fa "const char *name"
+.Fa "const char **old_name"
+.Fc
+.Ft OM_uint32
+.Fo gss_krb5_copy_ccache
+.Fa "OM_uint32 *minor"
+.Fa "gss_cred_id_t cred"
+.Fa "krb5_ccache out"
+.Fc
+.Ft OM_uint32
+.Fo gss_krb5_compat_des3_mic
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "int onoff"
+.Fc
+.Ft OM_uint32
+.Fo gsskrb5_extract_authz_data_from_sec_context
+.Fa "OM_uint32 *minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "int ad_type"
+.Fa "gss_buffer_t ad_data"
+.Fc
+.Ft OM_uint32
+.Fo gss_krb5_get_tkt_flags
+.Fa "OM_uint32 *minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "OM_uint32 *tkt_flags"
+.Fc
+.Ft OM_uint32
+.Fo gss_process_context_token
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "const gss_buffer_t token_buffer"
+.Fc
+.Ft OM_uint32
+.Fo gss_release_buffer
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_buffer_t buffer"
+.Fc
+.Ft OM_uint32
+.Fo gss_release_cred
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_cred_id_t * cred_handle"
+.Fc
+.Ft OM_uint32
+.Fo gss_release_name
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_name_t * input_name"
+.Fc
+.Ft OM_uint32
+.Fo gss_release_oid_set
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_OID_set * set"
+.Fc
+.Ft OM_uint32
+.Fo gss_seal
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "int conf_req_flag"
+.Fa "int qop_req"
+.Fa "gss_buffer_t input_message_buffer"
+.Fa "int * conf_state"
+.Fa "gss_buffer_t output_message_buffer"
+.Fc
+.Ft OM_uint32
+.Fo gss_sign
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "int qop_req"
+.Fa "gss_buffer_t message_buffer"
+.Fa "gss_buffer_t message_token"
+.Fc
+.Ft OM_uint32
+.Fo gss_test_oid_set_member
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_OID member"
+.Fa "const gss_OID_set set"
+.Fa "int * present"
+.Fc
+.Ft OM_uint32
+.Fo gss_unseal
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "gss_buffer_t input_message_buffer"
+.Fa "gss_buffer_t output_message_buffer"
+.Fa "int * conf_state"
+.Fa "int * qop_state"
+.Fc
+.Ft OM_uint32
+.Fo gss_unwrap
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "const gss_buffer_t input_message_buffer"
+.Fa "gss_buffer_t output_message_buffer"
+.Fa "int * conf_state"
+.Fa "gss_qop_t * qop_state"
+.Fc
+.Ft OM_uint32
+.Fo gss_verify
+.Fa "OM_uint32 * minor_status"
+.Fa "gss_ctx_id_t context_handle"
+.Fa "gss_buffer_t message_buffer"
+.Fa "gss_buffer_t token_buffer"
+.Fa "int * qop_state"
+.Fc
+.Ft OM_uint32
+.Fo gss_verify_mic
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "const gss_buffer_t message_buffer"
+.Fa "const gss_buffer_t token_buffer"
+.Fa "gss_qop_t * qop_state"
+.Fc
+.Ft OM_uint32
+.Fo gss_wrap
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "int conf_req_flag"
+.Fa "gss_qop_t qop_req"
+.Fa "const gss_buffer_t input_message_buffer"
+.Fa "int * conf_state"
+.Fa "gss_buffer_t output_message_buffer"
+.Fc
+.Ft OM_uint32
+.Fo gss_wrap_size_limit
+.Fa "OM_uint32 * minor_status"
+.Fa "const gss_ctx_id_t context_handle"
+.Fa "int conf_req_flag"
+.Fa "gss_qop_t qop_req"
+.Fa "OM_uint32 req_output_size"
+.Fa "OM_uint32 * max_input_size"
+.Fc
+.Sh DESCRIPTION
+Generic Security Service API (GSS-API) version 2, and its C binding,
+are described in RFC 2743 and RFC 2744.
+Version 1 (deprecated) of the C binding is described in RFC 1509.
+.Pp
+Heimdals GSS-API implementation supports the following mechanisms
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+.Li GSS_KRB5_MECHANISM
+.It
+.Li GSS_SPNEGO_MECHANISM
+.El
+.Pp
+GSS-API have generic name types that all mechanism are supposed to
+implement (if possible):
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+.Li GSS_C_NT_USER_NAME
+.It
+.Li GSS_C_NT_MACHINE_UID_NAME
+.It
+.Li GSS_C_NT_STRING_UID_NAME
+.It
+.Li GSS_C_NT_HOSTBASED_SERVICE
+.It
+.Li GSS_C_NT_ANONYMOUS
+.It
+.Li GSS_C_NT_EXPORT_NAME
+.El
+.Pp
+GSS-API implementations that supports Kerberos 5 have some additional
+name types:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+.Li GSS_KRB5_NT_PRINCIPAL_NAME
+.It
+.Li GSS_KRB5_NT_USER_NAME
+.It
+.Li GSS_KRB5_NT_MACHINE_UID_NAME
+.It
+.Li GSS_KRB5_NT_STRING_UID_NAME
+.El
+.Pp
+In GSS-API, names have two forms, internal names and contiguous string
+names.
+.Bl -bullet
+.It
+.Li Internal name and mechanism name
+.Pp
+Internal names are implementation specific representation of
+a GSS-API name.
+.Li Mechanism names
+special form of internal names corresponds to one and only one mechanism.
+.Pp
+In GSS-API an internal name is stored in a
+.Dv gss_name_t .
+.It
+.Li Contiguous string name and exported name
+.Pp
+Contiguous string names are gssapi names stored in a
+.Dv OCTET STRING
+that together with a name type identifier (OID) uniquely specifies a
+gss-name.
+A special form of the contiguous string name is the exported name that
+have a OID embedded in the string to make it unique.
+Exported name have the nametype
+.Dv GSS_C_NT_EXPORT_NAME .
+.Pp
+In GSS-API an contiguous string name is stored in a
+.Dv gss_buffer_t .
+.Pp
+Exported names also have the property that they are specified by the
+mechanism itself and compatible between diffrent GSS-API
+implementations.
+.El
+.Sh ACCESS CONTROL
+There are two ways of comparing GSS-API names, either comparing two
+internal names with each other or two contiguous string names with
+either other.
+.Pp
+To compare two internal names with each other, import (if needed) the
+names with
+.Fn gss_import_name
+into the GSS-API implementation and the compare the imported name with
+.Fn gss_compare_name .
+.Pp
+Importing names can be slow, so when its possible to store exported
+names in the access control list, comparing contiguous string name
+might be better.
+.Pp
+when comparing contiguous string name, first export them into a
+.Dv GSS_C_NT_EXPORT_NAME
+name with
+.Fn gss_export_name
+and then compare with
+.Xr memcmp 3 .
+.Pp
+Note that there are might be a difference between the two methods of
+comparing names.
+The first (using
+.Fn gss_compare_name )
+will compare to (unauthenticated) names are the same.
+The second will compare if a mechanism will authenticate them as the
+same principal.
+.Pp
+For example, if
+.Fn gss_import_name
+name was used with
+.Dv GSS_C_NO_OID
+the default syntax is used for all mechanism the GSS-API
+implementation supports.
+When compare the imported name of
+.Dv GSS_C_NO_OID
+it may match serveral mechanism names (MN).
+.Pp
+The resulting name from
+.Fn gss_display_name
+must not be used for acccess control.
+.Sh FUNCTIONS
+.Fn gss_display_name
+takes the gss name in
+.Fa input_name
+and puts a printable form in
+.Fa output_name_buffer .
+.Fa output_name_buffer
+should be freed when done using
+.Fn gss_release_buffer .
+.Fa output_name_type
+can either be
+.Dv NULL
+or a pointer to a
+.Li gss_OID
+and will in the latter case contain the OID type of the name.
+The name must only be used for printing.
+If access control is needed, see section
+.Sx ACCESS CONTROL .
+.Pp
+.Fn gss_inquire_context
+returns information about the context.
+Information is available even after the context have expired.
+.Fa lifetime_rec
+argument is set to
+.Dv GSS_C_INDEFINITE
+(dont expire) or the number of seconds that the context is still valid.
+A value of 0 means that the context is expired.
+.Fa mech_type
+argument should be considered readonly and must not be released.
+.Fa src_name
+and
+.Fn dest_name
+are both mechanims names and must be released with
+.Fn gss_release_name
+when no longer used.
+.Pp
+.Nm gss_context_time
+will return the amount of time (in seconds) of the context is still
+valid.
+If its expired
+.Fa time_rec
+will be set to 0 and
+.Dv GSS_S_CONTEXT_EXPIRED
+returned.
+.Pp
+.Fn gss_sign ,
+.Fn gss_verify ,
+.Fn gss_seal ,
+and
+.Fn gss_unseal
+are part of the GSS-API V1 interface and are obsolete.
+The functions should not be used for new applications.
+They are provided so that version 1 applications can link against the
+library.
+.Sh EXTENSIONS
+.Fn gss_krb5_ccache_name
+sets the internal kerberos 5 credential cache name to
+.Fa name .
+The old name is returned in
+.Fa old_name ,
+and must not be freed.
+The data allocated for
+.Fa old_name
+is free upon next call to
+.Fn gss_krb5_ccache_name .
+This function is not threadsafe if
+.Fa old_name
+argument is used.
+.Pp
+.Fn gss_krb5_copy_ccache
+will extract the krb5 credentials that are transferred from the
+initiator to the acceptor when using token delegation in the Kerberos
+mechanism.
+The acceptor receives the delegated token in the last argument to
+.Fn gss_accept_sec_context .
+.Pp
+.Fn gsskrb5_register_acceptor_identity
+sets the Kerberos 5 principal that the acceptor will use.
+.Pp
+.Fn gsskrb5_extract_authz_data_from_sec_context
+extracts the Kerberos authorizationdata that may be stored within the
+context.
+Tha caller must free the returned buffer
+.Fa ad_data
+with
+.Fn gss_release_buffer
+upon success.
+.Pp
+.Fn gss_krb5_get_tkt_flags
+return the ticket flags for the kerberos ticket receive when
+authenticating the initiator.
+Only valid on the acceptor context.
+.Pp
+.Fn gss_krb5_compat_des3_mic
+turns on or off the compatibility with older version of Heimdal using
+des3 get and verify mic, this is way to programmatically set the
+[gssapi]broken_des3_mic and [gssapi]correct_des3_mic flags (see
+COMPATIBILITY section in
+.Xr gssapi 3 ) .
+If the CPP symbol
+.Dv GSS_C_KRB5_COMPAT_DES3_MIC
+is present,
+.Fn gss_krb5_compat_des3_mic
+exists.
+.Fn gss_krb5_compat_des3_mic
+will be removed in a later version of the GSS-API library.
+.Sh SEE ALSO
+.Xr gssapi 3 ,
+.Xr krb5 3 ,
+.Xr krb5_ccache 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/gssapi/gssapi.3 b/src/kerberosV/src/lib/gssapi/gssapi.3
new file mode 100644 (file)
index 0000000..5ee61fa
--- /dev/null
@@ -0,0 +1,176 @@
+.\" Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: gssapi.3,v 1.11 2005/04/20 10:46:15 lha Exp $
+.\"
+.Dd April 20, 2005
+.Dt GSSAPI 3
+.Os
+.Sh NAME
+.Nm gssapi
+.Nd Generic Security Service Application Program Interface library
+.Sh LIBRARY
+GSS-API Library (libgssapi, -lgssapi)
+.Sh DESCRIPTION
+The Generic Security Service Application Program Interface (GSS-API)
+provides security services to callers in a generic fashion,
+supportable with a range of underlying mechanisms and technologies and
+hence allowing source-level portability of applications to different
+environments.
+.Pp
+The GSS-API implementation in Heimdal implements the Kerberos 5 and
+the SPNEGO GSS-API security mechanisms.
+.Sh LIST OF FUNCTIONS
+These functions constitute the gssapi library,
+.Em libgssapi .
+Declarations for these functions may be obtained from the include file
+.Pa gssapi.h .
+.sp 2
+.nf
+.ta \w'gss_inquire_names_for_mech'u+2n +\w'Description goes here'u
+\fIName/Page\fP        \fIDescription\fP
+.ta \w'gss_inquire_names_for_mech'u+2n +\w'Description goes here'u+6nC
+.sp 5p
+gss_accept_sec_context.3
+gss_acquire_cred.3
+gss_add_cred.3
+gss_add_oid_set_member.3
+gss_canonicalize_name.3
+gss_compare_name.3
+gss_context_time.3
+gss_create_empty_oid_set.3
+gss_delete_sec_context.3
+gss_display_name.3
+gss_display_status.3
+gss_duplicate_name.3
+gss_export_name.3
+gss_export_sec_context.3
+gss_get_mic.3
+gss_import_name.3
+gss_import_sec_context.3
+gss_indicate_mechs.3
+gss_init_sec_context.3
+gss_inquire_context.3
+gss_inquire_cred.3
+gss_inquire_cred_by_mech.3
+gss_inquire_mechs_for_name.3
+gss_inquire_names_for_mech.3
+gss_krb5_ccache_name.3
+gss_krb5_copy_ccache.3
+gss_krb5_compat_des3_mic.3
+gss_krb5_extract_authz_data_from_sec_context.3
+gss_process_context_token.3
+gss_release_buffer.3
+gss_release_cred.3
+gss_release_name.3
+gss_release_oid_set.3
+gss_seal.3
+gss_sign.3
+gss_test_oid_set_member.3
+gss_unseal.3
+gss_unwrap.3
+gss_verify.3
+gss_verify_mic.3
+gss_wrap.3
+gss_wrap_size_limit.3
+.ta
+.Fi
+.Sh COMPATIBILITY
+The
+.Nm Heimdal
+GSS-API implementation had a bug in releases before 0.6 that made it
+fail to inter-operate when using DES3 with other GSS-API
+implementations when using
+.Fn gss_get_mic
+/
+.Fn gss_verify_mic .
+It is possible to modify the behavior of the generator of the MIC with
+the
+.Pa krb5.conf
+configuration file so that old clients/servers will still
+work.
+.Pp
+New clients/servers will try both the old and new MIC in Heimdal 0.6.
+In 0.7 it will check only if configured - the compatibility code will
+be removed in 0.8.
+.Pp
+Heimdal 0.6 still generates by default the broken GSS-API DES3 mic,
+this will change in 0.7 to generate correct des3 mic.
+.Pp
+To turn on compatibility with older clients and servers, change the
+.Nm [gssapi]
+.Ar broken_des3_mic
+in
+.Pa krb5.conf
+that contains a list of globbing expressions that will be matched
+against the server name.
+To turn off generation of the old (incompatible) mic of the MIC use
+.Nm [gssapi]
+.Ar correct_des3_mic .
+.Pp
+If a match for a entry is in both
+.Nm [gssapi]
+.Ar correct_des3_mic
+and
+.Nm [gssapi]
+.Ar broken_des3_mic ,
+the later will override.
+.Pp
+This config option modifies behaviour for both clients and servers.
+.Pp
+Microsoft implemented SPNEGO to Windows2000, however, they manage to
+get it wrong, their implementation didn't fill in the MechListMIC in
+the reply token with the right content.
+There is a work around for this problem, but not all implementation
+support it.
+.Pp
+Heimdal defaults to correct SPNEGO when the the kerberos
+implementation uses CFX, or when its configured by the user.
+To turn on compatibility with peers, use option
+.Nm [gssapi]
+.Ar require_mechlist_mic .
+.Sh EXAMPLES
+.Bd -literal -offset indent
+[gssapi]
+       broken_des3_mic = cvs/*@SU.SE
+       broken_des3_mic = host/*@E.KTH.SE
+       correct_des3_mic = host/*@SU.SE
+       require_mechlist_mic = host/*@SU.SE
+.Ed
+.Sh BUGS
+All of 0.5.x versions of
+.Nm heimdal
+had broken token delegations in the client side, the server side was
+correct.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/gssapi/gssapi.h b/src/kerberosV/src/lib/gssapi/gssapi.h
new file mode 100644 (file)
index 0000000..eb87606
--- /dev/null
@@ -0,0 +1,797 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: gssapi.h,v 1.37 2005/02/21 08:48:15 lukeh Exp $ */
+
+#ifndef GSSAPI_H_
+#define GSSAPI_H_
+
+/*
+ * First, include stddef.h to get size_t defined.
+ */
+#include <stddef.h>
+
+#include <krb5-types.h>
+
+/*
+ * Now define the three implementation-dependent types.
+ */
+
+typedef u_int32_t OM_uint32;
+
+typedef u_int32_t gss_uint32;
+
+/*
+ * This is to avoid having to include <krb5.h>
+ */
+
+struct krb5_auth_context_data;
+
+struct Principal;
+
+/* typedef void *gss_name_t; */
+
+typedef struct Principal *gss_name_t;
+
+struct gss_ctx_id_t_desc_struct;
+typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t;
+
+typedef struct gss_OID_desc_struct {
+      OM_uint32 length;
+      void      *elements;
+} gss_OID_desc, *gss_OID;
+
+typedef struct gss_OID_set_desc_struct  {
+      size_t     count;
+      gss_OID    elements;
+} gss_OID_set_desc, *gss_OID_set;
+
+struct krb5_keytab_data;
+
+struct krb5_ccache_data;
+
+typedef int gss_cred_usage_t;
+
+struct gss_cred_id_t_desc_struct;
+typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t;
+
+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
+ */
+typedef OM_uint32 gss_qop_t;
+
+/*
+ * Flag bits for context-level services.
+ */
+#define GSS_C_DELEG_FLAG 1
+#define GSS_C_MUTUAL_FLAG 2
+#define GSS_C_REPLAY_FLAG 4
+#define GSS_C_SEQUENCE_FLAG 8
+#define GSS_C_CONF_FLAG 16
+#define GSS_C_INTEG_FLAG 32
+#define GSS_C_ANON_FLAG 64
+#define GSS_C_PROT_READY_FLAG 128
+#define GSS_C_TRANS_FLAG 256
+
+/*
+ * Credential usage options
+ */
+#define GSS_C_BOTH 0
+#define GSS_C_INITIATE 1
+#define GSS_C_ACCEPT 2
+
+/*
+ * Status code types for gss_display_status
+ */
+#define GSS_C_GSS_CODE 1
+#define GSS_C_MECH_CODE 2
+
+/*
+ * The constant definitions for channel-bindings address families
+ */
+#define GSS_C_AF_UNSPEC     0
+#define GSS_C_AF_LOCAL      1
+#define GSS_C_AF_INET       2
+#define GSS_C_AF_IMPLINK    3
+#define GSS_C_AF_PUP        4
+#define GSS_C_AF_CHAOS      5
+#define GSS_C_AF_NS         6
+#define GSS_C_AF_NBS        7
+#define GSS_C_AF_ECMA       8
+#define GSS_C_AF_DATAKIT    9
+#define GSS_C_AF_CCITT      10
+#define GSS_C_AF_SNA        11
+#define GSS_C_AF_DECnet     12
+#define GSS_C_AF_DLI        13
+#define GSS_C_AF_LAT        14
+#define GSS_C_AF_HYLINK     15
+#define GSS_C_AF_APPLETALK  16
+#define GSS_C_AF_BSC        17
+#define GSS_C_AF_DSS        18
+#define GSS_C_AF_OSI        19
+#define GSS_C_AF_X25        21
+#define GSS_C_AF_INET6     24
+
+#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 define GSS_C_QOP_DEFAULT to be either zero
+ * (as done here) to mean "default protection", or 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
+
+#define GSS_KRB5_CONF_C_QOP_DES                0x0100
+#define GSS_KRB5_CONF_C_QOP_DES3_KD    0x0200
+
+/*
+ * Expiration time of 2^32-1 seconds means infinite lifetime for a
+ * credential or security context
+ */
+#define GSS_C_INDEFINITE 0xfffffffful
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * 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.
+ */
+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.
+ */
+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.
+ */
+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
+ */
+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.
+ */
+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.
+ */
+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.
+ */
+extern gss_OID GSS_C_NT_EXPORT_NAME;
+
+/*
+ * RFC2478, SPNEGO:
+ *  The security mechanism of the initial
+ *  negotiation token is identified by the Object Identifier
+ *  iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2).
+ */
+extern gss_OID GSS_SPNEGO_MECHANISM;
+
+/*
+ * This if for kerberos5 names.
+ */
+
+extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME;
+extern gss_OID GSS_KRB5_NT_USER_NAME;
+extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME;
+extern gss_OID GSS_KRB5_NT_STRING_UID_NAME;
+
+extern gss_OID GSS_KRB5_MECHANISM;
+
+/* for compatibility with MIT api */
+
+#define gss_mech_krb5 GSS_KRB5_MECHANISM
+#define gss_krb5_nt_general_name GSS_KRB5_NT_PRINCIPAL_NAME
+
+/* 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 0377ul
+#define GSS_C_ROUTINE_ERROR_MASK 0377ul
+#define GSS_C_SUPPLEMENTARY_MASK 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 \
+                             (1ul << GSS_C_CALLING_ERROR_OFFSET)
+#define GSS_S_CALL_INACCESSIBLE_WRITE \
+                             (2ul << GSS_C_CALLING_ERROR_OFFSET)
+#define GSS_S_CALL_BAD_STRUCTURE \
+                             (3ul << GSS_C_CALLING_ERROR_OFFSET)
+
+/*
+ * Routine errors:
+ */
+#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET)
+
+#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_MIC GSS_S_BAD_SIG
+#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET)
+
+/*
+ * Supplementary info bits:
+ */
+#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
+#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
+#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
+#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
+#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
+
+/*
+ * From RFC1964:
+ *
+ * 4.1.1. Non-Kerberos-specific codes
+ */
+
+#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1
+           /* "No @ in SERVICE-NAME name string" */
+#define GSS_KRB5_S_G_BAD_STRING_UID 2
+           /* "STRING-UID-NAME contains nondigits" */
+#define GSS_KRB5_S_G_NOUSER 3
+           /* "UID does not resolve to username" */
+#define GSS_KRB5_S_G_VALIDATE_FAILED 4
+           /* "Validation error" */
+#define GSS_KRB5_S_G_BUFFER_ALLOC 5
+           /* "Couldn't allocate gss_buffer_t data" */
+#define GSS_KRB5_S_G_BAD_MSG_CTX 6
+           /* "Message context invalid" */
+#define GSS_KRB5_S_G_WRONG_SIZE 7
+           /* "Buffer is the wrong size" */
+#define GSS_KRB5_S_G_BAD_USAGE 8
+           /* "Credential usage type is unknown" */
+#define GSS_KRB5_S_G_UNKNOWN_QOP 9
+           /* "Unknown quality of protection specified" */
+
+  /*
+   * 4.1.2. Kerberos-specific-codes
+   */
+
+#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10
+           /* "Principal in credential cache does not match desired name" */
+#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11
+           /* "No principal in keytab matches desired name" */
+#define GSS_KRB5_S_KG_TGT_MISSING 12
+           /* "Credential cache has no TGT" */
+#define GSS_KRB5_S_KG_NO_SUBKEY 13
+           /* "Authenticator has no subkey" */
+#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14
+           /* "Context is already fully established" */
+#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15
+           /* "Unknown signature type in token" */
+#define GSS_KRB5_S_KG_BAD_LENGTH 16
+           /* "Invalid field length in token" */
+#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17
+           /* "Attempt to use incomplete security context" */
+
+/*
+ * Finally, function prototypes for the GSS-API routines.
+ */
+
+OM_uint32 gss_acquire_cred
+           (OM_uint32 * /*minor_status*/,
+            const gss_name_t /*desired_name*/,
+            OM_uint32 /*time_req*/,
+            const 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 gss_release_cred
+           (OM_uint32 * /*minor_status*/,
+            gss_cred_id_t * /*cred_handle*/
+           );
+
+OM_uint32 gss_init_sec_context
+           (OM_uint32 * /*minor_status*/,
+            const gss_cred_id_t /*initiator_cred_handle*/,
+            gss_ctx_id_t * /*context_handle*/,
+            const gss_name_t /*target_name*/,
+            const gss_OID /*mech_type*/,
+            OM_uint32 /*req_flags*/,
+            OM_uint32 /*time_req*/,
+            const gss_channel_bindings_t /*input_chan_bindings*/,
+            const 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*/,
+            const gss_cred_id_t /*acceptor_cred_handle*/,
+            const gss_buffer_t /*input_token_buffer*/,
+            const 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*/,
+            const gss_ctx_id_t /*context_handle*/,
+            const 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*/,
+            const gss_ctx_id_t /*context_handle*/,
+            OM_uint32 * /*time_rec*/
+           );
+
+OM_uint32 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 gss_verify_mic
+           (OM_uint32 * /*minor_status*/,
+            const gss_ctx_id_t /*context_handle*/,
+            const gss_buffer_t /*message_buffer*/,
+            const gss_buffer_t /*token_buffer*/,
+            gss_qop_t * /*qop_state*/
+           );
+
+OM_uint32 gss_wrap
+           (OM_uint32 * /*minor_status*/,
+            const gss_ctx_id_t /*context_handle*/,
+            int /*conf_req_flag*/,
+            gss_qop_t /*qop_req*/,
+            const gss_buffer_t /*input_message_buffer*/,
+            int * /*conf_state*/,
+            gss_buffer_t /*output_message_buffer*/
+           );
+
+OM_uint32 gss_unwrap
+           (OM_uint32 * /*minor_status*/,
+            const gss_ctx_id_t /*context_handle*/,
+            const 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*/,
+            const 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*/,
+            const gss_name_t /*name1*/,
+            const gss_name_t /*name2*/,
+            int * /*name_equal*/
+           );
+
+OM_uint32 gss_display_name
+           (OM_uint32 * /*minor_status*/,
+            const 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*/,
+            const gss_buffer_t /*input_name_buffer*/,
+            const gss_OID /*input_name_type*/,
+            gss_name_t * /*output_name*/
+           );
+
+OM_uint32 gss_export_name
+           (OM_uint32  * /*minor_status*/,
+            const gss_name_t /*input_name*/,
+            gss_buffer_t /*exported_name*/
+           );
+
+OM_uint32 gss_release_name
+           (OM_uint32 * /*minor_status*/,
+            gss_name_t * /*input_name*/
+           );
+
+OM_uint32 gss_release_buffer
+           (OM_uint32 * /*minor_status*/,
+            gss_buffer_t /*buffer*/
+           );
+
+OM_uint32 gss_release_oid_set
+           (OM_uint32 * /*minor_status*/,
+            gss_OID_set * /*set*/
+           );
+
+OM_uint32 gss_inquire_cred
+           (OM_uint32 * /*minor_status*/,
+            const 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 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 * /*open_context*/
+           );
+
+OM_uint32 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 gss_add_cred (
+            OM_uint32 * /*minor_status*/,
+            const gss_cred_id_t /*input_cred_handle*/,
+            const gss_name_t /*desired_name*/,
+            const 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_inquire_cred_by_mech (
+            OM_uint32 * /*minor_status*/,
+            const gss_cred_id_t /*cred_handle*/,
+            const 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_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*/,
+            const gss_buffer_t /*interprocess_token*/,
+            gss_ctx_id_t * /*context_handle*/
+           );
+
+OM_uint32 gss_create_empty_oid_set (
+            OM_uint32 * /*minor_status*/,
+            gss_OID_set * /*oid_set*/
+           );
+
+OM_uint32 gss_add_oid_set_member (
+            OM_uint32 * /*minor_status*/,
+            const gss_OID /*member_oid*/,
+            gss_OID_set * /*oid_set*/
+           );
+
+OM_uint32 gss_test_oid_set_member (
+            OM_uint32 * /*minor_status*/,
+            const gss_OID /*member*/,
+            const gss_OID_set /*set*/,
+            int * /*present*/
+           );
+
+OM_uint32 gss_inquire_names_for_mech (
+            OM_uint32 * /*minor_status*/,
+            const gss_OID /*mechanism*/,
+            gss_OID_set * /*name_types*/
+           );
+
+OM_uint32 gss_inquire_mechs_for_name (
+            OM_uint32 * /*minor_status*/,
+            const gss_name_t /*input_name*/,
+            gss_OID_set * /*mech_types*/
+           );
+
+OM_uint32 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 gss_duplicate_name (
+            OM_uint32 * /*minor_status*/,
+            const gss_name_t /*src_name*/,
+            gss_name_t * /*dest_name*/
+           );
+
+/*
+ * The following routines are obsolete variants of gss_get_mic,
+ * gss_verify_mic, gss_wrap 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, both to allow
+ * GSSAPI V1 applications to link against GSSAPI V2 implementations,
+ * and to retain the slight parameter type differences between the
+ * obsolete versions of these routines and their current forms.
+ */
+
+OM_uint32 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 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 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 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*/
+           );
+
+/*
+ * kerberos mechanism specific functions
+ */
+
+OM_uint32
+gss_krb5_ccache_name(OM_uint32 * /*minor_status*/, 
+                    const char * /*name */,
+                    const char ** /*out_name */);
+
+OM_uint32 gsskrb5_register_acceptor_identity
+        (const char */*identity*/);
+
+OM_uint32 gss_krb5_copy_ccache
+       (OM_uint32 */*minor*/,
+        gss_cred_id_t /*cred*/,
+        struct krb5_ccache_data */*out*/);
+
+OM_uint32 gss_krb5_get_tkt_flags
+       (OM_uint32 */*minor*/,
+        gss_ctx_id_t /*context_handle*/,
+        OM_uint32 */*tkt_flags*/);
+
+OM_uint32
+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*/);
+
+#define GSS_C_KRB5_COMPAT_DES3_MIC 1
+
+OM_uint32
+gss_krb5_compat_des3_mic(OM_uint32 *, gss_ctx_id_t, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GSSAPI_H_ */
diff --git a/src/kerberosV/src/lib/gssapi/gssapi_locl.h b/src/kerberosV/src/lib/gssapi/gssapi_locl.h
new file mode 100644 (file)
index 0000000..a942760
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: gssapi_locl.h,v 1.39 2005/05/30 20:53:46 lha Exp $ */
+
+#ifndef GSSAPI_LOCL_H
+#define GSSAPI_LOCL_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <krb5_locl.h>
+#include <gssapi.h>
+#include <assert.h>
+
+#include "cfx.h"
+#include "arcfour.h"
+
+#include "spnego_asn1.h"
+
+/*
+ *
+ */
+
+struct gss_msg_order;
+
+typedef struct gss_ctx_id_t_desc_struct {
+  struct krb5_auth_context_data *auth_context;
+  gss_name_t source, target;
+  OM_uint32 flags;
+  enum { LOCAL = 1, OPEN = 2, 
+        COMPAT_OLD_DES3 = 4,
+         COMPAT_OLD_DES3_SELECTED = 8,
+        ACCEPTOR_SUBKEY = 16
+  } more_flags;
+  struct krb5_ticket *ticket;
+  OM_uint32 lifetime;
+  HEIMDAL_MUTEX ctx_id_mutex;
+  struct gss_msg_order *order;
+} gss_ctx_id_t_desc;
+
+typedef struct gss_cred_id_t_desc_struct {
+  gss_name_t principal;
+  struct krb5_keytab_data *keytab;
+  OM_uint32 lifetime;
+  gss_cred_usage_t usage;
+  gss_OID_set mechanisms;
+  struct krb5_ccache_data *ccache;
+  HEIMDAL_MUTEX cred_id_mutex;
+} gss_cred_id_t_desc;
+
+/*
+ *
+ */
+
+extern krb5_context gssapi_krb5_context;
+
+extern krb5_keytab gssapi_krb5_keytab;
+extern HEIMDAL_MUTEX gssapi_keytab_mutex;
+
+struct gssapi_thr_context {
+    HEIMDAL_MUTEX mutex;
+    char *error_string;
+};
+
+/*
+ * Prototypes
+ */
+
+krb5_error_code gssapi_krb5_init (void);
+
+#define GSSAPI_KRB5_INIT() do {                                        \
+    krb5_error_code kret;                                      \
+    if((kret = gssapi_krb5_init ()) != 0) {    \
+       *minor_status = kret;                                   \
+       return GSS_S_FAILURE;                                   \
+    }                                                          \
+} while (0)
+
+struct gssapi_thr_context *
+gssapi_get_thread_context(int);
+
+void
+gsskrb5_is_cfx(gss_ctx_id_t, int *);
+
+OM_uint32
+gssapi_krb5_create_8003_checksum (
+                     OM_uint32 *minor_status,
+                     const gss_channel_bindings_t input_chan_bindings,
+                     OM_uint32 flags,
+                      const krb5_data *fwd_data,
+                     Checksum *result);
+
+OM_uint32
+gssapi_krb5_verify_8003_checksum (
+                     OM_uint32 *minor_status,
+                     const gss_channel_bindings_t input_chan_bindings,
+                     const Checksum *cksum,
+                     OM_uint32 *flags,
+                      krb5_data *fwd_data);
+
+void
+_gssapi_encap_length (size_t data_len,
+                     size_t *len,
+                     size_t *total_len,
+                     const gss_OID mech);
+
+void
+gssapi_krb5_encap_length (size_t data_len,
+                         size_t *len,
+                         size_t *total_len,
+                         const gss_OID mech);
+
+
+
+OM_uint32
+_gssapi_encapsulate(OM_uint32 *minor_status,
+                   const krb5_data *in_data,
+                   gss_buffer_t output_token,
+                   const gss_OID mech);
+
+
+OM_uint32
+gssapi_krb5_encapsulate(OM_uint32 *minor_status,    
+                       const krb5_data *in_data,
+                       gss_buffer_t output_token,
+                       const u_char *type,
+                       const gss_OID mech);
+
+OM_uint32
+gssapi_krb5_decapsulate(OM_uint32 *minor_status,
+                       gss_buffer_t input_token_buffer,
+                       krb5_data *out_data,
+                       char *type,
+                       gss_OID oid);
+
+u_char *
+gssapi_krb5_make_header (u_char *p,
+                        size_t len,
+                        const u_char *type,
+                        const gss_OID mech);
+
+u_char *
+_gssapi_make_mech_header(u_char *p,
+                        size_t len,
+                        const gss_OID mech);
+
+OM_uint32
+_gssapi_verify_mech_header(u_char **str,
+                          size_t total_len,
+                          gss_OID oid);
+
+OM_uint32
+gssapi_krb5_verify_header(u_char **str,
+                         size_t total_len,
+                         u_char *type,
+                         gss_OID oid);
+
+OM_uint32
+_gssapi_decapsulate(OM_uint32 *minor_status,
+                   gss_buffer_t input_token_buffer,
+                   krb5_data *out_data,
+                   const gss_OID mech);
+
+
+ssize_t
+gssapi_krb5_get_mech (const u_char *, size_t, const u_char **);
+
+OM_uint32
+_gssapi_verify_pad(gss_buffer_t, size_t, size_t *);
+
+OM_uint32
+gss_verify_mic_internal(OM_uint32 * minor_status,
+                       const gss_ctx_id_t context_handle,
+                       const gss_buffer_t message_buffer,
+                       const gss_buffer_t token_buffer,
+                       gss_qop_t * qop_state,
+                       char * type);
+
+OM_uint32
+gss_krb5_get_subkey(const gss_ctx_id_t context_handle,
+                   krb5_keyblock **key);
+
+krb5_error_code
+gss_address_to_krb5addr(OM_uint32 gss_addr_type,
+                        gss_buffer_desc *gss_addr,
+                        int16_t port,
+                        krb5_address *address);
+
+/* sec_context flags */
+
+#define SC_LOCAL_ADDRESS  0x01
+#define SC_REMOTE_ADDRESS 0x02
+#define SC_KEYBLOCK      0x04
+#define SC_LOCAL_SUBKEY          0x08
+#define SC_REMOTE_SUBKEY  0x10
+
+int
+gss_oid_equal(const gss_OID a, const gss_OID b);
+
+void
+gssapi_krb5_set_error_string (void);
+
+char *
+gssapi_krb5_get_error_string (void);
+
+OM_uint32
+_gss_DES3_get_mic_compat(OM_uint32 *, gss_ctx_id_t);
+
+OM_uint32
+_gss_spnego_require_mechlist_mic(OM_uint32 *, gss_ctx_id_t, krb5_boolean *);
+
+krb5_error_code
+_gss_check_compat(OM_uint32 *, gss_name_t, const char *,
+                 krb5_boolean *, krb5_boolean);
+
+OM_uint32
+gssapi_lifetime_left(OM_uint32 *, OM_uint32, OM_uint32 *);
+
+/* sequence */
+
+OM_uint32
+_gssapi_msg_order_create(OM_uint32 *, struct gss_msg_order **, 
+                        OM_uint32, OM_uint32, OM_uint32, int);
+OM_uint32
+_gssapi_msg_order_destroy(struct gss_msg_order **);
+
+OM_uint32
+_gssapi_msg_order_check(struct gss_msg_order *, OM_uint32);
+
+OM_uint32
+_gssapi_msg_order_f(OM_uint32);
+
+/* 8003 */
+
+krb5_error_code
+gssapi_encode_om_uint32(OM_uint32, u_char *);
+
+krb5_error_code
+gssapi_encode_be_om_uint32(OM_uint32, u_char *);
+
+krb5_error_code
+gssapi_decode_om_uint32(u_char *, OM_uint32 *);
+
+krb5_error_code
+gssapi_decode_be_om_uint32(u_char *, OM_uint32 *);
+
+#endif
diff --git a/src/kerberosV/src/lib/gssapi/import_name.c b/src/kerberosV/src/lib/gssapi/import_name.c
new file mode 100644 (file)
index 0000000..43d6d6c
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: import_name.c,v 1.13 2003/03/16 17:33:31 lha Exp $");
+
+static OM_uint32
+parse_krb5_name (OM_uint32 *minor_status,
+                const char *name,
+                gss_name_t *output_name)
+{
+    krb5_error_code kerr;
+
+    kerr = krb5_parse_name (gssapi_krb5_context, name, output_name);
+
+    if (kerr == 0)
+       return GSS_S_COMPLETE;
+    else if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kerr;
+       return GSS_S_BAD_NAME;
+    } else {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kerr;
+       return GSS_S_FAILURE;
+    }
+}
+
+static OM_uint32
+import_krb5_name (OM_uint32 *minor_status,
+                 const gss_buffer_t input_name_buffer,
+                 gss_name_t *output_name)
+{
+    OM_uint32 ret;
+    char *tmp;
+
+    tmp = malloc (input_name_buffer->length + 1);
+    if (tmp == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    memcpy (tmp,
+           input_name_buffer->value,
+           input_name_buffer->length);
+    tmp[input_name_buffer->length] = '\0';
+
+    ret = parse_krb5_name(minor_status, tmp, output_name);
+    free(tmp);
+
+    return ret;
+}
+
+static OM_uint32
+import_hostbased_name (OM_uint32 *minor_status,
+                      const gss_buffer_t input_name_buffer,
+                      gss_name_t *output_name)
+{
+    krb5_error_code kerr;
+    char *tmp;
+    char *p;
+    char *host;
+    char local_hostname[MAXHOSTNAMELEN];
+
+    *output_name = NULL;
+
+    tmp = malloc (input_name_buffer->length + 1);
+    if (tmp == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    memcpy (tmp,
+           input_name_buffer->value,
+           input_name_buffer->length);
+    tmp[input_name_buffer->length] = '\0';
+
+    p = strchr (tmp, '@');
+    if (p != NULL) {
+       *p = '\0';
+       host = p + 1;
+    } else {
+       if (gethostname(local_hostname, sizeof(local_hostname)) < 0) {
+           *minor_status = errno;
+           free (tmp);
+           return GSS_S_FAILURE;
+       }
+       host = local_hostname;
+    }
+
+    kerr = krb5_sname_to_principal (gssapi_krb5_context,
+                                   host,
+                                   tmp,
+                                   KRB5_NT_SRV_HST,
+                                   output_name);
+    free (tmp);
+    *minor_status = kerr;
+    if (kerr == 0)
+       return GSS_S_COMPLETE;
+    else if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kerr;
+       return GSS_S_BAD_NAME;
+    } else {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kerr;
+       return GSS_S_FAILURE;
+    }
+}
+
+static OM_uint32
+import_export_name (OM_uint32 *minor_status,
+                   const gss_buffer_t input_name_buffer,
+                   gss_name_t *output_name)
+{
+    unsigned char *p;
+    uint32_t length;
+    OM_uint32 ret;
+    char *name;
+
+    if (input_name_buffer->length < 10 + GSS_KRB5_MECHANISM->length)
+       return GSS_S_BAD_NAME;
+
+    /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */
+
+    p = input_name_buffer->value;
+
+    if (memcmp(&p[0], "\x04\x01\x00", 3) != 0 ||
+       p[3] != GSS_KRB5_MECHANISM->length + 2 ||
+       p[4] != 0x06 ||
+       p[5] != GSS_KRB5_MECHANISM->length ||
+       memcmp(&p[6], GSS_KRB5_MECHANISM->elements, 
+              GSS_KRB5_MECHANISM->length) != 0)
+       return GSS_S_BAD_NAME;
+
+    p += 6 + GSS_KRB5_MECHANISM->length;
+
+    length = p[0] << 24 | p[1] << 16 | p[2] << 8 | p[3];
+    p += 4;
+
+    if (length > input_name_buffer->length - 10 - GSS_KRB5_MECHANISM->length)
+       return GSS_S_BAD_NAME;
+
+    name = malloc(length + 1);
+    if (name == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    memcpy(name, p, length);
+    name[length] = '\0';
+
+    ret = parse_krb5_name(minor_status, name, output_name);
+    free(name);
+
+    return ret;
+}
+
+int
+gss_oid_equal(const gss_OID a, const gss_OID b)
+{
+       if (a == b)
+               return 1;
+       else if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length)
+               return 0;
+       else
+               return memcmp(a->elements, b->elements, a->length) == 0;
+}
+
+OM_uint32 gss_import_name
+           (OM_uint32 * minor_status,
+            const gss_buffer_t input_name_buffer,
+            const gss_OID input_name_type,
+            gss_name_t * output_name
+           )
+{
+    GSSAPI_KRB5_INIT ();
+
+    *minor_status = 0;
+    *output_name = GSS_C_NO_NAME;
+    
+    if (gss_oid_equal(input_name_type, GSS_C_NT_HOSTBASED_SERVICE))
+       return import_hostbased_name (minor_status,
+                                     input_name_buffer,
+                                     output_name);
+    else if (gss_oid_equal(input_name_type, GSS_C_NO_OID)
+            || gss_oid_equal(input_name_type, GSS_C_NT_USER_NAME)
+            || gss_oid_equal(input_name_type, GSS_KRB5_NT_PRINCIPAL_NAME))
+       /* default printable syntax */
+       return import_krb5_name (minor_status,
+                                input_name_buffer,
+                                output_name);
+    else if (gss_oid_equal(input_name_type, GSS_C_NT_EXPORT_NAME)) {
+       return import_export_name(minor_status,
+                                 input_name_buffer, 
+                                 output_name);
+    } else {
+       *minor_status = 0;
+       return GSS_S_BAD_NAMETYPE;
+    }
+}
diff --git a/src/kerberosV/src/lib/gssapi/import_sec_context.c b/src/kerberosV/src/lib/gssapi/import_sec_context.c
new file mode 100644 (file)
index 0000000..6c3a105
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1999 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: import_sec_context.c,v 1.12 2005/04/27 17:48:48 lha Exp $");
+
+OM_uint32
+gss_import_sec_context (
+    OM_uint32 * minor_status,
+    const gss_buffer_t interprocess_token,
+    gss_ctx_id_t * context_handle
+    )
+{
+    OM_uint32 ret = GSS_S_FAILURE;
+    krb5_error_code kret;
+    krb5_storage *sp;
+    krb5_auth_context ac;
+    krb5_address local, remote;
+    krb5_address *localp, *remotep;
+    krb5_data data;
+    gss_buffer_desc buffer;
+    krb5_keyblock keyblock;
+    int32_t tmp;
+    int32_t flags;
+    OM_uint32 minor;
+    int is_cfx = 0;
+
+    GSSAPI_KRB5_INIT ();
+
+    localp = remotep = NULL;
+
+    sp = krb5_storage_from_mem (interprocess_token->value,
+                               interprocess_token->length);
+    if (sp == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    *context_handle = malloc(sizeof(**context_handle));
+    if (*context_handle == NULL) {
+       *minor_status = ENOMEM;
+       krb5_storage_free (sp);
+       return GSS_S_FAILURE;
+    }
+    memset (*context_handle, 0, sizeof(**context_handle));
+    HEIMDAL_MUTEX_init(&(*context_handle)->ctx_id_mutex);
+
+    kret = krb5_auth_con_init (gssapi_krb5_context,
+                              &(*context_handle)->auth_context);
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    /* flags */
+
+    *minor_status = 0;
+
+    if (krb5_ret_int32 (sp, &flags) != 0)
+       goto failure;
+
+    /* retrieve the auth context */
+
+    ac = (*context_handle)->auth_context;
+    krb5_ret_int32 (sp, &ac->flags);
+    if (flags & SC_LOCAL_ADDRESS) {
+       if (krb5_ret_address (sp, localp = &local) != 0)
+           goto failure;
+    }
+
+    if (flags & SC_REMOTE_ADDRESS) {
+       if (krb5_ret_address (sp, remotep = &remote) != 0)
+           goto failure;
+    }
+
+    krb5_auth_con_setaddrs (gssapi_krb5_context, ac, localp, remotep);
+    if (localp)
+       krb5_free_address (gssapi_krb5_context, localp);
+    if (remotep)
+       krb5_free_address (gssapi_krb5_context, remotep);
+    localp = remotep = NULL;
+
+    if (krb5_ret_int16 (sp, &ac->local_port) != 0)
+       goto failure;
+
+    if (krb5_ret_int16 (sp, &ac->remote_port) != 0)
+       goto failure;
+    if (flags & SC_KEYBLOCK) {
+       if (krb5_ret_keyblock (sp, &keyblock) != 0)
+           goto failure;
+       krb5_auth_con_setkey (gssapi_krb5_context, ac, &keyblock);
+       krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock);
+    }
+    if (flags & SC_LOCAL_SUBKEY) {
+       if (krb5_ret_keyblock (sp, &keyblock) != 0)
+           goto failure;
+       krb5_auth_con_setlocalsubkey (gssapi_krb5_context, ac, &keyblock);
+       krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock);
+    }
+    if (flags & SC_REMOTE_SUBKEY) {
+       if (krb5_ret_keyblock (sp, &keyblock) != 0)
+           goto failure;
+       krb5_auth_con_setremotesubkey (gssapi_krb5_context, ac, &keyblock);
+       krb5_free_keyblock_contents (gssapi_krb5_context, &keyblock);
+    }
+    if (krb5_ret_int32 (sp, &ac->local_seqnumber))
+       goto failure;
+    if (krb5_ret_int32 (sp, &ac->remote_seqnumber))
+       goto failure;
+
+    if (krb5_ret_int32 (sp, &tmp) != 0)
+       goto failure;
+    ac->keytype = tmp;
+    if (krb5_ret_int32 (sp, &tmp) != 0)
+       goto failure;
+    ac->cksumtype = tmp;
+
+    /* names */
+
+    if (krb5_ret_data (sp, &data))
+       goto failure;
+    buffer.value  = data.data;
+    buffer.length = data.length;
+
+    ret = gss_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
+                          &(*context_handle)->source);
+    if (ret) {
+       ret = gss_import_name (minor_status, &buffer, GSS_C_NO_OID,
+                              &(*context_handle)->source);
+       if (ret) {
+           krb5_data_free (&data);
+           goto failure;
+       }
+    }
+    krb5_data_free (&data);
+
+    if (krb5_ret_data (sp, &data) != 0)
+       goto failure;
+    buffer.value  = data.data;
+    buffer.length = data.length;
+
+    ret = gss_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME,
+                          &(*context_handle)->target);
+    if (ret) {
+       ret = gss_import_name (minor_status, &buffer, GSS_C_NO_OID,
+                              &(*context_handle)->target);
+       if (ret) {
+           krb5_data_free (&data);
+           goto failure;
+       }
+    }    
+    krb5_data_free (&data);
+
+    if (krb5_ret_int32 (sp, &tmp))
+       goto failure;
+    (*context_handle)->flags = tmp;
+    if (krb5_ret_int32 (sp, &tmp))
+       goto failure;
+    (*context_handle)->more_flags = tmp;
+    if (krb5_ret_int32 (sp, &tmp) == 0)
+       (*context_handle)->lifetime = tmp;
+    else
+       (*context_handle)->lifetime = GSS_C_INDEFINITE;
+
+    gsskrb5_is_cfx(*context_handle, &is_cfx);
+
+    ret = _gssapi_msg_order_create(minor_status,
+                                  &(*context_handle)->order,
+                                  _gssapi_msg_order_f((*context_handle)->flags),
+                                  0, 0, is_cfx);
+    if (ret)
+       goto failure;
+
+    krb5_storage_free (sp);
+    return GSS_S_COMPLETE;
+
+failure:
+    krb5_auth_con_free (gssapi_krb5_context,
+                       (*context_handle)->auth_context);
+    if ((*context_handle)->source != NULL)
+       gss_release_name(&minor, &(*context_handle)->source);
+    if ((*context_handle)->target != NULL)
+       gss_release_name(&minor, &(*context_handle)->target);
+    if (localp)
+       krb5_free_address (gssapi_krb5_context, localp);
+    if (remotep)
+       krb5_free_address (gssapi_krb5_context, remotep);
+    if((*context_handle)->order)
+       _gssapi_msg_order_destroy(&(*context_handle)->order);
+    HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex);
+    krb5_storage_free (sp);
+    free (*context_handle);
+    *context_handle = GSS_C_NO_CONTEXT;
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/indicate_mechs.c b/src/kerberosV/src/lib/gssapi/indicate_mechs.c
new file mode 100644 (file)
index 0000000..39f2ce3
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: indicate_mechs.c,v 1.7 2003/09/12 21:15:42 lha Exp $");
+
+OM_uint32 gss_indicate_mechs
+           (OM_uint32 * minor_status,
+            gss_OID_set * mech_set
+           )
+{
+  OM_uint32 ret;
+
+  ret = gss_create_empty_oid_set(minor_status, mech_set);
+  if (ret)
+      return ret;
+
+  ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, mech_set);
+  if (ret) {
+      gss_release_oid_set(NULL, mech_set);
+      return ret;
+  }
+
+  ret = gss_add_oid_set_member(minor_status, GSS_SPNEGO_MECHANISM, mech_set);
+  if (ret) {
+      gss_release_oid_set(NULL, mech_set);
+      return ret;
+  }
+
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/init.c b/src/kerberosV/src/lib/gssapi/init.c
new file mode 100644 (file)
index 0000000..dee678b
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: init.c,v 1.7 2003/07/22 19:50:11 lha Exp $");
+
+static HEIMDAL_MUTEX gssapi_krb5_context_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static int created_key;
+static HEIMDAL_thread_key gssapi_context_key;
+
+static void
+gssapi_destroy_thread_context(void *ptr)
+{
+    struct gssapi_thr_context *ctx = ptr;
+
+    if (ctx == NULL)
+       return;
+    if (ctx->error_string)
+       free(ctx->error_string);
+    HEIMDAL_MUTEX_destroy(&ctx->mutex);
+    free(ctx);
+}
+
+
+struct gssapi_thr_context *
+gssapi_get_thread_context(int createp)
+{
+    struct gssapi_thr_context *ctx;
+    int ret;
+
+    HEIMDAL_MUTEX_lock(&gssapi_krb5_context_mutex);
+
+    if (!created_key)
+       abort();
+    ctx = HEIMDAL_getspecific(gssapi_context_key);
+    if (ctx == NULL) {
+       if (!createp)
+           goto fail;
+       ctx = malloc(sizeof(*ctx));
+       if (ctx == NULL)
+           goto fail;
+       ctx->error_string = NULL;
+       HEIMDAL_MUTEX_init(&ctx->mutex);
+       HEIMDAL_setspecific(gssapi_context_key, ctx, ret);
+       if (ret)
+           goto fail;
+    }
+    HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex);
+    return ctx;
+ fail:
+    HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex);
+    if (ctx)
+       free(ctx);
+    return NULL;
+}
+
+krb5_error_code
+gssapi_krb5_init (void)
+{
+    krb5_error_code ret = 0;
+
+    HEIMDAL_MUTEX_lock(&gssapi_krb5_context_mutex);
+
+    if(gssapi_krb5_context == NULL)
+       ret = krb5_init_context (&gssapi_krb5_context);
+    if (ret == 0 && !created_key) {
+       HEIMDAL_key_create(&gssapi_context_key, 
+                          gssapi_destroy_thread_context,
+                          ret);
+       if (ret) {
+           krb5_free_context(gssapi_krb5_context);
+           gssapi_krb5_context = NULL;
+       } else
+           created_key = 1;
+    }
+
+    HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex);
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/init_sec_context.c b/src/kerberosV/src/lib/gssapi/init_sec_context.c
new file mode 100644 (file)
index 0000000..8338900
--- /dev/null
@@ -0,0 +1,1093 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: init_sec_context.c,v 1.57 2005/05/30 20:58:29 lha Exp $");
+
+/*
+ * copy the addresses from `input_chan_bindings' (if any) to
+ * the auth context `ac'
+ */
+
+static OM_uint32
+set_addresses (krb5_auth_context ac,
+              const gss_channel_bindings_t input_chan_bindings)               
+{
+    /* Port numbers are expected to be in application_data.value, 
+     * initator's port first */ 
+
+    krb5_address initiator_addr, acceptor_addr;
+    krb5_error_code kret;
+       
+    if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS
+       || input_chan_bindings->application_data.length !=
+       2 * sizeof(ac->local_port))
+       return 0;
+
+    memset(&initiator_addr, 0, sizeof(initiator_addr));
+    memset(&acceptor_addr, 0, sizeof(acceptor_addr));
+       
+    ac->local_port =
+       *(int16_t *) input_chan_bindings->application_data.value;
+       
+    ac->remote_port =
+       *((int16_t *) input_chan_bindings->application_data.value + 1);
+       
+    kret = gss_address_to_krb5addr(input_chan_bindings->acceptor_addrtype,
+                                  &input_chan_bindings->acceptor_address,
+                                  ac->remote_port,
+                                  &acceptor_addr);
+    if (kret)
+       return kret;
+           
+    kret = gss_address_to_krb5addr(input_chan_bindings->initiator_addrtype,
+                                  &input_chan_bindings->initiator_address,
+                                  ac->local_port,
+                                  &initiator_addr);
+    if (kret) {
+       krb5_free_address (gssapi_krb5_context, &acceptor_addr);
+       return kret;
+    }
+       
+    kret = krb5_auth_con_setaddrs(gssapi_krb5_context,
+                                 ac,
+                                 &initiator_addr,  /* local address */
+                                 &acceptor_addr);  /* remote address */
+       
+    krb5_free_address (gssapi_krb5_context, &initiator_addr);
+    krb5_free_address (gssapi_krb5_context, &acceptor_addr);
+       
+#if 0
+    free(input_chan_bindings->application_data.value);
+    input_chan_bindings->application_data.value = NULL;
+    input_chan_bindings->application_data.length = 0;
+#endif
+
+    return kret;
+}
+
+/*
+ * handle delegated creds in init-sec-context
+ */
+
+static void
+do_delegation (krb5_auth_context ac,
+              krb5_ccache ccache,
+              krb5_creds *cred,
+              const gss_name_t target_name,
+              krb5_data *fwd_data,
+              int *flags)
+{
+    krb5_creds creds;
+    krb5_kdc_flags fwd_flags;
+    krb5_error_code kret;
+       
+    memset (&creds, 0, sizeof(creds));
+    krb5_data_zero (fwd_data);
+       
+    kret = krb5_cc_get_principal(gssapi_krb5_context, ccache, &creds.client);
+    if (kret) 
+       goto out;
+       
+    kret = krb5_build_principal(gssapi_krb5_context,
+                               &creds.server,
+                               strlen(creds.client->realm),
+                               creds.client->realm,
+                               KRB5_TGS_NAME,
+                               creds.client->realm,
+                               NULL);
+    if (kret)
+       goto out; 
+       
+    creds.times.endtime = 0;
+       
+    fwd_flags.i = 0;
+    fwd_flags.b.forwarded = 1;
+    fwd_flags.b.forwardable = 1;
+       
+    if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/
+       target_name->name.name_string.len < 2) 
+       goto out;
+       
+    kret = krb5_get_forwarded_creds(gssapi_krb5_context,
+                                   ac,
+                                   ccache,
+                                   fwd_flags.i,
+                                   target_name->name.name_string.val[1],
+                                   &creds,
+                                   fwd_data);
+       
+ out:
+    if (kret)
+       *flags &= ~GSS_C_DELEG_FLAG;
+    else
+       *flags |= GSS_C_DELEG_FLAG;
+       
+    if (creds.client)
+       krb5_free_principal(gssapi_krb5_context, creds.client);
+    if (creds.server)
+       krb5_free_principal(gssapi_krb5_context, creds.server);
+}
+
+/*
+ * first stage of init-sec-context
+ */
+
+static OM_uint32
+init_auth
+(OM_uint32 * minor_status,
+ const gss_cred_id_t initiator_cred_handle,
+ gss_ctx_id_t * context_handle,
+ const gss_name_t target_name,
+ const gss_OID mech_type,
+ OM_uint32 req_flags,
+ OM_uint32 time_req,
+ const gss_channel_bindings_t input_chan_bindings,
+ const 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 ret = GSS_S_FAILURE;
+    krb5_error_code kret;
+    krb5_flags ap_options;
+    krb5_creds this_cred, *cred = NULL;
+    krb5_data outbuf;
+    krb5_ccache ccache = NULL;
+    u_int32_t flags;
+    krb5_data authenticator;
+    Checksum cksum;
+    krb5_enctype enctype;
+    krb5_data fwd_data;
+    OM_uint32 lifetime_rec;
+
+    krb5_data_zero(&outbuf);
+    krb5_data_zero(&fwd_data);
+
+    *minor_status = 0;
+
+    *context_handle = malloc(sizeof(**context_handle));
+    if (*context_handle == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    (*context_handle)->auth_context = NULL;
+    (*context_handle)->source       = NULL;
+    (*context_handle)->target       = NULL;
+    (*context_handle)->flags        = 0;
+    (*context_handle)->more_flags   = 0;
+    (*context_handle)->ticket       = NULL;
+    (*context_handle)->lifetime     = GSS_C_INDEFINITE;
+    (*context_handle)->order       = NULL;
+    HEIMDAL_MUTEX_init(&(*context_handle)->ctx_id_mutex);
+
+    kret = krb5_auth_con_init (gssapi_krb5_context,
+                              &(*context_handle)->auth_context);
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    kret = set_addresses ((*context_handle)->auth_context,
+                         input_chan_bindings);
+    if (kret) {
+       *minor_status = kret;
+       ret = GSS_S_BAD_BINDINGS;
+       goto failure;
+    }
+
+    krb5_auth_con_addflags(gssapi_krb5_context,
+                          (*context_handle)->auth_context,
+                          KRB5_AUTH_CONTEXT_DO_SEQUENCE |
+                          KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED,
+                          NULL);
+
+    if (actual_mech_type)
+       *actual_mech_type = GSS_KRB5_MECHANISM;
+
+    if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) {
+       kret = krb5_cc_default (gssapi_krb5_context, &ccache);
+       if (kret) {
+           gssapi_krb5_set_error_string ();
+           *minor_status = kret;
+           ret = GSS_S_FAILURE;
+           goto failure;
+       }
+    } else
+       ccache = initiator_cred_handle->ccache;
+
+    kret = krb5_cc_get_principal (gssapi_krb5_context,
+                                 ccache,
+                                 &(*context_handle)->source);
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    kret = krb5_copy_principal (gssapi_krb5_context,
+                               target_name,
+                               &(*context_handle)->target);
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    ret = _gss_DES3_get_mic_compat(minor_status, *context_handle);
+    if (ret)
+       goto failure;
+
+
+    memset(&this_cred, 0, sizeof(this_cred));
+    this_cred.client          = (*context_handle)->source;
+    this_cred.server          = (*context_handle)->target;
+    if (time_req && time_req != GSS_C_INDEFINITE) {
+       krb5_timestamp ts;
+
+       krb5_timeofday (gssapi_krb5_context, &ts);
+       this_cred.times.endtime = ts + time_req;
+    } else
+       this_cred.times.endtime   = 0;
+    this_cred.session.keytype = KEYTYPE_NULL;
+
+    kret = krb5_get_credentials (gssapi_krb5_context,
+                                0,
+                                ccache,
+                                &this_cred,
+                                &cred);
+
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    (*context_handle)->lifetime = cred->times.endtime;
+
+    ret = gssapi_lifetime_left(minor_status,
+                              (*context_handle)->lifetime,
+                              &lifetime_rec);
+    if (ret) {
+       goto failure;
+    }
+
+    if (lifetime_rec == 0) {
+       *minor_status = 0;
+       ret = GSS_S_CONTEXT_EXPIRED;
+       goto failure;
+    }
+
+    krb5_auth_con_setkey(gssapi_krb5_context, 
+                        (*context_handle)->auth_context, 
+                        &cred->session);
+
+    kret = krb5_auth_con_generatelocalsubkey(gssapi_krb5_context, 
+                                            (*context_handle)->auth_context,
+                                            &cred->session);
+    if(kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+    
+    /* 
+     * If the realm policy approves a delegation, lets check local
+     * policy if the credentials should be delegated, defafult to
+     * false.
+     */
+    if (cred->flags.b.ok_as_delegate) {
+       krb5_boolean delegate = FALSE;
+    
+       _gss_check_compat(NULL, target_name, "ok-as-delegate",
+                         &delegate, TRUE);
+       krb5_appdefault_boolean(gssapi_krb5_context,
+                               "gssapi", target_name->realm,
+                               "ok-as-delegate", delegate, &delegate);
+       if (delegate)
+           req_flags |= GSS_C_DELEG_FLAG;
+    }
+
+    flags = 0;
+    ap_options = 0;
+    if (req_flags & GSS_C_DELEG_FLAG)
+       do_delegation ((*context_handle)->auth_context,
+                      ccache, cred, target_name, &fwd_data, &flags);
+    
+    if (req_flags & GSS_C_MUTUAL_FLAG) {
+       flags |= GSS_C_MUTUAL_FLAG;
+       ap_options |= AP_OPTS_MUTUAL_REQUIRED;
+    }
+    
+    if (req_flags & GSS_C_REPLAY_FLAG)
+       flags |= GSS_C_REPLAY_FLAG;
+    if (req_flags & GSS_C_SEQUENCE_FLAG)
+       flags |= GSS_C_SEQUENCE_FLAG;
+    if (req_flags & GSS_C_ANON_FLAG)
+       ;                               /* XXX */
+    flags |= GSS_C_CONF_FLAG;
+    flags |= GSS_C_INTEG_FLAG;
+    flags |= GSS_C_TRANS_FLAG;
+    
+    if (ret_flags)
+       *ret_flags = flags;
+    (*context_handle)->flags = flags;
+    (*context_handle)->more_flags |= LOCAL;
+    
+    ret = gssapi_krb5_create_8003_checksum (minor_status,
+                                           input_chan_bindings,
+                                           flags,
+                                           &fwd_data,
+                                           &cksum);
+    krb5_data_free (&fwd_data);
+    if (ret)
+       goto failure;
+
+    enctype = (*context_handle)->auth_context->keyblock->keytype;
+
+    kret = krb5_build_authenticator (gssapi_krb5_context,
+                                    (*context_handle)->auth_context,
+                                    enctype,
+                                    cred,
+                                    &cksum,
+                                    NULL,
+                                    &authenticator,
+                                    KRB5_KU_AP_REQ_AUTH);
+
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    kret = krb5_build_ap_req (gssapi_krb5_context,
+                             enctype,
+                             cred,
+                             ap_options,
+                             authenticator,
+                             &outbuf);
+
+    if (kret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       ret = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    ret = gssapi_krb5_encapsulate (minor_status, &outbuf, output_token,
+                                  "\x01\x00", GSS_KRB5_MECHANISM);
+    if (ret)
+       goto failure;
+
+    krb5_data_free (&outbuf);
+    krb5_free_creds(gssapi_krb5_context, cred);
+    free_Checksum(&cksum);
+    if (initiator_cred_handle == GSS_C_NO_CREDENTIAL)
+       krb5_cc_close(gssapi_krb5_context, ccache);
+
+    if (flags & GSS_C_MUTUAL_FLAG) {
+       return GSS_S_CONTINUE_NEEDED;
+    } else {
+       int32_t seq_number;
+       int is_cfx = 0;
+       
+       krb5_auth_getremoteseqnumber (gssapi_krb5_context,
+                                     (*context_handle)->auth_context,
+                                     &seq_number);
+
+       gsskrb5_is_cfx(*context_handle, &is_cfx);
+
+       ret = _gssapi_msg_order_create(minor_status,
+                                      &(*context_handle)->order,
+                                      _gssapi_msg_order_f(flags),
+                                      seq_number, 0, is_cfx);
+       if (ret)
+           goto failure;
+
+       if (time_rec)
+           *time_rec = lifetime_rec;
+
+       (*context_handle)->more_flags |= OPEN;
+       return GSS_S_COMPLETE;
+    }
+
+ failure:
+    krb5_auth_con_free (gssapi_krb5_context,
+                       (*context_handle)->auth_context);
+    krb5_data_free (&outbuf);
+    if(cred)
+       krb5_free_creds(gssapi_krb5_context, cred);
+    if (ccache && initiator_cred_handle == GSS_C_NO_CREDENTIAL)
+       krb5_cc_close(gssapi_krb5_context, ccache);
+    if((*context_handle)->source)
+       krb5_free_principal (gssapi_krb5_context,
+                            (*context_handle)->source);
+    if((*context_handle)->target)
+       krb5_free_principal (gssapi_krb5_context,
+                            (*context_handle)->target);
+    if((*context_handle)->order)
+       _gssapi_msg_order_destroy(&(*context_handle)->order);
+    HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex);
+    free (*context_handle);
+    *context_handle = GSS_C_NO_CONTEXT;
+    return ret;
+}
+
+static OM_uint32
+repl_mutual
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t * context_handle,
+            const gss_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const 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 ret, seq_number;
+    krb5_error_code kret;
+    krb5_data indata;
+    krb5_ap_rep_enc_part *repl;
+    int is_cfx = 0;
+
+    output_token->length = 0;
+    output_token->value = NULL;
+
+    HEIMDAL_MUTEX_lock(&(*context_handle)->ctx_id_mutex);
+
+    if (actual_mech_type)
+       *actual_mech_type = GSS_KRB5_MECHANISM;
+
+    ret = gssapi_krb5_decapsulate (minor_status, input_token, &indata,
+                                  "\x02\x00", GSS_KRB5_MECHANISM);
+    if (ret) {
+       HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+       /* XXX - Handle AP_ERROR */
+       return ret;
+    }
+    
+    kret = krb5_rd_rep (gssapi_krb5_context,
+                       (*context_handle)->auth_context,
+                       &indata,
+                       &repl);
+    if (kret) {
+       HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+       gssapi_krb5_set_error_string ();
+       *minor_status = kret;
+       return GSS_S_FAILURE;
+    }
+    krb5_free_ap_rep_enc_part (gssapi_krb5_context,
+                              repl);
+    
+    krb5_auth_getremoteseqnumber (gssapi_krb5_context,
+                                 (*context_handle)->auth_context,
+                                 &seq_number);
+
+    gsskrb5_is_cfx(*context_handle, &is_cfx);
+
+    ret = _gssapi_msg_order_create(minor_status,
+                                  &(*context_handle)->order,
+                                  _gssapi_msg_order_f((*context_handle)->flags),
+                                  seq_number, 0, is_cfx);
+    if (ret) {
+       HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+       return ret;
+    }
+       
+    (*context_handle)->more_flags |= OPEN;
+
+    *minor_status = 0;
+    if (time_rec) {
+       ret = gssapi_lifetime_left(minor_status,
+                                  (*context_handle)->lifetime,
+                                  time_rec);
+    } else {
+       ret = GSS_S_COMPLETE;
+    }
+    if (ret_flags)
+       *ret_flags = (*context_handle)->flags;
+    HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex);
+
+    return ret;
+}
+
+static OM_uint32
+gsskrb5_init_sec_context
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t * context_handle,
+            const gss_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const gss_buffer_t input_token,
+            gss_OID * actual_mech_type,
+            gss_buffer_t output_token,
+            OM_uint32 * ret_flags,
+            OM_uint32 * time_rec
+          )
+{
+    if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
+       return init_auth (minor_status,
+                         initiator_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);
+    else
+       return repl_mutual(minor_status,
+                          initiator_cred_handle,
+                          context_handle,
+                          target_name,
+                          mech_type,
+                          req_flags,
+                          time_req,
+                          input_chan_bindings,
+                          input_token,
+                          actual_mech_type,
+                          output_token,
+                          ret_flags,
+                          time_rec);
+}
+
+static OM_uint32
+spnego_reply
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t * context_handle,
+            const gss_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const 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 ret;
+    krb5_data indata;
+    NegTokenTarg targ;
+    u_char oidbuf[17];
+    size_t oidlen;
+    gss_buffer_desc sub_token;
+    ssize_t mech_len;
+    const u_char *p;
+    size_t len, taglen;
+    krb5_boolean require_mic;
+
+    output_token->length = 0;
+    output_token->value  = NULL;
+
+    /*
+     * SPNEGO doesn't include gss wrapping on SubsequentContextToken
+     * like the Kerberos 5 mech does. But lets check for it anyway.
+     */
+    
+    mech_len = gssapi_krb5_get_mech (input_token->value,
+                                    input_token->length,
+                                    &p);
+
+    if (mech_len < 0) {
+       indata.data = input_token->value;
+       indata.length = input_token->length;
+    } else if (mech_len == GSS_KRB5_MECHANISM->length
+       && memcmp(GSS_KRB5_MECHANISM->elements, p, mech_len) == 0)
+       return gsskrb5_init_sec_context (minor_status,
+                                        initiator_cred_handle,
+                                        context_handle,
+                                        target_name,
+                                        GSS_KRB5_MECHANISM,
+                                        req_flags,
+                                        time_req,
+                                        input_chan_bindings,
+                                        input_token,
+                                        actual_mech_type,
+                                        output_token,
+                                        ret_flags,
+                                        time_rec);
+    else if (mech_len == GSS_SPNEGO_MECHANISM->length
+            && memcmp(GSS_SPNEGO_MECHANISM->elements, p, mech_len) == 0){
+       ret = _gssapi_decapsulate (minor_status,
+                                  input_token,
+                                  &indata,
+                                  GSS_SPNEGO_MECHANISM);
+       if (ret)
+           return ret;
+    } else
+       return GSS_S_BAD_MECH;
+
+    ret = der_match_tag_and_length((const char *)indata.data,
+                                  indata.length,
+                                  ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
+    if (ret)
+       return ret;
+
+    if(len > indata.length - taglen)
+       return ASN1_OVERRUN;
+
+    ret = decode_NegTokenTarg((const char *)indata.data + taglen, 
+                             len, &targ, NULL);
+    if (ret) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    if (targ.negResult == NULL
+       || *(targ.negResult) == reject
+       || targ.supportedMech == NULL) {
+       free_NegTokenTarg(&targ);
+       return GSS_S_BAD_MECH;
+    }
+    
+    ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1,
+                     sizeof(oidbuf),
+                     targ.supportedMech,
+                     &oidlen);
+    if (ret || oidlen != GSS_KRB5_MECHANISM->length
+       || memcmp(oidbuf + sizeof(oidbuf) - oidlen,
+                 GSS_KRB5_MECHANISM->elements,
+                 oidlen) != 0) {
+       free_NegTokenTarg(&targ);
+       return GSS_S_BAD_MECH;
+    }
+
+    if (targ.responseToken != NULL) {
+       sub_token.length = targ.responseToken->length;
+       sub_token.value  = targ.responseToken->data;
+    } else {
+       sub_token.length = 0;
+       sub_token.value  = NULL;
+    }
+
+    ret = gsskrb5_init_sec_context(minor_status,
+                                  initiator_cred_handle,
+                                  context_handle,
+                                  target_name,
+                                  GSS_KRB5_MECHANISM,
+                                  req_flags,
+                                  time_req,
+                                  input_chan_bindings,
+                                  &sub_token,
+                                  actual_mech_type,
+                                  output_token,
+                                  ret_flags,
+                                  time_rec);
+    if (ret) {
+       free_NegTokenTarg(&targ);
+       return ret;
+    }
+
+    /*
+     * Verify the mechListMIC if CFX was used; or if local policy
+     * dictated so.
+     */
+    ret = _gss_spnego_require_mechlist_mic(minor_status, *context_handle,
+                                          &require_mic);
+    if (ret) {
+       free_NegTokenTarg(&targ);
+       return ret;
+    }
+
+    if (require_mic) {
+       MechTypeList mechlist;
+       MechType m0;
+       size_t buf_len;
+       gss_buffer_desc mic_buf, mech_buf;
+
+       if (targ.mechListMIC == NULL) {
+           free_NegTokenTarg(&targ);
+           *minor_status = 0;
+           return GSS_S_BAD_MIC;
+       }
+
+       mechlist.len = 1;
+       mechlist.val = &m0;
+
+       ret = der_get_oid(GSS_KRB5_MECHANISM->elements,
+                         GSS_KRB5_MECHANISM->length,
+                         &m0,
+                         NULL);
+       if (ret) {
+           free_NegTokenTarg(&targ);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+
+       ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length,
+                          &mechlist, &buf_len, ret);
+       if (ret) {
+           free_NegTokenTarg(&targ);
+           free_oid(&m0);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       if (mech_buf.length != buf_len)
+           abort();
+
+       mic_buf.length = targ.mechListMIC->length;
+       mic_buf.value  = targ.mechListMIC->data;
+
+       ret = gss_verify_mic(minor_status, *context_handle,
+                            &mech_buf, &mic_buf, NULL);
+       free(mech_buf.value);
+       free_oid(&m0);
+    }
+    free_NegTokenTarg(&targ);
+    return ret;
+}
+
+static OM_uint32
+spnego_initial
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t * context_handle,
+            const gss_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const gss_buffer_t input_token,
+            gss_OID * actual_mech_type,
+            gss_buffer_t output_token,
+            OM_uint32 * ret_flags,
+            OM_uint32 * time_rec
+          )
+{
+    NegTokenInit ni;
+    int ret;
+    OM_uint32 sub, minor;
+    gss_buffer_desc mech_token;
+    u_char *buf;
+    size_t buf_size, buf_len;
+    krb5_data data;
+#if 1
+    size_t ni_len;
+#endif
+
+    memset (&ni, 0, sizeof(ni));
+
+    ALLOC(ni.mechTypes, 1);
+    if (ni.mechTypes == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    ALLOC_SEQ(ni.mechTypes, 1);
+    if (ni.mechTypes->val == NULL) {
+       free_NegTokenInit(&ni);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    ret = der_get_oid(GSS_KRB5_MECHANISM->elements,
+                     GSS_KRB5_MECHANISM->length,
+                     &ni.mechTypes->val[0],
+                     NULL);
+    if (ret) {
+       free_NegTokenInit(&ni);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+#if 0
+    ALLOC(ni.reqFlags, 1);
+    if (ni.reqFlags == NULL) {
+       free_NegTokenInit(&ni);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    ni.reqFlags->delegFlag    = req_flags & GSS_C_DELEG_FLAG;
+    ni.reqFlags->mutualFlag   = req_flags & GSS_C_MUTUAL_FLAG;
+    ni.reqFlags->replayFlag   = req_flags & GSS_C_REPLAY_FLAG;
+    ni.reqFlags->sequenceFlag = req_flags & GSS_C_SEQUENCE_FLAG;
+    ni.reqFlags->anonFlag     = req_flags & GSS_C_ANON_FLAG;
+    ni.reqFlags->confFlag     = req_flags & GSS_C_CONF_FLAG;
+    ni.reqFlags->integFlag    = req_flags & GSS_C_INTEG_FLAG;
+#else
+    ni.reqFlags = NULL;
+#endif
+
+    sub = gsskrb5_init_sec_context(&minor,
+                                  initiator_cred_handle,
+                                  context_handle,
+                                  target_name,
+                                  GSS_KRB5_MECHANISM,
+                                  req_flags,
+                                  time_req,
+                                  input_chan_bindings,
+                                  GSS_C_NO_BUFFER,
+                                  actual_mech_type,
+                                  &mech_token,
+                                  ret_flags,
+                                  time_rec);
+    if (GSS_ERROR(sub)) {
+       free_NegTokenInit(&ni);
+       return sub;
+    }
+    if (mech_token.length != 0) {
+       ALLOC(ni.mechToken, 1);
+       if (ni.mechToken == NULL) {
+           free_NegTokenInit(&ni);
+           gss_release_buffer(&minor, &mech_token);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       ni.mechToken->length = mech_token.length;
+       ni.mechToken->data = malloc(mech_token.length);
+       if (ni.mechToken->data == NULL && mech_token.length != 0) {
+           free_NegTokenInit(&ni);
+           gss_release_buffer(&minor, &mech_token);
+           *minor_status = ENOMEM;
+           return GSS_S_FAILURE;
+       }
+       memcpy(ni.mechToken->data, mech_token.value, mech_token.length);
+       gss_release_buffer(&minor, &mech_token);
+    } else
+       ni.mechToken = NULL;
+
+    /* XXX ignore mech list mic for now */
+    ni.mechListMIC = NULL;
+
+
+#if 0
+    {
+       int ret;
+       NegotiationToken nt;
+
+       nt.element = choice_NegotiationToken_negTokenInit;
+       nt.u.negTokenInit = ni;
+
+       ASN1_MALLOC_ENCODE(NegotiationToken, buf, buf_size,
+                          &nt, &buf_len, ret);
+       if (buf_size != buf_len)
+           abort();
+    }
+#else
+    ni_len = length_NegTokenInit(&ni);
+    buf_size = 1 + length_len(ni_len) + ni_len;
+
+    buf = malloc(buf_size);
+    if (buf == NULL) {
+       free_NegTokenInit(&ni);
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+
+    ret = encode_NegTokenInit(buf + buf_size - 1,
+                             ni_len,
+                             &ni, &buf_len);
+    if (ret == 0 && ni_len != buf_len)
+       abort();
+
+    if (ret == 0) {
+       size_t tmp;
+
+       ret = der_put_length_and_tag(buf + buf_size - buf_len - 1,
+                                    buf_size - buf_len,
+                                    buf_len,
+                                    ASN1_C_CONTEXT,
+                                    CONS,
+                                    0,
+                                    &tmp);
+       if (ret == 0 && tmp + buf_len != buf_size)
+           abort();
+    }
+    if (ret) {
+       *minor_status = ret;
+       free(buf);
+       free_NegTokenInit(&ni);
+       return GSS_S_FAILURE;
+    }
+
+#endif
+    data.data   = buf;
+    data.length = buf_size;
+
+    free_NegTokenInit(&ni);
+    if (ret)
+       return ret;
+
+    sub = _gssapi_encapsulate(minor_status,
+                             &data,
+                             output_token,
+                             GSS_SPNEGO_MECHANISM);
+    free (buf);
+
+    if (sub)
+       return sub;
+
+    return GSS_S_CONTINUE_NEEDED;
+}
+
+static OM_uint32
+spnego_init_sec_context
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t * context_handle,
+            const gss_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const gss_buffer_t input_token,
+            gss_OID * actual_mech_type,
+            gss_buffer_t output_token,
+            OM_uint32 * ret_flags,
+            OM_uint32 * time_rec
+           )
+{
+    if (input_token == GSS_C_NO_BUFFER || input_token->length == 0)
+       return spnego_initial (minor_status,
+                              initiator_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);
+    else
+       return spnego_reply (minor_status,
+                            initiator_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);
+}
+
+/*
+ * gss_init_sec_context
+ */
+
+OM_uint32 gss_init_sec_context
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t initiator_cred_handle,
+            gss_ctx_id_t * context_handle,
+            const gss_name_t target_name,
+            const gss_OID mech_type,
+            OM_uint32 req_flags,
+            OM_uint32 time_req,
+            const gss_channel_bindings_t input_chan_bindings,
+            const gss_buffer_t input_token,
+            gss_OID * actual_mech_type,
+            gss_buffer_t output_token,
+            OM_uint32 * ret_flags,
+            OM_uint32 * time_rec
+           )
+{
+    GSSAPI_KRB5_INIT ();
+
+    output_token->length = 0;
+    output_token->value  = NULL;
+
+    if (ret_flags)
+       *ret_flags = 0;
+    if (time_rec)
+       *time_rec = 0;
+
+    if (target_name == GSS_C_NO_NAME) {
+       if (actual_mech_type)
+           *actual_mech_type = GSS_C_NO_OID;
+       *minor_status = 0;
+       return GSS_S_BAD_NAME;
+    }
+
+    if (mech_type == GSS_C_NO_OID || 
+       gss_oid_equal(mech_type,  GSS_KRB5_MECHANISM))
+       return gsskrb5_init_sec_context(minor_status,
+                                       initiator_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);
+    else if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM))
+       return spnego_init_sec_context (minor_status,
+                                       initiator_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);
+    else
+       return GSS_S_BAD_MECH;
+}
diff --git a/src/kerberosV/src/lib/gssapi/inquire_context.c b/src/kerberosV/src/lib/gssapi/inquire_context.c
new file mode 100644 (file)
index 0000000..d2bbd91
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1997, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: inquire_context.c,v 1.6 2003/05/21 14:52:13 lha Exp $");
+
+OM_uint32 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 * open_context
+           )
+{
+  OM_uint32 ret;
+
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+  if (src_name) {
+    ret = gss_duplicate_name (minor_status,
+                             context_handle->source,
+                             src_name);
+    if (ret)
+      goto failed;
+  }
+
+  if (targ_name) {
+    ret = gss_duplicate_name (minor_status,
+                             context_handle->target,
+                             targ_name);
+    if (ret)
+       goto failed;
+  }
+
+  if (lifetime_rec) {
+      ret = gssapi_lifetime_left(minor_status, 
+                                context_handle->lifetime,
+                                lifetime_rec);
+      if (ret)
+         goto failed;
+  }
+
+  if (mech_type)
+    *mech_type = GSS_KRB5_MECHANISM;
+
+  if (ctx_flags)
+    *ctx_flags = context_handle->flags;
+
+  if (locally_initiated)
+    *locally_initiated = context_handle->more_flags & LOCAL;
+
+  if (open_context)
+    *open_context = context_handle->more_flags & OPEN;
+
+  *minor_status = 0;
+  ret = GSS_S_COMPLETE;
+
+ failed:
+
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+  return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/inquire_cred.c b/src/kerberosV/src/lib/gssapi/inquire_cred.c
new file mode 100644 (file)
index 0000000..0052b7d
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1997, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: inquire_cred.c,v 1.7 2004/11/30 19:27:11 lha Exp $");
+
+OM_uint32 gss_inquire_cred
+           (OM_uint32 * minor_status,
+            const gss_cred_id_t cred_handle,
+            gss_name_t * name,
+            OM_uint32 * lifetime,
+            gss_cred_usage_t * cred_usage,
+            gss_OID_set * mechanisms
+           )
+{
+    gss_cred_id_t cred;
+    OM_uint32 ret;
+
+    *minor_status = 0;
+
+    if (name)
+       *name = NULL;
+    if (mechanisms)
+       *mechanisms = GSS_C_NO_OID_SET;
+
+    if (cred_handle == GSS_C_NO_CREDENTIAL) {
+       ret = gss_acquire_cred(minor_status, 
+                              GSS_C_NO_NAME,
+                              GSS_C_INDEFINITE,
+                              GSS_C_NO_OID_SET,
+                              GSS_C_BOTH,
+                              &cred,
+                              NULL,
+                              NULL);
+       if (ret)
+           return ret;
+    } else
+       cred = (gss_cred_id_t)cred_handle;
+
+    HEIMDAL_MUTEX_lock(&cred->cred_id_mutex);
+
+    if (name != NULL) {
+       if (cred->principal != NULL) {
+            ret = gss_duplicate_name(minor_status, cred->principal,
+               name);
+            if (ret)
+               goto out;
+       } else if (cred->usage == GSS_C_ACCEPT) {
+           *minor_status = krb5_sname_to_principal(gssapi_krb5_context, NULL,
+               NULL, KRB5_NT_SRV_HST, name);
+           if (*minor_status) {
+               ret = GSS_S_FAILURE;
+               goto out;
+           }
+       } else {
+           *minor_status = krb5_get_default_principal(gssapi_krb5_context,
+               name);
+           if (*minor_status) {
+               ret = GSS_S_FAILURE;
+               goto out;
+           }
+       }
+    }
+    if (lifetime != NULL) {
+       ret = gssapi_lifetime_left(minor_status, 
+                                  cred->lifetime,
+                                  lifetime);
+       if (ret)
+           goto out;
+    }
+    if (cred_usage != NULL)
+        *cred_usage = cred->usage;
+
+    if (mechanisms != NULL) {
+        ret = gss_create_empty_oid_set(minor_status, mechanisms);
+        if (ret)
+           goto out;
+        ret = gss_add_oid_set_member(minor_status,
+                                    &cred->mechanisms->elements[0],
+                                    mechanisms);
+        if (ret)
+           goto out;
+    }
+    ret = GSS_S_COMPLETE;
+ out:
+    HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex);
+
+    if (cred_handle == GSS_C_NO_CREDENTIAL)
+       ret = gss_release_cred(minor_status, &cred);
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/inquire_cred_by_mech.c b/src/kerberosV/src/lib/gssapi/inquire_cred_by_mech.c
new file mode 100644 (file)
index 0000000..df383cd
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: inquire_cred_by_mech.c,v 1.2 2003/05/21 14:52:14 lha Exp $");
+
+OM_uint32 gss_inquire_cred_by_mech (
+            OM_uint32 * minor_status,
+            const gss_cred_id_t cred_handle,
+            const gss_OID mech_type,
+            gss_name_t * name,
+            OM_uint32 * initiator_lifetime,
+            OM_uint32 * acceptor_lifetime,
+            gss_cred_usage_t * cred_usage
+    )
+{
+    OM_uint32 ret;
+    OM_uint32 lifetime;
+
+    if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 &&
+       gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) {
+       *minor_status = EINVAL;
+       return GSS_S_BAD_MECH;
+    }    
+
+    ret = gss_inquire_cred (minor_status,
+                           cred_handle,
+                           name,
+                           &lifetime,
+                           cred_usage,
+                           NULL);
+    
+    if (ret == 0 && cred_handle != GSS_C_NO_CREDENTIAL) {
+       gss_cred_usage_t usage;
+
+       HEIMDAL_MUTEX_lock(&cred_handle->cred_id_mutex);
+       usage = cred_handle->usage;
+       HEIMDAL_MUTEX_unlock(&cred_handle->cred_id_mutex);
+
+       if (initiator_lifetime) {
+           if (usage == GSS_C_INITIATE || usage == GSS_C_BOTH)
+               *initiator_lifetime = lifetime;
+       }
+       if (acceptor_lifetime) {
+           if (usage == GSS_C_ACCEPT || usage == GSS_C_BOTH)
+               *acceptor_lifetime = lifetime;
+       }
+    }
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/inquire_mechs_for_name.c b/src/kerberosV/src/lib/gssapi/inquire_mechs_for_name.c
new file mode 100644 (file)
index 0000000..9a63b64
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: inquire_mechs_for_name.c,v 1.1 2003/03/16 18:12:33 lha Exp $");
+
+OM_uint32 gss_inquire_mechs_for_name (
+            OM_uint32 * minor_status,
+            const gss_name_t input_name,
+            gss_OID_set * mech_types
+           )
+{
+    OM_uint32 ret;
+
+    ret = gss_create_empty_oid_set(minor_status, mech_types);
+    if (ret)
+       return ret;
+
+    ret = gss_add_oid_set_member(minor_status,
+                                GSS_KRB5_MECHANISM,
+                                mech_types);
+    if (ret)
+       gss_release_oid_set(NULL, mech_types);
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/inquire_names_for_mech.c b/src/kerberosV/src/lib/gssapi/inquire_names_for_mech.c
new file mode 100644 (file)
index 0000000..fe7abd8
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: inquire_names_for_mech.c,v 1.1 2003/03/16 18:15:29 lha Exp $");
+
+
+static gss_OID *name_list[] = {
+    &GSS_C_NT_HOSTBASED_SERVICE,
+    &GSS_C_NT_USER_NAME,
+    &GSS_KRB5_NT_PRINCIPAL_NAME,
+    &GSS_C_NT_EXPORT_NAME,
+    NULL
+};
+
+OM_uint32 gss_inquire_names_for_mech (
+            OM_uint32 * minor_status,
+            const gss_OID mechanism,
+            gss_OID_set * name_types
+           )
+{
+    OM_uint32 ret;
+    int i;
+
+    *minor_status = 0;
+
+    if (gss_oid_equal(mechanism, GSS_KRB5_MECHANISM) == 0 &&
+       gss_oid_equal(mechanism, GSS_C_NULL_OID) == 0) {
+       *name_types = GSS_C_NO_OID_SET;
+       return GSS_S_BAD_MECH;
+    }
+
+    ret = gss_create_empty_oid_set(minor_status, name_types);
+    if (ret != GSS_S_COMPLETE)
+       return ret;
+    
+    for (i = 0; name_list[i] != NULL; i++) {
+       ret = gss_add_oid_set_member(minor_status, 
+                                    *(name_list[i]),
+                                    name_types);
+       if (ret != GSS_S_COMPLETE)
+           break;
+    }
+
+    if (ret != GSS_S_COMPLETE)
+       gss_release_oid_set(NULL, name_types);
+       
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/process_context_token.c b/src/kerberosV/src/lib/gssapi/process_context_token.c
new file mode 100644 (file)
index 0000000..8e7dce4
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: process_context_token.c,v 1.1 2003/03/16 18:19:05 lha Exp $");
+
+OM_uint32 gss_process_context_token (
+       OM_uint32          *minor_status,
+       const gss_ctx_id_t context_handle,
+       const gss_buffer_t token_buffer
+    )
+{
+    OM_uint32 ret = GSS_S_FAILURE;
+    gss_buffer_desc empty_buffer;
+    gss_qop_t qop_state;
+
+    empty_buffer.length = 0;
+    empty_buffer.value = NULL;
+
+    qop_state = GSS_C_QOP_DEFAULT;
+
+    ret = gss_verify_mic_internal(minor_status, context_handle,
+                                 token_buffer, &empty_buffer,
+                                 GSS_C_QOP_DEFAULT, "\x01\x02");
+
+    if (ret == GSS_S_COMPLETE)
+       ret = gss_delete_sec_context(minor_status,
+                                    (gss_ctx_id_t *)&context_handle,
+                                    GSS_C_NO_BUFFER);
+    if (ret == GSS_S_COMPLETE)
+       *minor_status = 0;
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/release_buffer.c b/src/kerberosV/src/lib/gssapi/release_buffer.c
new file mode 100644 (file)
index 0000000..a10430f
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997 - 2000, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: release_buffer.c,v 1.5 2003/03/16 17:58:20 lha Exp $");
+
+OM_uint32 gss_release_buffer
+           (OM_uint32 * minor_status,
+            gss_buffer_t buffer
+           )
+{
+  *minor_status = 0;
+  free (buffer->value);
+  buffer->value  = NULL;
+  buffer->length = 0;
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/release_cred.c b/src/kerberosV/src/lib/gssapi/release_cred.c
new file mode 100644 (file)
index 0000000..09f5909
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: release_cred.c,v 1.10 2003/10/07 00:51:46 lha Exp $");
+
+OM_uint32 gss_release_cred
+           (OM_uint32 * minor_status,
+            gss_cred_id_t * cred_handle
+           )
+{
+    *minor_status = 0;
+
+    if (*cred_handle == GSS_C_NO_CREDENTIAL) {
+        return GSS_S_COMPLETE;
+    }
+
+    GSSAPI_KRB5_INIT ();
+
+    HEIMDAL_MUTEX_lock(&(*cred_handle)->cred_id_mutex);
+
+    if ((*cred_handle)->principal != NULL)
+        krb5_free_principal(gssapi_krb5_context, (*cred_handle)->principal);
+    if ((*cred_handle)->keytab != NULL)
+       krb5_kt_close(gssapi_krb5_context, (*cred_handle)->keytab);
+    if ((*cred_handle)->ccache != NULL) {
+       const krb5_cc_ops *ops;
+       ops = krb5_cc_get_ops(gssapi_krb5_context, (*cred_handle)->ccache);
+       if (ops == &krb5_mcc_ops)
+           krb5_cc_destroy(gssapi_krb5_context, (*cred_handle)->ccache);
+       else 
+           krb5_cc_close(gssapi_krb5_context, (*cred_handle)->ccache);
+    }
+    gss_release_oid_set(NULL, &(*cred_handle)->mechanisms);
+    HEIMDAL_MUTEX_unlock(&(*cred_handle)->cred_id_mutex);
+    HEIMDAL_MUTEX_destroy(&(*cred_handle)->cred_id_mutex);
+    memset(*cred_handle, 0, sizeof(**cred_handle));
+    free(*cred_handle);
+    *cred_handle = GSS_C_NO_CREDENTIAL;
+    return GSS_S_COMPLETE;
+}
+
diff --git a/src/kerberosV/src/lib/gssapi/release_name.c b/src/kerberosV/src/lib/gssapi/release_name.c
new file mode 100644 (file)
index 0000000..b364e6a
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: release_name.c,v 1.7 2003/03/16 17:52:48 lha Exp $");
+
+OM_uint32 gss_release_name
+           (OM_uint32 * minor_status,
+            gss_name_t * input_name
+           )
+{
+    GSSAPI_KRB5_INIT ();
+    if (minor_status)
+      *minor_status = 0;
+    krb5_free_principal(gssapi_krb5_context,
+                       *input_name);
+    *input_name = GSS_C_NO_NAME;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/release_oid_set.c b/src/kerberosV/src/lib/gssapi/release_oid_set.c
new file mode 100644 (file)
index 0000000..aa7c87b
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1997 - 2000, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: release_oid_set.c,v 1.5 2003/03/16 17:53:25 lha Exp $");
+
+OM_uint32 gss_release_oid_set
+           (OM_uint32 * minor_status,
+            gss_OID_set * set
+           )
+{
+  if (minor_status)
+      *minor_status = 0;
+  free ((*set)->elements);
+  free (*set);
+  *set = GSS_C_NO_OID_SET;
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/sequence.c b/src/kerberosV/src/lib/gssapi/sequence.c
new file mode 100644 (file)
index 0000000..f6d7b7b
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: sequence.c,v 1.5 2005/04/27 17:49:43 lha Exp $");
+
+#define DEFAULT_JITTER_WINDOW 20
+
+struct gss_msg_order {
+    OM_uint32 flags;
+    OM_uint32 start;
+    OM_uint32 length;
+    OM_uint32 jitter_window;
+    OM_uint32 first_seq;
+    OM_uint32 elem[1];
+};
+
+/*
+ *
+ */
+
+OM_uint32
+_gssapi_msg_order_create(OM_uint32 *minor_status,
+                        struct gss_msg_order **o, 
+                        OM_uint32 flags, 
+                        OM_uint32 seq_num, 
+                        OM_uint32 jitter_window,
+                        int use_64)
+{
+    size_t len;
+
+    if (jitter_window == 0)
+       jitter_window = DEFAULT_JITTER_WINDOW;
+
+    len = jitter_window * sizeof((*o)->elem[0]);
+    len += sizeof(**o);
+    len -= sizeof((*o)->elem[0]);
+    
+    *o = malloc(len);
+    if (*o == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }  
+    memset(*o, 0, len);
+    (*o)->flags = flags;
+    (*o)->length = 0;
+    (*o)->first_seq = seq_num;
+    (*o)->jitter_window = jitter_window;
+    (*o)->elem[0] = seq_num - 1;
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+_gssapi_msg_order_destroy(struct gss_msg_order **m)
+{
+    free(*m);
+    *m = NULL;
+    return GSS_S_COMPLETE;
+}
+
+static void
+elem_set(struct gss_msg_order *o, unsigned int slot, OM_uint32 val)
+{
+    o->elem[slot % o->jitter_window] = val;
+}
+
+static void
+elem_insert(struct gss_msg_order *o, 
+           unsigned int after_slot,
+           OM_uint32 seq_num)
+{
+    assert(o->jitter_window > after_slot);
+
+    if (o->length > after_slot)
+       memmove(&o->elem[after_slot + 1], &o->elem[after_slot],
+               (o->length - after_slot - 1) * sizeof(o->elem[0]));
+
+    elem_set(o, after_slot, seq_num);
+
+    if (o->length < o->jitter_window)
+       o->length++;
+}
+
+/* rule 1: expected sequence number */
+/* rule 2: > expected sequence number */
+/* rule 3: seqnum < seqnum(first) */
+/* rule 4+5: seqnum in [seqnum(first),seqnum(last)]  */
+
+OM_uint32
+_gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num)
+{
+    OM_uint32 r;
+    int i;
+
+    if (o == NULL)
+       return GSS_S_COMPLETE;
+
+    if ((o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG)) == 0)
+       return GSS_S_COMPLETE;
+
+    /* check if the packet is the next in order */
+    if (o->elem[0] == seq_num - 1) {
+       elem_insert(o, 0, seq_num);
+       return GSS_S_COMPLETE;
+    }
+
+    r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG;
+
+    /* sequence number larger then largest sequence number 
+     * or smaller then the first sequence number */
+    if (seq_num > o->elem[0]
+       || seq_num < o->first_seq
+       || o->length == 0) 
+    {
+       elem_insert(o, 0, seq_num);
+       if (r) {
+           return GSS_S_COMPLETE;
+       } else {
+           return GSS_S_GAP_TOKEN;
+       }
+    }
+
+    assert(o->length > 0);
+
+    /* sequence number smaller the first sequence number */
+    if (seq_num < o->elem[o->length - 1]) {
+       if (r)
+           return(GSS_S_OLD_TOKEN);
+       else
+           return(GSS_S_UNSEQ_TOKEN);
+    }
+
+    if (seq_num == o->elem[o->length - 1]) {
+       return GSS_S_DUPLICATE_TOKEN;
+    }
+
+    for (i = 0; i < o->length - 1; i++) {
+       if (o->elem[i] == seq_num)
+           return GSS_S_DUPLICATE_TOKEN;
+       if (o->elem[i + 1] < seq_num && o->elem[i] < seq_num) {
+           elem_insert(o, i, seq_num);
+           if (r)
+               return GSS_S_COMPLETE;
+           else
+               return GSS_S_UNSEQ_TOKEN;
+       }
+    }
+
+    return GSS_S_FAILURE;
+}
+
+OM_uint32
+_gssapi_msg_order_f(OM_uint32 flags)
+{
+    return flags & (GSS_C_SEQUENCE_FLAG|GSS_C_REPLAY_FLAG);
+}
diff --git a/src/kerberosV/src/lib/gssapi/spkm.asn1 b/src/kerberosV/src/lib/gssapi/spkm.asn1
new file mode 100644 (file)
index 0000000..1994e3b
--- /dev/null
@@ -0,0 +1,240 @@
+-- from rfc2025
+-- $KTH: spkm.asn1,v 1.1 2004/08/25 20:08:22 lha Exp $
+
+SpkmGssTokens DEFINITIONS ::=
+BEGIN
+
+IMPORTS AlgorithmIdentifier, Validity,
+       Attribute, Certificate, CertificateList, CertificatePair, Name
+       FROM rfc2459
+       AuthorizationData FROM krb5;
+
+SPKM-REQ ::= SEQUENCE {
+       requestToken      REQ-TOKEN,
+       certif-data [0]   CertificationData OPTIONAL,
+       auth-data [1]     AuthorizationData OPTIONAL
+}
+
+
+CertificationData ::= SEQUENCE {
+       certificationPath [0]     CertificationPath OPTIONAL,
+       certificateRevocationList [1]  CertificateList OPTIONAL
+} -- at least one of the above shall be present
+
+
+CertificationPath ::= SEQUENCE {
+       userKeyId [0]    OCTET STRING OPTIONAL,
+       userCertif [1]  Certificate OPTIONAL,
+       verifKeyId [2]  OCTET STRING OPTIONAL,
+       userVerifCertif [3]   Certificate OPTIONAL,
+       theCACertificates [4] SEQUENCE OF CertificatePair OPTIONAL
+} -- Presence of [2] or [3] implies that [0] or [1] must also be
+  -- present.  Presence of [4] implies that at least one of [0], [1],
+  -- [2], and [3] must also be present.
+
+REQ-TOKEN ::= SEQUENCE {
+       req-contents     Req-contents,
+       algId       AlgorithmIdentifier,
+       req-integrity    Integrity  -- "token" is Req-contents
+}
+
+Integrity ::= BIT STRING
+  -- If corresponding algId specifies a signing algorithm,
+  -- "Integrity" holds the result of applying the signing procedure
+  -- specified in algId to the BER-encoded octet string which results
+  -- from applying the hashing procedure (also specified in algId) to
+  -- the DER-encoded octets of "token".
+  -- Alternatively, if corresponding algId specifies a MACing
+  -- algorithm, "Integrity" holds the result of applying the MACing
+  -- procedure specified in algId to the DER-encoded octets of
+  -- "token"
+
+Req-contents ::= SEQUENCE {
+       tok-id     INTEGER --(256)--,  -- shall contain 0100 (hex)
+       context-id       Random-Integer,
+       pvno         BIT STRING,
+       timestamp       UTCTime OPTIONAL, -- mandatory for SPKM-2
+       randSrc   Random-Integer,
+       targ-name       Name,
+       src-name [0]     Name OPTIONAL,
+       req-data         Context-Data,
+       validity [1]     Validity OPTIONAL,
+       key-estb-set     Key-Estb-Algs,
+       key-estb-req     BIT STRING OPTIONAL,
+       key-src-bind     OCTET STRING OPTIONAL
+          -- This field must be present for the case of SPKM-2
+          -- unilateral authen. if the K-ALG in use does not provide
+          -- such a binding (but is optional for all other cases).
+          -- The octet string holds the result of applying the
+          -- mandatory hashing procedure (in MANDATORY I-ALG;
+          -- see Section 2.1) as follows:  MD5(src || context_key),
+          -- where "src" is the DER-encoded octets of src-name,
+          -- "context-key" is the symmetric key (i.e., the
+          -- unprotected version of what is transmitted in
+          -- key-estb-req), and "||" is the concatenation operation.
+}
+
+Random-Integer ::= BIT STRING
+
+Context-Data ::= SEQUENCE {
+       channelId       ChannelId OPTIONAL,
+       seq-number      INTEGER OPTIONAL,
+       options  Options,
+       conf-alg        Conf-Algs,
+       intg-alg        Intg-Algs,
+       owf-alg  OWF-Algs
+}
+
+ChannelId ::= OCTET STRING
+
+Options ::= BIT STRING {
+       delegation-state (0),
+       mutual-state (1),
+       replay-det-state (2),
+       sequence-state (3),
+       conf-avail (4),
+       integ-avail (5),
+       target-certif-data-required (6)
+}
+
+Conf-Algs ::= CHOICE {
+       algs [0]         SEQUENCE OF AlgorithmIdentifier,
+       null [1]         NULL
+}
+
+Intg-Algs ::= SEQUENCE OF AlgorithmIdentifier
+
+OWF-Algs ::= SEQUENCE OF AlgorithmIdentifier
+
+Key-Estb-Algs ::= SEQUENCE OF AlgorithmIdentifier
+
+
+SPKM-REP-TI ::= SEQUENCE {
+       responseToken    REP-TI-TOKEN,
+       certif-data      CertificationData OPTIONAL
+         -- present if target-certif-data-required option was
+}       -- set to TRUE in SPKM-REQ
+
+REP-TI-TOKEN ::= SEQUENCE {
+       rep-ti-contents  Rep-ti-contents,
+       algId       AlgorithmIdentifier,
+       rep-ti-integ     Integrity  -- "token" is Rep-ti-contents
+}
+
+Rep-ti-contents ::= SEQUENCE {
+       tok-id     INTEGER --(512)--,   -- shall contain 0200 (hex)
+       context-id       Random-Integer,
+       pvno [0]         BIT STRING OPTIONAL,
+       timestamp       UTCTime OPTIONAL, -- mandatory for SPKM-2
+       randTarg         Random-Integer,
+       src-name [1]     Name OPTIONAL,
+       targ-name       Name,
+       randSrc   Random-Integer,
+       rep-data         Context-Data,
+       validity [2]     Validity  OPTIONAL,
+       key-estb-id      AlgorithmIdentifier OPTIONAL,
+       key-estb-str     BIT STRING OPTIONAL
+}
+
+SPKM-REP-IT ::= SEQUENCE {
+       responseToken    REP-IT-TOKEN,
+       algId       AlgorithmIdentifier,
+       rep-it-integ     Integrity  -- "token" is REP-IT-TOKEN
+}
+
+REP-IT-TOKEN ::= SEQUENCE {
+       tok-id     INTEGER --(768)--,  -- shall contain 0300 (hex)
+       context-id       Random-Integer,
+       randSrc   Random-Integer,
+       randTarg         Random-Integer,
+       targ-name       Name,
+       src-name         Name OPTIONAL,
+       key-estb-rep     BIT STRING OPTIONAL
+}
+
+SPKM-ERROR ::= SEQUENCE {
+       errorToken       ERROR-TOKEN,
+       algId       AlgorithmIdentifier,
+       integrity       Integrity  -- "token" is ERROR-TOKEN
+}
+
+ERROR-TOKEN ::=   SEQUENCE {
+       tok-id     INTEGER --(1024)--, -- shall contain 0400 (hex)
+       context-id       Random-Integer
+}
+
+SPKM-MIC ::= SEQUENCE {
+       mic-header       Mic-Header,
+       int-cksum       BIT STRING
+}
+
+Mic-Header ::= SEQUENCE {
+       tok-id     INTEGER --(257)--, -- shall contain 0101 (hex)
+       context-id       Random-Integer,
+       int-alg [0]      AlgorithmIdentifier OPTIONAL,
+       snd-seq [1]      SeqNum OPTIONAL
+}
+
+SeqNum ::= SEQUENCE {
+       num           INTEGER,
+       dir-ind   BOOLEAN
+}
+
+SPKM-WRAP ::= SEQUENCE {
+       wrap-header       Wrap-Header,
+       wrap-body        Wrap-Body
+}
+
+Wrap-Header ::= SEQUENCE {
+       tok-id     INTEGER --(513)--, -- shall contain 0201 (hex)
+       context-id       Random-Integer,
+       int-alg [0]      AlgorithmIdentifier OPTIONAL,
+       conf-alg [1]     Conf-Alg OPTIONAL,
+       snd-seq [2]      SeqNum OPTIONAL
+}
+
+Wrap-Body ::= SEQUENCE {
+       int-cksum       BIT STRING,
+       data         BIT STRING
+}
+
+Conf-Alg ::= CHOICE {
+       algId [0]       AlgorithmIdentifier,
+       null [1]         NULL
+}
+
+
+SPKM-DEL ::= SEQUENCE {
+       del-header       Del-Header,
+       int-cksum       BIT STRING
+}
+
+Del-Header ::= SEQUENCE {
+       tok-id     INTEGER --(769)--, -- shall contain 0301 (hex)
+       context-id       Random-Integer,
+       int-alg [0]      AlgorithmIdentifier OPTIONAL,
+       snd-seq [1]      SeqNum OPTIONAL
+}
+
+
+-- other types --
+
+MechType ::= OBJECT IDENTIFIER
+
+SPKMInnerContextToken ::= CHOICE {
+       req    [0] SPKM-REQ,
+       rep-ti [1] SPKM-REP-TI,
+       rep-it [2] SPKM-REP-IT,
+       error  [3] SPKM-ERROR,
+       mic    [4] SPKM-MIC,
+       wrap   [5] SPKM-WRAP,
+       del    [6] SPKM-DEL
+}
+
+InitialContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE {
+       thisMech              MechType,
+       innerContextToken     SPKMInnerContextToken
+}     -- when thisMech is SPKM-1 or SPKM-2
+
+
+END
diff --git a/src/kerberosV/src/lib/gssapi/spnego.asn1 b/src/kerberosV/src/lib/gssapi/spnego.asn1
new file mode 100644 (file)
index 0000000..577cb21
--- /dev/null
@@ -0,0 +1,42 @@
+-- $KTH: spnego.asn1,v 1.4 2004/03/07 13:38:08 lha Exp $
+
+SPNEGO DEFINITIONS ::=
+BEGIN
+
+MechType::= OBJECT IDENTIFIER
+
+MechTypeList ::= SEQUENCE OF MechType
+
+ContextFlags ::= BIT STRING {
+        delegFlag       (0),
+        mutualFlag      (1),
+        replayFlag      (2),
+        sequenceFlag    (3),
+        anonFlag        (4),
+        confFlag        (5),
+        integFlag       (6)
+}
+
+NegTokenInit ::= SEQUENCE {
+                            mechTypes       [0] MechTypeList  OPTIONAL,
+                            reqFlags        [1] ContextFlags  OPTIONAL,
+                            mechToken       [2] OCTET STRING  OPTIONAL,
+                            mechListMIC     [3] OCTET STRING  OPTIONAL
+                         }
+
+NegTokenTarg ::= SEQUENCE {
+    negResult      [0] ENUMERATED {
+                            accept_completed    (0),
+                            accept_incomplete   (1),
+                            reject              (2) }          OPTIONAL,
+    supportedMech  [1] MechType                                OPTIONAL,
+    responseToken  [2] OCTET STRING                            OPTIONAL,
+    mechListMIC    [3] OCTET STRING                            OPTIONAL
+}
+
+NegotiationToken ::= CHOICE {
+       negTokenInit[0]         NegTokenInit,
+       negTokenTarg[1]         NegTokenTarg
+}
+
+END
diff --git a/src/kerberosV/src/lib/gssapi/test_acquire_cred.c b/src/kerberosV/src/lib/gssapi/test_acquire_cred.c
new file mode 100644 (file)
index 0000000..2baeaac
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#include "gssapi_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_acquire_cred.c,v 1.5 2004/03/14 13:44:47 lha Exp $");
+
+static void
+print_time(OM_uint32 time_rec)
+{
+    if (time_rec == GSS_C_INDEFINITE) {
+       printf("cred never expire\n");
+    } else {
+       time_t t = time_rec + time(NULL);
+       printf("expiration time: %s", ctime(&t));
+    }
+}
+
+static void
+test_add(gss_cred_id_t cred_handle)
+{
+    OM_uint32 major_status, minor_status;
+    gss_cred_id_t copy_cred;
+    OM_uint32 time_rec;
+
+    major_status = gss_add_cred (&minor_status,
+                                cred_handle,
+                                GSS_C_NO_NAME,
+                                GSS_KRB5_MECHANISM,
+                                GSS_C_INITIATE,
+                                0,
+                                0,
+                                &copy_cred,
+                                NULL,
+                                &time_rec,
+                                NULL);
+                           
+    if (GSS_ERROR(major_status))
+       errx(1, "add_cred failed");
+
+    print_time(time_rec);
+
+    major_status = gss_release_cred(&minor_status,
+                                   &copy_cred);
+    if (GSS_ERROR(major_status))
+       errx(1, "release_cred failed");
+}
+
+int
+main(int argc, char **argv)
+{
+    OM_uint32 major_status, minor_status;
+    gss_cred_id_t cred_handle;
+    OM_uint32 time_rec;
+
+    major_status = gss_acquire_cred(&minor_status, 
+                                   GSS_C_NO_NAME,
+                                   0,
+                                   NULL,
+                                   GSS_C_INITIATE,
+                                   &cred_handle,
+                                   NULL,
+                                   &time_rec);
+    if (GSS_ERROR(major_status))
+       errx(1, "acquire_cred failed");
+       
+    print_time(time_rec);
+
+    test_add(cred_handle);
+    test_add(cred_handle);
+    test_add(cred_handle);
+
+    major_status = gss_release_cred(&minor_status,
+                                   &cred_handle);
+    if (GSS_ERROR(major_status))
+       errx(1, "release_cred failed");
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/gssapi/test_cred.c b/src/kerberosV/src/lib/gssapi/test_cred.c
new file mode 100644 (file)
index 0000000..f2657ec
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2003-2004 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.
+ */
+
+#include "gssapi_locl.h"
+#include <err.h>
+#include <getarg.h>
+
+RCSID("$KTH: test_cred.c,v 1.2 2005/05/02 13:46:39 lha Exp $");
+
+static void
+acquire_release_loop(gss_name_t name, int counter, gss_cred_usage_t usage)
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_cred_id_t cred;
+    int i;
+
+    for (i = 0; i < counter; i++) {
+       maj_stat = gss_acquire_cred(&min_stat, name,
+                                   GSS_C_INDEFINITE,
+                                   GSS_C_NO_OID_SET,
+                                   usage,
+                                   &cred,
+                                   NULL,
+                                   NULL);
+       if (maj_stat != GSS_S_COMPLETE)
+           errx(1, "aquire %d %d != GSS_S_COMPLETE", i, (int)maj_stat);
+                                   
+       maj_stat = gss_release_cred(&min_stat, &cred);
+       if (maj_stat != GSS_S_COMPLETE)
+           errx(1, "release %d %d != GSS_S_COMPLETE", i, (int)maj_stat);
+    }
+}
+
+
+static void
+acquire_add_release_add(gss_name_t name, gss_cred_usage_t usage)
+{
+    OM_uint32 maj_stat, min_stat;
+    gss_cred_id_t cred, cred2, cred3;
+
+    maj_stat = gss_acquire_cred(&min_stat, name,
+                               GSS_C_INDEFINITE,
+                               GSS_C_NO_OID_SET,
+                               usage,
+                               &cred,
+                               NULL,
+                               NULL);
+    if (maj_stat != GSS_S_COMPLETE)
+       errx(1, "aquire %d != GSS_S_COMPLETE", (int)maj_stat);
+    
+    maj_stat = gss_add_cred(&min_stat,
+                           cred,
+                           GSS_C_NO_NAME,
+                           GSS_KRB5_MECHANISM,
+                           usage,
+                           GSS_C_INDEFINITE,
+                           GSS_C_INDEFINITE,
+                           &cred2,
+                           NULL,
+                           NULL,
+                           NULL);
+                           
+    if (maj_stat != GSS_S_COMPLETE)
+       errx(1, "add_cred %d != GSS_S_COMPLETE", (int)maj_stat);
+
+    maj_stat = gss_release_cred(&min_stat, &cred);
+    if (maj_stat != GSS_S_COMPLETE)
+       errx(1, "release %d != GSS_S_COMPLETE", (int)maj_stat);
+
+    maj_stat = gss_add_cred(&min_stat,
+                           cred2,
+                           GSS_C_NO_NAME,
+                           GSS_KRB5_MECHANISM,
+                           GSS_C_BOTH,
+                           GSS_C_INDEFINITE,
+                           GSS_C_INDEFINITE,
+                           &cred3,
+                           NULL,
+                           NULL,
+                           NULL);
+
+    maj_stat = gss_release_cred(&min_stat, &cred2);
+    if (maj_stat != GSS_S_COMPLETE)
+       errx(1, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat);
+
+    maj_stat = gss_release_cred(&min_stat, &cred3);
+    if (maj_stat != GSS_S_COMPLETE)
+       errx(1, "release 2 %d != GSS_S_COMPLETE", (int)maj_stat);
+}
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag, "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,  NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args, sizeof(args)/sizeof(*args),
+                   NULL, "service@host");
+    exit (ret);
+}
+
+
+int
+main(int argc, char **argv)
+{
+    struct gss_buffer_desc_struct name_buffer;
+    OM_uint32 maj_stat, min_stat;
+    gss_name_t name;
+    int optind = 0;
+
+    setprogname(argv[0]);
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc < 1)
+       errx(1, "argc < 1");
+
+    name_buffer.value = argv[0];
+    name_buffer.length = strlen(argv[0]);
+
+    maj_stat = gss_import_name(&min_stat, &name_buffer,
+                              GSS_C_NT_HOSTBASED_SERVICE,
+                              &name);
+    if (maj_stat != GSS_S_COMPLETE)
+       errx(1, "import name error");
+
+    acquire_release_loop(name, 100, GSS_C_ACCEPT);
+    acquire_release_loop(name, 100, GSS_C_INITIATE);
+    acquire_release_loop(name, 100, GSS_C_BOTH);
+
+    acquire_add_release_add(name, GSS_C_ACCEPT);
+    acquire_add_release_add(name, GSS_C_INITIATE);
+    acquire_add_release_add(name, GSS_C_BOTH);
+
+    gss_release_name(&min_stat, &name);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/gssapi/test_oid_set_member.c b/src/kerberosV/src/lib/gssapi/test_oid_set_member.c
new file mode 100644 (file)
index 0000000..3ab6293
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1997, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: test_oid_set_member.c,v 1.5 2003/03/16 17:54:06 lha Exp $");
+
+OM_uint32 gss_test_oid_set_member (
+            OM_uint32 * minor_status,
+            const gss_OID member,
+            const gss_OID_set set,
+            int * present
+           )
+{
+  size_t i;
+
+  *minor_status = 0;
+  *present = 0;
+  for (i = 0; i < set->count; ++i)
+      if (gss_oid_equal(member, &set->elements[i]) != 0) {
+         *present = 1;
+         break;
+      }
+  return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/test_sequence.c b/src/kerberosV/src/lib/gssapi/test_sequence.c
new file mode 100644 (file)
index 0000000..4f02c85
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: test_sequence.c,v 1.5 2005/04/27 17:50:13 lha Exp $");
+
+/* correct ordering */
+OM_uint32 pattern1[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13
+};
+
+/* gap 10 */
+OM_uint32 pattern2[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13
+};
+
+/* dup 9 */
+OM_uint32 pattern3[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13
+};
+
+/* gaps */
+OM_uint32 pattern4[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 16, 18, 100
+};
+
+/* 11 before 10 */
+OM_uint32 pattern5[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21
+};
+
+/* long */
+OM_uint32 pattern6[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+    30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+    40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
+    50, 51, 52, 53, 54, 55, 56, 57, 58, 59
+};
+
+/* dont start at 0 */
+OM_uint32 pattern7[] = {
+    11, 12, 13
+};
+
+/* wrap around */
+OM_uint32 pattern8[] = {
+    4294967293U, 4294967294U, 4294967295U, 0, 1, 2
+};
+
+static int
+test_seq(int t, OM_uint32 flags, OM_uint32 start_seq,
+        OM_uint32 *pattern, int pattern_len)
+{
+    struct gss_msg_order *o;
+    OM_uint32 maj_stat, min_stat;
+    int i;
+
+    maj_stat = _gssapi_msg_order_create(&min_stat, &o, flags, 
+                                       start_seq, 20, 0);
+    if (maj_stat)
+       err(1, "create: %d %d", maj_stat, min_stat);
+
+    for (i = 0; i < pattern_len; i++) {
+       maj_stat = _gssapi_msg_order_check(o, pattern[i]);
+       if (maj_stat)
+           return maj_stat;
+    }
+    _gssapi_msg_order_destroy(&o);
+
+    return 0;
+}
+
+struct {
+    OM_uint32 flags;
+    OM_uint32 *pattern;
+    int pattern_len;
+    OM_uint32 error_code;
+    OM_uint32 start_seq;
+} pl[] = {
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern1,
+       sizeof(pattern1)/sizeof(pattern1[0]),
+       0
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern2,
+       sizeof(pattern2)/sizeof(pattern2[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern3,
+       sizeof(pattern3)/sizeof(pattern3[0]),
+       GSS_S_DUPLICATE_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern4,
+       sizeof(pattern4)/sizeof(pattern4[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern5,
+       sizeof(pattern5)/sizeof(pattern5[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern6,
+       sizeof(pattern6)/sizeof(pattern6[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern7,
+       sizeof(pattern7)/sizeof(pattern7[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG,
+       pattern8,
+       sizeof(pattern8)/sizeof(pattern8[0]),
+       GSS_S_COMPLETE,
+       4294967293U
+    },
+    {
+       0,
+       pattern1,
+       sizeof(pattern1)/sizeof(pattern1[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern2,
+       sizeof(pattern2)/sizeof(pattern2[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern3,
+       sizeof(pattern3)/sizeof(pattern3[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern4,
+       sizeof(pattern4)/sizeof(pattern4[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern5,
+       sizeof(pattern5)/sizeof(pattern5[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern6,
+       sizeof(pattern6)/sizeof(pattern6[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern7,
+       sizeof(pattern7)/sizeof(pattern7[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       0,
+       pattern8,
+       sizeof(pattern8)/sizeof(pattern8[0]),
+       GSS_S_COMPLETE,
+       4294967293U
+
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern1,
+       sizeof(pattern1)/sizeof(pattern1[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern2,
+       sizeof(pattern2)/sizeof(pattern2[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern3,
+       sizeof(pattern3)/sizeof(pattern3[0]),
+       GSS_S_DUPLICATE_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern4,
+       sizeof(pattern4)/sizeof(pattern4[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern5,
+       sizeof(pattern5)/sizeof(pattern5[0]),
+       0
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern6,
+       sizeof(pattern6)/sizeof(pattern6[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern7,
+       sizeof(pattern7)/sizeof(pattern7[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern8,
+       sizeof(pattern8)/sizeof(pattern8[0]),
+       GSS_S_COMPLETE,
+       4294967293U
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern1,
+       sizeof(pattern1)/sizeof(pattern1[0]),
+       0
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern2,
+       sizeof(pattern2)/sizeof(pattern2[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern3,
+       sizeof(pattern3)/sizeof(pattern3[0]),
+       GSS_S_DUPLICATE_TOKEN
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern4,
+       sizeof(pattern4)/sizeof(pattern4[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern5,
+       sizeof(pattern5)/sizeof(pattern5[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern6,
+       sizeof(pattern6)/sizeof(pattern6[0]),
+       GSS_S_COMPLETE
+    },
+    {
+       GSS_C_SEQUENCE_FLAG,
+       pattern7,
+       sizeof(pattern7)/sizeof(pattern7[0]),
+       GSS_S_GAP_TOKEN
+    },
+    {
+       GSS_C_REPLAY_FLAG,
+       pattern8,
+       sizeof(pattern8)/sizeof(pattern8[0]),
+       GSS_S_COMPLETE,
+       4294967293U
+    }
+};
+
+int
+main(int argc, char **argv)
+{
+    OM_uint32 maj_stat;
+    int i, failed = 0;
+
+    for (i = 0; i < sizeof(pl)/sizeof(pl[0]); i++) {
+       maj_stat = test_seq(i,
+                           pl[i].flags,
+                           pl[i].start_seq,
+                           pl[i].pattern,
+                           pl[i].pattern_len);
+       if (maj_stat != pl[i].error_code) {
+           printf("test pattern %d failed with %d (should have been %d)\n",
+                  i, maj_stat, pl[i].error_code);
+           failed++;
+       }
+    }
+    if (failed)
+       printf("FAILED %d tests\n", failed);
+    return failed != 0;
+}
diff --git a/src/kerberosV/src/lib/gssapi/ticket_flags.c b/src/kerberosV/src/lib/gssapi/ticket_flags.c
new file mode 100644 (file)
index 0000000..e18bb14
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: ticket_flags.c,v 1.1 2004/03/19 14:55:50 lha Exp $");
+
+OM_uint32
+gss_krb5_get_tkt_flags(OM_uint32 *minor_status,
+                      gss_ctx_id_t context_handle,
+                      OM_uint32 *tkt_flags)
+{
+    if (context_handle == GSS_C_NO_CONTEXT) {
+       *minor_status = EINVAL;
+       return GSS_S_NO_CONTEXT;
+    }
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+    if (context_handle->ticket == NULL) {
+       HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+       *minor_status = EINVAL;
+       return GSS_S_BAD_MECH;
+    }
+
+    *tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags);
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+}
diff --git a/src/kerberosV/src/lib/gssapi/unwrap.c b/src/kerberosV/src/lib/gssapi/unwrap.c
new file mode 100644 (file)
index 0000000..1278119
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: unwrap.c,v 1.34 2005/04/27 17:50:40 lha Exp $");
+
+static OM_uint32
+unwrap_des
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t input_message_buffer,
+            gss_buffer_t output_message_buffer,
+            int * conf_state,
+            gss_qop_t * qop_state,
+           krb5_keyblock *key
+           )
+{
+  u_char *p, *seq;
+  size_t len;
+  MD5_CTX md5;
+  u_char hash[16];
+  DES_key_schedule schedule;
+  DES_cblock deskey;
+  DES_cblock zero;
+  int i;
+  int32_t seq_number;
+  size_t padlength;
+  OM_uint32 ret;
+  int cstate;
+  int cmp;
+
+  p = input_message_buffer->value;
+  ret = gssapi_krb5_verify_header (&p,
+                                  input_message_buffer->length,
+                                  "\x02\x01",
+                                  GSS_KRB5_MECHANISM);
+  if (ret)
+      return ret;
+
+  if (memcmp (p, "\x00\x00", 2) != 0)
+    return GSS_S_BAD_SIG;
+  p += 2;
+  if (memcmp (p, "\x00\x00", 2) == 0) {
+      cstate = 1;
+  } else if (memcmp (p, "\xFF\xFF", 2) == 0) {
+      cstate = 0;
+  } else
+      return GSS_S_BAD_MIC;
+  p += 2;
+  if(conf_state != NULL)
+      *conf_state = cstate;
+  if (memcmp (p, "\xff\xff", 2) != 0)
+    return GSS_S_DEFECTIVE_TOKEN;
+  p += 2;
+  p += 16;
+
+  len = p - (u_char *)input_message_buffer->value;
+
+  if(cstate) {
+      /* decrypt data */
+      memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+
+      for (i = 0; i < sizeof(deskey); ++i)
+         deskey[i] ^= 0xf0;
+      DES_set_key (&deskey, &schedule);
+      memset (&zero, 0, sizeof(zero));
+      DES_cbc_encrypt ((void *)p,
+                      (void *)p,
+                      input_message_buffer->length - len,
+                      &schedule,
+                      &zero,
+                      DES_DECRYPT);
+      
+      memset (deskey, 0, sizeof(deskey));
+      memset (&schedule, 0, sizeof(schedule));
+  }
+  /* check pad */
+  ret = _gssapi_verify_pad(input_message_buffer, 
+                          input_message_buffer->length - len,
+                          &padlength);
+  if (ret)
+      return ret;
+
+  MD5_Init (&md5);
+  MD5_Update (&md5, p - 24, 8);
+  MD5_Update (&md5, p, input_message_buffer->length - len);
+  MD5_Final (hash, &md5);
+
+  memset (&zero, 0, sizeof(zero));
+  memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
+                &schedule, &zero);
+  if (memcmp (p - 8, hash, 8) != 0)
+    return GSS_S_BAD_MIC;
+
+  /* verify sequence number */
+  
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+  p -= 16;
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_encrypt ((void *)p, (void *)p, 8,
+                  &schedule, (DES_cblock *)hash, DES_DECRYPT);
+
+  memset (deskey, 0, sizeof(deskey));
+  memset (&schedule, 0, sizeof(schedule));
+
+  seq = p;
+  gssapi_decode_om_uint32(seq, &seq_number);
+
+  if (context_handle->more_flags & LOCAL)
+      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
+  else
+      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
+
+  if (cmp != 0) {
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    return GSS_S_BAD_MIC;
+  }
+
+  ret = _gssapi_msg_order_check(context_handle->order, seq_number);
+  if (ret) {
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    return ret;
+  }
+
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+  /* copy out data */
+
+  output_message_buffer->length = input_message_buffer->length
+    - len - padlength - 8;
+  output_message_buffer->value  = malloc(output_message_buffer->length);
+  if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
+      return GSS_S_FAILURE;
+  memcpy (output_message_buffer->value,
+         p + 24,
+         output_message_buffer->length);
+  return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+unwrap_des3
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t input_message_buffer,
+            gss_buffer_t output_message_buffer,
+            int * conf_state,
+            gss_qop_t * qop_state,
+           krb5_keyblock *key
+           )
+{
+  u_char *p;
+  size_t len;
+  u_char *seq;
+  krb5_data seq_data;
+  u_char cksum[20];
+  int32_t seq_number;
+  size_t padlength;
+  OM_uint32 ret;
+  int cstate;
+  krb5_crypto crypto;
+  Checksum csum;
+  int cmp;
+
+  p = input_message_buffer->value;
+  ret = gssapi_krb5_verify_header (&p,
+                                  input_message_buffer->length,
+                                  "\x02\x01",
+                                  GSS_KRB5_MECHANISM);
+  if (ret)
+      return ret;
+
+  if (memcmp (p, "\x04\x00", 2) != 0) /* HMAC SHA1 DES3_KD */
+    return GSS_S_BAD_SIG;
+  p += 2;
+  if (memcmp (p, "\x02\x00", 2) == 0) {
+    cstate = 1;
+  } else if (memcmp (p, "\xff\xff", 2) == 0) {
+    cstate = 0;
+  } else
+    return GSS_S_BAD_MIC;
+  p += 2;
+  if(conf_state != NULL)
+    *conf_state = cstate;
+  if (memcmp (p, "\xff\xff", 2) != 0)
+    return GSS_S_DEFECTIVE_TOKEN;
+  p += 2;
+  p += 28;
+
+  len = p - (u_char *)input_message_buffer->value;
+
+  if(cstate) {
+      /* decrypt data */
+      krb5_data tmp;
+
+      ret = krb5_crypto_init(gssapi_krb5_context, key,
+                            ETYPE_DES3_CBC_NONE, &crypto);
+      if (ret) {
+         gssapi_krb5_set_error_string ();
+         *minor_status = ret;
+         return GSS_S_FAILURE;
+      }
+      ret = krb5_decrypt(gssapi_krb5_context, crypto, KRB5_KU_USAGE_SEAL,
+                        p, input_message_buffer->length - len, &tmp);
+      krb5_crypto_destroy(gssapi_krb5_context, crypto);
+      if (ret) {
+         gssapi_krb5_set_error_string ();
+         *minor_status = ret;
+         return GSS_S_FAILURE;
+      }
+      assert (tmp.length == input_message_buffer->length - len);
+
+      memcpy (p, tmp.data, tmp.length);
+      krb5_data_free(&tmp);
+  }
+  /* check pad */
+  ret = _gssapi_verify_pad(input_message_buffer, 
+                          input_message_buffer->length - len,
+                          &padlength);
+  if (ret)
+      return ret;
+
+  /* verify sequence number */
+  
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+  p -= 28;
+
+  ret = krb5_crypto_init(gssapi_krb5_context, key,
+                        ETYPE_DES3_CBC_NONE, &crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return GSS_S_FAILURE;
+  }
+  {
+      DES_cblock ivec;
+
+      memcpy(&ivec, p + 8, 8);
+      ret = krb5_decrypt_ivec (gssapi_krb5_context,
+                              crypto,
+                              KRB5_KU_USAGE_SEQ,
+                              p, 8, &seq_data,
+                              &ivec);
+  }
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return GSS_S_FAILURE;
+  }
+  if (seq_data.length != 8) {
+      krb5_data_free (&seq_data);
+      *minor_status = 0;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return GSS_S_BAD_MIC;
+  }
+
+  seq = seq_data.data;
+  gssapi_decode_om_uint32(seq, &seq_number);
+
+  if (context_handle->more_flags & LOCAL)
+      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
+  else
+      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
+  
+  krb5_data_free (&seq_data);
+  if (cmp != 0) {
+      *minor_status = 0;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return GSS_S_BAD_MIC;
+  }
+
+  ret = _gssapi_msg_order_check(context_handle->order, seq_number);
+  if (ret) {
+      *minor_status = 0;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return ret;
+  }
+
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+  /* verify checksum */
+
+  memcpy (cksum, p + 8, 20);
+
+  memcpy (p + 20, p - 8, 8);
+
+  csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
+  csum.checksum.length = 20;
+  csum.checksum.data   = cksum;
+
+  ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+
+  ret = krb5_verify_checksum (gssapi_krb5_context, crypto,
+                             KRB5_KU_USAGE_SIGN,
+                             p + 20,
+                             input_message_buffer->length - len + 8,
+                             &csum);
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+
+  /* copy out data */
+
+  output_message_buffer->length = input_message_buffer->length
+    - len - padlength - 8;
+  output_message_buffer->value  = malloc(output_message_buffer->length);
+  if(output_message_buffer->length != 0 && output_message_buffer->value == NULL)
+      return GSS_S_FAILURE;
+  memcpy (output_message_buffer->value,
+         p + 36,
+         output_message_buffer->length);
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_unwrap
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t input_message_buffer,
+            gss_buffer_t output_message_buffer,
+            int * conf_state,
+            gss_qop_t * qop_state
+           )
+{
+  krb5_keyblock *key;
+  OM_uint32 ret;
+  krb5_keytype keytype;
+
+  output_message_buffer->value = NULL;
+  output_message_buffer->length = 0;
+
+  if (qop_state != NULL)
+      *qop_state = GSS_C_QOP_DEFAULT;
+  ret = gss_krb5_get_subkey(context_handle, &key);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+  krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
+
+  *minor_status = 0;
+
+  switch (keytype) {
+  case KEYTYPE_DES :
+      ret = unwrap_des (minor_status, context_handle,
+                       input_message_buffer, output_message_buffer,
+                       conf_state, qop_state, key);
+      break;
+  case KEYTYPE_DES3 :
+      ret = unwrap_des3 (minor_status, context_handle,
+                        input_message_buffer, output_message_buffer,
+                        conf_state, qop_state, key);
+      break;
+  case KEYTYPE_ARCFOUR:
+  case KEYTYPE_ARCFOUR_56:
+      ret = _gssapi_unwrap_arcfour (minor_status, context_handle,
+                                   input_message_buffer, output_message_buffer,
+                                   conf_state, qop_state, key);
+      break;
+  default :
+      ret = _gssapi_unwrap_cfx (minor_status, context_handle,
+                               input_message_buffer, output_message_buffer,
+                               conf_state, qop_state, key);
+      break;
+  }
+  krb5_free_keyblock (gssapi_krb5_context, key);
+  return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/v1.c b/src/kerberosV/src/lib/gssapi/v1.c
new file mode 100644 (file)
index 0000000..64c32d4
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: v1.c,v 1.2 1999/12/02 17:05:04 joda Exp $");
+
+/* These functions are for V1 compatibility */
+
+OM_uint32 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
+           )
+{
+  return gss_get_mic(minor_status,
+       context_handle,
+       (gss_qop_t)qop_req,
+       message_buffer,
+       message_token);
+}
+
+OM_uint32 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
+           )
+{
+  return gss_verify_mic(minor_status,
+       context_handle,
+       message_buffer,
+       token_buffer,
+       (gss_qop_t *)qop_state);
+}
+
+OM_uint32 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
+           )
+{
+  return gss_wrap(minor_status,
+       context_handle,
+       conf_req_flag,
+       (gss_qop_t)qop_req,
+       input_message_buffer,
+       conf_state,
+       output_message_buffer);
+}
+
+OM_uint32 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
+           )
+{
+  return gss_unwrap(minor_status,
+       context_handle,
+       input_message_buffer,
+       output_message_buffer,
+       conf_state,
+       (gss_qop_t *)qop_state);
+}
diff --git a/src/kerberosV/src/lib/gssapi/verify_mic.c b/src/kerberosV/src/lib/gssapi/verify_mic.c
new file mode 100644 (file)
index 0000000..0040774
--- /dev/null
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: verify_mic.c,v 1.32 2005/04/27 17:51:04 lha Exp $");
+
+static OM_uint32
+verify_mic_des
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t message_buffer,
+            const gss_buffer_t token_buffer,
+            gss_qop_t * qop_state,
+           krb5_keyblock *key,
+           char *type
+           )
+{
+  u_char *p;
+  MD5_CTX md5;
+  u_char hash[16], *seq;
+  DES_key_schedule schedule;
+  DES_cblock zero;
+  DES_cblock deskey;
+  int32_t seq_number;
+  OM_uint32 ret;
+  int cmp;
+
+  p = token_buffer->value;
+  ret = gssapi_krb5_verify_header (&p,
+                                  token_buffer->length,
+                                  type,
+                                  GSS_KRB5_MECHANISM);
+  if (ret)
+      return ret;
+
+  if (memcmp(p, "\x00\x00", 2) != 0)
+      return GSS_S_BAD_SIG;
+  p += 2;
+  if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
+    return GSS_S_BAD_MIC;
+  p += 4;
+  p += 16;
+
+  /* verify checksum */
+  MD5_Init (&md5);
+  MD5_Update (&md5, p - 24, 8);
+  MD5_Update (&md5, message_buffer->value,
+            message_buffer->length);
+  MD5_Final (hash, &md5);
+
+  memset (&zero, 0, sizeof(zero));
+  memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
+                &schedule, &zero);
+  if (memcmp (p - 8, hash, 8) != 0) {
+    memset (deskey, 0, sizeof(deskey));
+    memset (&schedule, 0, sizeof(schedule));
+    return GSS_S_BAD_MIC;
+  }
+
+  /* verify sequence number */
+  
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+  p -= 16;
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_encrypt ((void *)p, (void *)p, 8,
+                  &schedule, (DES_cblock *)hash, DES_DECRYPT);
+
+  memset (deskey, 0, sizeof(deskey));
+  memset (&schedule, 0, sizeof(schedule));
+
+  seq = p;
+  gssapi_decode_om_uint32(seq, &seq_number);
+
+  if (context_handle->more_flags & LOCAL)
+      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
+  else
+      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
+
+  if (cmp != 0) {
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    return GSS_S_BAD_MIC;
+  }
+
+  ret = _gssapi_msg_order_check(context_handle->order, seq_number);
+  if (ret) {
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return ret;
+  }
+
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+  return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+verify_mic_des3
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t message_buffer,
+            const gss_buffer_t token_buffer,
+            gss_qop_t * qop_state,
+           krb5_keyblock *key,
+           char *type
+           )
+{
+  u_char *p;
+  u_char *seq;
+  int32_t seq_number;
+  OM_uint32 ret;
+  krb5_crypto crypto;
+  krb5_data seq_data;
+  int cmp, docompat;
+  Checksum csum;
+  char *tmp;
+  char ivec[8];
+  
+  p = token_buffer->value;
+  ret = gssapi_krb5_verify_header (&p,
+                                  token_buffer->length,
+                                  type,
+                                  GSS_KRB5_MECHANISM);
+  if (ret)
+      return ret;
+
+  if (memcmp(p, "\x04\x00", 2) != 0) /* SGN_ALG = HMAC SHA1 DES3-KD */
+      return GSS_S_BAD_SIG;
+  p += 2;
+  if (memcmp (p, "\xff\xff\xff\xff", 4) != 0)
+    return GSS_S_BAD_MIC;
+  p += 4;
+
+  ret = krb5_crypto_init(gssapi_krb5_context, key,
+                        ETYPE_DES3_CBC_NONE, &crypto);
+  if (ret){
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+
+  /* verify sequence number */
+  docompat = 0;
+retry:
+  if (docompat)
+      memset(ivec, 0, 8);
+  else
+      memcpy(ivec, p + 8, 8);
+
+  ret = krb5_decrypt_ivec (gssapi_krb5_context,
+                          crypto,
+                          KRB5_KU_USAGE_SEQ,
+                          p, 8, &seq_data, ivec);
+  if (ret) {
+      if (docompat++) {
+         gssapi_krb5_set_error_string ();
+         krb5_crypto_destroy (gssapi_krb5_context, crypto);
+         *minor_status = ret;
+         return GSS_S_FAILURE;
+      } else
+         goto retry;
+  }
+
+  if (seq_data.length != 8) {
+      krb5_data_free (&seq_data);
+      if (docompat++) {
+         krb5_crypto_destroy (gssapi_krb5_context, crypto);
+         return GSS_S_BAD_MIC;
+      } else
+         goto retry;
+  }
+
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+
+  seq = seq_data.data;
+  gssapi_decode_om_uint32(seq, &seq_number);
+
+  if (context_handle->more_flags & LOCAL)
+      cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4);
+  else
+      cmp = memcmp(&seq[4], "\x00\x00\x00\x00", 4);
+
+  krb5_data_free (&seq_data);
+  if (cmp != 0) {
+      krb5_crypto_destroy (gssapi_krb5_context, crypto);
+      *minor_status = 0;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return GSS_S_BAD_MIC;
+  }
+
+  ret = _gssapi_msg_order_check(context_handle->order, seq_number);
+  if (ret) {
+      krb5_crypto_destroy (gssapi_krb5_context, crypto);
+      *minor_status = 0;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return ret;
+  }
+
+  /* verify checksum */
+
+  tmp = malloc (message_buffer->length + 8);
+  if (tmp == NULL) {
+      krb5_crypto_destroy (gssapi_krb5_context, crypto);
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      *minor_status = ENOMEM;
+      return GSS_S_FAILURE;
+  }
+
+  memcpy (tmp, p - 8, 8);
+  memcpy (tmp + 8, message_buffer->value, message_buffer->length);
+
+  csum.cksumtype = CKSUMTYPE_HMAC_SHA1_DES3;
+  csum.checksum.length = 20;
+  csum.checksum.data   = p + 8;
+
+  ret = krb5_verify_checksum (gssapi_krb5_context, crypto,
+                             KRB5_KU_USAGE_SIGN,
+                             tmp, message_buffer->length + 8,
+                             &csum);
+  free (tmp);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      krb5_crypto_destroy (gssapi_krb5_context, crypto);
+      *minor_status = ret;
+      HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+      return GSS_S_BAD_MIC;
+  }
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32
+gss_verify_mic_internal
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t message_buffer,
+            const gss_buffer_t token_buffer,
+            gss_qop_t * qop_state,
+           char * type
+           )
+{
+    krb5_keyblock *key;
+    OM_uint32 ret;
+    krb5_keytype keytype;
+
+    ret = gss_krb5_get_subkey(context_handle, &key);
+    if (ret) {
+       gssapi_krb5_set_error_string ();
+       *minor_status = ret;
+       return GSS_S_FAILURE;
+    }
+    *minor_status = 0;
+    krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
+    switch (keytype) {
+    case KEYTYPE_DES :
+       ret = verify_mic_des (minor_status, context_handle,
+                             message_buffer, token_buffer, qop_state, key,
+                             type);
+       break;
+    case KEYTYPE_DES3 :
+       ret = verify_mic_des3 (minor_status, context_handle,
+                              message_buffer, token_buffer, qop_state, key,
+                              type);
+       break;
+    case KEYTYPE_ARCFOUR :
+    case KEYTYPE_ARCFOUR_56 :
+       ret = _gssapi_verify_mic_arcfour (minor_status, context_handle,
+                                         message_buffer, token_buffer,
+                                         qop_state, key, type);
+       break;
+    default :
+       ret = _gssapi_verify_mic_cfx (minor_status, context_handle,
+                                     message_buffer, token_buffer, qop_state,
+                                     key);
+       break;
+    }
+    krb5_free_keyblock (gssapi_krb5_context, key);
+    
+    return ret;
+}
+
+OM_uint32
+gss_verify_mic
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            const gss_buffer_t message_buffer,
+            const gss_buffer_t token_buffer,
+            gss_qop_t * qop_state
+           )
+{
+    OM_uint32 ret;
+
+    if (qop_state != NULL)
+       *qop_state = GSS_C_QOP_DEFAULT;
+
+    ret = gss_verify_mic_internal(minor_status, context_handle, 
+                                 message_buffer, token_buffer,
+                                 qop_state, "\x01\x01");
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/gssapi/wrap.c b/src/kerberosV/src/lib/gssapi/wrap.c
new file mode 100644 (file)
index 0000000..f8045f9
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "gssapi_locl.h"
+
+RCSID("$KTH: wrap.c,v 1.31 2005/01/05 02:52:12 lukeh Exp $");
+
+OM_uint32
+gss_krb5_get_subkey(const gss_ctx_id_t context_handle,
+                   krb5_keyblock **key)
+{
+    krb5_keyblock *skey = NULL;
+
+    HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+    if (context_handle->more_flags & LOCAL) {
+       krb5_auth_con_getremotesubkey(gssapi_krb5_context,
+                                     context_handle->auth_context, 
+                                     &skey);
+    } else {
+       krb5_auth_con_getlocalsubkey(gssapi_krb5_context,
+                                    context_handle->auth_context, 
+                                    &skey);
+    }
+    /*
+     * Only use the initiator subkey or ticket session key if
+     * an acceptor subkey was not required.
+     */
+    if (skey == NULL &&
+       (context_handle->more_flags & ACCEPTOR_SUBKEY) == 0) {
+       if (context_handle->more_flags & LOCAL) {
+           krb5_auth_con_getlocalsubkey(gssapi_krb5_context,
+                                        context_handle->auth_context,
+                                        &skey);
+       } else {
+           krb5_auth_con_getremotesubkey(gssapi_krb5_context,
+                                         context_handle->auth_context,
+                                         &skey);
+       }
+       if(skey == NULL)
+           krb5_auth_con_getkey(gssapi_krb5_context,
+                                context_handle->auth_context, 
+                                &skey);
+    }
+    HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+    if(skey == NULL)
+       return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */
+    *key = skey;
+    return 0;
+}
+
+static OM_uint32
+sub_wrap_size (
+            OM_uint32 req_output_size,
+            OM_uint32 * max_input_size,
+           int blocksize,
+           int extrasize
+           )
+{
+    size_t len, total_len; 
+
+    len = 8 + req_output_size + blocksize + extrasize;
+
+    gssapi_krb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM);
+
+    total_len -= req_output_size; /* token length */
+    if (total_len < req_output_size) {
+        *max_input_size = (req_output_size - total_len);
+        (*max_input_size) &= (~(OM_uint32)(blocksize - 1));
+    } else {
+        *max_input_size = 0;
+    }
+    return GSS_S_COMPLETE;
+}
+
+OM_uint32
+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
+           )
+{
+  krb5_keyblock *key;
+  OM_uint32 ret;
+  krb5_keytype keytype;
+
+  ret = gss_krb5_get_subkey(context_handle, &key);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+  krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
+
+  switch (keytype) {
+  case KEYTYPE_DES :
+  case KEYTYPE_ARCFOUR:
+  case KEYTYPE_ARCFOUR_56:
+      ret = sub_wrap_size(req_output_size, max_input_size, 8, 22);
+      break;
+  case KEYTYPE_DES3 :
+      ret = sub_wrap_size(req_output_size, max_input_size, 8, 34);
+      break;
+  default :
+      ret = _gssapi_wrap_size_cfx(minor_status, context_handle, 
+                                 conf_req_flag, qop_req, 
+                                 req_output_size, max_input_size, key);
+      break;
+  }
+  krb5_free_keyblock (gssapi_krb5_context, key);
+  *minor_status = 0;
+  return ret;
+}
+
+static OM_uint32
+wrap_des
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            int conf_req_flag,
+            gss_qop_t qop_req,
+            const gss_buffer_t input_message_buffer,
+            int * conf_state,
+            gss_buffer_t output_message_buffer,
+           krb5_keyblock *key
+           )
+{
+  u_char *p;
+  MD5_CTX md5;
+  u_char hash[16];
+  DES_key_schedule schedule;
+  DES_cblock deskey;
+  DES_cblock zero;
+  int i;
+  int32_t seq_number;
+  size_t len, total_len, padlength, datalen;
+
+  padlength = 8 - (input_message_buffer->length % 8);
+  datalen = input_message_buffer->length + padlength + 8;
+  len = datalen + 22;
+  gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+
+  output_message_buffer->length = total_len;
+  output_message_buffer->value  = malloc (total_len);
+  if (output_message_buffer->value == NULL) {
+    *minor_status = ENOMEM;
+    return GSS_S_FAILURE;
+  }
+
+  p = gssapi_krb5_make_header(output_message_buffer->value,
+                             len,
+                             "\x02\x01", /* TOK_ID */
+                             GSS_KRB5_MECHANISM);
+
+  /* SGN_ALG */
+  memcpy (p, "\x00\x00", 2);
+  p += 2;
+  /* SEAL_ALG */
+  if(conf_req_flag)
+      memcpy (p, "\x00\x00", 2);
+  else
+      memcpy (p, "\xff\xff", 2);
+  p += 2;
+  /* Filler */
+  memcpy (p, "\xff\xff", 2);
+  p += 2;
+
+  /* fill in later */
+  memset (p, 0, 16);
+  p += 16;
+
+  /* confounder + data + pad */
+  krb5_generate_random_block(p, 8);
+  memcpy (p + 8, input_message_buffer->value,
+         input_message_buffer->length);
+  memset (p + 8 + input_message_buffer->length, padlength, padlength);
+
+  /* checksum */
+  MD5_Init (&md5);
+  MD5_Update (&md5, p - 24, 8);
+  MD5_Update (&md5, p, datalen);
+  MD5_Final (hash, &md5);
+
+  memset (&zero, 0, sizeof(zero));
+  memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_cksum ((void *)hash, (void *)hash, sizeof(hash),
+                &schedule, &zero);
+  memcpy (p - 8, hash, 8);
+
+  /* sequence number */
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+  krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              &seq_number);
+
+  p -= 16;
+  p[0] = (seq_number >> 0)  & 0xFF;
+  p[1] = (seq_number >> 8)  & 0xFF;
+  p[2] = (seq_number >> 16) & 0xFF;
+  p[3] = (seq_number >> 24) & 0xFF;
+  memset (p + 4,
+         (context_handle->more_flags & LOCAL) ? 0 : 0xFF,
+         4);
+
+  DES_set_key (&deskey, &schedule);
+  DES_cbc_encrypt ((void *)p, (void *)p, 8,
+                  &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT);
+
+  krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              ++seq_number);
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+  /* encrypt the data */
+  p += 16;
+
+  if(conf_req_flag) {
+      memcpy (&deskey, key->keyvalue.data, sizeof(deskey));
+
+      for (i = 0; i < sizeof(deskey); ++i)
+         deskey[i] ^= 0xf0;
+      DES_set_key (&deskey, &schedule);
+      memset (&zero, 0, sizeof(zero));
+      DES_cbc_encrypt ((void *)p,
+                      (void *)p,
+                      datalen,
+                      &schedule,
+                      &zero,
+                      DES_ENCRYPT);
+  }
+  memset (deskey, 0, sizeof(deskey));
+  memset (&schedule, 0, sizeof(schedule));
+
+  if(conf_state != NULL)
+      *conf_state = conf_req_flag;
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+wrap_des3
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            int conf_req_flag,
+            gss_qop_t qop_req,
+            const gss_buffer_t input_message_buffer,
+            int * conf_state,
+            gss_buffer_t output_message_buffer,
+           krb5_keyblock *key
+           )
+{
+  u_char *p;
+  u_char seq[8];
+  int32_t seq_number;
+  size_t len, total_len, padlength, datalen;
+  u_int32_t ret;
+  krb5_crypto crypto;
+  Checksum cksum;
+  krb5_data encdata;
+
+  padlength = 8 - (input_message_buffer->length % 8);
+  datalen = input_message_buffer->length + padlength + 8;
+  len = datalen + 34;
+  gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM);
+
+  output_message_buffer->length = total_len;
+  output_message_buffer->value  = malloc (total_len);
+  if (output_message_buffer->value == NULL) {
+    *minor_status = ENOMEM;
+    return GSS_S_FAILURE;
+  }
+
+  p = gssapi_krb5_make_header(output_message_buffer->value,
+                             len,
+                             "\x02\x01", /* TOK_ID */
+                             GSS_KRB5_MECHANISM); 
+
+  /* SGN_ALG */
+  memcpy (p, "\x04\x00", 2);   /* HMAC SHA1 DES3-KD */
+  p += 2;
+  /* SEAL_ALG */
+  if(conf_req_flag)
+      memcpy (p, "\x02\x00", 2); /* DES3-KD */
+  else
+      memcpy (p, "\xff\xff", 2);
+  p += 2;
+  /* Filler */
+  memcpy (p, "\xff\xff", 2);
+  p += 2;
+
+  /* calculate checksum (the above + confounder + data + pad) */
+
+  memcpy (p + 20, p - 8, 8);
+  krb5_generate_random_block(p + 28, 8);
+  memcpy (p + 28 + 8, input_message_buffer->value,
+         input_message_buffer->length);
+  memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength);
+
+  ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      free (output_message_buffer->value);
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+
+  ret = krb5_create_checksum (gssapi_krb5_context,
+                             crypto,
+                             KRB5_KU_USAGE_SIGN,
+                             0,
+                             p + 20,
+                             datalen + 8,
+                             &cksum);
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      free (output_message_buffer->value);
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+
+  /* zero out SND_SEQ + SGN_CKSUM in case */
+  memset (p, 0, 28);
+
+  memcpy (p + 8, cksum.checksum.data, cksum.checksum.length);
+  free_Checksum (&cksum);
+
+  HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+  /* sequence number */
+  krb5_auth_con_getlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              &seq_number);
+
+  seq[0] = (seq_number >> 0)  & 0xFF;
+  seq[1] = (seq_number >> 8)  & 0xFF;
+  seq[2] = (seq_number >> 16) & 0xFF;
+  seq[3] = (seq_number >> 24) & 0xFF;
+  memset (seq + 4,
+         (context_handle->more_flags & LOCAL) ? 0 : 0xFF,
+         4);
+
+
+  ret = krb5_crypto_init(gssapi_krb5_context, key, ETYPE_DES3_CBC_NONE,
+                        &crypto);
+  if (ret) {
+      free (output_message_buffer->value);
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+
+  {
+      DES_cblock ivec;
+
+      memcpy (&ivec, p + 8, 8);
+      ret = krb5_encrypt_ivec (gssapi_krb5_context,
+                              crypto,
+                              KRB5_KU_USAGE_SEQ,
+                              seq, 8, &encdata,
+                              &ivec);
+  }
+  krb5_crypto_destroy (gssapi_krb5_context, crypto);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      free (output_message_buffer->value);
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+  
+  assert (encdata.length == 8);
+
+  memcpy (p, encdata.data, encdata.length);
+  krb5_data_free (&encdata);
+
+  krb5_auth_con_setlocalseqnumber (gssapi_krb5_context,
+                              context_handle->auth_context,
+                              ++seq_number);
+  HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+
+  /* encrypt the data */
+  p += 28;
+
+  if(conf_req_flag) {
+      krb5_data tmp;
+
+      ret = krb5_crypto_init(gssapi_krb5_context, key,
+                            ETYPE_DES3_CBC_NONE, &crypto);
+      if (ret) {
+         gssapi_krb5_set_error_string ();
+         free (output_message_buffer->value);
+         *minor_status = ret;
+         return GSS_S_FAILURE;
+      }
+      ret = krb5_encrypt(gssapi_krb5_context, crypto, KRB5_KU_USAGE_SEAL,
+                        p, datalen, &tmp);
+      krb5_crypto_destroy(gssapi_krb5_context, crypto);
+      if (ret) {
+         gssapi_krb5_set_error_string ();
+         free (output_message_buffer->value);
+         *minor_status = ret;
+         return GSS_S_FAILURE;
+      }
+      assert (tmp.length == datalen);
+
+      memcpy (p, tmp.data, datalen);
+      krb5_data_free(&tmp);
+  }
+  if(conf_state != NULL)
+      *conf_state = conf_req_flag;
+  *minor_status = 0;
+  return GSS_S_COMPLETE;
+}
+
+OM_uint32 gss_wrap
+           (OM_uint32 * minor_status,
+            const gss_ctx_id_t context_handle,
+            int conf_req_flag,
+            gss_qop_t qop_req,
+            const gss_buffer_t input_message_buffer,
+            int * conf_state,
+            gss_buffer_t output_message_buffer
+           )
+{
+  krb5_keyblock *key;
+  OM_uint32 ret;
+  krb5_keytype keytype;
+
+  ret = gss_krb5_get_subkey(context_handle, &key);
+  if (ret) {
+      gssapi_krb5_set_error_string ();
+      *minor_status = ret;
+      return GSS_S_FAILURE;
+  }
+  krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype);
+
+  switch (keytype) {
+  case KEYTYPE_DES :
+      ret = wrap_des (minor_status, context_handle, conf_req_flag,
+                     qop_req, input_message_buffer, conf_state,
+                     output_message_buffer, key);
+      break;
+  case KEYTYPE_DES3 :
+      ret = wrap_des3 (minor_status, context_handle, conf_req_flag,
+                      qop_req, input_message_buffer, conf_state,
+                      output_message_buffer, key);
+      break;
+  case KEYTYPE_ARCFOUR:
+  case KEYTYPE_ARCFOUR_56:
+      ret = _gssapi_wrap_arcfour (minor_status, context_handle, conf_req_flag,
+                                 qop_req, input_message_buffer, conf_state,
+                                 output_message_buffer, key);
+      break;
+  default :
+      ret = _gssapi_wrap_cfx (minor_status, context_handle, conf_req_flag,
+                             qop_req, input_message_buffer, conf_state,
+                             output_message_buffer, key);
+      break;
+  }
+  krb5_free_keyblock (gssapi_krb5_context, key);
+  return ret;
+}
diff --git a/src/kerberosV/src/lib/hdb/CVS/Entries b/src/kerberosV/src/lib/hdb/CVS/Entries
new file mode 100644 (file)
index 0000000..6ef4880
--- /dev/null
@@ -0,0 +1,20 @@
+/common.c/1.1.1.4/Fri Apr 14 07:33:01 2006//
+/convert_db.c/1.3/Fri Apr 14 08:15:04 2006//
+/db.c/1.1.1.3/Fri Apr 14 07:33:01 2006//
+/db3.c/1.1.1.4/Fri Apr 14 07:33:01 2006//
+/hdb-ldap.c/1.2/Sat Sep 30 17:48:22 2006//
+/hdb-private.h/1.1.1.2/Sun May 11 02:15:43 2003//
+/hdb-protos.h/1.1.1.4/Fri Apr 14 07:33:03 2006//
+/hdb.asn1/1.1.1.3/Fri Apr 14 07:33:02 2006//
+/hdb.c/1.1.1.3/Fri Apr 14 07:33:02 2006//
+/hdb.h/1.1.1.2/Fri Apr 14 07:33:02 2006//
+/hdb.schema/1.1.1.1/Fri Apr 14 07:33:02 2006//
+/hdb_err.et/1.1.1.1/Fri May 25 07:50:17 2001//
+/hdb_locl.h/1.5/Fri Apr 14 08:15:04 2006//
+/keys.c/1.1.1.1/Fri Apr 14 07:33:02 2006//
+/keytab.c/1.1.1.4/Fri Apr 14 07:33:02 2006//
+/libasn1.h/1.1.1.3/Wed Feb  6 08:55:12 2002//
+/mkey.c/1.3/Fri Apr 14 08:15:04 2006//
+/ndbm.c/1.1.1.3/Fri Apr 14 07:33:03 2006//
+/print.c/1.1.1.3/Sun May 11 02:15:43 2003//
+D
diff --git a/src/kerberosV/src/lib/hdb/CVS/Repository b/src/kerberosV/src/lib/hdb/CVS/Repository
new file mode 100644 (file)
index 0000000..bf51a1d
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/hdb
diff --git a/src/kerberosV/src/lib/hdb/CVS/Root b/src/kerberosV/src/lib/hdb/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/hdb/common.c b/src/kerberosV/src/lib/hdb/common.c
new file mode 100644 (file)
index 0000000..2302928
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: common.c,v 1.13 2003/09/19 00:17:20 lha Exp $");
+
+int
+hdb_principal2key(krb5_context context, krb5_principal p, krb5_data *key)
+{
+    Principal new;
+    size_t len;
+    int ret;
+
+    ret = copy_Principal(p, &new);
+    if(ret) 
+       return ret;
+    new.name.name_type = 0;
+
+    ASN1_MALLOC_ENCODE(Principal, key->data, key->length, &new, &len, ret);
+    free_Principal(&new);
+    return ret;
+}
+
+int
+hdb_key2principal(krb5_context context, krb5_data *key, krb5_principal p)
+{
+    return decode_Principal(key->data, key->length, p, NULL);
+}
+
+int
+hdb_entry2value(krb5_context context, hdb_entry *ent, krb5_data *value)
+{
+    size_t len;
+    int ret;
+    
+    ASN1_MALLOC_ENCODE(hdb_entry, value->data, value->length, ent, &len, ret);
+    return ret;
+}
+
+int
+hdb_value2entry(krb5_context context, krb5_data *value, hdb_entry *ent)
+{
+    return decode_hdb_entry(value->data, value->length, ent, NULL);
+}
+
+krb5_error_code
+_hdb_fetch(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    krb5_data key, value;
+    int code;
+
+    hdb_principal2key(context, entry->principal, &key);
+    code = db->hdb__get(context, db, key, &value);
+    krb5_data_free(&key);
+    if(code)
+       return code;
+    code = hdb_value2entry(context, &value, entry);
+    krb5_data_free(&value);
+    if (code)
+       return code;
+    if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
+       code = hdb_unseal_keys (context, db, entry);
+       if (code)
+           hdb_free_entry(context, entry);
+    }
+    return code;
+}
+
+krb5_error_code
+_hdb_store(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    krb5_data key, value;
+    int code;
+
+    if(entry->generation == NULL) {
+       struct timeval t;
+       entry->generation = malloc(sizeof(*entry->generation));
+       if(entry->generation == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       gettimeofday(&t, NULL);
+       entry->generation->time = t.tv_sec;
+       entry->generation->usec = t.tv_usec;
+       entry->generation->gen = 0;
+    } else
+       entry->generation->gen++;
+    hdb_principal2key(context, entry->principal, &key);
+    code = hdb_seal_keys(context, db, entry);
+    if (code) {
+       krb5_data_free(&key);
+       return code;
+    }
+    hdb_entry2value(context, entry, &value);
+    code = db->hdb__put(context, db, flags & HDB_F_REPLACE, key, value);
+    krb5_data_free(&value);
+    krb5_data_free(&key);
+    return code;
+}
+
+krb5_error_code
+_hdb_remove(krb5_context context, HDB *db, hdb_entry *entry)
+{
+    krb5_data key;
+    int code;
+
+    hdb_principal2key(context, entry->principal, &key);
+    code = db->hdb__del(context, db, key);
+    krb5_data_free(&key);
+    return code;
+}
+
diff --git a/src/kerberosV/src/lib/hdb/convert_db.c b/src/kerberosV/src/lib/hdb/convert_db.c
new file mode 100644 (file)
index 0000000..129eed7
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 1999 - 2001 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. */
+
+/* Converts a database from version 0.0* to 0.1. This is done by
+ * making three copies of each DES key (DES-CBC-CRC, DES-CBC-MD4, and
+ * DES-CBC-MD5).
+ *
+ * Use with care. 
+ */
+
+#include "hdb_locl.h"
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$KTH: convert_db.c,v 1.13 2003/09/19 00:17:42 lha Exp $");
+
+static krb5_error_code
+update_keytypes(krb5_context context, HDB *db, hdb_entry *entry, void *data)
+{
+    int i;
+    int n = 0;
+    Key *k;
+    int save_len;
+    Key *save_val;
+    HDB *new = data;
+    krb5_error_code ret;
+
+    for(i = 0; i < entry->keys.len; i++) 
+       if(entry->keys.val[i].key.keytype == KEYTYPE_DES)
+           n += 2;
+       else if(entry->keys.val[i].key.keytype == KEYTYPE_DES3)
+           n += 1;
+    k = malloc(sizeof(*k) * (entry->keys.len + n));
+    n = 0;
+    for(i = 0; i < entry->keys.len; i++) {
+       copy_Key(&entry->keys.val[i], &k[n]);
+       if(entry->keys.val[i].key.keytype == KEYTYPE_DES) {
+           copy_Key(&entry->keys.val[i], &k[n+1]);
+           k[n+1].key.keytype = ETYPE_DES_CBC_MD4;
+           copy_Key(&entry->keys.val[i], &k[n+2]);
+           k[n+2].key.keytype = ETYPE_DES_CBC_MD5;
+           n += 2;
+       }
+       else if(entry->keys.val[i].key.keytype == KEYTYPE_DES3) {
+           copy_Key(&entry->keys.val[i], &k[n+1]);
+           k[n+1].key.keytype = ETYPE_DES3_CBC_MD5;
+           n += 1;
+       }
+       n++;
+    }
+    save_len = entry->keys.len;
+    save_val = entry->keys.val;
+    entry->keys.len = n;
+    entry->keys.val = k;
+    ret = new->hdb_store(context, new, HDB_F_REPLACE, entry);
+    entry->keys.len = save_len;
+    entry->keys.val = save_val;
+    for(i = 0; i < n; i++) 
+       free_Key(&k[i]);
+    free(k);
+    return 0;
+}
+
+static krb5_error_code
+update_version2(krb5_context context, HDB *db, hdb_entry *entry, void *data)
+{
+    HDB *new = data;
+    if(!db->hdb_master_key_set) {
+       int i;
+       for(i = 0; i < entry->keys.len; i++) {
+           free(entry->keys.val[i].mkvno);
+           entry->keys.val[i].mkvno = NULL;
+       }
+    }
+    new->hdb_store(context, new, HDB_F_REPLACE, entry);
+    return 0;
+}
+
+char *old_database = HDB_DEFAULT_DB;
+char *new_database = HDB_DEFAULT_DB ".new";
+char *mkeyfile;
+int update_version;
+int help_flag;
+int version_flag;
+
+struct getargs args[] = {
+    { "old-database",  0,      arg_string, &old_database,
+      "name of database to convert", "file" },
+    { "new-database",  0,      arg_string, &new_database,
+      "name of converted database", "file" },
+    { "master-key",    0,      arg_string, &mkeyfile, 
+      "v5 master key file", "file" },
+    { "update-version", 0,     arg_flag, &update_version,
+      "update the database to the current version" },
+    { "help",          'h',    arg_flag,   &help_flag },
+    { "version",       0,      arg_flag,   &version_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    HDB *db, *new;
+    int optind = 0;
+    int master_key_set = 0;
+    
+    if(getarg(args, num_args, argc, argv, &optind))
+       krb5_std_usage(1, args, num_args);
+
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    ret = krb5_init_context(&context);
+    if(ret != 0)
+       errx(1, "krb5_init_context failed: %d", ret);
+    
+    ret = hdb_create(context, &db, old_database);
+    if(ret != 0)
+       krb5_err(context, 1, ret, "hdb_create");
+
+    ret = hdb_set_master_keyfile(context, db, mkeyfile);
+    if (ret)
+       krb5_err(context, 1, ret, "hdb_set_master_keyfile");
+    master_key_set = 1;
+    ret = hdb_create(context, &new, new_database);
+    if(ret != 0)
+       krb5_err(context, 1, ret, "hdb_create");
+    if (master_key_set) {
+       ret = hdb_set_master_keyfile(context, new, mkeyfile);
+       if (ret)
+           krb5_err(context, 1, ret, "hdb_set_master_keyfile");
+    }
+    ret = db->hdb_open(context, db, O_RDONLY, 0);
+    if(ret == HDB_ERR_BADVERSION) {
+       krb5_data tag;
+       krb5_data version;
+       int foo;
+       unsigned ver;
+       tag.data = HDB_DB_FORMAT_ENTRY;
+       tag.length = strlen(tag.data);
+       ret = (*db->hdb__get)(context, db, tag, &version);
+       if(ret)
+           krb5_errx(context, 1, "database is wrong version, "
+                     "but couldn't find version key (%s)", 
+                     HDB_DB_FORMAT_ENTRY);
+       foo = sscanf(version.data, "%u", &ver);
+       krb5_data_free (&version);
+       if(foo != 1)
+           krb5_errx(context, 1, "database version is not a number");
+       if(ver == 1 && HDB_DB_FORMAT == 2) {
+           krb5_warnx(context, "will upgrade database from version %d to %d", 
+                      ver, HDB_DB_FORMAT);
+           krb5_warnx(context, "rerun to do other conversions");
+           update_version = 1;
+       } else
+           krb5_errx(context, 1, 
+                     "don't know how to upgrade from version %d to %d", 
+                     ver, HDB_DB_FORMAT);
+    } else if(ret)
+       krb5_err(context, 1, ret, "%s", old_database);
+    ret = new->hdb_open(context, new, O_CREAT|O_EXCL|O_RDWR, 0600);
+    if(ret)
+       krb5_err(context, 1, ret, "%s", new_database);
+    if(update_version)
+       ret = hdb_foreach(context, db, 0, update_version2, new);
+    else
+       ret = hdb_foreach(context, db, 0, update_keytypes, new);
+    if(ret != 0)
+       krb5_err(context, 1, ret, "hdb_foreach");
+    db->hdb_close(context, db);
+    new->hdb_close(context, new);
+    krb5_warnx(context, "wrote converted database to `%s'", new_database);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/hdb/db.c b/src/kerberosV/src/lib/hdb/db.c
new file mode 100644 (file)
index 0000000..ea03bb8
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: db.c,v 1.31 2003/09/19 00:18:04 lha Exp $");
+
+#if HAVE_DB1
+
+#if defined(HAVE_DB_185_H)
+#include <db_185.h>
+#elif defined(HAVE_DB_H)
+#include <db.h>
+#endif
+
+static krb5_error_code
+DB_close(krb5_context context, HDB *db)
+{
+    DB *d = (DB*)db->hdb_db;
+    d->close(d);
+    return 0;
+}
+
+static krb5_error_code
+DB_destroy(krb5_context context, HDB *db)
+{
+    krb5_error_code ret;
+
+    ret = hdb_clear_master_key (context, db);
+    free(db->hdb_name);
+    free(db);
+    return ret;
+}
+
+static krb5_error_code
+DB_lock(krb5_context context, HDB *db, int operation)
+{
+    DB *d = (DB*)db->hdb_db;
+    int fd = (*d->fd)(d);
+    if(fd < 0)
+       return HDB_ERR_CANT_LOCK_DB;
+    return hdb_lock(fd, operation);
+}
+
+static krb5_error_code
+DB_unlock(krb5_context context, HDB *db)
+{
+    DB *d = (DB*)db->hdb_db;
+    int fd = (*d->fd)(d);
+    if(fd < 0)
+       return HDB_ERR_CANT_LOCK_DB;
+    return hdb_unlock(fd);
+}
+
+
+static krb5_error_code
+DB_seq(krb5_context context, HDB *db,
+       unsigned flags, hdb_entry *entry, int flag)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT key, value;
+    krb5_data key_data, data;
+    int code;
+
+    code = db->hdb_lock(context, db, HDB_RLOCK);
+    if(code == -1)
+       return HDB_ERR_DB_INUSE;
+    code = d->seq(d, &key, &value, flag);
+    db->hdb_unlock(context, db); /* XXX check value */
+    if(code == -1)
+       return errno;
+    if(code == 1)
+       return HDB_ERR_NOENTRY;
+
+    key_data.data = key.data;
+    key_data.length = key.size;
+    data.data = value.data;
+    data.length = value.size;
+    if (hdb_value2entry(context, &data, entry))
+       return DB_seq(context, db, flags, entry, R_NEXT);
+    if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
+       code = hdb_unseal_keys (context, db, entry);
+       if (code)
+           hdb_free_entry (context, entry);
+    }
+    if (code == 0 && entry->principal == NULL) {
+       entry->principal = malloc(sizeof(*entry->principal));
+       if (entry->principal == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           code = ENOMEM;
+           hdb_free_entry (context, entry);
+       } else {
+           hdb_key2principal(context, &key_data, entry->principal);
+       }
+    }
+    return code;
+}
+
+
+static krb5_error_code
+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    return DB_seq(context, db, flags, entry, R_FIRST);
+}
+
+
+static krb5_error_code
+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    return DB_seq(context, db, flags, entry, R_NEXT);
+}
+
+static krb5_error_code
+DB_rename(krb5_context context, HDB *db, const char *new_name)
+{
+    int ret;
+    char *old, *new;
+
+    asprintf(&old, "%s.db", db->hdb_name);
+    asprintf(&new, "%s.db", new_name);
+    ret = rename(old, new);
+    free(old);
+    free(new);
+    if(ret)
+       return errno;
+    
+    free(db->hdb_name);
+    db->hdb_name = strdup(new_name);
+    return 0;
+}
+
+static krb5_error_code
+DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT k, v;
+    int code;
+
+    k.data = key.data;
+    k.size = key.length;
+    code = db->hdb_lock(context, db, HDB_RLOCK);
+    if(code)
+       return code;
+    code = d->get(d, &k, &v, 0);
+    db->hdb_unlock(context, db);
+    if(code < 0)
+       return errno;
+    if(code == 1)
+       return HDB_ERR_NOENTRY;
+    
+    krb5_data_copy(reply, v.data, v.size);
+    return 0;
+}
+
+static krb5_error_code
+DB__put(krb5_context context, HDB *db, int replace, 
+       krb5_data key, krb5_data value)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT k, v;
+    int code;
+
+    k.data = key.data;
+    k.size = key.length;
+    v.data = value.data;
+    v.size = value.length;
+    code = db->hdb_lock(context, db, HDB_WLOCK);
+    if(code)
+       return code;
+    code = d->put(d, &k, &v, replace ? 0 : R_NOOVERWRITE);
+    db->hdb_unlock(context, db);
+    if(code < 0)
+       return errno;
+    if(code == 1)
+       return HDB_ERR_EXISTS;
+    return 0;
+}
+
+static krb5_error_code
+DB__del(krb5_context context, HDB *db, krb5_data key)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT k;
+    krb5_error_code code;
+    k.data = key.data;
+    k.size = key.length;
+    code = db->hdb_lock(context, db, HDB_WLOCK);
+    if(code)
+       return code;
+    code = d->del(d, &k, 0);
+    db->hdb_unlock(context, db);
+    if(code == 1)
+       return HDB_ERR_NOENTRY;
+    if(code < 0)
+       return errno;
+    return 0;
+}
+
+static krb5_error_code
+DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
+{
+    char *fn;
+    krb5_error_code ret;
+
+    asprintf(&fn, "%s.db", db->hdb_name);
+    if (fn == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    db->hdb_db = dbopen(fn, flags, mode, DB_BTREE, NULL);
+    free(fn);
+    /* try to open without .db extension */
+    if(db->hdb_db == NULL && errno == ENOENT)
+       db->hdb_db = dbopen(db->hdb_name, flags, mode, DB_BTREE, NULL);
+    if(db->hdb_db == NULL) {
+       ret = errno;
+       krb5_set_error_string(context, "dbopen (%s): %s",
+                             db->hdb_name, strerror(ret));
+       return ret;
+    }
+    if((flags & O_ACCMODE) == O_RDONLY)
+       ret = hdb_check_db_format(context, db);
+    else
+       ret = hdb_init_db(context, db);
+    if(ret == HDB_ERR_NOENTRY) {
+       krb5_clear_error_string(context);
+       return 0;
+    }
+    return ret;
+}
+
+krb5_error_code
+hdb_db_create(krb5_context context, HDB **db, 
+             const char *filename)
+{
+    *db = malloc(sizeof(**db));
+    if (*db == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    (*db)->hdb_db = NULL;
+    (*db)->hdb_name = strdup(filename);
+    if ((*db)->hdb_name == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free(*db);
+       *db = NULL;
+       return ENOMEM;
+    }
+    (*db)->hdb_master_key_set = 0;
+    (*db)->hdb_openp = 0;
+    (*db)->hdb_open = DB_open;
+    (*db)->hdb_close = DB_close;
+    (*db)->hdb_fetch = _hdb_fetch;
+    (*db)->hdb_store = _hdb_store;
+    (*db)->hdb_remove = _hdb_remove;
+    (*db)->hdb_firstkey = DB_firstkey;
+    (*db)->hdb_nextkey= DB_nextkey;
+    (*db)->hdb_lock = DB_lock;
+    (*db)->hdb_unlock = DB_unlock;
+    (*db)->hdb_rename = DB_rename;
+    (*db)->hdb__get = DB__get;
+    (*db)->hdb__put = DB__put;
+    (*db)->hdb__del = DB__del;
+    (*db)->hdb_destroy = DB_destroy;
+    return 0;
+}
+
+#endif /* HAVE_DB1 */
diff --git a/src/kerberosV/src/lib/hdb/db3.c b/src/kerberosV/src/lib/hdb/db3.c
new file mode 100644 (file)
index 0000000..f6fc2d5
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: db3.c,v 1.14.2.1 2005/08/09 09:31:16 lha Exp $");
+
+#if HAVE_DB3
+
+#ifdef HAVE_DB4_DB_H
+#include <db4/db.h>
+#elif defined(HAVE_DB3_DB_H)
+#include <db3/db.h>
+#else
+#include <db.h>
+#endif
+
+static krb5_error_code
+DB_close(krb5_context context, HDB *db)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBC *dbcp = (DBC*)db->hdb_dbc;
+
+    dbcp->c_close(dbcp);
+    db->hdb_dbc = 0;
+    d->close(d, 0);
+    return 0;
+}
+
+static krb5_error_code
+DB_destroy(krb5_context context, HDB *db)
+{
+    krb5_error_code ret;
+
+    ret = hdb_clear_master_key (context, db);
+    free(db->hdb_name);
+    free(db);
+    return ret;
+}
+
+static krb5_error_code
+DB_lock(krb5_context context, HDB *db, int operation)
+{
+    DB *d = (DB*)db->hdb_db;
+    int fd;
+    if ((*d->fd)(d, &fd))
+       return HDB_ERR_CANT_LOCK_DB;
+    return hdb_lock(fd, operation);
+}
+
+static krb5_error_code
+DB_unlock(krb5_context context, HDB *db)
+{
+    DB *d = (DB*)db->hdb_db;
+    int fd;
+    if ((*d->fd)(d, &fd))
+       return HDB_ERR_CANT_LOCK_DB;
+    return hdb_unlock(fd);
+}
+
+
+static krb5_error_code
+DB_seq(krb5_context context, HDB *db,
+       unsigned flags, hdb_entry *entry, int flag)
+{
+    DBT key, value;
+    DBC *dbcp = db->hdb_dbc;
+    krb5_data key_data, data;
+    int code;
+
+    memset(&key, 0, sizeof(DBT));
+    memset(&value, 0, sizeof(DBT));
+    if (db->hdb_lock(context, db, HDB_RLOCK))
+       return HDB_ERR_DB_INUSE;
+    code = dbcp->c_get(dbcp, &key, &value, flag);
+    db->hdb_unlock(context, db); /* XXX check value */
+    if (code == DB_NOTFOUND)
+       return HDB_ERR_NOENTRY;
+    if (code)
+       return code;
+
+    key_data.data = key.data;
+    key_data.length = key.size;
+    data.data = value.data;
+    data.length = value.size;
+    if (hdb_value2entry(context, &data, entry))
+       return DB_seq(context, db, flags, entry, DB_NEXT);
+    if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
+       code = hdb_unseal_keys (context, db, entry);
+       if (code)
+           hdb_free_entry (context, entry);
+    }
+    if (entry->principal == NULL) {
+       entry->principal = malloc(sizeof(*entry->principal));
+       if (entry->principal == NULL) {
+           hdb_free_entry (context, entry);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       } else {
+           hdb_key2principal(context, &key_data, entry->principal);
+       }
+    }
+    return 0;
+}
+
+
+static krb5_error_code
+DB_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    return DB_seq(context, db, flags, entry, DB_FIRST);
+}
+
+
+static krb5_error_code
+DB_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    return DB_seq(context, db, flags, entry, DB_NEXT);
+}
+
+static krb5_error_code
+DB_rename(krb5_context context, HDB *db, const char *new_name)
+{
+    int ret;
+    char *old, *new;
+
+    asprintf(&old, "%s.db", db->hdb_name);
+    asprintf(&new, "%s.db", new_name);
+    ret = rename(old, new);
+    free(old);
+    free(new);
+    if(ret)
+       return errno;
+    
+    free(db->hdb_name);
+    db->hdb_name = strdup(new_name);
+    return 0;
+}
+
+static krb5_error_code
+DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT k, v;
+    int code;
+
+    memset(&k, 0, sizeof(DBT));
+    memset(&v, 0, sizeof(DBT));
+    k.data = key.data;
+    k.size = key.length;
+    k.flags = 0;
+    if ((code = db->hdb_lock(context, db, HDB_RLOCK)))
+       return code;
+    code = d->get(d, NULL, &k, &v, 0);
+    db->hdb_unlock(context, db);
+    if(code == DB_NOTFOUND)
+       return HDB_ERR_NOENTRY;
+    if(code)
+       return code;
+
+    krb5_data_copy(reply, v.data, v.size);
+    return 0;
+}
+
+static krb5_error_code
+DB__put(krb5_context context, HDB *db, int replace, 
+       krb5_data key, krb5_data value)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT k, v;
+    int code;
+
+    memset(&k, 0, sizeof(DBT));
+    memset(&v, 0, sizeof(DBT));
+    k.data = key.data;
+    k.size = key.length;
+    k.flags = 0;
+    v.data = value.data;
+    v.size = value.length;
+    v.flags = 0;
+    if ((code = db->hdb_lock(context, db, HDB_WLOCK)))
+       return code;
+    code = d->put(d, NULL, &k, &v, replace ? 0 : DB_NOOVERWRITE);
+    db->hdb_unlock(context, db);
+    if(code == DB_KEYEXIST)
+       return HDB_ERR_EXISTS;
+    if(code)
+       return errno;
+    return 0;
+}
+
+static krb5_error_code
+DB__del(krb5_context context, HDB *db, krb5_data key)
+{
+    DB *d = (DB*)db->hdb_db;
+    DBT k;
+    krb5_error_code code;
+    memset(&k, 0, sizeof(DBT));
+    k.data = key.data;
+    k.size = key.length;
+    k.flags = 0;
+    code = db->hdb_lock(context, db, HDB_WLOCK);
+    if(code)
+       return code;
+    code = d->del(d, NULL, &k, 0);
+    db->hdb_unlock(context, db);
+    if(code == DB_NOTFOUND)
+       return HDB_ERR_NOENTRY;
+    if(code)
+       return code;
+    return 0;
+}
+
+static krb5_error_code
+DB_open(krb5_context context, HDB *db, int flags, mode_t mode)
+{
+    char *fn;
+    krb5_error_code ret;
+    DB *d;
+    int myflags = 0;
+
+    if (flags & O_CREAT)
+      myflags |= DB_CREATE;
+
+    if (flags & O_EXCL)
+      myflags |= DB_EXCL;
+
+    if((flags & O_ACCMODE) == O_RDONLY)
+      myflags |= DB_RDONLY;
+
+    if (flags & O_TRUNC)
+      myflags |= DB_TRUNCATE;
+
+    asprintf(&fn, "%s.db", db->hdb_name);
+    if (fn == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    db_create(&d, NULL, 0);
+    db->hdb_db = d;
+
+#if (DB_VERSION_MAJOR >= 4) && (DB_VERSION_MINOR >= 1)
+    ret = d->open(db->hdb_db, NULL, fn, NULL, DB_BTREE, myflags, mode);
+#else
+    ret = d->open(db->hdb_db, fn, NULL, DB_BTREE, myflags, mode);
+#endif
+
+    if (ret == ENOENT) {
+       /* try to open without .db extension */
+#if (DB_VERSION_MAJOR >= 4) && (DB_VERSION_MINOR >= 1)
+       ret = d->open(db->hdb_db, NULL, db->hdb_name, NULL, DB_BTREE, myflags, mode);
+#else
+       ret = d->open(db->hdb_db, db->hdb_name, NULL, DB_BTREE, myflags, mode);
+#endif
+    }
+
+    if (ret) {
+       free(fn);
+       krb5_set_error_string(context, "opening %s: %s",
+                             db->hdb_name, strerror(ret));
+       return ret;
+    }
+    free(fn);
+
+    ret = d->cursor(d, NULL, (DBC **)&db->hdb_dbc, 0);
+    if (ret) {
+       krb5_set_error_string(context, "d->cursor: %s", strerror(ret));
+        return ret;
+    }
+
+    if((flags & O_ACCMODE) == O_RDONLY)
+       ret = hdb_check_db_format(context, db);
+    else
+       ret = hdb_init_db(context, db);
+    if(ret == HDB_ERR_NOENTRY)
+       return 0;
+    if (ret) {
+       DB_close(context, db);
+       krb5_set_error_string(context, "hdb_open: failed %s database %s",
+                             (flags & O_ACCMODE) == O_RDONLY ? 
+                             "checking format of" : "initialize", 
+                             db->hdb_name);
+    }
+
+    return ret;
+}
+
+krb5_error_code
+hdb_db_create(krb5_context context, HDB **db, 
+             const char *filename)
+{
+    *db = malloc(sizeof(**db));
+    if (*db == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    (*db)->hdb_db = NULL;
+    (*db)->hdb_name = strdup(filename);
+    if ((*db)->hdb_name == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free(*db);
+       *db = NULL;
+       return ENOMEM;
+    }
+    (*db)->hdb_master_key_set = 0;
+    (*db)->hdb_openp = 0;
+    (*db)->hdb_open  = DB_open;
+    (*db)->hdb_close = DB_close;
+    (*db)->hdb_fetch = _hdb_fetch;
+    (*db)->hdb_store = _hdb_store;
+    (*db)->hdb_remove = _hdb_remove;
+    (*db)->hdb_firstkey = DB_firstkey;
+    (*db)->hdb_nextkey= DB_nextkey;
+    (*db)->hdb_lock = DB_lock;
+    (*db)->hdb_unlock = DB_unlock;
+    (*db)->hdb_rename = DB_rename;
+    (*db)->hdb__get = DB__get;
+    (*db)->hdb__put = DB__put;
+    (*db)->hdb__del = DB__del;
+    (*db)->hdb_destroy = DB_destroy;
+    return 0;
+}
+#endif /* HAVE_DB3 */
diff --git a/src/kerberosV/src/lib/hdb/hdb-ldap.c b/src/kerberosV/src/lib/hdb/hdb-ldap.c
new file mode 100644 (file)
index 0000000..6a1679c
--- /dev/null
@@ -0,0 +1,1753 @@
+/*
+ * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd.
+ * Copyright (c) 2004, Andrew Bartlett.
+ * Copyright (c) 2003 - 2004, Kungliga Tekniska Högskolan.
+ * 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 PADL Software  nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: hdb-ldap.c,v 1.49 2005/04/18 08:03:54 lha Exp $");
+
+#ifdef OPENLDAP
+
+#include <lber.h>
+#include <ldap.h>
+#include <sys/un.h>
+#include <hex.h>
+
+static krb5_error_code LDAP__connect(krb5_context context, HDB *);
+static krb5_error_code LDAP_close(krb5_context context, HDB *);
+
+static krb5_error_code
+LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
+                  hdb_entry * ent);
+
+static const char *default_structural_object = "account";
+static char *structural_object;
+static krb5_boolean samba_forwardable;
+
+struct hdbldapdb {
+    LDAP *h_lp;
+    int   h_msgid;
+    char *h_base;
+    char *h_createbase;
+};
+
+#define HDB2LDAP(db) (((struct hdbldapdb *)(db)->hdb_db)->h_lp)
+#define HDB2MSGID(db) (((struct hdbldapdb *)(db)->hdb_db)->h_msgid)
+#define HDBSETMSGID(db,msgid) \
+       do { ((struct hdbldapdb *)(db)->hdb_db)->h_msgid = msgid; } while(0)
+#define HDB2BASE(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_base)
+#define HDB2CREATE(db) (((struct hdbldapdb *)(db)->hdb_db)->h_createbase)
+
+/*
+ *
+ */
+
+static char * krb5kdcentry_attrs[] = { 
+    "cn",
+    "createTimestamp",
+    "creatorsName",
+    "krb5EncryptionType",
+    "krb5KDCFlags",
+    "krb5Key",
+    "krb5KeyVersionNumber",
+    "krb5MaxLife",
+    "krb5MaxRenew",
+    "krb5PasswordEnd",
+    "krb5PrincipalName",
+    "krb5PrincipalRealm",
+    "krb5ValidEnd",
+    "krb5ValidStart",
+    "modifiersName",
+    "modifyTimestamp",
+    "objectClass",
+    "sambaAcctFlags",
+    "sambaKickoffTime",
+    "sambaNTPassword",
+    "sambaPwdLastSet",
+    "sambaPwdMustChange",
+    "uid",
+    NULL
+};
+
+static char *krb5principal_attrs[] = {
+    "cn",
+    "createTimestamp",
+    "creatorsName",
+    "krb5PrincipalName",
+    "krb5PrincipalRealm",
+    "modifiersName",
+    "modifyTimestamp",
+    "objectClass",
+    "uid",
+    NULL
+};
+
+static int
+LDAP_no_size_limit(krb5_context context, LDAP *lp)
+{
+    int ret, limit = LDAP_NO_LIMIT;
+
+    ret = ldap_set_option(lp, LDAP_OPT_SIZELIMIT, (const void *)&limit);
+    if (ret != LDAP_SUCCESS) {
+       krb5_set_error_string(context, "ldap_set_option: %s",
+                             ldap_err2string(ret));
+       return HDB_ERR_BADVERSION;
+    }
+    return 0;
+}
+
+static int
+check_ldap(krb5_context context, HDB *db, int ret)
+{
+    switch (ret) {
+    case LDAP_SUCCESS:
+       return 0;
+    case LDAP_SERVER_DOWN:
+       LDAP_close(context, db);
+       return 1;
+    default:
+       return 1;
+    }
+}
+
+static krb5_error_code
+LDAP__setmod(LDAPMod *** modlist, int modop, const char *attribute,
+            int *pIndex)
+{
+    int cMods;
+
+    if (*modlist == NULL) {
+       *modlist = (LDAPMod **)ber_memcalloc(1, sizeof(LDAPMod *));
+       if (*modlist == NULL)
+           return ENOMEM;
+    }
+
+    for (cMods = 0; (*modlist)[cMods] != NULL; cMods++) {
+       if ((*modlist)[cMods]->mod_op == modop &&
+           strcasecmp((*modlist)[cMods]->mod_type, attribute) == 0) {
+           break;
+       }
+    }
+
+    *pIndex = cMods;
+
+    if ((*modlist)[cMods] == NULL) {
+       LDAPMod *mod;
+
+       *modlist = (LDAPMod **)ber_memrealloc(*modlist,
+                                             (cMods + 2) * sizeof(LDAPMod *));
+       if (*modlist == NULL)
+           return ENOMEM;
+
+       (*modlist)[cMods] = (LDAPMod *)ber_memalloc(sizeof(LDAPMod));
+       if ((*modlist)[cMods] == NULL)
+           return ENOMEM;
+
+       mod = (*modlist)[cMods];
+       mod->mod_op = modop;
+       mod->mod_type = ber_strdup(attribute);
+       if (mod->mod_type == NULL) {
+           ber_memfree(mod);
+           (*modlist)[cMods] = NULL;
+           return ENOMEM;
+       }
+
+       if (modop & LDAP_MOD_BVALUES) {
+           mod->mod_bvalues = NULL;
+       } else {
+           mod->mod_values = NULL;
+       }
+
+       (*modlist)[cMods + 1] = NULL;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+LDAP_addmod_len(LDAPMod *** modlist, int modop, const char *attribute,
+               unsigned char *value, size_t len)
+{
+    krb5_error_code ret;
+    int cMods, i = 0;
+
+    ret = LDAP__setmod(modlist, modop | LDAP_MOD_BVALUES, attribute, &cMods);
+    if (ret)
+       return ret;
+
+    if (value != NULL) {
+       struct berval **bv;
+
+       bv = (*modlist)[cMods]->mod_bvalues;
+       if (bv != NULL) {
+           for (i = 0; bv[i] != NULL; i++)
+               ;
+           bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv));
+       } else
+           bv = ber_memalloc(2 * sizeof(*bv));
+       if (bv == NULL)
+           return ENOMEM;
+
+       (*modlist)[cMods]->mod_bvalues = bv;
+
+       bv[i] = ber_memalloc(sizeof(*bv));;
+       if (bv[i] == NULL)
+           return ENOMEM;
+
+       bv[i]->bv_val = value;
+       bv[i]->bv_len = len;
+
+       bv[i + 1] = NULL;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+LDAP_addmod(LDAPMod *** modlist, int modop, const char *attribute,
+           const char *value)
+{
+    int cMods, i = 0;
+    krb5_error_code ret;
+
+    ret = LDAP__setmod(modlist, modop, attribute, &cMods);
+    if (ret)
+       return ret;
+
+    if (value != NULL) {
+       char **bv;
+
+       bv = (*modlist)[cMods]->mod_values;
+       if (bv != NULL) {
+           for (i = 0; bv[i] != NULL; i++)
+               ;
+           bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv));
+       } else
+           bv = ber_memalloc(2 * sizeof(*bv));
+       if (bv == NULL)
+           return ENOMEM;
+
+       (*modlist)[cMods]->mod_values = bv;
+
+       bv[i] = ber_strdup(value);
+       if (bv[i] == NULL)
+           return ENOMEM;
+
+       bv[i + 1] = NULL;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+LDAP_addmod_generalized_time(LDAPMod *** mods, int modop,
+                            const char *attribute, KerberosTime * time)
+{
+    char buf[22];
+    struct tm *tm;
+
+    /* XXX not threadsafe */
+    tm = gmtime(time);
+    strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm);
+
+    return LDAP_addmod(mods, modop, attribute, buf);
+}
+
+static krb5_error_code
+LDAP_addmod_integer(krb5_context context,
+                   LDAPMod *** mods, int modop,
+                   const char *attribute, unsigned long l)
+{
+    krb5_error_code ret;
+    char *buf;
+
+    ret = asprintf(&buf, "%ld", l);
+    if (ret < 0) {
+       krb5_set_error_string(context, "asprintf: out of memory:");
+       return ret;
+    }
+    ret = LDAP_addmod(mods, modop, attribute, buf);
+    free (buf);
+    return ret;
+}
+
+static krb5_error_code
+LDAP_get_string_value(HDB * db, LDAPMessage * entry,
+                     const char *attribute, char **ptr)
+{
+    char **vals;
+    int ret;
+
+    vals = ldap_get_values(HDB2LDAP(db), entry, (char *) attribute);
+    if (vals == NULL) {
+       *ptr = NULL;
+       return HDB_ERR_NOENTRY;
+    }
+
+    *ptr = strdup(vals[0]);
+    if (*ptr == NULL)
+       ret = ENOMEM;
+    else
+       ret = 0;
+
+    ldap_value_free(vals);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_get_integer_value(HDB * db, LDAPMessage * entry,
+                      const char *attribute, int *ptr)
+{
+    char **vals;
+
+    vals = ldap_get_values(HDB2LDAP(db), entry, (char *) attribute);
+    if (vals == NULL)
+       return HDB_ERR_NOENTRY;
+
+    *ptr = atoi(vals[0]);
+    ldap_value_free(vals);
+    return 0;
+}
+
+static krb5_error_code
+LDAP_get_generalized_time_value(HDB * db, LDAPMessage * entry,
+                               const char *attribute, KerberosTime * kt)
+{
+    char *tmp, *gentime;
+    struct tm tm;
+    int ret;
+
+    *kt = 0;
+
+    ret = LDAP_get_string_value(db, entry, attribute, &gentime);
+    if (ret)
+       return ret;
+
+    tmp = strptime(gentime, "%Y%m%d%H%M%SZ", &tm);
+    if (tmp == NULL) {
+       free(gentime);
+       return HDB_ERR_NOENTRY;
+    }
+
+    free(gentime);
+
+    *kt = timegm(&tm);
+
+    return 0;
+}
+
+static krb5_error_code
+LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry * ent,
+               LDAPMessage * msg, LDAPMod *** pmods)
+{
+    krb5_error_code ret;
+    krb5_boolean is_new_entry;
+    char *tmp = NULL;
+    LDAPMod **mods = NULL;
+    hdb_entry orig;
+    unsigned long oflags, nflags;
+    int i;
+
+    krb5_boolean is_samba_account = FALSE;
+    krb5_boolean is_account = FALSE;
+    krb5_boolean is_heimdal_entry = FALSE;
+    krb5_boolean is_heimdal_principal = FALSE;
+
+    char **values;
+
+    *pmods = NULL;
+
+    if (msg != NULL) {
+
+       ret = LDAP_message2entry(context, db, msg, &orig);
+       if (ret)
+           goto out;
+
+       is_new_entry = FALSE;
+           
+       values = ldap_get_values(HDB2LDAP(db), msg, "objectClass");
+       if (values) {
+           int num_objectclasses = ldap_count_values(values);
+           for (i=0; i < num_objectclasses; i++) {
+               if (strcasecmp(values[i], "sambaSamAccount") == 0) {
+                   is_samba_account = TRUE;
+               } else if (strcasecmp(values[i], structural_object) == 0) {
+                   is_account = TRUE;
+               } else if (strcasecmp(values[i], "krb5Principal") == 0) {
+                   is_heimdal_principal = TRUE;
+               } else if (strcasecmp(values[i], "krb5KDCEntry") == 0) {
+                   is_heimdal_entry = TRUE;
+               }
+           }
+           ldap_value_free(values);
+       }
+
+       /*
+        * If this is just a "account" entry and no other objectclass
+        * is hanging on this entry, its really a new entry.
+        */
+       if (is_samba_account == FALSE && is_heimdal_principal == FALSE && 
+           is_heimdal_entry == FALSE) {
+           if (is_account == TRUE) {
+               is_new_entry = TRUE;
+           } else {
+               ret = HDB_ERR_NOENTRY;
+               goto out;
+           }
+       }
+    } else
+       is_new_entry = TRUE;
+
+    if (is_new_entry) {
+
+       /* to make it perfectly obvious we're depending on
+        * orig being intiialized to zero */
+       memset(&orig, 0, sizeof(orig));
+
+       ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top");
+       if (ret)
+           goto out;
+       
+       /* account is the structural object class */
+       if (is_account == FALSE) {
+           ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", 
+                             structural_object);
+           is_account = TRUE;
+           if (ret)
+               goto out;
+       }
+
+       ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5Principal");
+       is_heimdal_principal = TRUE;
+       if (ret)
+           goto out;
+
+       ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5KDCEntry");
+       is_heimdal_entry = TRUE;
+       if (ret)
+           goto out;
+    }
+
+    if (is_new_entry || 
+       krb5_principal_compare(context, ent->principal, orig.principal)
+       == FALSE)
+    {
+       if (is_heimdal_principal || is_heimdal_entry) {
+
+           ret = krb5_unparse_name(context, ent->principal, &tmp);
+           if (ret)
+               goto out;
+
+           ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE,
+                             "krb5PrincipalName", tmp);
+           if (ret) {
+               free(tmp);
+               goto out;
+           }
+           free(tmp);
+       }
+
+       if (is_account || is_samba_account) {
+           ret = krb5_unparse_name_short(context, ent->principal, &tmp);
+           if (ret)
+               goto out;
+           ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp);
+           if (ret) {
+               free(tmp);
+               goto out;
+           }
+           free(tmp);
+       }
+    }
+
+    if (is_heimdal_entry && (ent->kvno != orig.kvno || is_new_entry)) {
+       ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
+                           "krb5KeyVersionNumber", 
+                           ent->kvno);
+       if (ret)
+           goto out;
+    }
+
+    if (is_heimdal_entry && ent->valid_start) {
+       if (orig.valid_end == NULL
+           || (*(ent->valid_start) != *(orig.valid_start))) {
+           ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
+                                              "krb5ValidStart",
+                                              ent->valid_start);
+           if (ret)
+               goto out;
+       }
+    }
+
+    if (ent->valid_end) {
+       if (orig.valid_end == NULL || (*(ent->valid_end) != *(orig.valid_end))) {
+           if (is_heimdal_entry) { 
+               ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
+                                                  "krb5ValidEnd",
+                                                  ent->valid_end);
+               if (ret)
+                   goto out;
+            }
+           if (is_samba_account) {
+               ret = LDAP_addmod_integer(context, &mods,  LDAP_MOD_REPLACE,
+                                         "sambaKickoffTime", 
+                                         *(ent->valid_end));
+               if (ret)
+                   goto out;
+           }
+       }
+    }
+
+    if (ent->pw_end) {
+       if (orig.pw_end == NULL || (*(ent->pw_end) != *(orig.pw_end))) {
+           if (is_heimdal_entry) {
+               ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE,
+                                                  "krb5PasswordEnd",
+                                                  ent->pw_end);
+               if (ret)
+                   goto out;
+           }
+
+           if (is_samba_account) {
+               ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
+                                         "sambaPwdMustChange", 
+                                         *(ent->pw_end));
+               if (ret)
+                   goto out;
+           }
+       }
+    }
+
+
+#if 0 /* we we have last_pw_change */
+    if (is_samba_account && ent->last_pw_change) {
+       if (orig.last_pw_change == NULL || (*(ent->last_pw_change) != *(orig.last_pw_change))) {
+           ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
+                                     "sambaPwdLastSet", 
+                                     *(ent->last_pw_change));
+           if (ret)
+               goto out;
+       }
+    }
+#endif
+
+    if (is_heimdal_entry && ent->max_life) {
+       if (orig.max_life == NULL
+           || (*(ent->max_life) != *(orig.max_life))) {
+
+           ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
+                                     "krb5MaxLife", 
+                                     *(ent->max_life));
+           if (ret)
+               goto out;
+       }
+    }
+
+    if (is_heimdal_entry && ent->max_renew) {
+       if (orig.max_renew == NULL
+           || (*(ent->max_renew) != *(orig.max_renew))) {
+
+           ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
+                                     "krb5MaxRenew",
+                                     *(ent->max_renew));
+           if (ret)
+               goto out;
+       }
+    }
+
+    oflags = HDBFlags2int(orig.flags);
+    nflags = HDBFlags2int(ent->flags);
+
+    if (is_heimdal_entry && oflags != nflags) {
+
+       ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE,
+                                 "krb5KDCFlags",
+                                 nflags);
+       if (ret)
+           goto out;
+    }
+
+    /* Remove keys if they exists, and then replace keys. */
+    if (!is_new_entry && orig.keys.len > 0) {
+       values = ldap_get_values(HDB2LDAP(db), msg, "krb5Key");
+       if (values) {
+           ldap_value_free(values);
+
+           ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL);
+           if (ret)
+               goto out;
+       }
+    }
+
+    for (i = 0; i < ent->keys.len; i++) {
+
+       if (is_samba_account
+           && ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) {
+           char *ntHexPassword;
+           char *nt;
+                   
+           /* the key might have been 'sealed', but samba passwords
+              are clear in the directory */
+           ret = hdb_unseal_key(context, db, &ent->keys.val[i]);
+           if (ret)
+               goto out;
+                   
+           nt = ent->keys.val[i].key.keyvalue.data;
+           /* store in ntPassword, not krb5key */
+           ret = hex_encode(nt, 16, &ntHexPassword);
+           if (ret < 0) {
+               krb5_set_error_string(context, "hdb-ldap: failed to "
+                                     "hex encode key");
+               ret = ENOMEM;
+               goto out;
+           }
+           ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "sambaNTPassword", 
+                             ntHexPassword);
+           free(ntHexPassword);
+           if (ret)
+               goto out;
+                   
+           /* have to kill the LM passwod if it exists */
+           values = ldap_get_values(HDB2LDAP(db), msg, "sambaLMPassword");
+           if (values) {
+               ldap_value_free(values);
+               ret = LDAP_addmod(&mods, LDAP_MOD_DELETE,
+                                 "sambaLMPassword", NULL);
+               if (ret)
+                   goto out;
+           }
+                   
+       } else if (is_heimdal_entry) {
+           unsigned char *buf;
+           size_t len, buf_size;
+
+           ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->keys.val[i], &len, ret);
+           if (ret)
+               goto out;
+           if(buf_size != len)
+               krb5_abortx(context, "internal error in ASN.1 encoder");
+
+           /* addmod_len _owns_ the key, doesn't need to copy it */
+           ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len);
+           if (ret)
+               goto out;
+       }
+    }
+
+    if (ent->etypes) {
+       /* clobber and replace encryption types. */
+       if (!is_new_entry) {
+           values = ldap_get_values(HDB2LDAP(db), msg, "krb5EncryptionType");
+           if (values) {
+               ldap_value_free(values);
+               ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType",
+                                 NULL);
+               if (ret)
+                   goto out;
+           }
+       }
+       for (i = 0; i < ent->etypes->len; i++) {
+           if (is_samba_account && 
+               ent->keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5)
+           {
+               ;
+           } else if (is_heimdal_entry) {
+               ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD,
+                                         "krb5EncryptionType",
+                                         ent->etypes->val[i]);
+               if (ret)
+                   goto out;
+           }
+       }
+    }
+
+    /* for clarity */
+    ret = 0;
+
+ out:
+
+    if (ret == 0)
+       *pmods = mods;
+    else if (mods != NULL) {
+       ldap_mods_free(mods, 1);
+       *pmods = NULL;
+    }
+
+    if (msg)
+       hdb_free_entry(context, &orig);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_dn2principal(krb5_context context, HDB * db, const char *dn,
+                 krb5_principal * principal)
+{
+    krb5_error_code ret;
+    int rc;
+    char **values;
+    LDAPMessage *res = NULL, *e;
+
+    ret = LDAP_no_size_limit(context, HDB2LDAP(db));
+    if (ret)
+       goto out;
+
+    rc = ldap_search_s(HDB2LDAP(db), dn, LDAP_SCOPE_SUBTREE,
+                      "(objectClass=krb5Principal)", krb5principal_attrs,
+                      0, &res);
+    if (check_ldap(context, db, rc)) {
+       krb5_set_error_string(context, "ldap_search_s: %s",
+                             ldap_err2string(rc));
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    e = ldap_first_entry(HDB2LDAP(db), res);
+    if (e == NULL) {
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    values = ldap_get_values(HDB2LDAP(db), e, "krb5PrincipalName");
+    if (values == NULL) {
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    ret = krb5_parse_name(context, values[0], principal);
+    ldap_value_free(values);
+
+  out:
+    if (res)
+       ldap_msgfree(res);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP__lookup_princ(krb5_context context,
+                  HDB *db,
+                  const char *princname,
+                  const char *userid,
+                  LDAPMessage **msg)
+{
+    krb5_error_code ret;
+    int rc;
+    char *filter = NULL;
+
+    ret = LDAP__connect(context, db);
+    if (ret)
+       return ret;
+
+    rc = asprintf(&filter,
+                 "(&(objectClass=krb5Principal)(krb5PrincipalName=%s))",
+                 princname);
+    if (rc < 0) {
+       krb5_set_error_string(context, "asprintf: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ret = LDAP_no_size_limit(context, HDB2LDAP(db));
+    if (ret)
+       goto out;
+
+    rc = ldap_search_s(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, filter, 
+                      krb5kdcentry_attrs, 0, msg);
+    if (check_ldap(context, db, rc)) {
+       krb5_set_error_string(context, "ldap_search_s: %s",
+                             ldap_err2string(rc));
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    if (userid && ldap_count_entries(HDB2LDAP(db), *msg) == 0) {
+       free(filter);
+       filter = NULL;
+       ldap_msgfree(*msg);
+       *msg = NULL;
+       
+       rc = asprintf(&filter,
+           "(&(|(objectClass=sambaSamAccount)(objectClass=%s))(uid=%s))",
+                     structural_object, userid);
+       if (rc < 0) {
+           krb5_set_error_string(context, "asprintf: out of memory");
+           ret = ENOMEM;
+           goto out;
+       }
+           
+       ret = LDAP_no_size_limit(context, HDB2LDAP(db));
+       if (ret)
+           goto out;
+
+       rc = ldap_search_s(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, 
+                          filter, krb5kdcentry_attrs, 0, msg);
+       if (check_ldap(context, db, rc)) {
+           krb5_set_error_string(context, "ldap_search_s: %s",
+                                 ldap_err2string(rc));
+           ret = HDB_ERR_NOENTRY;
+           goto out;
+       }
+    }
+
+    ret = 0;
+
+  out:
+    if (filter)
+       free(filter);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_principal2message(krb5_context context, HDB * db,
+                      krb5_principal princ, LDAPMessage ** msg)
+{
+    char *name, *name_short = NULL;
+    krb5_error_code ret;
+    krb5_realm *r, *r0;
+
+    *msg = NULL;
+
+    ret = krb5_unparse_name(context, princ, &name);
+    if (ret)
+       return ret;
+
+    ret = krb5_get_default_realms(context, &r0);
+    if(ret) {
+       free(name);
+       return ret;
+    }
+    for (r = r0; *r != NULL; r++) {
+       if(strcmp(krb5_principal_get_realm(context, princ), *r) == 0) {
+           ret = krb5_unparse_name_short(context, princ, &name_short);
+           if (ret) {
+               krb5_free_host_realm(context, r0);
+               free(name);
+               return ret;
+           }
+           break;
+       }
+    }
+    krb5_free_host_realm(context, r0);
+
+    ret = LDAP__lookup_princ(context, db, name, name_short, msg);
+    free(name);
+    free(name_short);
+
+    return ret;
+}
+
+/*
+ * Construct an hdb_entry from a directory entry.
+ */
+static krb5_error_code
+LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
+                  hdb_entry * ent)
+{
+    char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL;
+    char *samba_acct_flags = NULL;
+    int ret;
+    unsigned long tmp;
+    struct berval **keys;
+    char **values;
+    int tmp_time;
+
+    memset(ent, 0, sizeof(*ent));
+    ent->flags = int2HDBFlags(0);
+
+    ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name);
+    if (ret == 0) {
+       ret = krb5_parse_name(context, unparsed_name, &ent->principal);
+       if (ret)
+           goto out;
+    } else {
+       ret = LDAP_get_string_value(db, msg, "uid",
+                                   &unparsed_name);
+       if (ret == 0) {
+           ret = krb5_parse_name(context, unparsed_name, &ent->principal);
+           if (ret)
+               goto out;
+       } else {
+           krb5_set_error_string(context, "hdb-ldap: ldap entry missing"
+                                 "principal name");
+           return HDB_ERR_NOENTRY;
+       }
+    }
+
+    ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber",
+                                &ent->kvno);
+    if (ret)
+       ent->kvno = 0;
+
+    keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key");
+    if (keys != NULL) {
+       int i;
+       size_t l;
+
+       ent->keys.len = ldap_count_values_len(keys);
+       ent->keys.val = (Key *) calloc(ent->keys.len, sizeof(Key));
+       if (ent->keys.val == NULL) {
+           krb5_set_error_string(context, "calloc: out of memory");
+           ret = ENOMEM;
+           goto out;
+       }
+       for (i = 0; i < ent->keys.len; i++) {
+           decode_Key((unsigned char *) keys[i]->bv_val,
+                      (size_t) keys[i]->bv_len, &ent->keys.val[i], &l);
+       }
+       ber_bvecfree(keys);
+    } else {
+#if 1
+       /*
+        * This violates the ASN1 but it allows a principal to
+        * be related to a general directory entry without creating
+        * the keys. Hopefully it's OK.
+        */
+       ent->keys.len = 0;
+       ent->keys.val = NULL;
+#else
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+#endif
+    }
+
+    values = ldap_get_values(HDB2LDAP(db), msg, "krb5EncryptionType");
+    if (values != NULL) {
+       int i;
+
+       ent->etypes = malloc(sizeof(*(ent->etypes)));
+       if (ent->etypes == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           ret = ENOMEM;
+           goto out;
+       }
+       ent->etypes->len = ldap_count_values(values);
+       ent->etypes->val = calloc(ent->etypes->len, sizeof(int));
+       if (ent->etypes->val == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           ret = ENOMEM;
+           goto out;
+       }
+       for (i = 0; i < ent->etypes->len; i++) {
+           ent->etypes->val[i] = atoi(values[i]);
+       }
+       ldap_value_free(values);
+    }
+
+    /* manually construct the NT (type 23) key */
+    ret = LDAP_get_string_value(db, msg, "sambaNTPassword", &ntPasswordIN);
+    if (ret == 0) {
+       int *etypes;
+       Key *keys;
+
+       keys = realloc(ent->keys.val,
+                      (ent->keys.len + 1) * sizeof(ent->keys.val[0]));
+       if (keys == NULL) {
+           free(ntPasswordIN);
+           krb5_set_error_string(context, "malloc: out of memory");
+           ret = ENOMEM;
+           goto out;
+       }
+       ent->keys.val = keys;
+       memset(&ent->keys.val[ent->keys.len], 0, sizeof(Key));
+       ent->keys.val[ent->keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5;
+       ret = krb5_data_alloc (&ent->keys.val[ent->keys.len].key.keyvalue, 16);
+       if (ret) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           free(ntPasswordIN);
+           ret = ENOMEM;
+           goto out;
+       }
+       ret = hex_decode(ntPasswordIN,
+                        ent->keys.val[ent->keys.len].key.keyvalue.data, 16);
+       ent->keys.len++;
+
+       if (ent->etypes == NULL) {
+           ent->etypes = malloc(sizeof(*(ent->etypes)));
+           if (ent->etypes == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               ret = ENOMEM;
+               goto out;
+           }
+           ent->etypes->val = NULL;
+           ent->etypes->len = 0;
+       }
+
+       etypes = realloc(ent->etypes->val, 
+                        (ent->etypes->len + 1) * sizeof(ent->etypes->val[0]));
+       if (etypes == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           ret = ENOMEM;
+           goto out;                       
+       }
+       ent->etypes->val = etypes;
+       ent->etypes->val[ent->etypes->len] = ETYPE_ARCFOUR_HMAC_MD5;
+       ent->etypes->len++;
+    }
+
+    ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp",
+                                         &ent->created_by.time);
+    if (ret)
+       ent->created_by.time = time(NULL);
+
+    ent->created_by.principal = NULL;
+
+    ret = LDAP_get_string_value(db, msg, "creatorsName", &dn);
+    if (ret == 0) {
+       if (LDAP_dn2principal(context, db, dn, &ent->created_by.principal)
+           != 0) {
+           ent->created_by.principal = NULL;
+       }
+       free(dn);
+    }
+
+    ent->modified_by = (Event *) malloc(sizeof(Event));
+    if (ent->modified_by == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp",
+                                         &ent->modified_by->time);
+    if (ret == 0) {
+       ret = LDAP_get_string_value(db, msg, "modifiersName", &dn);
+       if (LDAP_dn2principal(context, db, dn, &ent->modified_by->principal))
+           ent->modified_by->principal = NULL;
+       free(dn);
+    } else {
+       free(ent->modified_by);
+       ent->modified_by = NULL;
+    }
+
+    ent->valid_start = malloc(sizeof(*ent->valid_start));
+    if (ent->valid_start == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart",
+                                         ent->valid_start);
+    if (ret) {
+       /* OPTIONAL */
+       free(ent->valid_start);
+       ent->valid_start = NULL;
+    }
+    
+    ent->valid_end = malloc(sizeof(*ent->valid_end));
+    if (ent->valid_end == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd",
+                                         ent->valid_end);
+    if (ret) {
+       /* OPTIONAL */
+       free(ent->valid_end);
+       ent->valid_end = NULL;
+    }
+
+    ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time);
+    if (ret == 0) {
+       if (ent->valid_end == NULL) {
+           ent->valid_end = malloc(sizeof(*ent->valid_end));
+           if (ent->valid_end == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               ret = ENOMEM;
+               goto out;
+           }
+       }
+       *ent->valid_end = tmp_time;
+    }
+
+    ent->pw_end = malloc(sizeof(*ent->pw_end));
+    if (ent->pw_end == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd",
+                                         ent->pw_end);
+    if (ret) {
+       /* OPTIONAL */
+       free(ent->pw_end);
+       ent->pw_end = NULL;
+    }
+
+    ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time);
+    if (ret == 0) {
+       if (ent->pw_end == NULL) {
+           ent->pw_end = malloc(sizeof(*ent->pw_end));
+           if (ent->pw_end == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               ret = ENOMEM;
+               goto out;
+           }
+       }
+       *ent->pw_end = tmp_time;
+    }
+
+#if 0 /* we we have last_pw_change */
+    ent->last_pw_change = malloc(sizeof(*ent->last_pw_change));
+    if (ent->last_pw_change == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet",
+                                &tmp_time);
+    if (ret) {
+       /* OPTIONAL */
+       free(ent->last_pw_change);
+       ent->last_pw_change = NULL;
+    } else
+       *ent->last_pw_change = tmp_time;
+#endif
+
+    ent->max_life = malloc(sizeof(*ent->max_life));
+    if (ent->max_life == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", ent->max_life);
+    if (ret) {
+       free(ent->max_life);
+       ent->max_life = NULL;
+    }
+
+    ent->max_renew = malloc(sizeof(*ent->max_renew));
+    if (ent->max_renew == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", ent->max_renew);
+    if (ret) {
+       free(ent->max_renew);
+       ent->max_renew = NULL;
+    }
+
+    values = ldap_get_values(HDB2LDAP(db), msg, "krb5KDCFlags");
+    if (values != NULL) {
+       errno = 0;
+       tmp = strtoul(values[0], (char **) NULL, 10);
+       if (tmp == ULONG_MAX && errno == ERANGE) {
+           krb5_set_error_string(context, "strtoul: could not convert flag");
+           ret = ERANGE;
+           goto out;
+       }
+    } else {
+       tmp = 0;
+    }
+
+    ent->flags = int2HDBFlags(tmp);
+
+    /* Try and find Samba flags to put into the mix */
+    ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags);
+    if (ret == 0) {
+       /* parse the [UXW...] string:
+              
+       'N'    No password       
+       'D'    Disabled  
+       'H'    Homedir required  
+       'T'    Temp account.     
+       'U'    User account (normal)     
+       'M'    MNS logon user account - what is this ?   
+       'W'    Workstation account       
+       'S'    Server account    
+       'L'    Locked account    
+       'X'    No Xpiry on password      
+       'I'    Interdomain trust account         
+           
+       */       
+           
+       int i;
+       int flags_len = strlen(samba_acct_flags);
+
+       if (flags_len < 2)
+           goto out2;
+
+       if (samba_acct_flags[0] != '[' 
+           || samba_acct_flags[flags_len - 1] != ']') 
+           goto out2;
+
+       /* Allow forwarding */
+       if (samba_forwardable)
+           ent->flags.forwardable = TRUE;
+
+       for (i=0; i < flags_len; i++) {
+           switch (samba_acct_flags[i]) {
+           case ' ':
+           case '[':
+           case ']':
+               break;
+           case 'N':
+               /* how to handle no password in kerberos? */
+               break;
+           case 'D':
+               ent->flags.invalid = TRUE;
+               break;
+           case 'H':
+               break;
+           case 'T':
+               /* temp duplicate */
+               ent->flags.invalid = TRUE;
+               break;
+           case 'U':
+               ent->flags.client = TRUE;
+               break;
+           case 'M':
+               break;
+           case 'W':
+           case 'S':
+               ent->flags.server = TRUE;
+               ent->flags.client = TRUE;
+               break;
+           case 'L':
+               ent->flags.invalid = TRUE;
+               break;
+           case 'X':
+               if (ent->pw_end) {
+                   free(ent->pw_end);
+                   ent->pw_end = NULL;
+               }
+               break;
+           case 'I':
+               ent->flags.server = TRUE;
+               ent->flags.client = TRUE;
+               break;
+           }
+       }
+    out2:
+       free(samba_acct_flags);
+    }
+
+    ret = 0;
+
+ out:
+    if (unparsed_name)
+       free(unparsed_name);
+
+    if (ret)
+       hdb_free_entry(context, ent);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_close(krb5_context context, HDB * db)
+{
+    if (HDB2LDAP(db)) {
+       ldap_unbind_ext(HDB2LDAP(db), NULL, NULL);
+       ((struct hdbldapdb *)db->hdb_db)->h_lp = NULL;
+    }
+    
+    return 0;
+}
+
+static krb5_error_code
+LDAP_lock(krb5_context context, HDB * db, int operation)
+{
+    return 0;
+}
+
+static krb5_error_code
+LDAP_unlock(krb5_context context, HDB * db)
+{
+    return 0;
+}
+
+static krb5_error_code
+LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry * entry)
+{
+    int msgid, rc, parserc;
+    krb5_error_code ret;
+    LDAPMessage *e;
+
+    msgid = HDB2MSGID(db);
+    if (msgid < 0)
+       return HDB_ERR_NOENTRY;
+
+    do {
+       rc = ldap_result(HDB2LDAP(db), msgid, LDAP_MSG_ONE, NULL, &e);
+       switch (rc) {
+       case LDAP_RES_SEARCH_REFERENCE:
+           ldap_msgfree(e);
+           ret = 0;
+           break;
+       case LDAP_RES_SEARCH_ENTRY:
+           /* We have an entry. Parse it. */
+           ret = LDAP_message2entry(context, db, e, entry);
+           ldap_msgfree(e);
+           break;
+       case LDAP_RES_SEARCH_RESULT:
+           /* We're probably at the end of the results. If not, abandon. */
+           parserc =
+               ldap_parse_result(HDB2LDAP(db), e, NULL, NULL, NULL,
+                                 NULL, NULL, 1);
+           if (parserc != LDAP_SUCCESS
+               && parserc != LDAP_MORE_RESULTS_TO_RETURN) {
+               krb5_set_error_string(context, "ldap_parse_result: %s",
+                                     ldap_err2string(parserc));
+               ldap_abandon(HDB2LDAP(db), msgid);
+           }
+           ret = HDB_ERR_NOENTRY;
+           HDBSETMSGID(db, -1);
+           break;
+       case LDAP_SERVER_DOWN:
+           ldap_msgfree(e);
+           LDAP_close(context, db);
+           HDBSETMSGID(db, -1);
+           ret = ENETDOWN;
+           break;
+       default:
+           /* Some unspecified error (timeout?). Abandon. */
+           ldap_msgfree(e);
+           ldap_abandon(HDB2LDAP(db), msgid);
+           ret = HDB_ERR_NOENTRY;
+           HDBSETMSGID(db, -1);
+           break;
+       }
+    } while (rc == LDAP_RES_SEARCH_REFERENCE);
+
+    if (ret == 0) {
+       if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
+           ret = hdb_unseal_keys(context, db, entry);
+           if (ret)
+               hdb_free_entry(context,entry);
+       }
+    }
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_firstkey(krb5_context context, HDB *db, unsigned flags,
+             hdb_entry *entry)
+{
+    krb5_error_code ret;
+    int msgid;
+
+    ret = LDAP__connect(context, db);
+    if (ret)
+       return ret;
+
+    ret = LDAP_no_size_limit(context, HDB2LDAP(db));
+    if (ret)
+       return ret;
+
+    msgid = ldap_search(HDB2LDAP(db), HDB2BASE(db),
+                       LDAP_SCOPE_SUBTREE,
+                       "(|(objectClass=krb5Principal)(objectClass=sambaSamAccount))",
+                       krb5kdcentry_attrs, 0);
+    if (msgid < 0)
+       return HDB_ERR_NOENTRY;
+
+    HDBSETMSGID(db, msgid);
+
+    return LDAP_seq(context, db, flags, entry);
+}
+
+static krb5_error_code
+LDAP_nextkey(krb5_context context, HDB * db, unsigned flags,
+            hdb_entry * entry)
+{
+    return LDAP_seq(context, db, flags, entry);
+}
+
+static krb5_error_code
+LDAP_rename(krb5_context context, HDB * db, const char *new_name)
+{
+    return HDB_ERR_DB_INUSE;
+}
+
+static krb5_error_code
+LDAP__connect(krb5_context context, HDB * db)
+{
+    int rc, version = LDAP_VERSION3;
+    /*
+     * Empty credentials to do a SASL bind with LDAP. Note that empty
+     * different from NULL credentials. If you provide NULL
+     * credentials instead of empty credentials you will get a SASL
+     * bind in progress message.
+     */
+    struct berval bv = { 0, "" };
+
+    if (HDB2LDAP(db)) {
+       /* connection has been opened. ping server. */
+       struct sockaddr_un addr;
+       socklen_t len = sizeof(addr);
+       int sd;
+
+       if (ldap_get_option(HDB2LDAP(db), LDAP_OPT_DESC, &sd) == 0 &&
+           getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
+           /* the other end has died. reopen. */
+           LDAP_close(context, db);
+       }
+    }
+
+    if (HDB2LDAP(db) != NULL) /* server is UP */
+       return 0;
+
+    rc = ldap_initialize(&((struct hdbldapdb *)db->hdb_db)->h_lp, "ldapi:///");
+    if (rc != LDAP_SUCCESS) {
+       krb5_set_error_string(context, "ldap_initialize: %s", 
+                             ldap_err2string(rc));
+       return HDB_ERR_NOENTRY;
+    }
+
+    rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_PROTOCOL_VERSION,
+                        (const void *)&version);
+    if (rc != LDAP_SUCCESS) {
+       krb5_set_error_string(context, "ldap_set_option: %s",
+                             ldap_err2string(rc));
+       LDAP_close(context, db);
+       return HDB_ERR_BADVERSION;
+    }
+
+    rc = ldap_sasl_bind_s(HDB2LDAP(db), NULL, "EXTERNAL", &bv,
+                         NULL, NULL, NULL);
+    if (rc != LDAP_SUCCESS) {
+       krb5_set_error_string(context, "ldap_sasl_bind_s: %s",
+                             ldap_err2string(rc));
+       LDAP_close(context, db);
+       return HDB_ERR_BADVERSION;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+LDAP_open(krb5_context context, HDB * db, int flags, mode_t mode)
+{
+    /* Not the right place for this. */
+#ifdef HAVE_SIGACTION
+    struct sigaction sa;
+
+    sa.sa_flags = 0;
+    sa.sa_handler = SIG_IGN;
+    sigemptyset(&sa.sa_mask);
+
+    sigaction(SIGPIPE, &sa, NULL);
+#else
+    signal(SIGPIPE, SIG_IGN);
+#endif /* HAVE_SIGACTION */
+
+    return LDAP__connect(context, db);
+}
+
+static krb5_error_code
+LDAP_fetch(krb5_context context, HDB * db, unsigned flags,
+          hdb_entry * entry)
+{
+    LDAPMessage *msg, *e;
+    krb5_error_code ret;
+
+    ret = LDAP_principal2message(context, db, entry->principal, &msg);
+    if (ret)
+       return ret;
+
+    e = ldap_first_entry(HDB2LDAP(db), msg);
+    if (e == NULL) {
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    ret = LDAP_message2entry(context, db, e, entry);
+    if (ret == 0) {
+       if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
+           ret = hdb_unseal_keys(context, db, entry);
+           if (ret)
+               hdb_free_entry(context,entry);
+       }
+    }
+
+  out:
+    ldap_msgfree(msg);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_store(krb5_context context, HDB * db, unsigned flags,
+          hdb_entry * entry)
+{
+    LDAPMod **mods = NULL;
+    krb5_error_code ret;
+    const char *errfn;
+    int rc;
+    LDAPMessage *msg = NULL, *e = NULL;
+    char *dn = NULL, *name = NULL;
+
+    ret = LDAP_principal2message(context, db, entry->principal, &msg);
+    if (ret == 0)
+       e = ldap_first_entry(HDB2LDAP(db), msg);
+
+    ret = krb5_unparse_name(context, entry->principal, &name);
+    if (ret) {
+       free(name);
+       return ret;
+    }
+
+    ret = hdb_seal_keys(context, db, entry);
+    if (ret)
+       goto out;
+
+    /* turn new entry into LDAPMod array */
+    ret = LDAP_entry2mods(context, db, entry, e, &mods);
+    if (ret)
+       goto out;
+
+    if (e == NULL) {
+       ret = asprintf(&dn, "krb5PrincipalName=%s,%s", name, HDB2CREATE(db));
+       if (ret < 0) {
+           krb5_set_error_string(context, "asprintf: out of memory");
+           ret = ENOMEM;
+           goto out;
+       }
+    } else if (flags & HDB_F_REPLACE) {
+       /* Entry exists, and we're allowed to replace it. */
+       dn = ldap_get_dn(HDB2LDAP(db), e);
+    } else {
+       /* Entry exists, but we're not allowed to replace it. Bail. */
+       ret = HDB_ERR_EXISTS;
+       goto out;
+    }
+
+    /* write entry into directory */
+    if (e == NULL) {
+       /* didn't exist before */
+       rc = ldap_add_s(HDB2LDAP(db), dn, mods);
+       errfn = "ldap_add_s";
+    } else {
+       /* already existed, send deltas only */
+       rc = ldap_modify_s(HDB2LDAP(db), dn, mods);
+       errfn = "ldap_modify_s";
+    }
+
+    if (check_ldap(context, db, rc)) {
+       char *ld_error = NULL;
+       ldap_get_option(HDB2LDAP(db), LDAP_OPT_ERROR_STRING,
+                       &ld_error);
+       krb5_set_error_string(context, "%s: %s (dn=%s) %s: %s", 
+                             errfn, name, dn, ldap_err2string(rc), ld_error);
+       ret = HDB_ERR_CANT_LOCK_DB;
+    } else
+       ret = 0;
+
+  out:
+    /* free stuff */
+    if (dn)
+       free(dn);
+    if (msg)
+       ldap_msgfree(msg);
+    if (mods)
+       ldap_mods_free(mods, 1);
+    if (name)
+       free(name);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_remove(krb5_context context, HDB * db, hdb_entry * entry)
+{
+    krb5_error_code ret;
+    LDAPMessage *msg, *e;
+    char *dn = NULL;
+    int rc, limit = LDAP_NO_LIMIT;
+
+    ret = LDAP_principal2message(context, db, entry->principal, &msg);
+    if (ret)
+       goto out;
+
+    e = ldap_first_entry(HDB2LDAP(db), msg);
+    if (e == NULL) {
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    dn = ldap_get_dn(HDB2LDAP(db), e);
+    if (dn == NULL) {
+       ret = HDB_ERR_NOENTRY;
+       goto out;
+    }
+
+    rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_SIZELIMIT, (const void *)&limit);
+    if (rc != LDAP_SUCCESS) {
+       krb5_set_error_string(context, "ldap_set_option: %s",
+                             ldap_err2string(rc));
+       ret = HDB_ERR_BADVERSION;
+       goto out;
+    }
+
+    rc = ldap_delete_s(HDB2LDAP(db), dn);
+    if (check_ldap(context, db, rc)) {
+       krb5_set_error_string(context, "ldap_delete_s: %s", 
+                             ldap_err2string(rc));
+       ret = HDB_ERR_CANT_LOCK_DB;
+    } else
+       ret = 0;
+
+  out:
+    if (dn != NULL)
+       free(dn);
+    if (msg != NULL)
+       ldap_msgfree(msg);
+
+    return ret;
+}
+
+static krb5_error_code
+LDAP_destroy(krb5_context context, HDB * db)
+{
+    krb5_error_code ret;
+
+    LDAP_close(context, db);
+
+    ret = hdb_clear_master_key(context, db);
+    if (HDB2BASE(db))
+       free(HDB2BASE(db));
+    if (HDB2CREATE(db))
+       free(HDB2CREATE(db));
+    if (db->hdb_name)
+       free(db->hdb_name);
+    free(db->hdb_db);
+    free(db);
+
+    return ret;
+}
+
+krb5_error_code
+hdb_ldap_create(krb5_context context, HDB ** db, const char *arg)
+{
+    struct hdbldapdb *h;
+    const char *create_base = NULL;
+
+    if (arg == NULL && arg[0] == '\0') {
+       krb5_set_error_string(context, "ldap search base not configured");
+       return ENOMEM; /* XXX */
+    }
+
+    if (structural_object == NULL) {
+       const char *p;
+
+       p = krb5_config_get_string(context, NULL, "kdc", 
+                                  "hdb-ldap-structural-object", NULL);
+       if (p == NULL)
+           p = default_structural_object;
+       structural_object = strdup(p);
+       if (structural_object == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+    }
+
+    samba_forwardable = 
+       krb5_config_get_bool_default(context, NULL, TRUE,
+                                    "kdc", "hdb-samba-forwardable", NULL);
+
+    *db = malloc(sizeof(**db));
+    if (*db == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memset(*db, 0, sizeof(**db));
+
+    h = malloc(sizeof(*h));
+    if (h == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free(*db);
+       *db = NULL;
+       return ENOMEM;
+    }
+    memset(h, 0, sizeof(*h));
+
+    asprintf(&(*db)->hdb_name, "ldap:%s", arg);
+
+    (*db)->hdb_db = h;
+    h->h_base = strdup(arg);
+    if (h->h_base == NULL) {
+       LDAP_destroy(context, *db);
+       krb5_set_error_string(context, "strdup: out of memory");
+       *db = NULL;
+       return ENOMEM;
+    }
+
+    create_base = krb5_config_get_string(context, NULL, "kdc", 
+                                        "hdb-ldap-create-base", NULL);
+    if (create_base == NULL)
+       create_base = h->h_base;
+
+    h->h_createbase = strdup(create_base);
+    if (h->h_createbase == NULL) {
+       LDAP_destroy(context, *db);
+       krb5_set_error_string(context, "strdup: out of memory");
+       *db = NULL;
+       return ENOMEM;
+    }
+
+    (*db)->hdb_master_key_set = 0;
+    (*db)->hdb_openp = 0;
+    (*db)->hdb_open = LDAP_open;
+    (*db)->hdb_close = LDAP_close;
+    (*db)->hdb_fetch = LDAP_fetch;
+    (*db)->hdb_store = LDAP_store;
+    (*db)->hdb_remove = LDAP_remove;
+    (*db)->hdb_firstkey = LDAP_firstkey;
+    (*db)->hdb_nextkey = LDAP_nextkey;
+    (*db)->hdb_lock = LDAP_lock;
+    (*db)->hdb_unlock = LDAP_unlock;
+    (*db)->hdb_rename = LDAP_rename;
+    (*db)->hdb__get = NULL;
+    (*db)->hdb__put = NULL;
+    (*db)->hdb__del = NULL;
+    (*db)->hdb_destroy = LDAP_destroy;
+
+    return 0;
+}
+
+#ifdef OPENLDAP_MODULE
+
+struct hdb_so_method hdb_ldap_interface = {
+    HDB_INTERFACE_VERSION,
+    "ldap",
+    hdb_ldap_create
+};
+
+#endif
+
+#endif                         /* OPENLDAP */
diff --git a/src/kerberosV/src/lib/hdb/hdb-private.h b/src/kerberosV/src/lib/hdb/hdb-private.h
new file mode 100644 (file)
index 0000000..a47de70
--- /dev/null
@@ -0,0 +1,27 @@
+/* This is a generated file */
+#ifndef __hdb_private_h__
+#define __hdb_private_h__
+
+#include <stdarg.h>
+
+krb5_error_code
+_hdb_fetch (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       unsigned /*flags*/,
+       hdb_entry */*entry*/);
+
+krb5_error_code
+_hdb_remove (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       hdb_entry */*entry*/);
+
+krb5_error_code
+_hdb_store (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       unsigned /*flags*/,
+       hdb_entry */*entry*/);
+
+#endif /* __hdb_private_h__ */
diff --git a/src/kerberosV/src/lib/hdb/hdb-protos.h b/src/kerberosV/src/lib/hdb/hdb-protos.h
new file mode 100644 (file)
index 0000000..886d48e
--- /dev/null
@@ -0,0 +1,247 @@
+/* This is a generated file */
+#ifndef __hdb_protos_h__
+#define __hdb_protos_h__
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+krb5_error_code
+hdb_add_master_key (
+       krb5_context /*context*/,
+       krb5_keyblock */*key*/,
+       hdb_master_key */*inout*/);
+
+krb5_error_code
+hdb_check_db_format (
+       krb5_context /*context*/,
+       HDB */*db*/);
+
+krb5_error_code
+hdb_clear_master_key (
+       krb5_context /*context*/,
+       HDB */*db*/);
+
+krb5_error_code
+hdb_create (
+       krb5_context /*context*/,
+       HDB **/*db*/,
+       const char */*filename*/);
+
+krb5_error_code
+hdb_db_create (
+       krb5_context /*context*/,
+       HDB **/*db*/,
+       const char */*filename*/);
+
+krb5_error_code
+hdb_enctype2key (
+       krb5_context /*context*/,
+       hdb_entry */*e*/,
+       krb5_enctype /*enctype*/,
+       Key **/*key*/);
+
+krb5_error_code
+hdb_entry2string (
+       krb5_context /*context*/,
+       hdb_entry */*ent*/,
+       char **/*str*/);
+
+int
+hdb_entry2value (
+       krb5_context /*context*/,
+       hdb_entry */*ent*/,
+       krb5_data */*value*/);
+
+krb5_error_code
+hdb_foreach (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       unsigned /*flags*/,
+       hdb_foreach_func_t /*func*/,
+       void */*data*/);
+
+void
+hdb_free_entry (
+       krb5_context /*context*/,
+       hdb_entry */*ent*/);
+
+void
+hdb_free_key (Key */*key*/);
+
+void
+hdb_free_keys (
+       krb5_context /*context*/,
+       int /*len*/,
+       Key */*keys*/);
+
+void
+hdb_free_master_key (
+       krb5_context /*context*/,
+       hdb_master_key /*mkey*/);
+
+krb5_error_code
+hdb_generate_key_set (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       Key **/*ret_key_set*/,
+       size_t */*nkeyset*/,
+       int /*no_salt*/);
+
+krb5_error_code
+hdb_generate_key_set_password (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       const char */*password*/,
+       Key **/*keys*/,
+       size_t */*num_keys*/);
+
+krb5_error_code
+hdb_init_db (
+       krb5_context /*context*/,
+       HDB */*db*/);
+
+int
+hdb_key2principal (
+       krb5_context /*context*/,
+       krb5_data */*key*/,
+       krb5_principal /*p*/);
+
+krb5_error_code
+hdb_ldap_create (
+       krb5_context /*context*/,
+       HDB ** /*db*/,
+       const char */*arg*/);
+
+krb5_error_code
+hdb_list_builtin (
+       krb5_context /*context*/,
+       char **/*list*/);
+
+krb5_error_code
+hdb_lock (
+       int /*fd*/,
+       int /*operation*/);
+
+krb5_error_code
+hdb_ndbm_create (
+       krb5_context /*context*/,
+       HDB **/*db*/,
+       const char */*filename*/);
+
+krb5_error_code
+hdb_next_enctype2key (
+       krb5_context /*context*/,
+       const hdb_entry */*e*/,
+       krb5_enctype /*enctype*/,
+       Key **/*key*/);
+
+int
+hdb_principal2key (
+       krb5_context /*context*/,
+       krb5_principal /*p*/,
+       krb5_data */*key*/);
+
+krb5_error_code
+hdb_print_entry (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       hdb_entry */*entry*/,
+       void */*data*/);
+
+krb5_error_code
+hdb_process_master_key (
+       krb5_context /*context*/,
+       int /*kvno*/,
+       krb5_keyblock */*key*/,
+       krb5_enctype /*etype*/,
+       hdb_master_key */*mkey*/);
+
+krb5_error_code
+hdb_read_master_key (
+       krb5_context /*context*/,
+       const char */*filename*/,
+       hdb_master_key */*mkey*/);
+
+krb5_error_code
+hdb_seal_key (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       Key */*k*/);
+
+krb5_error_code
+hdb_seal_key_mkey (
+       krb5_context /*context*/,
+       Key */*k*/,
+       hdb_master_key /*mkey*/);
+
+krb5_error_code
+hdb_seal_keys (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       hdb_entry */*ent*/);
+
+krb5_error_code
+hdb_seal_keys_mkey (
+       krb5_context /*context*/,
+       hdb_entry */*ent*/,
+       hdb_master_key /*mkey*/);
+
+krb5_error_code
+hdb_set_master_key (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code
+hdb_set_master_keyfile (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       const char */*keyfile*/);
+
+krb5_error_code
+hdb_unlock (int /*fd*/);
+
+krb5_error_code
+hdb_unseal_key (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       Key */*k*/);
+
+krb5_error_code
+hdb_unseal_key_mkey (
+       krb5_context /*context*/,
+       Key */*k*/,
+       hdb_master_key /*mkey*/);
+
+krb5_error_code
+hdb_unseal_keys (
+       krb5_context /*context*/,
+       HDB */*db*/,
+       hdb_entry */*ent*/);
+
+krb5_error_code
+hdb_unseal_keys_mkey (
+       krb5_context /*context*/,
+       hdb_entry */*ent*/,
+       hdb_master_key /*mkey*/);
+
+int
+hdb_value2entry (
+       krb5_context /*context*/,
+       krb5_data */*value*/,
+       hdb_entry */*ent*/);
+
+krb5_error_code
+hdb_write_master_key (
+       krb5_context /*context*/,
+       const char */*filename*/,
+       hdb_master_key /*mkey*/);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __hdb_protos_h__ */
diff --git a/src/kerberosV/src/lib/hdb/hdb.asn1 b/src/kerberosV/src/lib/hdb/hdb.asn1
new file mode 100644 (file)
index 0000000..06a2cfe
--- /dev/null
@@ -0,0 +1,70 @@
+-- $KTH: hdb.asn1,v 1.12 2004/11/10 18:50:27 lha Exp $
+HDB DEFINITIONS ::=
+BEGIN
+
+IMPORTS EncryptionKey, KerberosTime, Principal FROM krb5;
+
+HDB_DB_FORMAT INTEGER ::= 2    -- format of database, 
+                               -- update when making changes
+
+-- these must have the same value as the pa-* counterparts
+hdb-pw-salt    INTEGER ::= 3
+hdb-afs3-salt  INTEGER ::= 10
+
+Salt ::= SEQUENCE {
+       type[0]         INTEGER (0..4294967295),
+       salt[1]         OCTET STRING
+}
+
+Key ::= SEQUENCE {
+       mkvno[0]        INTEGER (0..4294967295) OPTIONAL, -- master key version number
+       key[1]          EncryptionKey,
+       salt[2]         Salt OPTIONAL
+}
+
+Event ::= SEQUENCE {
+       time[0]         KerberosTime,
+       principal[1]    Principal OPTIONAL
+}
+
+HDBFlags ::= BIT STRING {
+       initial(0),                     -- require as-req
+       forwardable(1),                 -- may issue forwardable
+       proxiable(2),                   -- may issue proxiable
+       renewable(3),                   -- may issue renewable
+       postdate(4),                    -- may issue postdatable
+       server(5),                      -- may be server
+       client(6),                      -- may be client
+       invalid(7),                     -- entry is invalid
+       require-preauth(8),             -- must use preauth
+       change-pw(9),                   -- change password service
+       require-hwauth(10),             -- must use hwauth
+       ok-as-delegate(11),             -- as in TicketFlags
+       user-to-user(12),               -- may use user-to-user auth
+       immutable(13)                   -- may not be deleted
+}
+
+GENERATION ::= SEQUENCE {
+       time[0]         KerberosTime,                   -- timestamp
+       usec[1]         INTEGER (0..4294967295),        -- microseconds
+       gen[2]          INTEGER (0..4294967295)         -- generation number
+}
+
+hdb_entry ::= SEQUENCE {
+       principal[0]    Principal  OPTIONAL, -- this is optional only 
+                                            -- for compatibility with libkrb5
+       kvno[1]         INTEGER (0..4294967295),
+       keys[2]         SEQUENCE OF Key,
+       created-by[3]   Event,
+       modified-by[4]  Event OPTIONAL,
+       valid-start[5]  KerberosTime OPTIONAL,
+       valid-end[6]    KerberosTime OPTIONAL,
+       pw-end[7]       KerberosTime OPTIONAL,
+       max-life[8]     INTEGER (0..4294967295) OPTIONAL,
+       max-renew[9]    INTEGER (0..4294967295) OPTIONAL,
+       flags[10]       HDBFlags,
+       etypes[11]      SEQUENCE OF INTEGER (0..4294967295) OPTIONAL,
+       generation[12]  GENERATION OPTIONAL
+}
+
+END
diff --git a/src/kerberosV/src/lib/hdb/hdb.c b/src/kerberosV/src/lib/hdb/hdb.c
new file mode 100644 (file)
index 0000000..8c2c8d9
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: hdb.c,v 1.54 2005/05/29 18:12:28 lha Exp $");
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+struct hdb_method {
+    const char *prefix;
+    krb5_error_code (*create)(krb5_context, HDB **, const char *filename);
+};
+
+static struct hdb_method methods[] = {
+#if HAVE_DB1 || HAVE_DB3
+    {"db:",    hdb_db_create},
+#endif
+#if HAVE_NDBM
+    {"ndbm:",  hdb_ndbm_create},
+#endif
+#if defined(OPENLDAP) && !defined(OPENLDAP_MODULE)
+    {"ldap:",  hdb_ldap_create},
+#endif
+#if HAVE_DB1 || HAVE_DB3
+    {"",       hdb_db_create},
+#elif defined(HAVE_NDBM)
+    {"",       hdb_ndbm_create},
+#elif defined(OPENLDAP) && !defined(OPENLDAP_MODULE)
+    {"",       hdb_ldap_create},
+#endif
+    {NULL,     NULL}
+};
+
+krb5_error_code
+hdb_next_enctype2key(krb5_context context,
+                    const hdb_entry *e,
+                    krb5_enctype enctype,
+                    Key **key)
+{
+    Key *k;
+    
+    for (k = *key ? (*key) + 1 : e->keys.val;
+        k < e->keys.val + e->keys.len; 
+        k++)
+       if(k->key.keytype == enctype){
+           *key = k;
+           return 0;
+       }
+    return KRB5_PROG_ETYPE_NOSUPP; /* XXX */
+}
+
+krb5_error_code
+hdb_enctype2key(krb5_context context, 
+               hdb_entry *e, 
+               krb5_enctype enctype, 
+               Key **key)
+{
+    *key = NULL;
+    return hdb_next_enctype2key(context, e, enctype, key);
+}
+
+void
+hdb_free_key(Key *key)
+{
+    memset(key->key.keyvalue.data, 
+          0,
+          key->key.keyvalue.length);
+    free_Key(key);
+    free(key);
+}
+
+
+krb5_error_code
+hdb_lock(int fd, int operation)
+{
+    int i, code = 0;
+
+    for(i = 0; i < 3; i++){
+       code = flock(fd, (operation == HDB_RLOCK ? LOCK_SH : LOCK_EX) | LOCK_NB);
+       if(code == 0 || errno != EWOULDBLOCK)
+           break;
+       sleep(1);
+    }
+    if(code == 0)
+       return 0;
+    if(errno == EWOULDBLOCK)
+       return HDB_ERR_DB_INUSE;
+    return HDB_ERR_CANT_LOCK_DB;
+}
+
+krb5_error_code
+hdb_unlock(int fd)
+{
+    int code;
+    code = flock(fd, LOCK_UN);
+    if(code)
+       return 4711 /* XXX */;
+    return 0;
+}
+
+void
+hdb_free_entry(krb5_context context, hdb_entry *ent)
+{
+    int i;
+
+    for(i = 0; i < ent->keys.len; ++i) {
+       Key *k = &ent->keys.val[i];
+
+       memset (k->key.keyvalue.data, 0, k->key.keyvalue.length);
+    }
+    free_hdb_entry(ent);
+}
+
+krb5_error_code
+hdb_foreach(krb5_context context,
+           HDB *db,
+           unsigned flags,
+           hdb_foreach_func_t func,
+           void *data)
+{
+    krb5_error_code ret;
+    hdb_entry entry;
+    ret = db->hdb_firstkey(context, db, flags, &entry);
+    while(ret == 0){
+       ret = (*func)(context, db, &entry, data);
+       hdb_free_entry(context, &entry);
+       if(ret == 0)
+           ret = db->hdb_nextkey(context, db, flags, &entry);
+    }
+    if(ret == HDB_ERR_NOENTRY)
+       ret = 0;
+    return ret;
+}
+
+krb5_error_code
+hdb_check_db_format(krb5_context context, HDB *db)
+{
+    krb5_data tag;
+    krb5_data version;
+    krb5_error_code ret;
+    unsigned ver;
+    int foo;
+
+    tag.data = HDB_DB_FORMAT_ENTRY;
+    tag.length = strlen(tag.data);
+    ret = (*db->hdb__get)(context, db, tag, &version);
+    if(ret)
+       return ret;
+    foo = sscanf(version.data, "%u", &ver);
+    krb5_data_free (&version);
+    if (foo != 1)
+       return HDB_ERR_BADVERSION;
+    if(ver != HDB_DB_FORMAT)
+       return HDB_ERR_BADVERSION;
+    return 0;
+}
+
+krb5_error_code
+hdb_init_db(krb5_context context, HDB *db)
+{
+    krb5_error_code ret;
+    krb5_data tag;
+    krb5_data version;
+    char ver[32];
+    
+    ret = hdb_check_db_format(context, db);
+    if(ret != HDB_ERR_NOENTRY)
+       return ret;
+    
+    tag.data = HDB_DB_FORMAT_ENTRY;
+    tag.length = strlen(tag.data);
+    snprintf(ver, sizeof(ver), "%u", HDB_DB_FORMAT);
+    version.data = ver;
+    version.length = strlen(version.data) + 1; /* zero terminated */
+    ret = (*db->hdb__put)(context, db, 0, tag, version);
+    return ret;
+}
+
+#ifdef HAVE_DLOPEN
+
+ /*
+ * Load a dynamic backend from /usr/heimdal/lib/hdb_NAME.so,
+ * looking for the hdb_NAME_create symbol.
+ */
+
+static const struct hdb_method *
+find_dynamic_method (krb5_context context,
+                    const char *filename, 
+                    const char **rest)
+{
+    static struct hdb_method method;
+    struct hdb_so_method *mso;
+    char *prefix, *path, *symbol;
+    const char *p;
+    void *dl;
+    size_t len;
+    
+    p = strchr(filename, ':');
+
+    /* if no prefix, don't know what module to load, just ignore it */
+    if (p == NULL)
+       return NULL;
+
+    len = p - filename;
+    *rest = filename + len + 1;
+    
+    prefix = strndup(filename, len);
+    if (prefix == NULL)
+       krb5_errx(context, 1, "out of memory");
+    
+    if (asprintf(&path, LIBDIR "/hdb_%s.so", prefix) == -1)
+       krb5_errx(context, 1, "out of memory");
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+#ifndef RTLD_GLOBAL
+#define RTLD_GLOBAL 0
+#endif
+
+    dl = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+    if (dl == NULL) {
+       krb5_warnx(context, "error trying to load dynamic module %s: %s\n",
+                  path, dlerror());
+       free(prefix);
+       free(path);
+       return NULL;
+    }
+    
+    if (asprintf(&symbol, "hdb_%s_interface", prefix) == -1)
+       krb5_errx(context, 1, "out of memory");
+       
+    mso = dlsym(dl, symbol);
+    if (mso == NULL) {
+       krb5_warnx(context, "error finding symbol %s in %s: %s\n", 
+                  symbol, path, dlerror());
+       dlclose(dl);
+       free(symbol);
+       free(prefix);
+       free(path);
+       return NULL;
+    }
+    free(path);
+    free(symbol);
+
+    if (mso->version != HDB_INTERFACE_VERSION) {
+       krb5_warnx(context, 
+                  "error wrong version in shared module %s "
+                  "version: %d should have been %d\n", 
+                  prefix, mso->version, HDB_INTERFACE_VERSION);
+       dlclose(dl);
+       free(prefix);
+       return NULL;
+    }
+
+    if (mso->create == NULL) {
+       krb5_errx(context, 1,
+                 "no entry point function in shared mod %s ",
+                  prefix);
+       dlclose(dl);
+       free(prefix);
+       return NULL;
+    }
+
+    method.create = mso->create;
+    method.prefix = prefix;
+
+    return &method;
+}
+#endif /* HAVE_DLOPEN */
+
+/*
+ * find the relevant method for `filename', returning a pointer to the
+ * rest in `rest'.
+ * return NULL if there's no such method.
+ */
+
+static const struct hdb_method *
+find_method (const char *filename, const char **rest)
+{
+    const struct hdb_method *h;
+
+    for (h = methods; h->prefix != NULL; ++h)
+       if (strncmp (filename, h->prefix, strlen(h->prefix)) == 0) {
+           *rest = filename + strlen(h->prefix);
+           return h;
+       }
+    return NULL;
+}
+
+krb5_error_code
+hdb_list_builtin(krb5_context context, char **list)
+{
+    const struct hdb_method *h;
+    size_t len = 0;
+    char *buf = NULL;
+
+    for (h = methods; h->prefix != NULL; ++h) {
+       if (h->prefix[0] == '\0')
+           continue;
+       len += strlen(h->prefix) + 2;
+    }
+
+    len += 1;
+    buf = malloc(len);
+    if (buf == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    buf[0] = '\0';
+
+    for (h = methods; h->prefix != NULL; ++h) {
+       if (h->prefix[0] == '\0')
+           continue;
+       if (h != methods)
+           strlcat(buf, ", ", len);
+       strlcat(buf, h->prefix, len);
+    }
+    *list = buf;
+    return 0;
+}
+
+krb5_error_code
+hdb_create(krb5_context context, HDB **db, const char *filename)
+{
+    const struct hdb_method *h;
+    const char *residual;
+
+    if(filename == NULL)
+       filename = HDB_DEFAULT_DB;
+    krb5_add_et_list(context, initialize_hdb_error_table_r);
+    h = find_method (filename, &residual);
+#ifdef HAVE_DLOPEN
+    if (h == NULL)
+       h = find_dynamic_method (context, filename, &residual);
+#endif
+    if (h == NULL)
+       krb5_errx(context, 1, "No database support! (hdb_create)");
+    return (*h->create)(context, db, residual);
+}
diff --git a/src/kerberosV/src/lib/hdb/hdb.h b/src/kerberosV/src/lib/hdb/hdb.h
new file mode 100644 (file)
index 0000000..56a85c4
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: hdb.h,v 1.33 2003/09/19 00:19:36 lha Exp $ */
+
+#ifndef __HDB_H__
+#define __HDB_H__
+
+#include <hdb_err.h>
+
+#include <hdb_asn1.h>
+
+enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
+
+/* flags for various functions */
+#define HDB_F_DECRYPT  1 /* decrypt keys */
+#define HDB_F_REPLACE  2 /* replace entry */
+
+/* key usage for master key */
+#define HDB_KU_MKEY    0x484442
+
+typedef struct hdb_master_key_data *hdb_master_key;
+
+typedef struct HDB{
+    void *hdb_db;
+    void *hdb_dbc;
+    char *hdb_name;
+    int hdb_master_key_set;
+    hdb_master_key hdb_master_key;
+    int hdb_openp;
+
+    krb5_error_code (*hdb_open)(krb5_context, struct HDB*, int, mode_t);
+    krb5_error_code (*hdb_close)(krb5_context, struct HDB*);
+    krb5_error_code (*hdb_fetch)(krb5_context,struct HDB*,unsigned,hdb_entry*);
+    krb5_error_code (*hdb_store)(krb5_context,struct HDB*,unsigned,hdb_entry*);
+    krb5_error_code (*hdb_remove)(krb5_context, struct HDB*, hdb_entry*);
+    krb5_error_code (*hdb_firstkey)(krb5_context, struct HDB*, 
+                               unsigned, hdb_entry*);
+    krb5_error_code (*hdb_nextkey)(krb5_context, struct HDB*, 
+                              unsigned, hdb_entry*);
+    krb5_error_code (*hdb_lock)(krb5_context, struct HDB*, int operation);
+    krb5_error_code (*hdb_unlock)(krb5_context, struct HDB*);
+    krb5_error_code (*hdb_rename)(krb5_context, struct HDB*, const char*);
+    krb5_error_code (*hdb__get)(krb5_context,struct HDB*,krb5_data,krb5_data*);
+    krb5_error_code (*hdb__put)(krb5_context, struct HDB*, int, 
+                           krb5_data, krb5_data);
+    krb5_error_code (*hdb__del)(krb5_context, struct HDB*, krb5_data);
+    krb5_error_code (*hdb_destroy)(krb5_context, struct HDB*);
+}HDB;
+
+#define HDB_INTERFACE_VERSION  1
+
+struct hdb_so_method {
+    int version;
+    const char *prefix;
+    krb5_error_code (*create)(krb5_context, HDB **, const char *filename);
+};
+
+#define HDB_DB_DIR "/var/heimdal"
+#define HDB_DEFAULT_DB HDB_DB_DIR "/heimdal"
+#define HDB_DB_FORMAT_ENTRY "hdb/db-format"
+
+typedef krb5_error_code (*hdb_foreach_func_t)(krb5_context, HDB*,
+                                             hdb_entry*, void*);
+extern krb5_kt_ops hdb_kt_ops;
+
+#include <hdb-protos.h>
+
+#endif /* __HDB_H__ */
diff --git a/src/kerberosV/src/lib/hdb/hdb.schema b/src/kerberosV/src/lib/hdb/hdb.schema
new file mode 100644 (file)
index 0000000..1959b1e
--- /dev/null
@@ -0,0 +1,139 @@
+# Definitions for a Kerberos V KDC schema
+#
+# $KTH: hdb.schema,v 1.3 2005/04/25 17:33:40 lha Exp $
+#
+# This version is compatible with OpenLDAP 1.8
+#
+# OID Base is iso(1) org(3) dod(6) internet(1) private(4) enterprise(1) padl(5322) kdcSchema(10)
+#
+# Syntaxes are under 1.3.6.1.4.1.5322.10.0
+# Attributes types are under 1.3.6.1.4.1.5322.10.1
+# Object classes are under 1.3.6.1.4.1.5322.10.2
+
+# Syntax definitions
+
+#krb5KDCFlagsSyntax SYNTAX ::= {
+#   WITH SYNTAX            INTEGER
+#--        initial(0),             -- require as-req
+#--        forwardable(1),         -- may issue forwardable
+#--        proxiable(2),           -- may issue proxiable
+#--        renewable(3),           -- may issue renewable
+#--        postdate(4),            -- may issue postdatable
+#--        server(5),              -- may be server
+#--        client(6),              -- may be client
+#--        invalid(7),             -- entry is invalid
+#--        require-preauth(8),     -- must use preauth
+#--        change-pw(9),           -- change password service
+#--        require-hwauth(10),     -- must use hwauth
+#--        ok-as-delegate(11),     -- as in TicketFlags
+#--        user-to-user(12),       -- may use user-to-user auth
+#--        immutable(13)           -- may not be deleted         
+#   ID                     { 1.3.6.1.4.1.5322.10.0.1 }
+#}
+
+#krb5PrincipalNameSyntax SYNTAX ::= {
+#   WITH SYNTAX            OCTET STRING
+#-- String representations of distinguished names as per RFC1510
+#   ID                     { 1.3.6.1.4.1.5322.10.0.2 }
+#}
+
+# Attribute type definitions
+attributetype ( 1.3.6.1.4.1.5322.10.1.1
+       NAME 'krb5PrincipalName'
+       DESC 'The unparsed Kerberos principal name'
+       EQUALITY caseExactIA5Match
+       SINGLE-VALUE
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.2
+       NAME 'krb5KeyVersionNumber'
+       EQUALITY integerMatch
+       SINGLE-VALUE
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.3
+       NAME 'krb5MaxLife'
+       EQUALITY integerMatch
+       SINGLE-VALUE
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.4
+       NAME 'krb5MaxRenew'
+       EQUALITY integerMatch
+       SINGLE-VALUE
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.5
+       NAME 'krb5KDCFlags'
+       EQUALITY integerMatch
+       SINGLE-VALUE
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.6
+       NAME 'krb5EncryptionType'
+       EQUALITY integerMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.7
+       NAME 'krb5ValidStart'
+       EQUALITY generalizedTimeMatch
+       ORDERING generalizedTimeOrderingMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+       SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.8
+       NAME 'krb5ValidEnd'
+       EQUALITY generalizedTimeMatch
+       ORDERING generalizedTimeOrderingMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+       SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.9
+       NAME 'krb5PasswordEnd'
+       EQUALITY generalizedTimeMatch
+       ORDERING generalizedTimeOrderingMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
+       SINGLE-VALUE )
+
+# this is temporary; keys will eventually
+# be child entries or compound attributes.
+attributetype ( 1.3.6.1.4.1.5322.10.1.10
+       NAME 'krb5Key'
+       DESC 'Encoded ASN1 Key as an octet string'
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.11
+       NAME 'krb5PrincipalRealm'
+       DESC 'Distinguished name of krb5Realm entry'
+       SUP distinguishedName )
+
+attributetype ( 1.3.6.1.4.1.5322.10.1.12
+       NAME 'krb5RealmName'
+       EQUALITY octetStringMatch
+       SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
+
+# Object class definitions
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.1
+       NAME 'krb5Principal'
+       SUP top
+       AUXILIARY
+       MUST ( krb5PrincipalName )
+       MAY ( cn $ krb5PrincipalRealm ) )
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.2
+       NAME 'krb5KDCEntry'
+       SUP krb5Principal
+       AUXILIARY
+       MUST ( krb5KeyVersionNumber )
+       MAY ( krb5ValidStart $ krb5ValidEnd $ krb5PasswordEnd $
+              krb5MaxLife $ krb5MaxRenew $ krb5KDCFlags $
+              krb5EncryptionType $ krb5Key ) )
+
+objectclass ( 1.3.6.1.4.1.5322.10.2.3
+       NAME 'krb5Realm'
+       SUP top
+       AUXILIARY
+       MUST ( krb5RealmName ) )
+
diff --git a/src/kerberosV/src/lib/hdb/hdb_err.et b/src/kerberosV/src/lib/hdb/hdb_err.et
new file mode 100644 (file)
index 0000000..ce1561a
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Error messages for the hdb library
+#
+# This might look like a com_err file, but is not
+#
+id "$KTH: hdb_err.et,v 1.5 2001/01/28 23:05:52 assar Exp $"
+
+error_table hdb
+
+prefix HDB_ERR
+
+index 1
+#error_code INUSE,             "Entry already exists in database"
+error_code UK_SERROR,          "Database store error"
+error_code UK_RERROR,          "Database read error"
+error_code NOENTRY,            "No such entry in the database"
+error_code DB_INUSE,           "Database is locked or in use--try again later"
+error_code DB_CHANGED,         "Database was modified during read"
+error_code RECURSIVELOCK,      "Attempt to lock database twice"
+error_code NOTLOCKED,          "Attempt to unlock database when not locked"
+error_code BADLOCKMODE,                "Invalid kdb lock mode"
+error_code CANT_LOCK_DB,       "Insufficient access to lock database"
+error_code EXISTS,             "Entry already exists in database"
+error_code BADVERSION,         "Wrong database version"
+error_code NO_MKEY,            "No correct master key"
+
+end
diff --git a/src/kerberosV/src/lib/hdb/hdb_locl.h b/src/kerberosV/src/lib/hdb/hdb_locl.h
new file mode 100644 (file)
index 0000000..1d58cb0
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: hdb_locl.h,v 1.19 2003/09/10 21:54:58 lha Exp $ */
+
+#ifndef __HDB_LOCL_H__
+#define __HDB_LOCL_H__
+
+#include <config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#include <roken.h>
+
+#include "crypto-headers.h"
+#include <krb5.h>
+#include <hdb.h>
+#include <hdb-private.h>
+
+#endif /* __HDB_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/hdb/keys.c b/src/kerberosV/src/lib/hdb/keys.c
new file mode 100644 (file)
index 0000000..a9b1f7e
--- /dev/null
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: keys.c,v 1.3 2005/03/17 00:42:05 lha Exp $");
+
+/*
+ * free all the memory used by (len, keys)
+ */
+
+void
+hdb_free_keys (krb5_context context, int len, Key *keys)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+       free(keys[i].mkvno);
+       keys[i].mkvno = NULL;
+       if (keys[i].salt != NULL) {
+           free_Salt(keys[i].salt);
+           free(keys[i].salt);
+           keys[i].salt = NULL;
+       }
+       krb5_free_keyblock_contents(context, &keys[i].key);
+    }
+    free (keys);
+}
+
+/* 
+ * for each entry in `default_keys' try to parse it as a sequence
+ * of etype:salttype:salt, syntax of this if something like:
+ * [(des|des3|etype):](pw-salt|afs3)[:string], if etype is omitted it
+ *      means all etypes, and if string is omitted is means the default
+ * string (for that principal). Additional special values:
+ *     v5 == pw-salt, and
+ *     v4 == des:pw-salt:
+ *     afs or afs3 == des:afs3-salt
+ */
+
+/* the 3 DES types must be first */
+static const krb5_enctype all_etypes[] = { 
+    ETYPE_DES_CBC_MD5,
+    ETYPE_DES_CBC_MD4,
+    ETYPE_DES_CBC_CRC,
+    ETYPE_AES256_CTS_HMAC_SHA1_96,
+    ETYPE_ARCFOUR_HMAC_MD5,
+    ETYPE_DES3_CBC_SHA1
+};
+
+static krb5_error_code
+parse_key_set(krb5_context context, const char *key, 
+             krb5_enctype **ret_enctypes, size_t *ret_num_enctypes, 
+             krb5_salt *salt, krb5_principal principal)
+{
+    const char *p;
+    char buf[3][256];
+    int num_buf = 0;
+    int i, num_enctypes = 0;
+    krb5_enctype e;
+    const krb5_enctype *enctypes = NULL;
+    krb5_error_code ret;
+    
+    p = key;
+
+    *ret_enctypes = NULL;
+    *ret_num_enctypes = 0;
+
+    /* split p in a list of :-separated strings */
+    for(num_buf = 0; num_buf < 3; num_buf++)
+       if(strsep_copy(&p, ":", buf[num_buf], sizeof(buf[num_buf])) == -1)
+           break;
+
+    salt->saltvalue.data = NULL;
+    salt->saltvalue.length = 0;
+
+    for(i = 0; i < num_buf; i++) {
+       if(enctypes == NULL) {
+           /* this might be a etype specifier */
+           /* XXX there should be a string_to_etypes handling
+              special cases like `des' and `all' */
+           if(strcmp(buf[i], "des") == 0) {
+               enctypes = all_etypes;
+               num_enctypes = 3;
+               continue;
+           } else if(strcmp(buf[i], "des3") == 0) {
+               e = ETYPE_DES3_CBC_SHA1;
+               enctypes = &e;
+               num_enctypes = 1;
+               continue;
+           } else {
+               ret = krb5_string_to_enctype(context, buf[i], &e);
+               if (ret == 0) {
+                   enctypes = &e;
+                   num_enctypes = 1;
+                   continue;
+               }
+           }
+       }
+
+       if(salt->salttype == 0) {
+           /* interpret string as a salt specifier, if no etype
+              is set, this sets default values */
+           /* XXX should perhaps use string_to_salttype, but that
+              interface sucks */
+           if(strcmp(buf[i], "pw-salt") == 0) {
+               if(enctypes == NULL) {
+                   enctypes = all_etypes;
+                   num_enctypes = sizeof(all_etypes)/sizeof(all_etypes[0]);
+               }
+               salt->salttype = KRB5_PW_SALT;
+           } else if(strcmp(buf[i], "afs3-salt") == 0) {
+               if(enctypes == NULL) {
+                   enctypes = all_etypes;
+                   num_enctypes = 3;
+               }
+               salt->salttype = KRB5_AFS3_SALT;
+           }
+       } else {
+           /* if there is a final string, use it as the string to
+              salt with, this is mostly useful with null salt for
+              v4 compat, and a cell name for afs compat */
+           salt->saltvalue.data = strdup(buf[i]);
+           if (salt->saltvalue.data == NULL) {
+               krb5_set_error_string(context, "malloc out of memory");
+               return ENOMEM;
+           }
+           salt->saltvalue.length = strlen(buf[i]);
+       }
+    }
+    
+    if(enctypes == NULL || salt->salttype == 0) {
+       krb5_set_error_string(context, "bad value for default_keys `%s'", key);
+       return EINVAL;
+    }
+    
+    /* if no salt was specified make up default salt */
+    if(salt->saltvalue.data == NULL) {
+       if(salt->salttype == KRB5_PW_SALT)
+           ret = krb5_get_pw_salt(context, principal, salt);
+       else if(salt->salttype == KRB5_AFS3_SALT) {
+           krb5_realm *realm = krb5_princ_realm(context, principal);
+           salt->saltvalue.data = strdup(*realm);
+           if(salt->saltvalue.data == NULL) {
+               krb5_set_error_string(context, "out of memory while "
+                                     "parsing salt specifiers");
+               return ENOMEM;
+           }
+           strlwr(salt->saltvalue.data);
+           salt->saltvalue.length = strlen(*realm);
+       }
+    }
+
+    *ret_enctypes = malloc(sizeof(enctypes[0]) * num_enctypes);
+    if (*ret_enctypes == NULL) {
+       krb5_free_salt(context, *salt);
+       krb5_set_error_string(context, "out of memory");
+       return ENOMEM;
+    }
+    memcpy(*ret_enctypes, enctypes, sizeof(enctypes[0]) * num_enctypes);
+    *ret_num_enctypes = num_enctypes;
+
+    return 0;
+}
+
+static krb5_error_code
+add_enctype_to_key_set(Key **key_set, size_t *nkeyset, 
+                      krb5_enctype enctype, krb5_salt *salt)
+{
+    krb5_error_code ret;
+    Key key, *tmp;
+
+    memset(&key, 0, sizeof(key));
+
+    tmp = realloc(*key_set, (*nkeyset + 1) * sizeof((*key_set)[0]));
+    if (tmp == NULL)
+       return ENOMEM;
+    
+    *key_set = tmp;
+
+    key.key.keytype = enctype;
+    key.key.keyvalue.length = 0;
+    key.key.keyvalue.data = NULL;
+    
+    if (salt) {
+       key.salt = malloc(sizeof(*key.salt));
+       if (key.salt == NULL) {
+           free_Key(&key);
+           return ENOMEM;
+       }
+       
+       key.salt->type = salt->salttype;
+       krb5_data_zero (&key.salt->salt);
+       
+       ret = krb5_data_copy(&key.salt->salt, 
+                            salt->saltvalue.data, 
+                            salt->saltvalue.length);
+       if (ret) {
+           free_Key(&key);
+           return ret;
+       }
+    } else
+       key.salt = NULL;
+    
+    (*key_set)[*nkeyset] = key;
+    
+    *nkeyset += 1;
+
+    return 0;
+}
+
+
+/*
+ * Generate the `key_set' from the [kadmin]default_keys statement. If
+ * `no_salt' is set, salt is not important (and will not be set) since
+ * its random keys that is going to be created.
+ */
+
+krb5_error_code
+hdb_generate_key_set(krb5_context context, krb5_principal principal,
+                    Key **ret_key_set, size_t *nkeyset, int no_salt)
+{
+    char **ktypes, **kp;
+    krb5_error_code ret;
+    Key *k, *key_set;
+    int i, j;
+    char *default_keytypes[] = {
+       "des:pw-salt",
+       "aes256-cts-hmac-sha1-96:pw-salt",
+       "des3-cbc-sha1:pw-salt",
+       "arcfour-hmac-md5:pw-salt",
+       NULL
+    };
+    
+    ktypes = krb5_config_get_strings(context, NULL, "kadmin",
+                                    "default_keys", NULL);
+    if (ktypes == NULL)
+       ktypes = default_keytypes;
+
+    if (ktypes == NULL)
+       abort();
+
+    *ret_key_set = key_set = NULL;
+    *nkeyset = 0;
+
+    ret = 0;
+    for(kp = ktypes; kp && *kp; kp++) {
+       const char *p;
+       krb5_salt salt;
+       krb5_enctype *enctypes;
+       size_t num_enctypes;
+
+       p = *kp;
+       /* check alias */
+       if(strcmp(p, "v5") == 0)
+           p = "pw-salt";
+       else if(strcmp(p, "v4") == 0)
+           p = "des:pw-salt:";
+       else if(strcmp(p, "afs") == 0 || strcmp(p, "afs3") == 0)
+           p = "des:afs3-salt";
+       else if (strcmp(p, "arcfour-hmac-md5") == 0)
+           p = "arcfour-hmac-md5:pw-salt";
+           
+       memset(&salt, 0, sizeof(salt));
+
+       ret = parse_key_set(context, p,
+                           &enctypes, &num_enctypes, &salt, principal);
+       if (ret) {
+           krb5_warnx(context, "bad value for default_keys `%s'", *kp);
+           continue;
+       }
+
+       for (i = 0; i < num_enctypes; i++) {
+           /* find duplicates */
+           for (j = 0; j < *nkeyset; j++) {
+
+               k = &key_set[j];
+
+               if (k->key.keytype == enctypes[i]) {
+                   if (no_salt)
+                       break;
+                   if (k->salt == NULL && salt.salttype == KRB5_PW_SALT)
+                       break;
+                   if (k->salt->type == salt.salttype &&
+                       k->salt->salt.length == salt.saltvalue.length &&
+                       memcmp(k->salt->salt.data, salt.saltvalue.data, 
+                              salt.saltvalue.length) == 0)
+                       break;
+               }
+           }
+           /* not a duplicate, lets add it */
+           if (j == *nkeyset) {
+               ret = add_enctype_to_key_set(&key_set, nkeyset, enctypes[i], 
+                                            no_salt ? NULL : &salt);
+               if (ret) {
+                   free(enctypes);
+                   krb5_free_salt(context, salt);
+                   goto out;
+               }
+           }
+       }
+       free(enctypes);
+       krb5_free_salt(context, salt);
+    }
+    
+ out:
+    if (ret) {
+       krb5_warn(context, ret, 
+                 "failed to parse the [kadmin]default_keys values");
+
+       for (i = 0; i < *nkeyset; i++)
+           free_Key(&key_set[i]);
+       free(key_set);
+    } else if (*nkeyset == 0) {
+       krb5_warnx(context, 
+                  "failed to parse any of the [kadmin]default_keys values");
+       ret = EINVAL; /* XXX */
+    }
+
+    *ret_key_set = key_set;
+
+    return ret;
+}
+
+
+krb5_error_code
+hdb_generate_key_set_password(krb5_context context, 
+                             krb5_principal principal, 
+                             const char *password, 
+                             Key **keys, size_t *num_keys) 
+{
+    krb5_error_code ret;
+    int i;
+
+    ret = hdb_generate_key_set(context, principal,
+                               keys, num_keys, 0);
+    if (ret)
+       return ret;
+
+    for (i = 0; i < (*num_keys); i++) {
+       krb5_salt salt;
+
+       salt.salttype = (*keys)[i].salt->type;
+       salt.saltvalue.length = (*keys)[i].salt->salt.length;
+       salt.saltvalue.data = (*keys)[i].salt->salt.data;
+
+       ret = krb5_string_to_key_salt (context,
+                                      (*keys)[i].key.keytype,
+                                      password,
+                                      salt,
+                                      &(*keys)[i].key);
+
+       if(ret)
+           break;
+    }
+
+    if(ret) {
+       hdb_free_keys (context, *num_keys, *keys);
+       return ret;
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/hdb/keytab.c b/src/kerberosV/src/lib/hdb/keytab.c
new file mode 100644 (file)
index 0000000..ae17398
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 1999 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+/* keytab backend for HDB databases */
+
+RCSID("$KTH: keytab.c,v 1.6 2003/09/19 00:19:58 lha Exp $");
+
+struct hdb_data {
+    char *dbname;
+    char *mkey;
+};
+
+/*
+ * the format for HDB keytabs is:
+ * HDB:[database:mkey]
+ */
+
+static krb5_error_code
+hdb_resolve(krb5_context context, const char *name, krb5_keytab id)
+{
+    struct hdb_data *d;
+    const char *db, *mkey;
+
+    d = malloc(sizeof(*d));
+    if(d == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    db = name;
+    mkey = strchr(name, ':');
+    if(mkey == NULL || mkey[1] == '\0') {
+       if(*name == '\0')
+           d->dbname = NULL;
+       else {
+           d->dbname = strdup(name);
+           if(d->dbname == NULL) {
+               free(d);
+               krb5_set_error_string(context, "malloc: out of memory");
+               return ENOMEM;
+           }
+       }
+       d->mkey = NULL;
+    } else {
+       if((mkey - db) == 0) {
+           d->dbname = NULL;
+       } else {
+           d->dbname = malloc(mkey - db);
+           if(d->dbname == NULL) {
+               free(d);
+               krb5_set_error_string(context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           memmove(d->dbname, db, mkey - db);
+           d->dbname[mkey - db] = '\0';
+       }
+       d->mkey = strdup(mkey + 1);
+       if(d->mkey == NULL) {
+           free(d->dbname);
+           free(d);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+    }
+    id->data = d;
+    return 0;
+}
+
+static krb5_error_code
+hdb_close(krb5_context context, krb5_keytab id)
+{
+    struct hdb_data *d = id->data;
+
+    free(d->dbname);
+    free(d->mkey);
+    free(d);
+    return 0;
+}
+
+static krb5_error_code 
+hdb_get_name(krb5_context context, 
+            krb5_keytab id, 
+            char *name, 
+            size_t namesize)
+{
+    struct hdb_data *d = id->data;
+
+    snprintf(name, namesize, "%s%s%s", 
+            d->dbname ? d->dbname : "",
+            (d->dbname || d->mkey) ? ":" : "",
+            d->mkey ? d->mkey : "");
+    return 0;
+}
+
+static void
+set_config (krb5_context context,
+           krb5_config_binding *binding,
+           const char **dbname,
+           const char **mkey)
+{
+    *dbname = krb5_config_get_string(context, binding, "dbname", NULL);
+    *mkey   = krb5_config_get_string(context, binding, "mkey_file", NULL);
+}
+
+/*
+ * try to figure out the database (`dbname') and master-key (`mkey')
+ * that should be used for `principal'.
+ */
+
+static void
+find_db (krb5_context context,
+        const char **dbname,
+        const char **mkey,
+        krb5_const_principal principal)
+{
+    const krb5_config_binding *top_bind = NULL;
+    krb5_config_binding *default_binding = NULL;
+    krb5_config_binding *db;
+    krb5_realm *prealm = krb5_princ_realm(context, (krb5_principal)principal);
+
+    *dbname = *mkey = NULL;
+
+    while ((db = (krb5_config_binding *)
+           krb5_config_get_next(context,
+                                NULL,
+                                &top_bind,
+                                krb5_config_list,
+                                "kdc",
+                                "database",
+                                NULL)) != NULL) {
+       const char *p;
+       
+       p = krb5_config_get_string (context, db, "realm", NULL);
+       if (p == NULL) {
+           if(default_binding) {
+               krb5_warnx(context, "WARNING: more than one realm-less "
+                          "database specification");
+               krb5_warnx(context, "WARNING: using the first encountered");
+           } else
+               default_binding = db;
+       } else if (strcmp (*prealm, p) == 0) {
+           set_config (context, db, dbname, mkey);
+           break;
+       }
+    }
+    if (*dbname == NULL && default_binding != NULL)
+       set_config (context, default_binding, dbname, mkey);
+    if (*dbname == NULL)
+       *dbname = HDB_DEFAULT_DB;
+}
+
+/*
+ * find the keytab entry in `id' for `principal, kvno, enctype' and return
+ * it in `entry'.  return 0 or an error code
+ */
+
+static krb5_error_code
+hdb_get_entry(krb5_context context,
+             krb5_keytab id,
+             krb5_const_principal principal,
+             krb5_kvno kvno,
+             krb5_enctype enctype,
+             krb5_keytab_entry *entry)
+{
+    hdb_entry ent;
+    krb5_error_code ret;
+    struct hdb_data *d = id->data;
+    int i;
+    HDB *db;
+    const char *dbname = d->dbname;
+    const char *mkey   = d->mkey;
+
+    if (dbname == NULL)
+       find_db (context, &dbname, &mkey, principal);
+
+    ret = hdb_create (context, &db, dbname);
+    if (ret)
+       return ret;
+    ret = hdb_set_master_keyfile (context, db, mkey);
+    if (ret) {
+       (*db->hdb_destroy)(context, db);
+       return ret;
+    }
+       
+    ret = (*db->hdb_open)(context, db, O_RDONLY, 0);
+    if (ret) {
+       (*db->hdb_destroy)(context, db);
+       return ret;
+    }
+    ent.principal = (krb5_principal)principal;
+    ret = (*db->hdb_fetch)(context, db, HDB_F_DECRYPT, &ent);
+    (*db->hdb_close)(context, db);
+    (*db->hdb_destroy)(context, db);
+
+    if(ret == HDB_ERR_NOENTRY)
+       return KRB5_KT_NOTFOUND;
+    else if(ret)
+       return ret;
+    if(kvno && ent.kvno != kvno) {
+       hdb_free_entry(context, &ent);
+       return KRB5_KT_NOTFOUND;
+    }
+    if(enctype == 0)
+       if(ent.keys.len > 0)
+           enctype = ent.keys.val[0].key.keytype;
+    ret = KRB5_KT_NOTFOUND;
+    for(i = 0; i < ent.keys.len; i++) {
+       if(ent.keys.val[i].key.keytype == enctype) {
+           krb5_copy_principal(context, principal, &entry->principal);
+           entry->vno = ent.kvno;
+           krb5_copy_keyblock_contents(context, 
+                                       &ent.keys.val[i].key, 
+                                       &entry->keyblock);
+           ret = 0;
+           break;
+       }
+    }
+    hdb_free_entry(context, &ent);
+    return ret;
+}
+
+krb5_kt_ops hdb_kt_ops = {
+    "HDB",
+    hdb_resolve,
+    hdb_get_name,
+    hdb_close,
+    hdb_get_entry,
+    NULL,              /* start_seq_get */
+    NULL,              /* next_entry */
+    NULL,              /* end_seq_get */
+    NULL,              /* add */
+    NULL               /* remove */
+};
diff --git a/src/kerberosV/src/lib/hdb/libasn1.h b/src/kerberosV/src/lib/hdb/libasn1.h
new file mode 100644 (file)
index 0000000..e425f5a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: libasn1.h,v 1.7 2001/06/23 23:18:50 assar Exp $ */
+
+#ifndef __LIBASN1_H__
+#define __LIBASN1_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <krb5_asn1.h>
+#include <der.h>
+#include "hdb_asn1.h"
+#include <asn1_err.h>
+#include <parse_units.h>
+
+#endif /* __LIBASN1_H__ */
diff --git a/src/kerberosV/src/lib/hdb/mkey.c b/src/kerberosV/src/lib/hdb/mkey.c
new file mode 100644 (file)
index 0000000..75f6022
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ * Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+RCSID("$KTH: mkey.c,v 1.18.4.2 2005/08/19 13:23:11 lha Exp $");
+
+struct hdb_master_key_data {
+    krb5_keytab_entry keytab;
+    krb5_crypto crypto;
+    struct hdb_master_key_data *next;
+};
+
+void
+hdb_free_master_key(krb5_context context, hdb_master_key mkey)
+{
+    struct hdb_master_key_data *ptr;
+    while(mkey) {
+       krb5_kt_free_entry(context, &mkey->keytab);
+       if (mkey->crypto)
+           krb5_crypto_destroy(context, mkey->crypto);
+       ptr = mkey;
+       mkey = mkey->next;
+       free(ptr);
+    }
+}
+
+krb5_error_code
+hdb_process_master_key(krb5_context context,
+                      int kvno, krb5_keyblock *key, krb5_enctype etype,
+                      hdb_master_key *mkey)
+{
+    krb5_error_code ret;
+
+    *mkey = calloc(1, sizeof(**mkey));
+    if(*mkey == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    (*mkey)->keytab.vno = kvno;
+    ret = krb5_parse_name(context, "K/M", &(*mkey)->keytab.principal);
+    if(ret)
+       goto fail;
+    ret = krb5_copy_keyblock_contents(context, key, &(*mkey)->keytab.keyblock);
+    if(ret)
+       goto fail;
+    if(etype != 0)
+       (*mkey)->keytab.keyblock.keytype = etype;
+    (*mkey)->keytab.timestamp = time(NULL);
+    ret = krb5_crypto_init(context, key, etype, &(*mkey)->crypto);
+    if(ret)
+       goto fail;
+    return 0;
+ fail:
+    hdb_free_master_key(context, *mkey);
+    *mkey = NULL;
+    return ret;
+}
+
+krb5_error_code
+hdb_add_master_key(krb5_context context, krb5_keyblock *key,
+                  hdb_master_key *inout)
+{
+    int vno = 0;
+    hdb_master_key p;
+    krb5_error_code ret;
+
+    for(p = *inout; p; p = p->next)
+       vno = max(vno, p->keytab.vno);
+    vno++;
+    ret = hdb_process_master_key(context, vno, key, 0, &p);
+    if(ret)
+       return ret;
+    p->next = *inout;
+    *inout = p;
+    return 0;
+}
+
+static krb5_error_code
+read_master_keytab(krb5_context context, const char *filename, 
+                  hdb_master_key *mkey)
+{
+    krb5_error_code ret;
+    krb5_keytab id;
+    krb5_kt_cursor cursor;
+    krb5_keytab_entry entry;
+    hdb_master_key p;
+    
+    ret = krb5_kt_resolve(context, filename, &id);
+    if(ret)
+       return ret;
+
+    ret = krb5_kt_start_seq_get(context, id, &cursor);
+    if(ret)
+       goto out;
+    *mkey = NULL;
+    while(krb5_kt_next_entry(context, id, &entry, &cursor) == 0) {
+       p = calloc(1, sizeof(*p));
+       p->keytab = entry;
+       ret = krb5_crypto_init(context, &p->keytab.keyblock, 0, &p->crypto);
+       p->next = *mkey;
+       *mkey = p;
+    }
+    krb5_kt_end_seq_get(context, id, &cursor);
+  out:
+    krb5_kt_close(context, id);
+    return ret;
+}
+
+/* read a MIT master keyfile */
+static krb5_error_code
+read_master_mit(krb5_context context, const char *filename, 
+               hdb_master_key *mkey)
+{
+    int fd;
+    krb5_error_code ret;
+    krb5_storage *sp;
+    int16_t enctype;
+    krb5_keyblock key;
+              
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if(fd < 0) {
+       int save_errno = errno;
+       krb5_set_error_string(context, "failed to open %s: %s", filename,
+                             strerror(save_errno));
+       return save_errno;
+    }
+    sp = krb5_storage_from_fd(fd);
+    if(sp == NULL) {
+       close(fd);
+       return errno;
+    }
+    krb5_storage_set_flags(sp, KRB5_STORAGE_HOST_BYTEORDER);
+#if 0
+    /* could possibly use ret_keyblock here, but do it with more
+       checks for now */
+    ret = krb5_ret_keyblock(sp, &key);
+#else
+    ret = krb5_ret_int16(sp, &enctype);
+    if((htons(enctype) & 0xff00) == 0x3000) {
+       krb5_set_error_string(context, "unknown keytype in %s: %#x, expected %#x", 
+                             filename, htons(enctype), 0x3000);
+       ret = HEIM_ERR_BAD_MKEY;
+       goto out;
+    }
+    key.keytype = enctype;
+    ret = krb5_ret_data(sp, &key.keyvalue);
+    if(ret)
+       goto out;
+#endif
+    ret = hdb_process_master_key(context, 0, &key, 0, mkey);
+    krb5_free_keyblock_contents(context, &key);
+  out:
+    krb5_storage_free(sp);
+    close(fd);
+    return ret;
+}
+
+/* read an old master key file */
+static krb5_error_code
+read_master_encryptionkey(krb5_context context, const char *filename, 
+                         hdb_master_key *mkey)
+{
+    int fd;
+    krb5_keyblock key;
+    krb5_error_code ret;
+    unsigned char buf[256];
+    ssize_t len;
+    size_t ret_len;
+              
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if(fd < 0) {
+       int save_errno = errno;
+       krb5_set_error_string(context, "failed to open %s: %s", 
+                             filename, strerror(save_errno));
+       return save_errno;
+    }
+    
+    len = read(fd, buf, sizeof(buf));
+    close(fd);
+    if(len < 0) {
+       int save_errno = errno;
+       krb5_set_error_string(context, "error reading %s: %s", 
+                             filename, strerror(save_errno));
+       return save_errno;
+    }
+
+    ret = decode_EncryptionKey(buf, len, &key, &ret_len);
+    memset(buf, 0, sizeof(buf));
+    if(ret)
+       return ret;
+
+    /* Originally, the keytype was just that, and later it got changed
+       to des-cbc-md5, but we always used des in cfb64 mode. This
+       should cover all cases, but will break if someone has hacked
+       this code to really use des-cbc-md5 -- but then that's not my
+       problem. */
+    if(key.keytype == KEYTYPE_DES || key.keytype == ETYPE_DES_CBC_MD5)
+       key.keytype = ETYPE_DES_CFB64_NONE;
+    
+    ret = hdb_process_master_key(context, 0, &key, 0, mkey);
+    krb5_free_keyblock_contents(context, &key);
+    return ret;
+}
+
+/* read a krb4 /.k style file */
+static krb5_error_code
+read_master_krb4(krb5_context context, const char *filename, 
+                hdb_master_key *mkey)
+{
+    int fd;
+    krb5_keyblock key;
+    krb5_error_code ret;
+    unsigned char buf[256];
+    ssize_t len;
+              
+    fd = open(filename, O_RDONLY | O_BINARY);
+    if(fd < 0) {
+       int save_errno = errno;
+       krb5_set_error_string(context, "failed to open %s: %s", 
+                             filename, strerror(save_errno));
+       return save_errno;
+    }
+    
+    len = read(fd, buf, sizeof(buf));
+    close(fd);
+    if(len < 0) {
+       int save_errno = errno;
+       krb5_set_error_string(context, "error reading %s: %s", 
+                             filename, strerror(save_errno));
+       return save_errno;
+    }
+    if(len != 8) {
+       krb5_set_error_string(context, "bad contents of %s", filename);
+       return HEIM_ERR_EOF; /* XXX file might be too large */
+    }
+
+    memset(&key, 0, sizeof(key));
+    key.keytype = ETYPE_DES_PCBC_NONE;
+    ret = krb5_data_copy(&key.keyvalue, buf, len);
+    memset(buf, 0, sizeof(buf));
+    if(ret) 
+       return ret;
+
+    ret = hdb_process_master_key(context, 0, &key, 0, mkey);
+    krb5_free_keyblock_contents(context, &key);
+    return ret;
+}
+
+krb5_error_code
+hdb_read_master_key(krb5_context context, const char *filename, 
+                   hdb_master_key *mkey)
+{
+    FILE *f;
+    unsigned char buf[16];
+    krb5_error_code ret;
+
+    off_t len;
+
+    *mkey = NULL;
+
+    if(filename == NULL)
+       filename = HDB_DB_DIR "/m-key";
+
+    f = fopen(filename, "r");
+    if(f == NULL) {
+       int save_errno = errno;
+       krb5_set_error_string(context, "failed to open %s: %s", 
+                             filename, strerror(save_errno));
+       return save_errno;
+    }
+    
+    if(fread(buf, 1, 2, f) != 2) {
+       krb5_set_error_string(context, "end of file reading %s", filename);
+       fclose(f);
+       return HEIM_ERR_EOF;
+    }
+    
+    fseek(f, 0, SEEK_END);
+    len = ftello(f);
+
+    if(fclose(f) != 0)
+       return errno;
+    
+    if(len < 0)
+       return errno;
+    
+    if(len == 8) {
+       ret = read_master_krb4(context, filename, mkey);
+    } else if(buf[0] == 0x30 && len <= 127 && buf[1] == len - 2) {
+       ret = read_master_encryptionkey(context, filename, mkey);
+    } else if(buf[0] == 5 && buf[1] >= 1 && buf[1] <= 2) {
+       ret = read_master_keytab(context, filename, mkey);
+    } else {
+       ret = read_master_mit(context, filename, mkey);
+    }
+    return ret;
+}
+
+krb5_error_code
+hdb_write_master_key(krb5_context context, const char *filename, 
+                    hdb_master_key mkey)
+{
+    krb5_error_code ret;
+    hdb_master_key p;
+    krb5_keytab kt;
+
+    if(filename == NULL)
+       filename = HDB_DB_DIR "/m-key";
+
+    ret = krb5_kt_resolve(context, filename, &kt);
+    if(ret)
+       return ret;
+
+    for(p = mkey; p; p = p->next) {
+       ret = krb5_kt_add_entry(context, kt, &p->keytab);
+    }
+
+    krb5_kt_close(context, kt);
+
+    return ret;
+}
+
+static hdb_master_key
+find_master_key(Key *key, hdb_master_key mkey)
+{
+    hdb_master_key ret = NULL;
+    while(mkey) {
+       if(ret == NULL && mkey->keytab.vno == 0)
+           ret = mkey;
+       if(key->mkvno == NULL) {
+           if(ret == NULL || mkey->keytab.vno > ret->keytab.vno)
+               ret = mkey;
+       } else if(mkey->keytab.vno == *key->mkvno)
+           return mkey;
+       mkey = mkey->next;
+    }
+    return ret;
+}
+
+krb5_error_code
+hdb_unseal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey) 
+{
+       
+    krb5_error_code ret;
+    krb5_data res;
+    size_t keysize;
+
+    hdb_master_key key;
+
+    if(k->mkvno == NULL)
+       return 0;
+       
+    key = find_master_key(k, mkey);
+
+    if (key == NULL)
+       return HDB_ERR_NO_MKEY;
+
+    ret = krb5_decrypt(context, key->crypto, HDB_KU_MKEY,
+                      k->key.keyvalue.data,
+                      k->key.keyvalue.length,
+                      &res);
+    if (ret)
+       return ret;
+
+    /* fixup keylength if the key got padded when encrypting it */
+    ret = krb5_enctype_keysize(context, k->key.keytype, &keysize);
+    if (ret) {
+       krb5_data_free(&res);
+       return ret;
+    }
+    if (keysize > res.length) {
+       krb5_data_free(&res);
+       return KRB5_BAD_KEYSIZE;
+    }
+
+    memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
+    free(k->key.keyvalue.data);
+    k->key.keyvalue = res;
+    k->key.keyvalue.length = keysize;
+    free(k->mkvno);
+    k->mkvno = NULL;
+
+    return 0;
+}
+
+krb5_error_code
+hdb_unseal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+{
+    int i;
+
+    for(i = 0; i < ent->keys.len; i++){
+       krb5_error_code ret;
+
+       ret = hdb_unseal_key_mkey(context, &ent->keys.val[i], mkey);
+       if (ret) 
+           return ret;
+    }
+    return 0;
+}
+
+krb5_error_code
+hdb_unseal_keys(krb5_context context, HDB *db, hdb_entry *ent)
+{
+    if (db->hdb_master_key_set == 0)
+       return 0;
+    return hdb_unseal_keys_mkey(context, ent, db->hdb_master_key);
+}
+
+krb5_error_code
+hdb_unseal_key(krb5_context context, HDB *db, Key *k)
+{
+    if (db->hdb_master_key_set == 0)
+       return 0;
+    return hdb_unseal_key_mkey(context, k, db->hdb_master_key);
+}
+
+krb5_error_code
+hdb_seal_key_mkey(krb5_context context, Key *k, hdb_master_key mkey)
+{
+    krb5_error_code ret;
+    krb5_data res;
+    hdb_master_key key;
+
+    if(k->mkvno != NULL)
+       return 0;
+
+    key = find_master_key(k, mkey);
+
+    if (key == NULL)
+       return HDB_ERR_NO_MKEY;
+
+    ret = krb5_encrypt(context, key->crypto, HDB_KU_MKEY,
+                      k->key.keyvalue.data,
+                      k->key.keyvalue.length,
+                      &res);
+    if (ret)
+       return ret;
+
+    memset(k->key.keyvalue.data, 0, k->key.keyvalue.length);
+    free(k->key.keyvalue.data);
+    k->key.keyvalue = res;
+
+    k->mkvno = malloc(sizeof(*k->mkvno));
+    if (k->mkvno == NULL)
+       return ENOMEM;
+    *k->mkvno = key->keytab.vno;
+       
+    return 0;
+}
+
+krb5_error_code
+hdb_seal_keys_mkey(krb5_context context, hdb_entry *ent, hdb_master_key mkey)
+{
+    int i;
+    for(i = 0; i < ent->keys.len; i++){
+       krb5_error_code ret;
+
+       ret = hdb_seal_key_mkey(context, &ent->keys.val[i], mkey);
+       if (ret)
+           return ret;
+    }
+    return 0;
+}
+
+krb5_error_code
+hdb_seal_keys(krb5_context context, HDB *db, hdb_entry *ent)
+{
+    if (db->hdb_master_key_set == 0)
+       return 0;
+    
+    return hdb_seal_keys_mkey(context, ent, db->hdb_master_key);
+}
+
+krb5_error_code
+hdb_seal_key(krb5_context context, HDB *db, Key *k)
+{
+    if (db->hdb_master_key_set == 0)
+       return 0;
+    
+    return hdb_seal_key_mkey(context, k, db->hdb_master_key);
+}
+
+krb5_error_code
+hdb_set_master_key (krb5_context context,
+                   HDB *db,
+                   krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    hdb_master_key mkey;
+
+    ret = hdb_process_master_key(context, 0, key, 0, &mkey);
+    if (ret)
+       return ret;
+    db->hdb_master_key = mkey;
+#if 0 /* XXX - why? */
+    des_set_random_generator_seed(key.keyvalue.data);
+#endif
+    db->hdb_master_key_set = 1;
+    return 0;
+}
+
+krb5_error_code
+hdb_set_master_keyfile (krb5_context context,
+                       HDB *db,
+                       const char *keyfile)
+{
+    hdb_master_key key;
+    krb5_error_code ret;
+
+    ret = hdb_read_master_key(context, keyfile, &key);
+    if (ret) {
+       if (ret != ENOENT)
+           return ret;
+       krb5_clear_error_string(context);
+       return 0;
+    }
+    db->hdb_master_key = key;
+    db->hdb_master_key_set = 1;
+    return ret;
+}
+
+krb5_error_code
+hdb_clear_master_key (krb5_context context,
+                     HDB *db)
+{
+    if (db->hdb_master_key_set) {
+       hdb_free_master_key(context, db->hdb_master_key);
+       db->hdb_master_key_set = 0;
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/hdb/ndbm.c b/src/kerberosV/src/lib/hdb/ndbm.c
new file mode 100644 (file)
index 0000000..ec93214
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "hdb_locl.h"
+
+RCSID("$KTH: ndbm.c,v 1.34 2003/09/19 00:20:43 lha Exp $");
+
+#if HAVE_NDBM
+
+#if defined(HAVE_GDBM_NDBM_H)
+#include <gdbm/ndbm.h>
+#elif defined(HAVE_NDBM_H)
+#include <ndbm.h>
+#elif defined(HAVE_DBM_H)
+#include <dbm.h>
+#endif
+
+struct ndbm_db {
+    DBM *db;
+    int lock_fd;
+};
+
+static krb5_error_code
+NDBM_destroy(krb5_context context, HDB *db)
+{
+    krb5_error_code ret;
+
+    ret = hdb_clear_master_key (context, db);
+    free(db->hdb_name);
+    free(db);
+    return 0;
+}
+
+static krb5_error_code
+NDBM_lock(krb5_context context, HDB *db, int operation)
+{
+    struct ndbm_db *d = db->hdb_db;
+    return hdb_lock(d->lock_fd, operation);
+}
+
+static krb5_error_code
+NDBM_unlock(krb5_context context, HDB *db)
+{
+    struct ndbm_db *d = db->hdb_db;
+    return hdb_unlock(d->lock_fd);
+}
+
+static krb5_error_code
+NDBM_seq(krb5_context context, HDB *db, 
+        unsigned flags, hdb_entry *entry, int first)
+
+{
+    struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
+    datum key, value;
+    krb5_data key_data, data;
+    krb5_error_code ret = 0;
+
+    if(first)
+       key = dbm_firstkey(d->db);
+    else
+       key = dbm_nextkey(d->db);
+    if(key.dptr == NULL)
+       return HDB_ERR_NOENTRY;
+    key_data.data = key.dptr;
+    key_data.length = key.dsize;
+    ret = db->hdb_lock(context, db, HDB_RLOCK);
+    if(ret) return ret;
+    value = dbm_fetch(d->db, key);
+    db->hdb_unlock(context, db);
+    data.data = value.dptr;
+    data.length = value.dsize;
+    if(hdb_value2entry(context, &data, entry))
+       return NDBM_seq(context, db, flags, entry, 0);
+    if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) {
+       ret = hdb_unseal_keys (context, db, entry);
+       if (ret)
+           hdb_free_entry (context, entry);
+    }
+    if (entry->principal == NULL) {
+       entry->principal = malloc (sizeof(*entry->principal));
+       if (entry->principal == NULL) {
+           ret = ENOMEM;
+           hdb_free_entry (context, entry);
+           krb5_set_error_string(context, "malloc: out of memory");
+       } else {
+           hdb_key2principal (context, &key_data, entry->principal);
+       }
+    }
+    return ret;
+}
+
+
+static krb5_error_code
+NDBM_firstkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    return NDBM_seq(context, db, flags, entry, 1);
+}
+
+
+static krb5_error_code
+NDBM_nextkey(krb5_context context, HDB *db, unsigned flags, hdb_entry *entry)
+{
+    return NDBM_seq(context, db, flags, entry, 0);
+}
+
+static krb5_error_code
+NDBM_rename(krb5_context context, HDB *db, const char *new_name)
+{
+    /* XXX this function will break */
+    struct ndbm_db *d = db->hdb_db;
+
+    int ret;
+    char *old_dir, *old_pag, *new_dir, *new_pag;
+    char *new_lock;
+    int lock_fd;
+
+    /* lock old and new databases */
+    ret = db->hdb_lock(context, db, HDB_WLOCK);
+    if(ret)
+       return ret;
+    asprintf(&new_lock, "%s.lock", new_name);
+    if(new_lock == NULL) {
+       db->hdb_unlock(context, db);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    lock_fd = open(new_lock, O_RDWR | O_CREAT, 0600);
+    if(lock_fd < 0) {
+       ret = errno;
+       db->hdb_unlock(context, db);
+       krb5_set_error_string(context, "open(%s): %s", new_lock,
+                             strerror(ret));
+       free(new_lock);
+       return ret;
+    }
+    free(new_lock);
+    ret = hdb_lock(lock_fd, HDB_WLOCK);
+    if(ret) {
+       db->hdb_unlock(context, db);
+       close(lock_fd);
+       return ret;
+    }
+
+    asprintf(&old_dir, "%s.dir", db->hdb_name);
+    asprintf(&old_pag, "%s.pag", db->hdb_name);
+    asprintf(&new_dir, "%s.dir", new_name);
+    asprintf(&new_pag, "%s.pag", new_name);
+
+    ret = rename(old_dir, new_dir) || rename(old_pag, new_pag);
+    free(old_dir);
+    free(old_pag);
+    free(new_dir);
+    free(new_pag);
+    hdb_unlock(lock_fd);
+    db->hdb_unlock(context, db);
+
+    if(ret) {
+       ret = errno;
+       close(lock_fd);
+       krb5_set_error_string(context, "rename: %s", strerror(ret));
+       return ret;
+    }
+
+    close(d->lock_fd);
+    d->lock_fd = lock_fd;
+    
+    free(db->hdb_name);
+    db->hdb_name = strdup(new_name);
+    return 0;
+}
+
+static krb5_error_code
+NDBM__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply)
+{
+    struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
+    datum k, v;
+    int code;
+
+    k.dptr  = key.data;
+    k.dsize = key.length;
+    code = db->hdb_lock(context, db, HDB_RLOCK);
+    if(code)
+       return code;
+    v = dbm_fetch(d->db, k);
+    db->hdb_unlock(context, db);
+    if(v.dptr == NULL)
+       return HDB_ERR_NOENTRY;
+
+    krb5_data_copy(reply, v.dptr, v.dsize);
+    return 0;
+}
+
+static krb5_error_code
+NDBM__put(krb5_context context, HDB *db, int replace, 
+       krb5_data key, krb5_data value)
+{
+    struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
+    datum k, v;
+    int code;
+
+    k.dptr  = key.data;
+    k.dsize = key.length;
+    v.dptr  = value.data;
+    v.dsize = value.length;
+
+    code = db->hdb_lock(context, db, HDB_WLOCK);
+    if(code)
+       return code;
+    code = dbm_store(d->db, k, v, replace ? DBM_REPLACE : DBM_INSERT);
+    db->hdb_unlock(context, db);
+    if(code == 1)
+       return HDB_ERR_EXISTS;
+    if (code < 0)
+       return code;
+    return 0;
+}
+
+static krb5_error_code
+NDBM__del(krb5_context context, HDB *db, krb5_data key)
+{
+    struct ndbm_db *d = (struct ndbm_db *)db->hdb_db;
+    datum k;
+    int code;
+    krb5_error_code ret;
+
+    k.dptr = key.data;
+    k.dsize = key.length;
+    ret = db->hdb_lock(context, db, HDB_WLOCK);
+    if(ret) return ret;
+    code = dbm_delete(d->db, k);
+    db->hdb_unlock(context, db);
+    if(code < 0)
+       return errno;
+    return 0;
+}
+
+static krb5_error_code
+NDBM_open(krb5_context context, HDB *db, int flags, mode_t mode)
+{
+    krb5_error_code ret;
+    struct ndbm_db *d = malloc(sizeof(*d));
+    char *lock_file;
+
+    if(d == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    asprintf(&lock_file, "%s.lock", (char*)db->hdb_name);
+    if(lock_file == NULL) {
+       free(d);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    d->db = dbm_open((char*)db->hdb_name, flags, mode);
+    if(d->db == NULL){
+       ret = errno;
+       free(d);
+       free(lock_file);
+       krb5_set_error_string(context, "dbm_open(%s): %s", db->hdb_name,
+                             strerror(ret));
+       return ret;
+    }
+    d->lock_fd = open(lock_file, O_RDWR | O_CREAT, 0600);
+    if(d->lock_fd < 0){
+       ret = errno;
+       dbm_close(d->db);
+       free(d);
+       krb5_set_error_string(context, "open(%s): %s", lock_file,
+                             strerror(ret));
+       free(lock_file);
+       return ret;
+    }
+    free(lock_file);
+    db->hdb_db = d;
+    if((flags & O_ACCMODE) == O_RDONLY)
+       ret = hdb_check_db_format(context, db);
+    else
+       ret = hdb_init_db(context, db);
+    if(ret == HDB_ERR_NOENTRY)
+       return 0;
+    return ret;
+}
+
+static krb5_error_code
+NDBM_close(krb5_context context, HDB *db)
+{
+    struct ndbm_db *d = db->hdb_db;
+    dbm_close(d->db);
+    close(d->lock_fd);
+    free(d);
+    return 0;
+}
+
+krb5_error_code
+hdb_ndbm_create(krb5_context context, HDB **db, 
+               const char *filename)
+{
+    *db = malloc(sizeof(**db));
+    if (*db == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    (*db)->hdb_db = NULL;
+    (*db)->hdb_name = strdup(filename);
+    if ((*db)->hdb_name == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free(*db);
+       *db = NULL;
+       return ENOMEM;
+    }
+    (*db)->hdb_master_key_set = 0;
+    (*db)->hdb_openp = 0;
+    (*db)->hdb_open = NDBM_open;
+    (*db)->hdb_close = NDBM_close;
+    (*db)->hdb_fetch = _hdb_fetch;
+    (*db)->hdb_store = _hdb_store;
+    (*db)->hdb_remove = _hdb_remove;
+    (*db)->hdb_firstkey = NDBM_firstkey;
+    (*db)->hdb_nextkey= NDBM_nextkey;
+    (*db)->hdb_lock = NDBM_lock;
+    (*db)->hdb_unlock = NDBM_unlock;
+    (*db)->hdb_rename = NDBM_rename;
+    (*db)->hdb__get = NDBM__get;
+    (*db)->hdb__put = NDBM__put;
+    (*db)->hdb__del = NDBM__del;
+    (*db)->hdb_destroy = NDBM_destroy;
+    return 0;
+}
+
+#endif /* HAVE_NDBM */
diff --git a/src/kerberosV/src/lib/hdb/print.c b/src/kerberosV/src/lib/hdb/print.c
new file mode 100644 (file)
index 0000000..93a7c46
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1999-2002 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. */
+
+#include "hdb_locl.h"
+#include <ctype.h>
+
+RCSID("$KTH: print.c,v 1.8 2002/05/24 15:18:02 joda Exp $");
+
+/* 
+   This is the present contents of a dump line. This might change at
+   any time. Fields are separated by white space.
+
+  principal
+  keyblock
+       kvno
+       keys...
+               mkvno
+               enctype
+               keyvalue
+               salt (- means use normal salt)
+  creation date and principal
+  modification date and principal
+  principal valid from date (not used)
+  principal valid end date (not used)
+  principal key expires (not used)
+  max ticket life
+  max renewable life
+  flags
+  generation number
+  */
+
+static krb5_error_code
+append_string(krb5_context context, krb5_storage *sp, const char *fmt, ...)
+{
+    krb5_error_code ret;
+    char *s;
+    va_list ap;
+    va_start(ap, fmt);
+    vasprintf(&s, fmt, ap);
+    va_end(ap);
+    if(s == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = krb5_storage_write(sp, s, strlen(s));
+    free(s);
+    return ret;
+}
+
+static krb5_error_code
+append_hex(krb5_context context, krb5_storage *sp, krb5_data *data)
+{
+    int i, printable = 1;
+    char *p;
+
+    p = data->data;
+    for(i = 0; i < data->length; i++)
+       if(!isalnum((unsigned char)p[i]) && p[i] != '.'){
+           printable = 0;
+           break;
+       }
+    if(printable)
+       return append_string(context, sp, "\"%.*s\"",
+                            data->length, data->data);
+    for(i = 0; i < data->length; i++) 
+       append_string(context, sp, "%02x", ((unsigned char*)data->data)[i]);
+    return 0;
+}
+
+static char *
+time2str(time_t t)
+{
+    static char buf[128];
+    strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", gmtime(&t));
+    return buf;
+}
+
+static krb5_error_code
+append_event(krb5_context context, krb5_storage *sp, Event *ev)
+{
+    char *pr = NULL;
+    krb5_error_code ret;
+    if(ev == NULL)
+       return append_string(context, sp, "- ");
+    if (ev->principal != NULL) {
+       ret = krb5_unparse_name(context, ev->principal, &pr);
+       if(ret)
+           return ret;
+    }
+    ret = append_string(context, sp, "%s:%s ",
+                       time2str(ev->time), pr ? pr : "UNKNOWN");
+    free(pr);
+    return ret;
+}
+
+static krb5_error_code
+entry2string_int (krb5_context context, krb5_storage *sp, hdb_entry *ent)
+{
+    char *p;
+    int i;
+    krb5_error_code ret;
+
+    /* --- principal */
+    ret = krb5_unparse_name(context, ent->principal, &p);
+    if(ret)
+       return ret;
+    append_string(context, sp, "%s ", p);
+    free(p);
+    /* --- kvno */
+    append_string(context, sp, "%d", ent->kvno);
+    /* --- keys */
+    for(i = 0; i < ent->keys.len; i++){
+       /* --- mkvno, keytype */
+       if(ent->keys.val[i].mkvno)
+           append_string(context, sp, ":%d:%d:", 
+                         *ent->keys.val[i].mkvno, 
+                         ent->keys.val[i].key.keytype);
+       else
+           append_string(context, sp, "::%d:", 
+                         ent->keys.val[i].key.keytype);
+       /* --- keydata */
+       append_hex(context, sp, &ent->keys.val[i].key.keyvalue);
+       append_string(context, sp, ":");
+       /* --- salt */
+       if(ent->keys.val[i].salt){
+           append_string(context, sp, "%u/", ent->keys.val[i].salt->type);
+           append_hex(context, sp, &ent->keys.val[i].salt->salt);
+       }else
+           append_string(context, sp, "-");
+    }
+    append_string(context, sp, " ");
+    /* --- created by */
+    append_event(context, sp, &ent->created_by);
+    /* --- modified by */
+    append_event(context, sp, ent->modified_by);
+
+    /* --- valid start */
+    if(ent->valid_start)
+       append_string(context, sp, "%s ", time2str(*ent->valid_start));
+    else
+       append_string(context, sp, "- ");
+
+    /* --- valid end */
+    if(ent->valid_end)
+       append_string(context, sp, "%s ", time2str(*ent->valid_end));
+    else
+       append_string(context, sp, "- ");
+    
+    /* --- password ends */
+    if(ent->pw_end)
+       append_string(context, sp, "%s ", time2str(*ent->pw_end));
+    else
+       append_string(context, sp, "- ");
+
+    /* --- max life */
+    if(ent->max_life)
+       append_string(context, sp, "%d ", *ent->max_life);
+    else
+       append_string(context, sp, "- ");
+
+    /* --- max renewable life */
+    if(ent->max_renew)
+       append_string(context, sp, "%d ", *ent->max_renew);
+    else
+       append_string(context, sp, "- ");
+    
+    /* --- flags */
+    append_string(context, sp, "%d ", HDBFlags2int(ent->flags));
+
+    /* --- generation number */
+    if(ent->generation) {
+       append_string(context, sp, "%s:%d:%d", time2str(ent->generation->time),
+                     ent->generation->usec,
+                     ent->generation->gen);
+    } else
+       append_string(context, sp, "-");
+    
+    return 0;
+}
+
+krb5_error_code
+hdb_entry2string (krb5_context context, hdb_entry *ent, char **str)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    krb5_storage *sp;
+
+    sp = krb5_storage_emem();
+    if(sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    
+    ret = entry2string_int(context, sp, ent);
+    if(ret) {
+       krb5_storage_free(sp);
+       return ret;
+    }
+
+    krb5_storage_write(sp, "\0", 1);
+    krb5_storage_to_data(sp, &data);
+    krb5_storage_free(sp);
+    *str = data.data;
+    return 0;
+}
+
+/* print a hdb_entry to (FILE*)data; suitable for hdb_foreach */
+
+krb5_error_code
+hdb_print_entry(krb5_context context, HDB *db, hdb_entry *entry, void *data)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+
+    FILE *f = data;
+
+    fflush(f);
+    sp = krb5_storage_from_fd(fileno(f));
+    if(sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    
+    ret = entry2string_int(context, sp, entry);
+    if(ret) {
+       krb5_storage_free(sp);
+       return ret;
+    }
+
+    krb5_storage_write(sp, "\n", 1);
+    krb5_storage_free(sp);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/CVS/Entries b/src/kerberosV/src/lib/kadm5/CVS/Entries
new file mode 100644 (file)
index 0000000..6789822
--- /dev/null
@@ -0,0 +1,63 @@
+/ChangeLog/1.1.1.6/Fri Apr 14 07:33:04 2006//
+/acl.c/1.1.1.3/Fri Apr 14 07:33:04 2006//
+/ad.c/1.1.1.1/Fri Apr 14 07:33:05 2006//
+/admin.h/1.1.1.2/Fri Apr 14 07:33:05 2006//
+/bump_pw_expire.c/1.1.1.1/Fri May 25 07:50:22 2001//
+/check-cracklib.pl/1.1.1.1/Fri Apr 14 07:33:05 2006//
+/chpass_c.c/1.1.1.1/Fri May 25 07:50:22 2001//
+/chpass_s.c/1.1.1.3/Fri Apr 14 07:33:05 2006//
+/client_glue.c/1.1.1.1/Fri May 25 07:50:22 2001//
+/common_glue.c/1.1.1.1/Fri May 25 07:50:22 2001//
+/context_s.c/1.1.1.3/Sun May 11 02:15:44 2003//
+/create_c.c/1.1.1.1/Fri May 25 07:50:23 2001//
+/create_s.c/1.1.1.2/Fri Apr 14 07:33:05 2006//
+/default_keys.c/1.1.1.1/Fri Apr 14 07:33:05 2006//
+/delete_c.c/1.1.1.1/Fri May 25 07:50:23 2001//
+/delete_s.c/1.1.1.2/Fri Apr 14 07:33:05 2006//
+/destroy_c.c/1.1.1.2/Fri Apr 14 07:33:05 2006//
+/destroy_s.c/1.1.1.2/Fri Apr 14 07:33:05 2006//
+/dump_log.c/1.4/Fri Apr 14 08:15:04 2006//
+/ent_setup.c/1.1.1.2/Fri Apr 14 07:33:06 2006//
+/error.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/flush.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/flush_c.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/flush_s.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/free.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/get_c.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/get_princs_c.c/1.1.1.1/Fri May 25 07:50:24 2001//
+/get_princs_s.c/1.1.1.2/Fri Apr 14 07:33:06 2006//
+/get_s.c/1.1.1.2/Fri Apr 14 07:33:06 2006//
+/init_c.c/1.2/Fri Oct  6 07:09:10 2006//
+/init_s.c/1.1.1.1/Fri May 25 07:50:25 2001//
+/iprop.8/1.2/Fri Sep 14 15:42:34 2007//
+/iprop.h/1.4/Fri Apr 14 08:15:04 2006//
+/ipropd_master.c/1.6/Mon Dec 18 21:08:28 2006//
+/ipropd_slave.c/1.7/Fri Apr 14 08:15:04 2006//
+/kadm5-private.h/1.1.1.3/Fri Apr 14 07:33:09 2006//
+/kadm5-protos.h/1.1.1.3/Fri Apr 14 07:33:09 2006//
+/kadm5-pwcheck.h/1.1.1.1/Fri Apr 14 07:33:07 2006//
+/kadm5_err.et/1.1.1.3/Fri Apr 14 07:33:07 2006//
+/kadm5_locl.h/1.2/Mon Jul 14 16:14:44 2003//
+/kadm5_pwcheck.3/1.1.1.1/Fri Apr 14 07:33:07 2006//
+/keys.c/1.1.1.2/Fri Apr 14 07:33:07 2006//
+/log.c/1.2/Fri Oct  6 07:09:10 2006//
+/marshall.c/1.1.1.1/Fri May 25 07:50:28 2001//
+/modify_c.c/1.1.1.1/Fri May 25 07:50:28 2001//
+/modify_s.c/1.1.1.2/Fri Apr 14 07:33:08 2006//
+/password_quality.c/1.1.1.2/Fri Apr 14 07:33:08 2006//
+/private.h/1.1.1.3/Fri Apr 14 07:33:08 2006//
+/privs_c.c/1.1.1.1/Fri May 25 07:50:29 2001//
+/privs_s.c/1.1.1.1/Fri May 25 07:50:29 2001//
+/randkey_c.c/1.1.1.1/Fri May 25 07:50:29 2001//
+/randkey_s.c/1.1.1.2/Fri Apr 14 07:33:08 2006//
+/rename_c.c/1.1.1.1/Fri May 25 07:50:29 2001//
+/rename_s.c/1.1.1.2/Fri Apr 14 07:33:09 2006//
+/replay_log.c/1.1.1.4/Fri Apr 14 07:33:09 2006//
+/sample_passwd_check.c/1.1.1.1/Fri May 25 07:50:29 2001//
+/send_recv.c/1.1.1.2/Sun May 11 02:15:46 2003//
+/server_glue.c/1.1.1.1/Fri May 25 07:50:30 2001//
+/set_keys.c/1.1.1.3/Fri Apr 14 07:33:09 2006//
+/set_modifier.c/1.1.1.1/Fri May 25 07:50:30 2001//
+/test_pw_quality.c/1.1.1.1/Fri Apr 14 07:33:09 2006//
+/truncate_log.c/1.1.1.3/Fri Apr 14 07:33:09 2006//
+D
diff --git a/src/kerberosV/src/lib/kadm5/CVS/Repository b/src/kerberosV/src/lib/kadm5/CVS/Repository
new file mode 100644 (file)
index 0000000..d2eaa49
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/kadm5
diff --git a/src/kerberosV/src/lib/kadm5/CVS/Root b/src/kerberosV/src/lib/kadm5/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/kadm5/ChangeLog b/src/kerberosV/src/lib/kadm5/ChangeLog
new file mode 100644 (file)
index 0000000..d2be23b
--- /dev/null
@@ -0,0 +1,972 @@
+2006-02-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kadm5_err.et: 1.7: (PASS_REUSE): Spelling, from Václav H?la
+       <ax@natur.cuni.cz>
+       
+2005-05-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ent_setup.c (attr_to_flags): check for KRB5_KDB_OK_AS_DELEGATE
+       
+       * get_s.c (kadm5_s_get_principal): set KRB5_KDB_OK_AS_DELEGATE
+
+       * admin.h: add KRB5_KDB_OK_AS_DELEGATE, sync KRB5_TL_ flags
+
+2005-05-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kadm5_pwcheck.3: please mdoclint
+
+2005-05-25  Dave Love  <fx@gnu.org>
+
+       * kadm5_pwcheck.3: document kadm5_add_passwd_quality_verifier,
+       improve text
+
+2005-05-24  Dave Love  <fx@gnu.org>
+
+       * iprop.8: Added some info about defaults, fixed some markup.
+       
+2005-05-23  Dave Love  <fx@gnu.org>
+
+       * ipropd_slave.c: Don't test HAVE_DAEMON since roken supplies it.
+
+       * ipropd_master.c: Don't test HAVE_DAEMON since roken supplies it.
+
+2005-05-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_c.c (_kadm5_c_init_context): fix memory leak in case of
+       failure
+
+2005-05-09  Dave Love  <fx@gnu.org>
+
+       * password_quality.c (find_func): Fix off-by-one and logic error.
+       (external_passwd_quality): Improve messages.
+
+       * test_pw_quality.c (main): Call kadm5_setup_passwd_quality_check
+       and kadm5_add_passwd_quality_verifier.
+
+2005-04-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * default_keys.c: #include <err.h>, only print salt it its longer
+       then 0, use krb5_err instead of errx where appropriate
+       
+2005-04-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ipropd_slave.c: add the documented option --port
+
+       * ipropd_master.c: add the documented option --port
+       
+       * dump_log.c: use the newly generated units function
+
+2005-04-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * dump_log.c: use strlcpy
+       
+       * password_quality.c: don't use sizeof(pointer)
+       
+2005-04-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * check-cracklib.pl: external password verifier sample
+
+       * password_quality.c (kadm5_add_passwd_quality_verifier): if NULL
+       is passed in, load defaults
+
+2005-04-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * password_quality.c: add an end tag to the external password
+       quality check protocol
+
+2005-04-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * password_quality.c: add external passsword quality check builtin
+       module
+       
+       [password_quality]
+               policies = external-check
+               external-program = /bin/false
+       
+       To approve password a, make the test program return APPROVED on
+       stderr and fail with exit code 0.
+       
+2004-10-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: bump version to 7:7:0 and 6:5:2
+       
+       * default_keys.c (parse_file): use hdb_generate_key_set
+       
+       * keys.c,set_keys.c: Move keyset parsing and password based keyset
+       generation into hdb.  Requested by Andrew Bartlett <abartlet@samba.org>
+       for hdb-ldb backend.
+       
+2004-09-23  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_master.c: add help strings to some options
+       
+2004-09-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * chpass_s.c: deal with changed prototype for _kadm5_free_keys
+       
+       * keys.c (_kadm5_free_keys): change prototype, make it use
+       krb5_context instead of a kadm5_server_context
+       
+       * set_keys.c (parse_key_set): do way with static returning
+       (function) static variable and returned allocated memory
+       (_kadm5_generate_key_set): free enctypes returned by parse_key_set
+
+2004-09-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c: Fix memory leak, don't return stack variables From
+       Andrew Bartlett
+       
+       * set_keys.c: make all_etypes const and move outside function to
+       avoid returning data on stack
+       
+2004-08-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * acl.c (fetch_acl): use " \t\n" instead of just "\n" for the
+       delim of the third element, this is so we can match
+       "foo@REALM<SPC>all<SPC><SPC>*@REALM", before it just matched
+       "foo@REALM<SPC>all<SPC>*@REALM", but that is kind of lucky since
+       what really happen was that the last <SPC> was stamped out, and
+       the it never strtok_r never needed to parse over it.
+       
+2004-08-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c (_kadm5_generate_key_set): since arcfour-hmac-md5 is
+       without salting, some people tries to add the string
+       "arcfour-hmac-md5" when they really should have used
+       "arcfour-hmac-md5:pw-salt", help them and add glue for that
+       
+2004-08-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_slave.c: add --detach
+
+2004-07-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: use new tsasl interface remove debug printf add upn to
+       computer-accounts
+       
+2004-06-28  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: implement kadm5_ad_init_with_password_ctx set more error
+       strings
+       
+2004-06-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: man_MANS = kadm5_pwcheck.3
+       
+       * kadm5_pwcheck.3: document new password quality api
+       
+       * password_quality.c: new password check interface (old still
+       supported)
+       
+       * kadm5-pwcheck.h: new password check interface
+       
+2004-06-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ipropd_master.c (main): process all slaves, not just up to the
+       last slave sending data
+       (bug report from Björn Sandell <biorn@dce.chalmers.se>)
+       (*): only send one ARE_YOU_THERE
+
+2004-06-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: use krb5_set_password_using_ccache
+       
+2004-06-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: try handle spn's better
+       
+2004-05-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: add expiration time
+       
+       * ad.c: add modify operations
+       
+       * ad.c: handle create and delete
+       
+2004-05-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: more code for get, handle attributes
+       
+       * ad.c: more code for get, handle time stamps and bad password
+       counter
+
+       * ad.c: more code for get, only fetches kvno for now
+       
+2004-05-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ad.c: add support for tsasl
+       
+       * private.h: add kadm5_ad_context
+       
+       * ipropd_master.c (prop_one): store the opcode in the begining of
+       the blob, not the end
+       
+       * ad.c: try all ldap servers in dns, generate a random password,
+       base64(random_block(64)), XXX must make it support other then
+       ARCFOUR
+       
+       * ad.c: framework for windows AD backend
+       
+2004-03-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * create_s.c (kadm5_s_create_principal): remove old XXX command
+       and related code, _kadm5_set_keys will do all this now
+       
+2004-02-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c (_kadm5_set_keys_randomly): make sure enctype to copy
+       enctype for des keys From: Andrew Bartlett <abartlet@samba.org>
+       
+       * create_s.c (kadm5_s_create_principal_with_key): don't call
+       _kadm5_set_keys2, create_principal will do that for us. Set kvno
+       to 1.
+
+       * chpass_s.c (change): bump kvno
+       (kadm5_s_chpass_principal_with_key): bump kvno
+
+       * randkey_s.c (kadm5_s_randkey_principal): bump kvno
+       
+       * set_keys.c (_kadm5_set_*): don't change the kvno, let the callee
+       to that
+
+2003-12-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * chpass_s.c (change): fix same-password-again by decrypting keys
+       and setting an error code From: Buck Huppmann <buckh@pobox.com>
+       
+2003-12-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_c.c (_kadm5_c_init_context): catch errors from strdup and
+       other krb5_ functions
+
+2003-12-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * rename_s.c (kadm5_s_rename_principal): allow principal to change
+       realm From Panasas Inc
+       
+2003-12-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * destroy_c.c (kadm5_c_destroy): fix memory leaks, From Panasas,
+       Inc
+
+2003-11-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * iprop.h: don't include <krb5-private.h>
+       
+       * ipropd_slave.c: stop using krb5 lib private byte-frobbing
+       functions and replace them with with krb5_storage
+       
+       * ipropd_master.c: stop using krb5 lib private byte-frobbing
+       functions and replace them with with krb5_storage
+       
+2003-11-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ipropd_slave.c (receive_loop): when seeking over the entries we
+       already have, skip over the trailer.  From: Jeffrey Hutzelman
+       <jhutz@cmu.edu>
+
+       * dump_log.c,ipropd_master.c,ipropd_slave.c,
+       replay_log.c,truncate_log.c: parse kdc.conf
+       From: Jeffrey Hutzelman <jhutz@cmu.edu>
+
+2003-10-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: += test_pw_quality
+       
+       * test_pw_quality.c: test program for verifying password quality
+       function
+
+2003-09-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: add and enable check program default_keys
+       
+       * default_keys.c: test program for _kadm5_generate_key_set
+       
+       * init_c.c: use
+       krb5_get_init_creds_opt_alloc/krb5_get_init_creds_opt_free
+
+2003-08-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c (_kadm5_set_keys_randomly): remove dup return
+       
+       * ipropd_master.c (main): make sure current_version is initialized
+       
+2003-08-15  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c: use default_keys for the both random keys and
+       password derived keys if its defined
+       
+2003-07-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ipropd_slave.c (receive_everything): switch close and rename
+       From: Alf Wachsmann <alfw@SLAC.Stanford.EDU>
+       
+2003-07-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * iprop.h, ipropd_master.c, ipropd_slave.c:
+       Add probing from the server that the client is still there, also
+       make the client check that the server is probing.
+
+2003-07-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * truncate_log.c (main): add missing ``if (ret)''
+       
+2003-06-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c (make_keys): add AES support
+       
+       * set_keys.c: fix off by one in the aes case, pointed out by Ken
+       Raeburn
+
+2003-04-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * set_keys.c (_kadm5_set_keys_randomly): add
+       ETYPE_AES256_CTS_HMAC_SHA1_96 key when configuried with aes
+       support
+
+2003-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * send_recv.c: check return values from krb5_data_alloc
+       * log.c: check return values from krb5_data_alloc
+       
+2003-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * dump_log.c (print_entry): check return values from
+       krb5_data_alloc
+
+2003-04-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * init_c.c (kadm_connect): if a context realm was passed in, use
+       that to form the kadmin/admin principal
+       
+2003-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ipropd_master.c (main): make sure we don't consider dead slave
+       for select processing
+       (write_stats): use slave_stats_file variable, 
+       check return value of strftime
+       (args): allow specifying slave stats file
+       (slave_dead): close the fd when the slave dies
+
+2002-10-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_slave.c (from Derrick Brashear): Propagating a large
+       database without this means the slave kdcs can get erroneous
+       HDB_NOENTRY and return the resulting errors. This creates a new db
+       handle, populates it, and moves it into place.
+
+2002-08-26  Assar Westerlund  <assar@kth.se>
+
+       * ipropd_slave.c (receive_everything): type-correctness calling
+       _krb5_get_int
+
+       * context_s.c (find_db_spec): const-correctness in parameters to
+       krb5_config_get_next
+
+2002-08-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * private.h: rename header file flag macro
+
+       * Makefile.am: generate kadm5-{protos,private}.h
+
+2002-08-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_master.c: check return value of krb5_sockaddr2address
+
+2002-07-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_master.c: handle slaves that come and go; add status
+       reporting (both from Love)
+
+       * iprop.h: KADM5_SLAVE_STATS
+
+2002-03-25  Jacques Vidrine  <n@nectar.com>
+
+       * init_c.c (get_cred_cache): bug fix: the default credentials
+       cache was not being used if a client name was specified.
+
+2002-03-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * init_c.c (get_cred_cache): when getting the default_client from
+       the cred cache, make sure the instance part is "admin"; this
+       should require fewer uses of -p
+
+2002-03-11  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5srv_la_LDFLAGS): set version to 7:5:0
+       (libkadm5clnt_la_LDFLAGS): set version to 6:3:2
+
+2002-02-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * init_c.c: we have to create our own param struct before
+       marshaling
+
+2001-09-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: link with LIB_pidfile
+
+       * iprop.h: include util.h for pidfile
+
+2001-08-31  Assar Westerlund  <assar@sics.se>
+
+       * ipropd_slave.c (main): syslog with the correct name
+
+2001-08-30  Jacques Vidrine <n@nectar.com>
+
+       * ipropd_slave.c, ipropd_master.c (main): call pidfile
+
+2001-08-28  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5srv_la_LDFLAGS): set version to 7:4:0
+
+2001-08-24  Assar Westerlund  <assar@sics.se>
+
+       * acl.c (fetch_acl): do not return bogus flags and re-organize
+       function
+
+       * Makefile.am: rename variable name to avoid error from current
+       automake
+
+2001-08-13  Johan Danielsson  <joda@pdc.kth.se>
+
+       * set_keys.c: add easier afs configuration, defaulting to the
+       local realm in lower case; also try to remove duplicate salts
+
+2001-07-12  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add required library dependencies
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5clnt_la_LDFLAGS): set version to 6:2:2
+
+2001-06-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * init_c.c: call krb5_get_init_creds_opt_set_default_flags
+
+2001-02-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * replay_log.c: add --{start-end}-version flags to replay just
+       part of the log
+
+2001-02-15  Assar Westerlund  <assar@sics.se>
+
+       * ipropd_master.c (main): fix select-loop to decrement ret
+       correctly.  from "Brandon S. Allbery KF8NH" <allbery@ece.cmu.edu>
+
+2001-01-30  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump versions
+
+2000-12-31  Assar Westerlund  <assar@sics.se>
+
+       * init_s.c (*): handle krb5_init_context failure consistently
+       * init_c.c (init_context): handle krb5_init_context failure
+       consistently
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5srv_la_LDFLAGS): bump version to 7:2:0
+
+2000-11-16  Assar Westerlund  <assar@sics.se>
+
+       * set_keys.c (make_keys): clean-up salting loop and try not to
+       leak memory
+
+       * ipropd_master.c (main): check for fd's being too large to select
+       on
+
+2000-08-16  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5srv_la_LDFLAGS): bump version to 7:1:0
+
+2000-08-10  Assar Westerlund  <assar@sics.se>
+
+       * acl.c (fetch_acl): fix wrong cases, use krb5_principal_match
+
+2000-08-07  Assar Westerlund  <assar@sics.se>
+
+       * ipropd_master.c (main): ignore SIGPIPE
+
+2000-08-06  Assar Westerlund  <assar@sics.se>
+
+       * ipropd_slave.c (receive_everything): make `fd' an int instead of
+       a pointer.  From Derrick J Brashear <shadow@dementia.org>
+
+2000-08-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * admin.h: change void** to void*
+
+2000-07-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: bump versions to 7:0:0 and 6:0:2
+
+2000-07-24  Assar Westerlund  <assar@sics.se>
+
+       * log.c (kadm5_log_get_version): rename kadm5_log_get_version_fd
+       and make a new that takes a context
+       (kadm5_log_nop): add logging of missing lengths
+       (kadm5_log_truncate): new function
+
+       * dump_log.c (print_entry): update and correct
+       * randkey_s.c: call _kadm5_bump_pw_expire
+       * truncate_log.c: new program for truncating the log
+       * Makefile.am (sbin_PROGRAMS): add truncate_log
+       (C_SOURCES): add bump_pw_expire.c
+       * bump_pw_expire.c: new function for extending password expiration
+
+2000-07-22  Assar Westerlund  <assar@sics.se>
+
+       * keys.c: new file with _kadm5_free_keys, _kadm5_init_keys
+
+       * set_keys.c (free_keys, init_keys): elevate to internal kadm5
+       functions
+
+       * chpass_s.c (kadm5_s_chpass_principal_cond): new function
+       * Makefile.am (C_SOURCES): add keys.c
+       * init_c.c: remove unused variable and handle some parameters
+       being NULL
+
+2000-07-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_slave.c: use krb5_read_priv_message
+
+       * ipropd_master.c: use krb5_{read,write}_priv_message
+
+       * init_c.c: use krb5_write_priv_message
+
+2000-07-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_slave.c: no need to call gethostname, since
+       sname_to_principal will
+
+       * send_recv.c: assert that we have a connected socket
+
+       * get_princs_c.c: call _kadm5_connect
+
+       * rename_c.c: call _kadm5_connect
+
+       * randkey_c.c: call _kadm5_connect
+
+       * privs_c.c: call _kadm5_connect
+
+       * modify_c.c: call _kadm5_connect
+
+       * get_c.c: call _kadm5_connect
+
+       * delete_c.c: call _kadm5_connect
+
+       * create_c.c: call _kadm5_connect
+
+       * chpass_c.c: call _kadm5_connect
+
+       * private.h: add more fields to client context; remove prototypes
+
+       * admin.h: remove prototypes
+
+       * kadm5-protos.h: move public prototypes here
+
+       * kadm5-private.h: move private prototypes here
+
+       * init_c.c: break out connection code to separate function, and
+       defer calling it until we actually do something
+
+2000-07-07  Assar Westerlund  <assar@sics.se>
+
+       * set_keys.c (make_keys): also support `[kadmin]use_v4_salt' for
+       backwards compatability
+
+2000-06-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * set_keys.c (_kadm5_set_keys): rewrite this to be more easily
+       adaptable to different salts
+       
+2000-06-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * get_s.c: pa_* -> KRB5_PADATA_*
+
+2000-06-16  Assar Westerlund  <assar@sics.se>
+
+       * ipropd_slave.c: change default keytab to default keytab (as in
+       typically FILE:/etc/krb5.keytab)
+
+2000-06-08  Assar Westerlund  <assar@sics.se>
+
+       * ipropd_slave.c: bug fixes, for actually writing the full dump to
+       the database.  based on a patch from Love <lha@stacken.kth.se>
+
+2000-06-07  Assar Westerlund  <assar@sics.se>
+
+       * acl.c: add support for patterns of principals
+       * log.c (kadm5_log_replay_create): handle more NULL pointers
+       (should they really happen?)
+       * log.c (kadm5_log_replay_modify): handle max_life == NULL and
+       max_renew == NULL
+
+       * ipropd_master.c: use syslog.  be less verbose
+       * ipropd_slave.c: use syslog
+
+2000-06-05  Assar Westerlund  <assar@sics.se>
+
+       * private.h (kadm_ops): add kadm_nop more prototypes
+       * log.c (kadm5_log_set_version, kadm5_log_reinit, kadm5_log_nop,
+       kadm5_log_replay_nop): add
+       * ipropd_slave.c: and some more improvements
+       * ipropd_master.c: lots of improvements
+       * iprop.h (IPROP_PORT, IPROP_SERVICE): add
+       (iprop_cmd): add new commands
+
+       * dump_log.c: add nop
+
+2000-05-15  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5clnt_la_LDFLAGS): set version to 5:1:1
+
+2000-05-12  Assar Westerlund  <assar@sics.se>
+
+       * get_s.c (kadm5_s_get_principal): set life, rlife to INT_MAX as a
+       fallback.  handle not having any creator.
+       * destroy_s.c (kadm5_s_destroy): free all allocated memory
+       * context_s.c (set_field): free variable if it's already set
+       (find_db_spec): malloc space for all strings
+
+2000-04-05  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (LDADD): add LIB_openldap
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5srv_la_LDFLAGS): set version to 6:0:1
+       (libkadm5clnt_la_LDFLAGS): set version to 5:0:1
+
+2000-03-24  Assar Westerlund  <assar@sics.se>
+
+       * set_keys.c (_kadm5_set_keys2): rewrite
+       (_kadm5_set_keys3): add
+
+       * private.h (struct kadm_func): add chpass_principal_with_key
+       * init_c.c (set_funcs): add chpass_principal_with_key
+
+2000-03-23  Assar Westerlund  <assar@sics.se>
+
+       * context_s.c (set_funcs): add chpass_principal_with_key
+       * common_glue.c (kadm5_chpass_principal_with_key): add
+       * chpass_s.c: comment-ize and change calling convention for
+       _kadm5_set_keys*
+       * chpass_c.c (kadm5_c_chpass_principal_with_key): add
+
+2000-02-07  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5clnt_la_LDFLAGS): set version to 4:2:0
+
+2000-01-28  Assar Westerlund  <assar@sics.se>
+
+       * init_c.c (get_new_cache): make sure to request non-forwardable,
+       non-proxiable
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5srv.la): bump version to 5:1:0
+
+       * context_s.c (_kadm5_s_init_context): handle params == NULL
+
+1999-12-26  Assar Westerlund  <assar@sics.se>
+
+       * get_s.c (kadm5_s_get_principal): handle modified_by->principal
+       == NULL
+
+1999-12-20  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkadm5clnt_la_LDFLAGS): bump version to 4:1:0
+
+       * init_c.c (_kadm5_c_init_context): handle getting back port
+       number from admin host
+       (kadm5_c_init_with_context): remove `proto/' part before doing
+       getaddrinfo()
+
+1999-12-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 5:0:0 and 4:0:0
+
+       * init_c.c (kadm5_c_init_with_context): don't use unitialized
+       stuff
+
+1999-12-04  Assar Westerlund  <assar@sics.se>
+
+       * replay_log.c: adapt to changed kadm5_log_foreach
+
+       * log.c (kadm5_log_foreach): change to take a
+       `kadm5_server_context'
+
+       * init_c.c: use krb5_warn{,x}
+
+       * dump_log.c: adapt to changed kadm5_log_foreach
+
+       * init_c.c: re-write to use getaddrinfo
+       * Makefile.am (install-build-headers): add dependency
+       
+1999-12-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * log.c (kadm5_log_foreach): pass context
+
+       * dump_log.c: print more interesting things
+
+1999-12-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ipropd_master.c (process_msg): check for short reads
+
+1999-11-25  Assar Westerlund  <assar@sics.se>
+
+       * modify_s.c (kadm5_s_modify_principal): support key_data
+       (kadm5_s_modify_principal_with_key): remove
+
+       * admin.h (kadm5_s_modify_principal_with_key): remove
+
+1999-11-20  Assar Westerlund  <assar@sics.se>
+
+       * context_s.c (find_db_spec): ugly cast work-around.
+
+1999-11-14  Assar Westerlund  <assar@sics.se>
+
+       * context_s.c (_kadm5_s_init_context): call krb5_add_et_list so
+       that we aren't dependent on the layout of krb5_context_data
+       * init_c.c (_kadm5_c_init_context): call krb5_add_et_list so that
+       we aren't dependent on the layout of krb5_context_data
+
+1999-11-13  Assar Westerlund  <assar@sics.se>
+
+       * password_quality.c (kadm5_setup_passwd_quality_check): use
+       correct types for function pointers
+       
+1999-11-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * randkey_s.c: always bail out if the fetch fails
+
+       * admin.h (kadm5_config_params): remove fields we're not using
+
+       * ipropd_slave.c: allow passing a realm
+
+       * ipropd_master.c: allow passing a realm
+
+       * dump_log.c: allow passing a realm
+
+       * acl.c: correctly get acl file
+
+       * private.h (kadm5_server_context): add config_params struct and
+       remove acl_file; bump protocol version number
+
+       * marshall.c: marshalling of config parameters
+
+       * init_c.c (kadm5_c_init_with_context): try to cope with old
+       servers
+
+       * init_s.c (kadm5_s_init_with_context): actually use some passed
+       values
+
+       * context_s.c (_kadm5_s_init_context): get dbname, acl_file, and
+       stash_file from the config parameters, try to figure out these if
+       they're not provided
+
+1999-11-05  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (install-build-headers): use `cp' instead of
+       INSTALL_DATA
+
+1999-11-04  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 4:0:0 and 3:0:0 (they access fields
+       directly in libkrb5's context - bad functions)
+
+       * set_keys.c (_kadm5_set_keys_randomly): set enctypes correctly in
+       the copied keys
+
+1999-10-20  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version of kadm5srv to 3:0:2 (new password
+       quality functions).
+       set version of kdam5clnt to 2:1:1 (no interface changes)
+
+       * Makefile.am (LDADD): add $(LIB_dlopen)
+
+1999-10-17  Assar Westerlund  <assar@sics.se>
+
+       * randkey_s.c (kadm5_s_randkey_principal): use
+       _kadm5_set_keys_randomly
+
+       * set_keys.c (free_keys): free more memory
+       (_kadm5_set_keys): a little bit more generic
+       (_kadm5_set_keys_randomly): new function for setting random keys.
+
+1999-10-14  Assar Westerlund  <assar@sics.se>
+
+       * set_keys.c (_kadm5_set_keys): ignore old keys when setting new
+       ones and always add 3 DES keys and one 3DES key
+
+1999-10-03  Assar Westerlund  <assar@sics.se>
+
+       * init_c.c (_kadm5_c_init_context): use `krb5_get_krb_admin_hst'.
+       check return value from strdup
+
+1999-09-26  Assar Westerlund  <assar@sics.se>
+
+       * acl.c (_kadm5_privs_to_string): forgot one strcpy_truncate ->
+       strlcpy
+
+1999-09-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * dump_log.c: remove unused `optind'
+
+       * replay_log.c: remove unused `optind'
+
+1999-09-13  Assar Westerlund  <assar@sics.se>
+
+       * chpass_c.c (kadm5_c_chpass_principal): new _kadm5_client_recv
+
+       * send_recv.c (_kadm5_client_recv): return result in a `krb5_data'
+       so that we avoid copying it and don't need to dimension in
+       advance.  change all callers.
+
+1999-09-10  Assar Westerlund  <assar@sics.se>
+
+       * password_quality.c: new file
+
+       * admin.h
+       (kadm5_setup_passwd_quality_check,kadm5_check_password_quality):
+       add prototypes
+
+       * Makefile.am (S_SOURCES): add password_quality.c
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: update versions to 2:0:1
+
+1999-07-24  Assar Westerlund  <assar@sics.se>
+
+       * ent_setup.c (_kadm5_setup_entry): make princ_expire_time == 0
+       and pw_expiration == 0 mean never
+
+1999-07-22  Assar Westerlund  <assar@sics.se>
+
+       * log.c (kadm5_log_flush): extra cast
+
+1999-07-07  Assar Westerlund  <assar@sics.se>
+
+       * marshall.c (store_principal_ent): encoding princ_expire_time and
+       pw_expiration in correct order
+
+1999-06-28  Assar Westerlund  <assar@sics.se>
+
+       * randkey_s.c (kadm5_s_randkey_principal): nuke old mkvno,
+       otherwise hdb will think that the new random keys are already
+       encrypted which will cause lots of confusion later.
+
+1999-06-23  Assar Westerlund  <assar@sics.se>
+
+       * ent_setup.c (_kadm5_setup_entry): handle 0 == unlimited
+       correctly.  From Michal Vocu <michal@karlin.mff.cuni.cz>
+
+1999-06-15  Assar Westerlund  <assar@sics.se>
+
+       * init_c.c (get_cred_cache): use get_default_username
+
+1999-05-23  Assar Westerlund  <assar@sics.se>
+
+       * create_s.c (create_principal): if there's no default entry the
+       mask should be zero.
+
+1999-05-21  Assar Westerlund  <assar@sics.se>
+
+       * init_c.c (get_cred_cache): use $USERNAME
+
+1999-05-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * init_c.c (get_cred_cache): figure out principal
+
+1999-05-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * send_recv.c: cleanup _kadm5_client_{send,recv}
+
+1999-05-04  Assar Westerlund  <assar@sics.se>
+
+       * set_keys.c (_kadm5_set_keys2): don't check the recently created
+       memory for NULL pointers
+
+       * private.h (_kadm5_setup_entry): change prototype
+
+       * modify_s.c: call new _kadm5_setup_entry
+
+       * ent_setup.c (_kadm5_setup_entry): change so that it takes three
+       masks, one for what bits to set and one for each of principal and
+       def containing the bits that are set there.
+
+       * create_s.c: call new _kadm5_setup_entry
+
+       * create_s.c (get_default): check return value
+       (create_principal): send wider mask to _kadm5_setup_entry
+
+1999-05-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * send_recv.c (_kadm5_client_recv): handle arbitrarily sized
+       packets, check for errors
+
+       * get_c.c: check for failure from _kadm5_client_{send,recv}
+
+1999-05-04  Assar Westerlund  <assar@sics.se>
+
+       * init_c.c (get_new_cache): don't abort when interrupted from
+       password prompt
+       
+       * destroy_c.c (kadm5_c_destroy): check if we should destroy the
+       auth context
+
+1999-05-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * chpass_s.c: fix arguments to _kadm5_set_keys2
+
+       * private.h: proto
+
+       * set_keys.c: clear mkvno
+
+       * rename_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * randkey_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * modify_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * log.c: add flags to fetch and store; seal keys before logging
+
+       * get_s.c: add flags to fetch and store; seal keys before logging
+
+       * get_princs_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * delete_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * create_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * chpass_s.c: add flags to fetch and store; seal keys before
+       logging
+
+       * Makefile.am: remove server.c
+
+       * admin.h: add prototypes
+
+       * ent_setup.c (_kadm5_setup_entry): set key_data
+
+       * set_keys.c: add _kadm5_set_keys2 to sey keys from key_data
+
+       * modify_s.c: add kadm5_s_modify_principal_with_key
+
+       * create_s.c: add kadm5_s_create_principal_with_key
+
+       * chpass_s.c: add kadm5_s_chpass_principal_with_key
+
+       * kadm5_locl.h: move stuff to private.h
+
+       * private.h: move stuff from kadm5_locl.h
+       
diff --git a/src/kerberosV/src/lib/kadm5/acl.c b/src/kerberosV/src/lib/kadm5/acl.c
new file mode 100644 (file)
index 0000000..5d9f4b2
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: acl.c,v 1.14 2004/08/26 07:48:46 lha Exp $");
+
+static struct units acl_units[] = {
+    { "all",           KADM5_PRIV_ALL },
+    { "change-password",KADM5_PRIV_CPW },
+    { "cpw",           KADM5_PRIV_CPW },
+    { "list",          KADM5_PRIV_LIST },
+    { "delete",                KADM5_PRIV_DELETE },
+    { "modify",                KADM5_PRIV_MODIFY },
+    { "add",           KADM5_PRIV_ADD },
+    { "get",           KADM5_PRIV_GET },
+    { NULL }
+};
+
+kadm5_ret_t
+_kadm5_string_to_privs(const char *s, u_int32_t* privs)
+{
+    int flags;
+    flags = parse_flags(s, acl_units, 0);
+    if(flags < 0)
+       return KADM5_FAILURE;
+    *privs = flags;
+    return 0;
+}
+
+kadm5_ret_t
+_kadm5_privs_to_string(u_int32_t privs, char *string, size_t len)
+{
+    if(privs == 0)
+       strlcpy(string, "none", len);
+    else
+       unparse_flags(privs, acl_units + 1, string, len);
+    return 0;
+}
+
+/*
+ * retrieve the right for the current caller on `princ' (NULL means all)
+ * and store them in `ret_flags'
+ * return 0 or an error.
+ */
+
+static kadm5_ret_t
+fetch_acl (kadm5_server_context *context,
+          krb5_const_principal princ,
+          unsigned *ret_flags)
+{
+    FILE *f;
+    krb5_error_code ret = 0;
+    char buf[256];
+
+    *ret_flags = 0;
+
+    /* no acl file -> no rights */
+    f = fopen(context->config.acl_file, "r");
+    if (f == NULL)
+       return 0;
+
+    while(fgets(buf, sizeof(buf), f) != NULL) {
+       char *foo = NULL, *p;
+       krb5_principal this_princ;
+       unsigned flags = 0;
+
+       p = strtok_r(buf, " \t\n", &foo);
+       if(p == NULL)
+           continue;
+       if (*p == '#')          /* comment */
+           continue;
+       ret = krb5_parse_name(context->context, p, &this_princ);
+       if(ret)
+           break;
+       if(!krb5_principal_compare(context->context, 
+                                  context->caller, this_princ)) {
+           krb5_free_principal(context->context, this_princ);
+           continue;
+       }
+       krb5_free_principal(context->context, this_princ);
+       p = strtok_r(NULL, " \t\n", &foo);
+       if(p == NULL)
+           continue;
+       ret = _kadm5_string_to_privs(p, &flags);
+       if (ret)
+           break;
+       p = strtok_r(NULL, " \t\n", &foo);
+       if (p == NULL) {
+           *ret_flags = flags;
+           break;
+       }
+       if (princ != NULL) {
+           krb5_principal pattern_princ;
+           krb5_boolean match;
+
+           ret = krb5_parse_name (context->context, p, &pattern_princ);
+           if (ret)
+               break;
+           match = krb5_principal_match (context->context,
+                                         princ, pattern_princ);
+           krb5_free_principal (context->context, pattern_princ);
+           if (match) {
+               *ret_flags = flags;
+               break;
+           }
+       }
+    }
+    fclose(f);
+    return ret;
+}
+
+/*
+ * set global acl flags in `context' for the current caller.
+ * return 0 on success or an error
+ */
+
+kadm5_ret_t
+_kadm5_acl_init(kadm5_server_context *context)
+{
+    krb5_principal princ;
+    krb5_error_code ret;
+    
+    ret = krb5_parse_name(context->context, KADM5_ADMIN_SERVICE, &princ);
+    if (ret)
+       return ret;
+    ret = krb5_principal_compare(context->context, context->caller, princ);
+    krb5_free_principal(context->context, princ);
+    if(ret != 0) {
+       context->acl_flags = KADM5_PRIV_ALL;
+       return 0;
+    }
+
+    return fetch_acl (context, NULL, &context->acl_flags);
+}
+
+/*
+ * check if `flags' allows `op'
+ * return 0 if OK or an error
+ */
+
+static kadm5_ret_t
+check_flags (unsigned op,
+            unsigned flags)
+{
+    unsigned res = ~flags & op;
+
+    if(res & KADM5_PRIV_GET)
+       return KADM5_AUTH_GET;
+    if(res & KADM5_PRIV_ADD)
+       return KADM5_AUTH_ADD;
+    if(res & KADM5_PRIV_MODIFY)
+       return KADM5_AUTH_MODIFY;
+    if(res & KADM5_PRIV_DELETE)
+       return KADM5_AUTH_DELETE;
+    if(res & KADM5_PRIV_CPW)
+       return KADM5_AUTH_CHANGEPW;
+    if(res & KADM5_PRIV_LIST)
+       return KADM5_AUTH_LIST;
+    if(res)
+       return KADM5_AUTH_INSUFFICIENT;
+    return 0;
+}
+
+/*
+ * return 0 if the current caller in `context' is allowed to perform
+ * `op' on `princ' and otherwise an error
+ * princ == NULL if it's not relevant.
+ */
+
+kadm5_ret_t
+_kadm5_acl_check_permission(kadm5_server_context *context,
+                           unsigned op,
+                           krb5_const_principal princ)
+{
+    kadm5_ret_t ret;
+    unsigned princ_flags;
+
+    ret = check_flags (op, context->acl_flags);
+    if (ret == 0)
+       return ret;
+    ret = fetch_acl (context, princ, &princ_flags);
+    if (ret)
+       return ret;
+    return check_flags (op, princ_flags);
+}
diff --git a/src/kerberosV/src/lib/kadm5/ad.c b/src/kerberosV/src/lib/kadm5/ad.c
new file mode 100644 (file)
index 0000000..b47816a
--- /dev/null
@@ -0,0 +1,1449 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#define HAVE_TSASL 1
+
+#include "kadm5_locl.h"
+#if 1
+#undef OPENLDAP
+#undef HAVE_TSASL
+#endif
+#ifdef OPENLDAP
+#include <ldap.h>
+#ifdef HAVE_TSASL
+#include <tsasl.h>
+#endif
+#include <resolve.h>
+#include <base64.h>
+#endif
+
+RCSID("$KTH: ad.c,v 1.14 2004/07/06 04:11:08 lha Exp $");
+
+#ifdef OPENLDAP
+
+#define CTX2LP(context) ((LDAP *)((context)->ldap_conn))
+#define CTX2BASE(context) ((context)->base_dn)
+
+/*
+ * userAccountControl
+ */
+
+#define UF_SCRIPT                              0x00000001
+#define UF_ACCOUNTDISABLE                      0x00000002
+#define UF_UNUSED_0                            0x00000004
+#define UF_HOMEDIR_REQUIRED                    0x00000008
+#define UF_LOCKOUT                             0x00000010
+#define UF_PASSWD_NOTREQD                      0x00000020
+#define UF_PASSWD_CANT_CHANGE                  0x00000040
+#define UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED     0x00000080
+#define UF_TEMP_DUPLICATE_ACCOUNT              0x00000100
+#define UF_NORMAL_ACCOUNT                      0x00000200
+#define UF_UNUSED_1                            0x00000400
+#define UF_INTERDOMAIN_TRUST_ACCOUNT           0x00000800
+#define UF_WORKSTATION_TRUST_ACCOUNT           0x00001000
+#define UF_SERVER_TRUST_ACCOUNT                0x00002000
+#define UF_UNUSED_2                            0x00004000
+#define UF_UNUSED_3                            0x00008000
+#define UF_PASSWD_NOT_EXPIRE                   0x00010000
+#define UF_MNS_LOGON_ACCOUNT                   0x00020000
+#define UF_SMARTCARD_REQUIRED                  0x00040000
+#define UF_TRUSTED_FOR_DELEGATION              0x00080000
+#define UF_NOT_DELEGATED                       0x00100000
+#define UF_USE_DES_KEY_ONLY                    0x00200000
+#define UF_DONT_REQUIRE_PREAUTH                        0x00400000
+#define UF_UNUSED_4                            0x00800000
+#define UF_UNUSED_5                            0x01000000
+#define UF_UNUSED_6                            0x02000000
+#define UF_UNUSED_7                            0x04000000
+#define UF_UNUSED_8                            0x08000000
+#define UF_UNUSED_9                            0x10000000
+#define UF_UNUSED_10                           0x20000000
+#define UF_UNUSED_11                           0x40000000
+#define UF_UNUSED_12                           0x80000000
+
+/*
+ *
+ */
+
+#ifndef HAVE_TSASL
+static int
+sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *interact)
+{
+    return LDAP_SUCCESS;
+}
+#endif
+
+#if 0
+static Sockbuf_IO ldap_tsasl_io = {
+    NULL,                      /* sbi_setup */
+    NULL,                      /* sbi_remove */
+    NULL,                      /* sbi_ctrl */
+    NULL,                      /* sbi_read */
+    NULL,                      /* sbi_write */
+    NULL                       /* sbi_close */
+};
+#endif
+
+#ifdef HAVE_TSASL
+static int
+ldap_tsasl_bind_s(LDAP *ld,
+                 LDAP_CONST char *dn,
+                 LDAPControl **serverControls,
+                 LDAPControl **clientControls,
+                 const char *host)
+{
+    char *attrs[] = { "supportedSASLMechanisms", NULL };
+    struct tsasl_peer *peer = NULL;
+    struct tsasl_buffer in, out;
+    struct berval ccred, *scred;
+    LDAPMessage *m, *m0;
+    const char *mech;
+    char **vals;
+    int ret, rc;
+
+    ret = tsasl_peer_init(TSASL_FLAGS_INITIATOR | TSASL_FLAGS_CLEAR,
+                         "ldap", host, &peer);
+    if (ret != TSASL_DONE) {
+       rc = LDAP_LOCAL_ERROR;
+       goto out;
+    }
+
+    rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, &m0);
+    if (rc != LDAP_SUCCESS)
+       goto out;
+    
+    m = ldap_first_entry(ld, m0);
+    if (m == NULL) {
+       ldap_msgfree(m0);
+       goto out;
+    }
+
+    vals = ldap_get_values(ld, m, "supportedSASLMechanisms");
+    if (vals == NULL) {
+       ldap_msgfree(m0);
+       goto out;
+    }
+
+    ret = tsasl_find_best_mech(peer, vals, &mech);
+    if (ret) {
+       ldap_msgfree(m0);
+       goto out;
+    }
+
+    ldap_msgfree(m0);
+
+    ret = tsasl_select_mech(peer, mech);
+    if (ret != TSASL_DONE) {
+       rc = LDAP_LOCAL_ERROR;
+       goto out;
+    }
+
+    in.tb_data = NULL;
+    in.tb_size = 0;
+
+    do {
+       ret = tsasl_request(peer, &in, &out);
+       if (in.tb_size != 0) {
+           free(in.tb_data);
+           in.tb_data = NULL; 
+           in.tb_size = 0;
+       }
+       if (ret != TSASL_DONE && ret != TSASL_CONTINUE) {
+           rc = LDAP_AUTH_UNKNOWN;
+           goto out;
+       }
+
+       ccred.bv_val = out.tb_data;
+       ccred.bv_len = out.tb_size;
+
+       rc = ldap_sasl_bind_s(ld, dn, mech, &ccred,
+                             serverControls, clientControls, &scred);
+       tsasl_buffer_free(&out);
+
+       if (rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS) {
+           if(scred && scred->bv_len)
+               ber_bvfree(scred);
+           goto out;
+       }
+
+       in.tb_data = malloc(scred->bv_len);
+       if (in.tb_data == NULL) {
+           rc = LDAP_LOCAL_ERROR;
+           goto out;
+       }
+       memcpy(in.tb_data, scred->bv_val, scred->bv_len);
+       in.tb_size = scred->bv_len;
+       ber_bvfree(scred);
+
+    } while (rc == LDAP_SASL_BIND_IN_PROGRESS);
+
+ out:
+    if (rc == LDAP_SUCCESS) {
+#if 0
+       ber_sockbuf_add_io(ld->ld_conns->lconn_sb, &ldap_tsasl_io,
+                          LBER_SBIOD_LEVEL_APPLICATION, peer);
+
+#endif
+    } else if (peer != NULL)
+       tsasl_peer_free(peer);
+
+    return rc;
+}
+#endif /* HAVE_TSASL */
+
+
+static int
+check_ldap(kadm5_ad_context *context, int ret)
+{
+    switch (ret) {
+    case LDAP_SUCCESS:
+       return 0;
+    case LDAP_SERVER_DOWN: {
+       LDAP *lp = CTX2LP(context);
+       ldap_unbind(lp);
+       context->ldap_conn = NULL;
+       free(context->base_dn);
+       context->base_dn = NULL;
+       return 1;
+    }
+    default:
+       return 1;
+    }
+}
+
+/*
+ *
+ */
+
+static void
+laddattr(char ***al, int *attrlen, char *attr)
+{
+    char **a;
+    a = realloc(*al, (*attrlen + 2) * sizeof(**al));
+    if (a == NULL)
+       return;
+    a[*attrlen] = attr;
+    a[*attrlen + 1] = NULL;
+    (*attrlen)++;
+    *al = a;
+}
+
+static kadm5_ret_t
+_kadm5_ad_connect(void *server_handle)
+{
+    kadm5_ad_context *context = server_handle;
+    struct {
+       char *server;
+       int port;
+    } *s, *servers = NULL;
+    int i, num_servers = 0;
+
+    if (context->ldap_conn)
+       return 0;
+
+    {
+       struct dns_reply *r;
+       struct resource_record *rr;
+       char *domain;
+
+       asprintf(&domain, "_ldap._tcp.%s", context->realm);
+       if (domain == NULL) {
+           krb5_set_error_string(context->context, "malloc");
+           return KADM5_NO_SRV;
+       }
+
+       r = dns_lookup(domain, "SRV");
+       free(domain);
+       if (r == NULL) {
+           krb5_set_error_string(context->context, "Didn't find ldap dns");
+           return KADM5_NO_SRV;
+       }       
+
+       for (rr = r->head ; rr != NULL; rr = rr->next) {
+           if (rr->type != T_SRV)
+               continue;
+           s = realloc(servers, sizeof(*servers) * (num_servers + 1));
+           if (s == NULL) {
+               krb5_set_error_string(context->context, "malloc");
+               dns_free_data(r);
+               goto fail;
+           }
+           servers = s;
+           num_servers++;
+           servers[num_servers - 1].port =  rr->u.srv->port;
+           servers[num_servers - 1].server =  strdup(rr->u.srv->target);
+       }
+       dns_free_data(r);
+    }
+
+    if (num_servers == 0) {
+       krb5_set_error_string(context->context, "No AD server found in DNS");
+       return KADM5_NO_SRV;
+    }
+
+    for (i = 0; i < num_servers; i++) {
+       int lret, version = LDAP_VERSION3;
+       LDAP *lp;
+
+       lp = ldap_init(servers[i].server, servers[i].port);
+       if (lp == NULL)
+           continue;
+       
+       if (ldap_set_option(lp, LDAP_OPT_PROTOCOL_VERSION, &version)) {
+           ldap_unbind(lp);
+           continue;
+       }
+       
+       if (ldap_set_option(lp, LDAP_OPT_REFERRALS, LDAP_OPT_OFF)) {
+           ldap_unbind(lp);
+           continue;
+       }
+       
+#ifdef HAVE_TSASL
+       lret = ldap_tsasl_bind_s(lp, NULL, NULL, NULL, servers[i].server);
+                                
+#else
+       lret = ldap_sasl_interactive_bind_s(lp, NULL, NULL, NULL, NULL, 
+                                           LDAP_SASL_QUIET,
+                                           sasl_interact, NULL);
+#endif
+       if (lret != LDAP_SUCCESS) {
+           krb5_set_error_string(context->context, 
+                                 "Couldn't contact any AD servers: %s",
+                                 ldap_err2string(lret));
+           ldap_unbind(lp);
+           continue;
+       }
+
+       context->ldap_conn = lp;
+       break;
+    }
+    if (i >= num_servers) {
+       goto fail;
+    }
+
+    {
+       LDAPMessage *m, *m0;
+       char **attr = NULL;
+       int attrlen = 0;
+       char **vals;
+       int ret;
+       
+       laddattr(&attr, &attrlen, "defaultNamingContext");
+
+       ret = ldap_search_s(CTX2LP(context), "", LDAP_SCOPE_BASE, 
+                           "objectclass=*", attr, 0, &m);
+       free(attr);
+       if (check_ldap(context, ret))
+           goto fail;
+
+       if (ldap_count_entries(CTX2LP(context), m) > 0) {
+           m0 = ldap_first_entry(CTX2LP(context), m);
+           if (m0 == NULL) {
+               krb5_set_error_string(context->context,
+                                     "Error in AD ldap responce");
+               ldap_msgfree(m);
+               goto fail;
+           }
+           vals = ldap_get_values(CTX2LP(context), 
+                                  m0, "defaultNamingContext");
+           if (vals == NULL) {
+               krb5_set_error_string(context->context,
+                                     "No naming context found");
+               goto fail;
+           }
+           context->base_dn = strdup(vals[0]);
+       } else
+           goto fail;
+       ldap_msgfree(m);
+    }
+
+    for (i = 0; i < num_servers; i++)
+       free(servers[i].server);
+    free(servers);
+
+    return 0;
+
+ fail:
+    for (i = 0; i < num_servers; i++)
+       free(servers[i].server);
+    free(servers);
+
+    if (context->ldap_conn) {
+       ldap_unbind(CTX2LP(context));
+       context->ldap_conn = NULL;
+    }
+    return KADM5_RPC_ERROR;
+}
+
+#define NTTIME_EPOCH 0x019DB1DED53E8000LL
+
+static time_t
+nt2unixtime(const char *str)
+{
+    unsigned long long t;
+    t = strtoll(str, NULL, 10);
+    t = ((t - NTTIME_EPOCH) / (long long)10000000);
+    if (t > (((time_t)(~(long long)0)) >> 1))
+       return 0;
+    return (time_t)t;
+}
+
+static long long
+unix2nttime(time_t unix_time)
+{
+    long long wt;
+    wt = unix_time * (long long)10000000 + (long long)NTTIME_EPOCH;
+    return wt;
+}
+
+/* XXX create filter in a better way */
+
+static int
+ad_find_entry(kadm5_ad_context *context,
+             const char *fqdn,
+             const char *pn,
+             char **name)
+{
+    LDAPMessage *m, *m0;
+    char *attr[] = { "distinguishedName", NULL };
+    char *filter;
+    int ret;
+
+    if (name)
+       *name = NULL;
+
+    if (fqdn)
+       asprintf(&filter, 
+                "(&(objectClass=computer)(|(dNSHostName=%s)(servicePrincipalName=%s)))",
+                fqdn, pn);
+    else if(pn)
+       asprintf(&filter, "(&(objectClass=account)(userPrincipalName=%s))", pn);
+    else
+       return KADM5_RPC_ERROR;
+
+    ret = ldap_search_s(CTX2LP(context), CTX2BASE(context),
+                       LDAP_SCOPE_SUBTREE, 
+                       filter, attr, 0, &m);
+    free(filter);
+    if (check_ldap(context, ret))
+       return KADM5_RPC_ERROR;
+
+    if (ldap_count_entries(CTX2LP(context), m) > 0) {
+       char **vals;
+       m0 = ldap_first_entry(CTX2LP(context), m);
+       vals = ldap_get_values(CTX2LP(context), m0, "distinguishedName");
+       if (vals == NULL || vals[0] == NULL) {
+           ldap_msgfree(m);
+           return KADM5_RPC_ERROR;
+       }
+       if (name)
+           *name = strdup(vals[0]);
+       ldap_msgfree(m);
+    } else
+       return KADM5_UNK_PRINC;
+
+    return 0;
+}
+
+#endif /* OPENLDAP */
+
+static kadm5_ret_t
+ad_get_cred(kadm5_ad_context *context, const char *password)
+{
+    kadm5_ret_t ret;
+    krb5_ccache cc;
+    char *service;
+
+    if (context->ccache)
+       return 0;
+
+    asprintf(&service, "%s/%s@%s", KRB5_TGS_NAME,
+            context->realm, context->realm);
+    if (service == NULL)
+       return ENOMEM;
+
+    ret = _kadm5_c_get_cred_cache(context->context,
+                                 context->client_name,
+                                 service,
+                                 password, krb5_prompter_posix, 
+                                 NULL, NULL, &cc);
+    free(service);
+    if(ret)
+       return ret; /* XXX */
+    context->ccache = cc;
+    return 0;
+}
+
+static kadm5_ret_t
+kadm5_ad_chpass_principal(void *server_handle,
+                         krb5_principal principal,
+                         char *password)
+{
+    kadm5_ad_context *context = server_handle;
+    krb5_data result_code_string, result_string;
+    int result_code;
+    kadm5_ret_t ret;
+
+    ret = ad_get_cred(context, NULL);
+    if (ret)
+       return ret;
+
+    krb5_data_zero (&result_code_string);
+    krb5_data_zero (&result_string);
+
+    ret = krb5_set_password_using_ccache (context->context, 
+                                         context->ccache,
+                                         password,
+                                         principal,
+                                         &result_code,
+                                         &result_code_string,
+                                         &result_string);
+    
+    krb5_data_free (&result_code_string);
+    krb5_data_free (&result_string);
+
+    /* XXX do mapping here on error codes */
+
+    return ret;
+}
+
+#ifdef OPENLDAP
+static const char *
+get_fqdn(krb5_context context, const krb5_principal p)
+{
+    const char *s, *hosttypes[] = { "host", "ldap", "gc", "cifs", "dns" };
+    int i;
+
+    s = krb5_principal_get_comp_string(context, p, 0);
+    if (p == NULL)
+       return NULL;
+    
+    for (i = 0; i < sizeof(hosttypes)/sizeof(hosttypes[0]); i++) {
+       if (strcasecmp(s, hosttypes[i]) == 0)
+           return krb5_principal_get_comp_string(context, p, 1);
+    }
+    return 0;
+}
+#endif
+
+
+static kadm5_ret_t
+kadm5_ad_create_principal(void *server_handle,
+                         kadm5_principal_ent_t entry,
+                         u_int32_t mask,
+                         char *password)
+{
+    kadm5_ad_context *context = server_handle;
+
+    /*
+     * KADM5_PRINC_EXPIRE_TIME
+     *
+     * return 0 || KADM5_DUP;
+     */
+
+#ifdef OPENLDAP
+    LDAPMod *attrs[8], rattrs[7], *a;
+    char *useraccvals[2] = { NULL, NULL }, 
+       *samvals[2], *dnsvals[2], *spnvals[5], *upnvals[2], *tv[2];
+    char *ocvals_spn[] = { "top", "person", "organizationalPerson", 
+                          "user", "computer", NULL}; 
+    char *p, *realmless_p, *p_msrealm = NULL, *dn = NULL;
+    const char *fqdn;
+    char *s, *samname = NULL, *short_spn = NULL;
+    int ret, i;
+    int32_t uf_flags = 0;
+    
+    if ((mask & KADM5_PRINCIPAL) == 0)
+       return KADM5_BAD_MASK;
+
+    for (i = 0; i < sizeof(rattrs)/sizeof(rattrs[0]); i++)
+       attrs[i] = &rattrs[i];
+    attrs[i] = NULL;
+    
+    ret = ad_get_cred(context, NULL);
+    if (ret)
+       return ret;
+    
+    ret = _kadm5_ad_connect(server_handle);
+    if (ret)
+       return ret;
+    
+    fqdn = get_fqdn(context->context, entry->principal);
+    
+    ret = krb5_unparse_name(context->context, entry->principal, &p);
+    if (ret)
+       return ret;
+    
+    if (ad_find_entry(context, fqdn, p, NULL) == 0) {
+       free(p);
+       return KADM5_DUP;
+    }
+    
+    if (mask & KADM5_ATTRIBUTES) {
+       if (entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX)
+           uf_flags |= UF_ACCOUNTDISABLE|UF_LOCKOUT;
+       if ((entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH) == 0)
+           uf_flags |= UF_DONT_REQUIRE_PREAUTH;
+       if (entry->attributes & KRB5_KDB_REQUIRES_HW_AUTH)
+           uf_flags |= UF_SMARTCARD_REQUIRED;
+    }
+    
+    realmless_p = strdup(p);
+    if (realmless_p == NULL) {
+       ret = ENOMEM;
+       goto out;
+    }
+    s = strrchr(realmless_p, '@');
+    if (s)
+       *s = '\0';
+    
+    if (fqdn) {
+       /* create computer account */
+       asprintf(&samname, "%s$", fqdn);
+       if (samname == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+       s = strchr(samname, '.');
+       if (s) {
+           s[0] = '$';
+           s[1] = '\0';
+       }
+       
+       short_spn = strdup(p);
+       if (short_spn == NULL) {
+           errno = ENOMEM;
+           goto out;
+       }
+       s = strchr(short_spn, '.');
+       if (s) {
+           *s = '\0';
+       } else {
+           free(short_spn);
+           short_spn = NULL;
+       }
+
+       p_msrealm = strdup(p);
+       if (p_msrealm == NULL) {
+           errno = ENOMEM;
+           goto out;
+       }
+       s = strrchr(p_msrealm, '@');
+       if (s) {
+           *s = '/';
+       } else {
+           free(p_msrealm);
+           p_msrealm = NULL;
+       }
+
+       asprintf(&dn, "cn=%s, cn=Computers, %s", fqdn, CTX2BASE(context));
+       if (dn == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+
+       a = &rattrs[0];
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "objectClass";
+       a->mod_values = ocvals_spn;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "userAccountControl";
+       a->mod_values = useraccvals;
+       asprintf(&useraccvals[0], "%d",
+                uf_flags |
+                UF_PASSWD_NOT_EXPIRE |
+                UF_WORKSTATION_TRUST_ACCOUNT);
+       useraccvals[1] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "sAMAccountName";
+       a->mod_values = samvals;
+       samvals[0] = samname;
+       samvals[1] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "dNSHostName";
+       a->mod_values = dnsvals;
+       dnsvals[0] = (char *)fqdn;
+       dnsvals[1] = NULL;
+       a++;
+
+       /* XXX  add even more spn's */
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "servicePrincipalName";
+       a->mod_values = spnvals;
+       i = 0;
+       spnvals[i++] = p;
+       spnvals[i++] = realmless_p;
+       if (short_spn)
+           spnvals[i++] = short_spn;
+       if (p_msrealm)
+           spnvals[i++] = p_msrealm;
+       spnvals[i++] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "userPrincipalName";
+       a->mod_values = upnvals;
+       upnvals[0] = p;
+       upnvals[1] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "accountExpires";
+       a->mod_values = tv;
+       tv[0] = "9223372036854775807"; /* "never" */
+       tv[1] = NULL;
+       a++;
+
+    } else {
+       /* create user account */
+       
+       a = &rattrs[0];
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "userAccountControl";
+       a->mod_values = useraccvals;
+       asprintf(&useraccvals[0], "%d", 
+                uf_flags |
+                UF_PASSWD_NOT_EXPIRE);
+       useraccvals[1] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "sAMAccountName";
+       a->mod_values = samvals;
+       samvals[0] = realmless_p;
+       samvals[1] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "userPrincipalName";
+       a->mod_values = upnvals;
+       upnvals[0] = p;
+       upnvals[1] = NULL;
+       a++;
+
+       a->mod_op = LDAP_MOD_ADD;
+       a->mod_type = "accountExpires";
+       a->mod_values = tv;
+       tv[0] = "9223372036854775807"; /* "never" */
+       tv[1] = NULL;
+       a++;
+    }
+
+    attrs[a - &rattrs[0]] = NULL;
+
+    ret = ldap_add_s(CTX2LP(context), dn, attrs);
+
+ out:
+    if (useraccvals[0])
+       free(useraccvals[0]);
+    if (realmless_p)
+       free(realmless_p);
+    if (samname)
+       free(samname);
+    if (short_spn)
+       free(short_spn);
+    if (p_msrealm)
+       free(p_msrealm);
+    free(p);
+
+    if (check_ldap(context, ret))
+       return KADM5_RPC_ERROR;
+
+    return 0;
+#else
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_delete_principal(void *server_handle, krb5_principal principal)
+{
+    kadm5_ad_context *context = server_handle;
+#ifdef OPENLDAP
+    char *p, *dn = NULL;
+    const char *fqdn;
+    int ret;
+
+    ret = ad_get_cred(context, NULL);
+    if (ret)
+       return ret;
+
+    ret = _kadm5_ad_connect(server_handle);
+    if (ret)
+       return ret;
+
+    fqdn = get_fqdn(context->context, principal);
+
+    ret = krb5_unparse_name(context->context, principal, &p);
+    if (ret)
+       return ret;
+
+    if (ad_find_entry(context, fqdn, p, &dn) != 0) {
+       free(p);
+       return KADM5_UNK_PRINC;
+    }
+
+    ret = ldap_delete_s(CTX2LP(context), dn);
+
+    free(dn);
+    free(p);
+
+    if (check_ldap(context, ret))
+       return KADM5_RPC_ERROR;
+    return 0;
+#else
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_destroy(void *server_handle)
+{
+    kadm5_ad_context *context = server_handle;
+
+    if (context->ccache)
+       krb5_cc_destroy(context->context, context->ccache);
+
+#ifdef OPENLDAP
+    {
+       LDAP *lp = CTX2LP(context);
+       if (lp)
+           ldap_unbind(lp);
+       if (context->base_dn)
+           free(context->base_dn);
+    }
+#endif
+    free(context->realm);
+    free(context->client_name);
+    krb5_free_principal(context->context, context->caller);
+    if(context->my_context)
+       krb5_free_context(context->context);
+    return 0;
+}
+
+static kadm5_ret_t
+kadm5_ad_flush(void *server_handle)
+{
+    kadm5_ad_context *context = server_handle;
+#ifdef OPENLDAP
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#else
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_get_principal(void *server_handle,
+                      krb5_principal principal, 
+                      kadm5_principal_ent_t entry, 
+                      u_int32_t mask)
+{
+    kadm5_ad_context *context = server_handle;
+#ifdef OPENLDAP
+    LDAPMessage *m, *m0;
+    char **attr = NULL;
+    int attrlen = 0;
+    char *filter, *p, *q, *u;
+    int ret;
+
+    /*
+     * principal
+     * KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES
+     */
+
+    /*
+     * return 0 || KADM5_DUP;
+     */
+
+    memset(entry, 0, sizeof(*entry));
+
+    if (mask & KADM5_KVNO)
+       laddattr(&attr, &attrlen, "msDS-KeyVersionNumber");
+
+    if (mask & KADM5_PRINCIPAL) {
+       laddattr(&attr, &attrlen, "userPrincipalName");
+       laddattr(&attr, &attrlen, "servicePrincipalName");
+    }
+    laddattr(&attr, &attrlen, "objectClass");
+    laddattr(&attr, &attrlen, "lastLogon");
+    laddattr(&attr, &attrlen, "badPwdCount");
+    laddattr(&attr, &attrlen, "badPasswordTime");
+    laddattr(&attr, &attrlen, "pwdLastSet");
+    laddattr(&attr, &attrlen, "accountExpires");
+    laddattr(&attr, &attrlen, "userAccountControl");
+
+    krb5_unparse_name_short(context->context, principal, &p);
+    krb5_unparse_name(context->context, principal, &u);
+
+    /* replace @ in domain part with a / */
+    q = strrchr(p, '@');
+    if (q && (p != q && *(q - 1) != '\\'))
+       *q = '/';
+
+    asprintf(&filter, 
+            "(|(userPrincipalName=%s)(servicePrincipalName=%s)(servicePrincipalName=%s))",
+            u, p, u);
+    free(p);
+    free(u);
+
+    ret = ldap_search_s(CTX2LP(context), CTX2BASE(context),
+                       LDAP_SCOPE_SUBTREE, 
+                       filter, attr, 0, &m);
+    free(attr);
+    if (check_ldap(context, ret))
+       return KADM5_RPC_ERROR;
+
+    if (ldap_count_entries(CTX2LP(context), m) > 0) {
+       char **vals;
+       m0 = ldap_first_entry(CTX2LP(context), m);
+       if (m0 == NULL) {
+           ldap_msgfree(m);
+           goto fail;
+       }
+#if 0
+       vals = ldap_get_values(CTX2LP(context), m0, "servicePrincipalName");
+       if (vals)
+           printf("servicePrincipalName %s\n", vals[0]);
+       vals = ldap_get_values(CTX2LP(context), m0, "userPrincipalName");
+       if (vals)
+           printf("userPrincipalName %s\n", vals[0]);
+       vals = ldap_get_values(CTX2LP(context), m0, "userAccountControl");
+       if (vals)
+           printf("userAccountControl %s\n", vals[0]);
+#endif
+       entry->princ_expire_time = 0;
+       if (mask & KADM5_PRINC_EXPIRE_TIME) {
+           vals = ldap_get_values(CTX2LP(context), m0, "accountExpires");
+           if (vals)
+               entry->princ_expire_time = nt2unixtime(vals[0]);
+       }
+       entry->last_success = 0;
+       if (mask & KADM5_LAST_SUCCESS) {
+           vals = ldap_get_values(CTX2LP(context), m0, "lastLogon");
+           if (vals)
+               entry->last_success = nt2unixtime(vals[0]);
+       }
+       if (mask & KADM5_LAST_FAILED) {
+           vals = ldap_get_values(CTX2LP(context), m0, "badPasswordTime");
+           if (vals)
+               entry->last_failed = nt2unixtime(vals[0]);
+       }
+       if (mask & KADM5_LAST_PWD_CHANGE) {
+           vals = ldap_get_values(CTX2LP(context), m0, "pwdLastSet");
+           if (vals)
+               entry->last_pwd_change = nt2unixtime(vals[0]);
+       }
+       if (mask & KADM5_FAIL_AUTH_COUNT) {
+           vals = ldap_get_values(CTX2LP(context), m0, "badPwdCount");
+           if (vals)
+               entry->fail_auth_count = atoi(vals[0]);
+       }
+       if (mask & KADM5_ATTRIBUTES) {
+           vals = ldap_get_values(CTX2LP(context), m0, "userAccountControl");
+           if (vals) {
+               u_int32_t i;
+               i = atoi(vals[0]);
+               if (i & (UF_ACCOUNTDISABLE|UF_LOCKOUT))
+                   entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
+               if ((i & UF_DONT_REQUIRE_PREAUTH) == 0)
+                   entry->attributes |= KRB5_KDB_REQUIRES_PRE_AUTH;
+               if (i & UF_SMARTCARD_REQUIRED)
+                   entry->attributes |= KRB5_KDB_REQUIRES_HW_AUTH;
+               if ((i & UF_WORKSTATION_TRUST_ACCOUNT) == 0)
+                   entry->attributes |= KRB5_KDB_DISALLOW_SVR;
+           }
+       }
+       if (mask & KADM5_KVNO) {
+           vals = ldap_get_values(CTX2LP(context), m0, 
+                                  "msDS-KeyVersionNumber");
+           if (vals)
+               entry->kvno = atoi(vals[0]);
+           else
+               entry->kvno = 0;
+       }
+       ldap_msgfree(m);
+    } else {
+       return KADM5_UNK_PRINC;
+    }
+
+    if (mask & KADM5_PRINCIPAL)
+       krb5_copy_principal(context->context, principal, &entry->principal);
+
+    return 0;
+ fail:
+    return KADM5_RPC_ERROR;
+#else
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_get_principals(void *server_handle,
+                       const char *exp,
+                       char ***principals,
+                       int *count)
+{
+    kadm5_ad_context *context = server_handle;
+
+    /*
+     * KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES
+     */
+
+#ifdef OPENLDAP
+    kadm5_ret_t ret;
+
+    ret = ad_get_cred(context, NULL);
+    if (ret)
+       return ret;
+
+    ret = _kadm5_ad_connect(server_handle);
+    if (ret)
+       return ret;
+
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#else
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_get_privs(void *server_handle, u_int32_t*privs)
+{
+    kadm5_ad_context *context = server_handle;
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+}
+
+static kadm5_ret_t
+kadm5_ad_modify_principal(void *server_handle,
+                         kadm5_principal_ent_t entry,
+                         u_int32_t mask)
+{
+    kadm5_ad_context *context = server_handle;
+
+    /* 
+     * KADM5_ATTRIBUTES
+     * KRB5_KDB_DISALLOW_ALL_TIX (| KADM5_KVNO)
+     */
+
+#ifdef OPENLDAP
+    LDAPMessage *m = NULL, *m0;
+    kadm5_ret_t ret;
+    char **attr = NULL;
+    int attrlen = 0;
+    char *p = NULL, *s = NULL, *q;
+    char **vals;
+    LDAPMod *attrs[4], rattrs[3], *a;
+    char *uaf[2] = { NULL, NULL };
+    char *kvno[2] = { NULL, NULL };
+    char *tv[2] = { NULL, NULL };
+    char *filter, *dn;
+    int i;
+
+    for (i = 0; i < sizeof(rattrs)/sizeof(rattrs[0]); i++)
+       attrs[i] = &rattrs[i];
+    attrs[i] = NULL;
+    a = &rattrs[0];
+
+    ret = _kadm5_ad_connect(server_handle);
+    if (ret)
+       return ret;
+
+    if (mask & KADM5_KVNO)
+       laddattr(&attr, &attrlen, "msDS-KeyVersionNumber");
+    if (mask & KADM5_PRINC_EXPIRE_TIME)
+       laddattr(&attr, &attrlen, "accountExpires");
+    if (mask & KADM5_ATTRIBUTES)
+       laddattr(&attr, &attrlen, "userAccountControl");
+    laddattr(&attr, &attrlen, "distinguishedName");
+
+    krb5_unparse_name(context->context, entry->principal, &p);
+
+    s = strdup(p);
+
+    q = strrchr(s, '@');
+    if (q && (p != q && *(q - 1) != '\\'))
+       *q = '\0';
+
+    asprintf(&filter, 
+            "(|(userPrincipalName=%s)(servicePrincipalName=%s))",
+            s, s);
+    free(p);
+    free(s);
+
+    ret = ldap_search_s(CTX2LP(context), CTX2BASE(context),
+                       LDAP_SCOPE_SUBTREE, 
+                       filter, attr, 0, &m);
+    free(attr);
+    free(filter);
+    if (check_ldap(context, ret))
+       return KADM5_RPC_ERROR;
+
+    if (ldap_count_entries(CTX2LP(context), m) <= 0) {
+       ret = KADM5_RPC_ERROR;
+       goto out;
+    }
+
+    m0 = ldap_first_entry(CTX2LP(context), m);
+
+    if (mask & KADM5_ATTRIBUTES) {
+       int32_t i;
+
+       vals = ldap_get_values(CTX2LP(context), m0, "userAccountControl");
+       if (vals == NULL) {
+           ret = KADM5_RPC_ERROR;
+           goto out;
+       }
+
+       i = atoi(vals[0]);
+       if (i == 0)
+           return KADM5_RPC_ERROR;
+
+       if (entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX)
+           i |= (UF_ACCOUNTDISABLE|UF_LOCKOUT);
+       else
+           i &= ~(UF_ACCOUNTDISABLE|UF_LOCKOUT);
+       if (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)
+           i &= ~UF_DONT_REQUIRE_PREAUTH;
+       else
+           i |= UF_DONT_REQUIRE_PREAUTH;
+       if (entry->attributes & KRB5_KDB_REQUIRES_HW_AUTH)
+           i |= UF_SMARTCARD_REQUIRED;
+       else
+           i &= UF_SMARTCARD_REQUIRED;
+       if (entry->attributes & KRB5_KDB_DISALLOW_SVR)
+           i &= ~UF_WORKSTATION_TRUST_ACCOUNT;
+       else
+           i |= UF_WORKSTATION_TRUST_ACCOUNT;
+
+       asprintf(&uaf[0], "%d", i);
+
+       a->mod_op = LDAP_MOD_REPLACE;
+       a->mod_type = "userAccountControl";
+       a->mod_values = uaf;
+       a++;
+    }
+
+    if (mask & KADM5_KVNO) {
+       vals = ldap_get_values(CTX2LP(context), m0, "msDS-KeyVersionNumber");
+       if (vals == NULL) {
+           entry->kvno = 0;
+       } else {
+           asprintf(&kvno[0], "%d", entry->kvno);
+
+           a->mod_op = LDAP_MOD_REPLACE;
+           a->mod_type = "msDS-KeyVersionNumber";
+           a->mod_values = kvno;
+           a++;
+       }
+    }
+
+    if (mask & KADM5_PRINC_EXPIRE_TIME) {
+       long long wt;
+       vals = ldap_get_values(CTX2LP(context), m0, "accountExpires");
+       if (vals == NULL) {
+           ret = KADM5_RPC_ERROR;
+           goto out;
+       }
+
+       wt = unix2nttime(entry->princ_expire_time);
+
+       asprintf(&tv[0], "%llu", wt);
+
+       a->mod_op = LDAP_MOD_REPLACE;
+       a->mod_type = "accountExpires";
+       a->mod_values = tv;
+       a++;
+    }
+    
+    vals = ldap_get_values(CTX2LP(context), m0, "distinguishedName");
+    if (vals == NULL) {
+       ret = KADM5_RPC_ERROR;
+       goto out;
+    }
+    dn = vals[0];
+
+    attrs[a - &rattrs[0]] = NULL;
+
+    ret = ldap_modify_s(CTX2LP(context), dn, attrs);
+    if (check_ldap(context, ret))
+       return KADM5_RPC_ERROR;
+
+ out:
+    if (m)
+       ldap_msgfree(m);
+    if (uaf[0])
+       free(uaf[0]);
+    if (kvno[0])
+       free(kvno[0]);
+    if (tv[0])
+       free(tv[0]);
+    return ret;
+#else
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_randkey_principal(void *server_handle,
+                          krb5_principal principal,
+                          krb5_keyblock **keys,
+                          int *n_keys)
+{
+    kadm5_ad_context *context = server_handle;
+
+    /*
+     * random key
+     */
+
+#ifdef OPENLDAP
+    krb5_data result_code_string, result_string;
+    int result_code, plen;
+    kadm5_ret_t ret;
+    char *password;
+
+    *keys = NULL;
+    *n_keys = 0;
+
+    {
+       char p[64];
+       krb5_generate_random_block(p, sizeof(p));
+       plen = base64_encode(p, sizeof(p), &password);
+       if (plen < 0)
+           return ENOMEM;
+    }
+
+    ret = ad_get_cred(context, NULL);
+    if (ret) {
+       free(password);
+       return ret;
+    }
+
+    krb5_data_zero (&result_code_string);
+    krb5_data_zero (&result_string);
+
+    ret = krb5_set_password_using_ccache (context->context, 
+                                         context->ccache,
+                                         password,
+                                         principal,
+                                         &result_code,
+                                         &result_code_string,
+                                         &result_string);
+
+    krb5_data_free (&result_code_string);
+    krb5_data_free (&result_string);
+
+    if (ret == 0) {
+
+       *keys = malloc(sizeof(**keys) * 1);
+       if (*keys == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+       *n_keys = 1;
+
+       ret = krb5_string_to_key(context->context,
+                                ENCTYPE_ARCFOUR_HMAC_MD5,
+                                password,
+                                principal,
+                                &(*keys)[0]);
+       memset(password, 0, sizeof(password));
+       if (ret) {
+           free(*keys);
+           *keys = NULL;
+           *n_keys = 0;
+           goto out;
+       }
+    }
+    memset(password, 0, plen);
+    free(password);
+ out:
+    return ret;
+#else
+    *keys = NULL;
+    *n_keys = 0;
+
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+#endif
+}
+
+static kadm5_ret_t
+kadm5_ad_rename_principal(void *server_handle,
+                         krb5_principal from,
+                         krb5_principal to)
+{
+    kadm5_ad_context *context = server_handle;
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+}
+
+static kadm5_ret_t
+kadm5_ad_chpass_principal_with_key(void *server_handle, 
+                                  krb5_principal princ,
+                                  int n_key_data,
+                                  krb5_key_data *key_data)
+{
+    kadm5_ad_context *context = server_handle;
+    krb5_set_error_string(context->context, "Function not implemented");
+    return KADM5_RPC_ERROR;
+}
+
+static void
+set_funcs(kadm5_ad_context *c)
+{
+#define SET(C, F) (C)->funcs.F = kadm5_ad_ ## F
+    SET(c, chpass_principal);
+    SET(c, chpass_principal_with_key);
+    SET(c, create_principal);
+    SET(c, delete_principal);
+    SET(c, destroy);
+    SET(c, flush);
+    SET(c, get_principal);
+    SET(c, get_principals);
+    SET(c, get_privs);
+    SET(c, modify_principal);
+    SET(c, randkey_principal);
+    SET(c, rename_principal);
+}
+
+kadm5_ret_t 
+kadm5_ad_init_with_password_ctx(krb5_context context,
+                               const char *client_name,
+                               const char *password,
+                               const char *service_name,
+                               kadm5_config_params *realm_params,
+                               unsigned long struct_version,
+                               unsigned long api_version,
+                               void **server_handle)
+{
+    kadm5_ret_t ret;
+    kadm5_ad_context *ctx;
+
+    ctx = malloc(sizeof(*ctx));
+    if(ctx == NULL)
+       return ENOMEM;
+    memset(ctx, 0, sizeof(*ctx));
+    set_funcs(ctx);
+
+    ctx->context = context;
+    krb5_add_et_list (context, initialize_kadm5_error_table_r);
+
+    ret = krb5_parse_name(ctx->context, client_name, &ctx->caller);
+    if(ret) {
+       free(ctx);
+       return ret;
+    }
+
+    if(realm_params->mask & KADM5_CONFIG_REALM) {
+       ret = 0;
+       ctx->realm = strdup(realm_params->realm);
+       if (ctx->realm == NULL)
+           ret = ENOMEM;
+    } else
+       ret = krb5_get_default_realm(ctx->context, &ctx->realm);
+    if (ret) {
+       free(ctx);
+       return ret;
+    }
+
+    ctx->client_name = strdup(client_name);
+
+    if(password != NULL && *password != '\0')
+       ret = ad_get_cred(ctx, password);
+    else
+       ret = ad_get_cred(ctx, NULL);
+    if(ret) {
+       kadm5_ad_destroy(ctx);
+       return ret;
+    }
+
+#ifdef OPENLDAP
+    ret = _kadm5_ad_connect(ctx);
+    if (ret) {
+       kadm5_ad_destroy(ctx);
+       return ret;
+    }
+#endif
+
+    *server_handle = ctx;
+    return 0;
+}
+
+kadm5_ret_t 
+kadm5_ad_init_with_password(const char *client_name,
+                           const char *password,
+                           const char *service_name,
+                           kadm5_config_params *realm_params,
+                           unsigned long struct_version,
+                           unsigned long api_version,
+                           void **server_handle)
+{
+    krb5_context context;
+    kadm5_ret_t ret;
+    kadm5_ad_context *ctx;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       return ret;
+    ret = kadm5_ad_init_with_password_ctx(context, 
+                                         client_name,
+                                         password,
+                                         service_name,
+                                         realm_params,
+                                         struct_version,
+                                         api_version,
+                                         server_handle);
+    if(ret) {
+       krb5_free_context(context);
+       return ret;
+    }
+    ctx = *server_handle;
+    ctx->my_context = 1;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/admin.h b/src/kerberosV/src/lib/kadm5/admin.h
new file mode 100644 (file)
index 0000000..ed6c93e
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 1997-2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+/* $KTH: admin.h,v 1.19 2005/05/30 20:32:58 lha Exp $ */
+
+#ifndef __KADM5_ADMIN_H__
+#define __KADM5_ADMIN_H__
+
+#define KADM5_API_VERSION_1 1
+#define KADM5_API_VERSION_2 2
+
+#ifndef USE_KADM5_API_VERSION
+#define USE_KADM5_API_VERSION KADM5_API_VERSION_2
+#endif
+
+#if USE_KADM5_API_VERSION != KADM5_API_VERSION_2
+#error No support for API versions other than 2
+#endif
+
+#define KADM5_STRUCT_VERSION 0
+
+#include <krb5.h>
+
+#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                0x00010000
+
+#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
+#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
+
+#define KADM5_PRINCIPAL_NORMAL_MASK (~(KADM5_KEY_DATA | KADM5_TL_DATA))
+
+#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
+
+#define KADM5_POLICY_NORMAL_MASK (~0)
+
+#define KADM5_ADMIN_SERVICE    "kadmin/admin"
+#define KADM5_HIST_PRINCIPAL   "kadmin/history"
+#define KADM5_CHANGEPW_SERVICE "kadmin/changepw"
+
+typedef struct _krb5_key_data {
+    int16_t key_data_ver;      /* Version */
+    int16_t key_data_kvno;     /* Key Version */
+    int16_t key_data_type[2];  /* Array of types */
+    int16_t key_data_length[2];        /* Array of lengths */
+    void*   key_data_contents[2];/* Array of pointers */
+} krb5_key_data;
+
+typedef struct _krb5_tl_data {
+    struct _krb5_tl_data* tl_data_next;
+    int16_t tl_data_type;         
+    int16_t tl_data_length;       
+    void*   tl_data_contents;     
+} krb5_tl_data;
+
+#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
+#define KRB5_TL_SECURID_STATE           0x0006
+
+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_t aux_attributes;
+
+    krb5_deltat max_renewable_life;
+    krb5_timestamp last_success;
+    krb5_timestamp last_failed;
+    krb5_kvno fail_auth_count;
+    int16_t n_key_data;
+    int16_t n_tl_data;
+    krb5_tl_data *tl_data;
+    krb5_key_data *key_data;
+} kadm5_principal_ent_rec, *kadm5_principal_ent_t;
+
+typedef struct _kadm5_policy_ent_t {
+    char *policy;
+
+    u_int32_t pw_min_life;
+    u_int32_t pw_max_life;
+    u_int32_t pw_min_length;
+    u_int32_t pw_min_classes;
+    u_int32_t pw_history_num;
+    u_int32_t policy_refcnt;
+} kadm5_policy_ent_rec, *kadm5_policy_ent_t;
+
+#define KADM5_CONFIG_REALM                     (1 << 0)
+#define KADM5_CONFIG_PROFILE                   (1 << 1)
+#define KADM5_CONFIG_KADMIND_PORT              (1 << 2)
+#define KADM5_CONFIG_ADMIN_SERVER              (1 << 3)
+#define KADM5_CONFIG_DBNAME                    (1 << 4)
+#define KADM5_CONFIG_ADBNAME                   (1 << 5)
+#define KADM5_CONFIG_ADB_LOCKFILE              (1 << 6)
+#define KADM5_CONFIG_ACL_FILE                  (1 << 7)
+#define KADM5_CONFIG_DICT_FILE                 (1 << 8)
+#define KADM5_CONFIG_ADMIN_KEYTAB              (1 << 9)
+#define KADM5_CONFIG_MKEY_FROM_KEYBOARD                (1 << 10)
+#define KADM5_CONFIG_STASH_FILE                        (1 << 11)
+#define KADM5_CONFIG_MKEY_NAME                 (1 << 12)
+#define KADM5_CONFIG_ENCTYPE                   (1 << 13)
+#define KADM5_CONFIG_MAX_LIFE                  (1 << 14)
+#define KADM5_CONFIG_MAX_RLIFE                 (1 << 15)
+#define KADM5_CONFIG_EXPIRATION                        (1 << 16)
+#define KADM5_CONFIG_FLAGS                     (1 << 17)
+#define KADM5_CONFIG_ENCTYPES                  (1 << 18)
+
+#define KADM5_PRIV_GET         (1 << 0)
+#define KADM5_PRIV_ADD                 (1 << 1)
+#define KADM5_PRIV_MODIFY      (1 << 2)
+#define KADM5_PRIV_DELETE      (1 << 3)
+#define KADM5_PRIV_LIST                (1 << 4)
+#define KADM5_PRIV_CPW         (1 << 5)
+#define KADM5_PRIV_ALL         (KADM5_PRIV_GET | KADM5_PRIV_ADD | KADM5_PRIV_MODIFY | KADM5_PRIV_DELETE | KADM5_PRIV_LIST | KADM5_PRIV_CPW)
+
+typedef struct {
+    int XXX;
+}krb5_key_salt_tuple;
+
+typedef struct _kadm5_config_params {
+    u_int32_t mask;
+
+    /* Client and server fields */
+    char *realm;
+    int kadmind_port;
+
+    /* client fields */
+    char *admin_server;
+
+    /* server fields */
+    char *dbname;
+    char *acl_file;
+
+    /* server library (database) fields */
+    char *stash_file;
+} kadm5_config_params;
+
+typedef krb5_error_code kadm5_ret_t;
+
+#include "kadm5-protos.h"
+
+#if 0
+/* unimplemented functions */
+kadm5_ret_t 
+kadm5_decrypt_key(void *server_handle,
+                 kadm5_principal_ent_t entry, int32_t
+                 ktype, int32_t stype, int32_t
+                 kvno, krb5_keyblock *keyblock,
+                 krb5_keysalt *keysalt, int *kvnop);
+
+kadm5_ret_t
+kadm5_create_policy(void *server_handle,
+                   kadm5_policy_ent_t policy, u_int32_t mask); 
+
+kadm5_ret_t
+kadm5_delete_policy(void *server_handle, char *policy);
+
+
+kadm5_ret_t
+kadm5_modify_policy(void *server_handle,
+                   kadm5_policy_ent_t policy, 
+                   u_int32_t mask);
+
+kadm5_ret_t
+kadm5_get_policy(void *server_handle, char *policy, kadm5_policy_ent_t ent); 
+
+kadm5_ret_t
+kadm5_get_policies(void *server_handle, char *exp,
+                  char ***pols, int *count);
+
+void 
+kadm5_free_policy_ent(kadm5_policy_ent_t policy);
+
+#endif
+
+#endif /* __KADM5_ADMIN_H__ */
diff --git a/src/kerberosV/src/lib/kadm5/bump_pw_expire.c b/src/kerberosV/src/lib/kadm5/bump_pw_expire.c
new file mode 100644 (file)
index 0000000..d051b9a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: bump_pw_expire.c,v 1.1 2000/07/24 03:47:54 assar Exp $");
+
+/*
+ * extend password_expiration if it's defined
+ */
+
+kadm5_ret_t
+_kadm5_bump_pw_expire(kadm5_server_context *context,
+                     hdb_entry *ent)
+{
+    if (ent->pw_end != NULL) {
+       time_t life;
+
+       life = krb5_config_get_time_default(context->context,
+                                           NULL,
+                                           365 * 24 * 60 * 60,
+                                           "kadmin",
+                                           "password_lifetime",
+                                           NULL);
+
+       *(ent->pw_end) = time(NULL) + life;
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/check-cracklib.pl b/src/kerberosV/src/lib/kadm5/check-cracklib.pl
new file mode 100755 (executable)
index 0000000..edd5ff3
--- /dev/null
@@ -0,0 +1,35 @@
+#!/usr/pkg/bin/perl
+#
+# Sample cracklib password verifier for Heimdals external password
+# verifier, see the chapter "Password changing" in the the info
+# documentation for more information about the protocol used.
+#
+# $KTH: check-cracklib.pl,v 1.1 2005/04/15 12:29:51 lha Exp $
+
+use strict;
+use Crypt::Cracklib;
+
+my $database = '/usr/pkg/libdata/pw_dict';
+
+my %params;
+
+while (<>) {
+    last if /^end$/;
+    if (!/^([^:]+): (.+)$/) {
+       die "key value pair not correct: $_";
+    }
+    $params{$1} = $2;
+}
+
+die "missing password" if (!defined $params{'new-password'});
+
+my $reason = fascist_check($params{'new-password'}, $database);
+
+if ($reason eq "ok") {
+    print "APPROVED\n";
+} else {
+    print "$reason\n";
+}
+
+exit 0
+
diff --git a/src/kerberosV/src/lib/kadm5/chpass_c.c b/src/kerberosV/src/lib/kadm5/chpass_c.c
new file mode 100644 (file)
index 0000000..bb16b20
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: chpass_c.c,v 1.5 2000/07/11 15:59:14 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_chpass_principal(void *server_handle, 
+                        krb5_principal princ,
+                        char *password)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_chpass);
+    krb5_store_principal(sp, princ);
+    krb5_store_string(sp, password);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return tmp;
+}
+
+kadm5_ret_t
+kadm5_c_chpass_principal_with_key(void *server_handle, 
+                                 krb5_principal princ,
+                                 int n_key_data,
+                                 krb5_key_data *key_data)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+    int i;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_chpass_with_key);
+    krb5_store_principal(sp, princ);
+    krb5_store_int32(sp, n_key_data);
+    for (i = 0; i < n_key_data; ++i)
+       kadm5_store_key_data (sp, &key_data[i]);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/kadm5/chpass_s.c b/src/kerberosV/src/lib/kadm5/chpass_s.c
new file mode 100644 (file)
index 0000000..af5173b
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: chpass_s.c,v 1.17 2004/09/12 12:10:35 lha Exp $");
+
+static kadm5_ret_t
+change(void *server_handle, 
+       krb5_principal princ,
+       char *password,
+       int cond)
+{
+    kadm5_server_context *context = server_handle;
+    hdb_entry ent;
+    kadm5_ret_t ret;
+    Key *keys;
+    size_t num_keys;
+    int cmp = 1;
+
+    ent.principal = princ;
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       return ret;
+    ret = context->db->hdb_fetch(context->context, context->db, 
+                                HDB_F_DECRYPT, &ent);
+    if(ret == HDB_ERR_NOENTRY)
+       goto out;
+
+    num_keys = ent.keys.len;
+    keys     = ent.keys.val;
+
+    ent.keys.len = 0;
+    ent.keys.val = NULL;
+
+    ret = _kadm5_set_keys(context, &ent, password);
+    if(ret) {
+       _kadm5_free_keys (context->context, num_keys, keys);
+       goto out2;
+    }
+    ent.kvno++;
+    if (cond)
+       cmp = _kadm5_cmp_keys (ent.keys.val, ent.keys.len,
+                              keys, num_keys);
+    _kadm5_free_keys (context->context, num_keys, keys);
+
+    if (cmp == 0) {
+       krb5_set_error_string(context->context, "Password reuse forbidden");
+       ret = KADM5_PASS_REUSE;
+       goto out2;
+    }
+
+    ret = _kadm5_set_modifier(context, &ent);
+    if(ret)
+       goto out2;
+
+    ret = _kadm5_bump_pw_expire(context, &ent);
+    if (ret)
+       goto out2;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out2;
+
+    kadm5_log_modify (context,
+                     &ent,
+                     KADM5_PRINCIPAL | KADM5_MOD_NAME | KADM5_MOD_TIME |
+                     KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION);
+    
+    ret = context->db->hdb_store(context->context, context->db, 
+                                HDB_F_REPLACE, &ent);
+out2:
+    hdb_free_entry(context->context, &ent);
+out:
+    context->db->hdb_close(context->context, context->db);
+    return _kadm5_error_code(ret);
+}
+
+
+
+/*
+ * change the password of `princ' to `password' if it's not already that.
+ */
+
+kadm5_ret_t
+kadm5_s_chpass_principal_cond(void *server_handle, 
+                             krb5_principal princ,
+                             char *password)
+{
+    return change (server_handle, princ, password, 1);
+}
+
+/*
+ * change the password of `princ' to `password'
+ */
+
+kadm5_ret_t
+kadm5_s_chpass_principal(void *server_handle, 
+                        krb5_principal princ,
+                        char *password)
+{
+    return change (server_handle, princ, password, 0);
+}
+
+/*
+ * change keys for `princ' to `keys'
+ */
+
+kadm5_ret_t
+kadm5_s_chpass_principal_with_key(void *server_handle, 
+                                 krb5_principal princ,
+                                 int n_key_data,
+                                 krb5_key_data *key_data)
+{
+    kadm5_server_context *context = server_handle;
+    hdb_entry ent;
+    kadm5_ret_t ret;
+    ent.principal = princ;
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       return ret;
+    ret = context->db->hdb_fetch(context->context, context->db, 0, &ent);
+    if(ret == HDB_ERR_NOENTRY)
+       goto out;
+    ret = _kadm5_set_keys2(context, &ent, n_key_data, key_data);
+    if(ret)
+       goto out2;
+    ent.kvno++;
+    ret = _kadm5_set_modifier(context, &ent);
+    if(ret)
+       goto out2;
+    ret = _kadm5_bump_pw_expire(context, &ent);
+    if (ret)
+       goto out2;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out2;
+
+    kadm5_log_modify (context,
+                     &ent,
+                     KADM5_PRINCIPAL | KADM5_MOD_NAME | KADM5_MOD_TIME |
+                     KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION);
+    
+    ret = context->db->hdb_store(context->context, context->db, 
+                                HDB_F_REPLACE, &ent);
+out2:
+    hdb_free_entry(context->context, &ent);
+out:
+    context->db->hdb_close(context->context, context->db);
+    return _kadm5_error_code(ret);
+}
diff --git a/src/kerberosV/src/lib/kadm5/client_glue.c b/src/kerberosV/src/lib/kadm5/client_glue.c
new file mode 100644 (file)
index 0000000..ffb2610
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: client_glue.c,v 1.5 1999/12/02 17:05:05 joda Exp $");
+
+kadm5_ret_t
+kadm5_init_with_password(const char *client_name,
+                        const char *password,
+                        const char *service_name,
+                        kadm5_config_params *realm_params,
+                        unsigned long struct_version,
+                        unsigned long api_version,
+                        void **server_handle)
+{
+    return kadm5_c_init_with_password(client_name,
+                                     password,
+                                     service_name,
+                                     realm_params,
+                                     struct_version,
+                                     api_version,
+                                     server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_password_ctx(krb5_context context,
+                            const char *client_name,
+                            const char *password,
+                            const char *service_name,
+                            kadm5_config_params *realm_params,
+                            unsigned long struct_version,
+                            unsigned long api_version,
+                            void **server_handle)
+{
+    return kadm5_c_init_with_password_ctx(context,
+                                         client_name,
+                                         password,
+                                         service_name,
+                                         realm_params,
+                                         struct_version,
+                                         api_version,
+                                         server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_skey(const char *client_name,
+                    const char *keytab,
+                    const char *service_name,
+                    kadm5_config_params *realm_params,
+                    unsigned long struct_version,
+                    unsigned long api_version,
+                    void **server_handle)
+{
+    return kadm5_c_init_with_skey(client_name,
+                                 keytab,
+                                 service_name,
+                                 realm_params,
+                                 struct_version,
+                                 api_version,
+                                 server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_skey_ctx(krb5_context context,
+                        const char *client_name,
+                        const char *keytab,
+                        const char *service_name,
+                        kadm5_config_params *realm_params,
+                        unsigned long struct_version,
+                        unsigned long api_version,
+                        void **server_handle)
+{
+    return kadm5_c_init_with_skey_ctx(context,
+                                     client_name,
+                                     keytab,
+                                     service_name,
+                                     realm_params,
+                                     struct_version,
+                                     api_version,
+                                     server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_creds(const char *client_name,
+                     krb5_ccache ccache,
+                     const char *service_name,
+                     kadm5_config_params *realm_params,
+                     unsigned long struct_version,
+                     unsigned long api_version,
+                     void **server_handle)
+{
+    return kadm5_c_init_with_creds(client_name,
+                                  ccache,
+                                  service_name,
+                                  realm_params,
+                                  struct_version,
+                                  api_version,
+                                  server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_creds_ctx(krb5_context context,
+                         const char *client_name,
+                         krb5_ccache ccache,
+                         const char *service_name,
+                         kadm5_config_params *realm_params,
+                         unsigned long struct_version,
+                         unsigned long api_version,
+                         void **server_handle)
+{
+    return kadm5_c_init_with_creds_ctx(context,
+                                      client_name,
+                                      ccache,
+                                      service_name,
+                                      realm_params,
+                                      struct_version,
+                                      api_version,
+                                      server_handle);
+}
diff --git a/src/kerberosV/src/lib/kadm5/common_glue.c b/src/kerberosV/src/lib/kadm5/common_glue.c
new file mode 100644 (file)
index 0000000..f89f065
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: common_glue.c,v 1.5 2000/03/23 22:58:26 assar Exp $");
+
+#define __CALL(F, P) (*((kadm5_common_context*)server_handle)->funcs.F)P;
+
+kadm5_ret_t
+kadm5_chpass_principal(void *server_handle,
+                      krb5_principal princ,
+                      char *password)
+{
+    return __CALL(chpass_principal, (server_handle, princ, password));
+}
+
+kadm5_ret_t
+kadm5_chpass_principal_with_key(void *server_handle,
+                               krb5_principal princ,
+                               int n_key_data,
+                               krb5_key_data *key_data)
+{
+    return __CALL(chpass_principal_with_key,
+                 (server_handle, princ, n_key_data, key_data));
+}
+
+kadm5_ret_t
+kadm5_create_principal(void *server_handle,
+                      kadm5_principal_ent_t princ,
+                      u_int32_t mask,
+                      char *password)
+{
+    return __CALL(create_principal, (server_handle, princ, mask, password));
+}
+
+kadm5_ret_t
+kadm5_delete_principal(void *server_handle,
+                      krb5_principal princ)
+{
+    return __CALL(delete_principal, (server_handle, princ));
+}
+
+kadm5_ret_t
+kadm5_destroy (void *server_handle)
+{
+    return __CALL(destroy, (server_handle));
+}
+
+kadm5_ret_t
+kadm5_flush (void *server_handle)
+{
+    return __CALL(flush, (server_handle));
+}
+
+kadm5_ret_t
+kadm5_get_principal(void *server_handle,
+                   krb5_principal princ,
+                   kadm5_principal_ent_t out,
+                   u_int32_t mask)
+{
+    return __CALL(get_principal, (server_handle, princ, out, mask));
+}
+
+kadm5_ret_t
+kadm5_modify_principal(void *server_handle,
+                      kadm5_principal_ent_t princ,
+                      u_int32_t mask)
+{
+    return __CALL(modify_principal, (server_handle, princ, mask));
+}
+
+kadm5_ret_t
+kadm5_randkey_principal(void *server_handle,
+                       krb5_principal princ,
+                       krb5_keyblock **new_keys,
+                       int *n_keys)
+{
+    return __CALL(randkey_principal, (server_handle, princ, new_keys, n_keys));
+}
+
+kadm5_ret_t
+kadm5_rename_principal(void *server_handle,
+                      krb5_principal source,
+                      krb5_principal target)
+{
+    return __CALL(rename_principal, (server_handle, source, target));
+}
+
+kadm5_ret_t
+kadm5_get_principals(void *server_handle,
+                    const char *exp,
+                    char ***princs,
+                    int *count)
+{
+    return __CALL(get_principals, (server_handle, exp, princs, count));
+}
+
+kadm5_ret_t
+kadm5_get_privs(void *server_handle,
+               u_int32_t *privs)
+{
+    return __CALL(get_privs, (server_handle, privs));
+}
diff --git a/src/kerberosV/src/lib/kadm5/context_s.c b/src/kerberosV/src/lib/kadm5/context_s.c
new file mode 100644 (file)
index 0000000..1b0c64d
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: context_s.c,v 1.17 2002/08/26 13:28:36 assar Exp $");
+
+static void
+set_funcs(kadm5_server_context *c)
+{
+#define SET(C, F) (C)->funcs.F = kadm5_s_ ## F
+    SET(c, chpass_principal);
+    SET(c, chpass_principal_with_key);
+    SET(c, create_principal);
+    SET(c, delete_principal);
+    SET(c, destroy);
+    SET(c, flush);
+    SET(c, get_principal);
+    SET(c, get_principals);
+    SET(c, get_privs);
+    SET(c, modify_principal);
+    SET(c, randkey_principal);
+    SET(c, rename_principal);
+}
+
+struct database_spec {
+    char *dbpath;
+    char *logfile;
+    char *mkeyfile;
+    char *aclfile;
+};
+
+static void
+set_field(krb5_context context, krb5_config_binding *binding, 
+         const char *dbname, const char *name, const char *ext, 
+         char **variable)
+{
+    const char *p;
+
+    if (*variable != NULL)
+       free (*variable);
+
+    p = krb5_config_get_string(context, binding, name, NULL);
+    if(p)
+       *variable = strdup(p);
+    else {
+       p = strrchr(dbname, '.');
+       if(p == NULL)
+           asprintf(variable, "%s.%s", dbname, ext);
+       else
+           asprintf(variable, "%.*s.%s", (int)(p - dbname), dbname, ext);
+    }
+}
+
+static void
+set_socket_name(const char *dbname, struct sockaddr_un *un)
+{
+    const char *p;
+    memset(un, 0, sizeof(*un));
+    un->sun_family = AF_UNIX;
+    p = strrchr(dbname, '.');
+    if(p == NULL)
+       snprintf(un->sun_path, sizeof(un->sun_path), "%s.signal", 
+                dbname);
+    else
+       snprintf(un->sun_path, sizeof(un->sun_path), "%.*s.signal", 
+                (int)(p - dbname), dbname);
+}
+
+static void
+set_config(kadm5_server_context *ctx,
+          krb5_config_binding *binding)
+{
+    const char *p;
+    if(ctx->config.dbname == NULL) {
+       p = krb5_config_get_string(ctx->context, binding, "dbname", NULL);
+       if(p)
+           ctx->config.dbname = strdup(p);
+       else
+           ctx->config.dbname = strdup(HDB_DEFAULT_DB);
+    }
+    if(ctx->log_context.log_file == NULL)
+       set_field(ctx->context, binding, ctx->config.dbname, 
+                 "log_file", "log", &ctx->log_context.log_file);
+    set_socket_name(ctx->config.dbname, &ctx->log_context.socket_name);
+    if(ctx->config.acl_file == NULL)
+       set_field(ctx->context, binding, ctx->config.dbname, 
+                 "acl_file", "acl", &ctx->config.acl_file);
+    if(ctx->config.stash_file == NULL)
+       set_field(ctx->context, binding, ctx->config.dbname, 
+                 "mkey_file", "mkey", &ctx->config.stash_file);
+}
+
+static kadm5_ret_t
+find_db_spec(kadm5_server_context *ctx)
+{
+    const krb5_config_binding *top_binding = NULL;
+    krb5_config_binding *db_binding;
+    krb5_config_binding *default_binding = NULL;
+    krb5_context context = ctx->context;
+
+    while((db_binding = (krb5_config_binding *)
+          krb5_config_get_next(context,
+                               NULL,
+                               &top_binding, 
+                               krb5_config_list, 
+                               "kdc", 
+                               "database",
+                               NULL))) {
+       const char *p;
+       p = krb5_config_get_string(context, db_binding, "realm", NULL);
+       if(p == NULL) {
+           if(default_binding) {
+               krb5_warnx(context, "WARNING: more than one realm-less "
+                          "database specification");
+               krb5_warnx(context, "WARNING: using the first encountered");
+           } else
+               default_binding = db_binding;
+           continue;
+       }
+       if(strcmp(ctx->config.realm, p) != 0)
+           continue;
+       
+       set_config(ctx, db_binding);
+       return 0;
+    }
+    if(default_binding)
+       set_config(ctx, default_binding);
+    else {
+       ctx->config.dbname        = strdup(HDB_DEFAULT_DB);
+       ctx->config.acl_file      = strdup(HDB_DB_DIR "/kadmind.acl");
+       ctx->config.stash_file    = strdup(HDB_DB_DIR "/m-key");
+       ctx->log_context.log_file = strdup(HDB_DB_DIR "/log");
+       memset(&ctx->log_context.socket_name, 0, 
+              sizeof(ctx->log_context.socket_name));
+       ctx->log_context.socket_name.sun_family = AF_UNIX;
+       strlcpy(ctx->log_context.socket_name.sun_path, 
+               KADM5_LOG_SIGNAL, 
+               sizeof(ctx->log_context.socket_name.sun_path));
+    }
+    return 0;
+}
+
+kadm5_ret_t
+_kadm5_s_init_context(kadm5_server_context **ctx, 
+                     kadm5_config_params *params,
+                     krb5_context context)
+{
+    *ctx = malloc(sizeof(**ctx));
+    if(*ctx == NULL)
+       return ENOMEM;
+    memset(*ctx, 0, sizeof(**ctx));
+    set_funcs(*ctx);
+    (*ctx)->context = context;
+    krb5_add_et_list (context, initialize_kadm5_error_table_r);
+#define is_set(M) (params && params->mask & KADM5_CONFIG_ ## M)
+    if(is_set(REALM))
+       (*ctx)->config.realm = strdup(params->realm);
+    else
+       krb5_get_default_realm(context, &(*ctx)->config.realm);
+    if(is_set(DBNAME))
+       (*ctx)->config.dbname = strdup(params->dbname);
+    if(is_set(ACL_FILE))
+       (*ctx)->config.acl_file = strdup(params->acl_file);
+    if(is_set(STASH_FILE))
+       (*ctx)->config.stash_file = strdup(params->stash_file);
+    
+    find_db_spec(*ctx);
+    
+    /* PROFILE can't be specified for now */
+    /* KADMIND_PORT is supposed to be used on the server also, 
+       but this doesn't make sense */
+    /* ADMIN_SERVER is client only */
+    /* ADNAME is not used at all (as far as I can tell) */
+    /* ADB_LOCKFILE ditto */
+    /* DICT_FILE */
+    /* ADMIN_KEYTAB */
+    /* MKEY_FROM_KEYBOARD is not supported */
+    /* MKEY_NAME neither */
+    /* ENCTYPE */
+    /* MAX_LIFE */
+    /* MAX_RLIFE */
+    /* EXPIRATION */
+    /* FLAGS */
+    /* ENCTYPES */
+
+    return 0;
+}
+
+HDB *
+_kadm5_s_get_db(void *server_handle)
+{
+    kadm5_server_context *context = server_handle;
+    return context->db;
+}
diff --git a/src/kerberosV/src/lib/kadm5/create_c.c b/src/kerberosV/src/lib/kadm5/create_c.c
new file mode 100644 (file)
index 0000000..d05b1cd
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: create_c.c,v 1.4 2000/07/11 15:59:21 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_create_principal(void *server_handle,
+                        kadm5_principal_ent_t princ, 
+                        u_int32_t mask,
+                        char *password)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_create);
+    kadm5_store_principal_ent(sp, princ);
+    krb5_store_int32(sp, mask);
+    krb5_store_string(sp, password);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return tmp;
+}
+
diff --git a/src/kerberosV/src/lib/kadm5/create_s.c b/src/kerberosV/src/lib/kadm5/create_s.c
new file mode 100644 (file)
index 0000000..56b9e2f
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: create_s.c,v 1.22 2004/03/07 22:43:46 lha Exp $");
+
+static kadm5_ret_t
+get_default(kadm5_server_context *context, krb5_principal princ, 
+           kadm5_principal_ent_t def)
+{
+    kadm5_ret_t ret;
+    krb5_principal def_principal;
+    krb5_realm *realm = krb5_princ_realm(context->context, princ);
+
+    ret = krb5_make_principal(context->context, &def_principal, 
+                             *realm, "default", NULL);
+    if (ret)
+       return ret;
+    ret = kadm5_s_get_principal(context, def_principal, def, 
+                               KADM5_PRINCIPAL_NORMAL_MASK);
+    krb5_free_principal (context->context, def_principal);
+    return ret;
+}
+
+static kadm5_ret_t
+create_principal(kadm5_server_context *context,
+                kadm5_principal_ent_t princ,
+                u_int32_t mask,
+                hdb_entry *ent,
+                u_int32_t required_mask,
+                u_int32_t forbidden_mask)
+{
+    kadm5_ret_t ret;
+    kadm5_principal_ent_rec defrec, *defent;
+    u_int32_t def_mask;
+    
+    if((mask & required_mask) != required_mask)
+       return KADM5_BAD_MASK;
+    if((mask & forbidden_mask))
+       return KADM5_BAD_MASK;
+    if((mask & KADM5_POLICY) && strcmp(princ->policy, "default"))
+       /* XXX no real policies for now */
+       return KADM5_UNK_POLICY;
+    memset(ent, 0, sizeof(*ent));
+    ret  = krb5_copy_principal(context->context, princ->principal, 
+                              &ent->principal);
+    if(ret)
+       return ret;
+    
+    defent = &defrec;
+    ret = get_default(context, princ->principal, defent);
+    if(ret) {
+       defent   = NULL;
+       def_mask = 0;
+    } else {
+       def_mask = KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE;
+    }
+
+    ret = _kadm5_setup_entry(context,
+                            ent, mask | def_mask,
+                            princ, mask,
+                            defent, def_mask);
+    if(defent)
+       kadm5_free_principal_ent(context, defent);
+    
+    ent->created_by.time = time(NULL);
+    ret = krb5_copy_principal(context->context, context->caller, 
+                             &ent->created_by.principal);
+
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_s_create_principal_with_key(void *server_handle,
+                                 kadm5_principal_ent_t princ,
+                                 u_int32_t mask)
+{
+    kadm5_ret_t ret;
+    hdb_entry ent;
+    kadm5_server_context *context = server_handle;
+
+    ret = create_principal(context, princ, mask, &ent,
+                          KADM5_PRINCIPAL | KADM5_KEY_DATA,
+                          KADM5_LAST_PWD_CHANGE | KADM5_MOD_TIME 
+                          | KADM5_MOD_NAME | KADM5_MKVNO 
+                          | KADM5_AUX_ATTRIBUTES 
+                          | KADM5_POLICY_CLR | KADM5_LAST_SUCCESS 
+                          | KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT);
+    if(ret)
+       goto out;
+
+    ent.kvno = 1;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out;
+    
+    kadm5_log_create (context, &ent);
+
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       goto out;
+    ret = context->db->hdb_store(context->context, context->db, 0, &ent);
+    context->db->hdb_close(context->context, context->db);
+out:
+    hdb_free_entry(context->context, &ent);
+    return _kadm5_error_code(ret);
+}
+                                 
+
+kadm5_ret_t
+kadm5_s_create_principal(void *server_handle,
+                        kadm5_principal_ent_t princ, 
+                        u_int32_t mask,
+                        char *password)
+{
+    kadm5_ret_t ret;
+    hdb_entry ent;
+    kadm5_server_context *context = server_handle;
+
+    ret = create_principal(context, princ, mask, &ent,
+                          KADM5_PRINCIPAL,
+                          KADM5_LAST_PWD_CHANGE | KADM5_MOD_TIME 
+                          | KADM5_MOD_NAME | KADM5_MKVNO 
+                          | KADM5_AUX_ATTRIBUTES | KADM5_KEY_DATA
+                          | KADM5_POLICY_CLR | KADM5_LAST_SUCCESS 
+                          | KADM5_LAST_FAILED | KADM5_FAIL_AUTH_COUNT);
+    if(ret)
+       goto out;
+
+    ent.keys.len = 0;
+    ent.keys.val = NULL;
+
+    ret = _kadm5_set_keys(context, &ent, password);
+    if (ret)
+       goto out;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out;
+    
+    kadm5_log_create (context, &ent);
+
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       goto out;
+    ret = context->db->hdb_store(context->context, context->db, 0, &ent);
+    context->db->hdb_close(context->context, context->db);
+ out:
+    hdb_free_entry(context->context, &ent);
+    return _kadm5_error_code(ret);
+}
+
diff --git a/src/kerberosV/src/lib/kadm5/default_keys.c b/src/kerberosV/src/lib/kadm5/default_keys.c
new file mode 100644 (file)
index 0000000..1dfe963
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: default_keys.c,v 1.3 2005/04/30 15:38:49 lha Exp $");
+
+static void
+print_keys(krb5_context context, Key *keys, size_t nkeys)
+{
+    krb5_error_code ret;
+    char *str;
+    int i;
+
+    printf("keys:\n");
+
+    for (i = 0; i < nkeys; i++) {
+
+       ret = krb5_enctype_to_string(context, keys[i].key.keytype, &str);
+       if (ret)
+           krb5_err(context, ret, 1, "krb5_enctype_to_string: %d\n",
+                    (int)keys[i].key.keytype);
+
+       printf("\tenctype %s", str);
+       free(str);
+
+       if (keys[i].salt) {
+           printf(" salt: ");
+
+           switch (keys[i].salt->type) {
+           case KRB5_PW_SALT:
+               printf("pw-salt:");
+               break;
+           case KRB5_AFS3_SALT:
+               printf("afs3-salt:");
+               break;
+           default:
+               printf("unknown salt: %d", keys[i].salt->type);
+               break;
+           }
+           if (keys[i].salt->salt.length)
+               printf("%.*s", (int)keys[i].salt->salt.length,
+                      (char *)keys[i].salt->salt.data);
+       }       
+       printf("\n");
+    }
+    printf("end keys:\n");
+}
+
+static void
+parse_file(krb5_context context, krb5_principal principal, int no_salt)
+{
+    krb5_error_code ret;
+    size_t nkeys;
+    Key *keys;
+
+    ret = hdb_generate_key_set(context, principal, &keys, &nkeys, no_salt);
+    if (ret)
+       krb5_err(context, 1, ret, "hdb_generate_key_set");
+
+    print_keys(context, keys, nkeys);
+
+    _kadm5_free_keys(context, nkeys, keys);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_principal principal;
+
+    ret = krb5_init_context(&context);
+    if (ret) 
+       errx(1, "krb5_init_context");
+
+    ret = krb5_parse_name(context, "lha@SU.SE", &principal);
+    if (ret)
+       krb5_err(context, ret, 1, "krb5_parse_name");
+
+    parse_file(context, principal, 0);
+    parse_file(context, principal, 1);
+
+    krb5_free_principal(context, principal);
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/delete_c.c b/src/kerberosV/src/lib/kadm5/delete_c.c
new file mode 100644 (file)
index 0000000..5b5b5d4
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: delete_c.c,v 1.4 2000/07/11 15:59:29 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_delete_principal(void *server_handle, krb5_principal princ)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_delete);
+    krb5_store_principal(sp, princ);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    if (ret)
+       return ret;
+    ret = _kadm5_client_recv(context, &reply);
+    if (ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if(sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/kadm5/delete_s.c b/src/kerberosV/src/lib/kadm5/delete_s.c
new file mode 100644 (file)
index 0000000..d77e997
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: delete_s.c,v 1.10 2003/09/19 00:21:50 lha Exp $");
+
+kadm5_ret_t
+kadm5_s_delete_principal(void *server_handle, krb5_principal princ)
+{
+    kadm5_server_context *context = server_handle;
+    kadm5_ret_t ret;
+    hdb_entry ent;
+
+    ent.principal = princ;
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret) {
+       krb5_warn(context->context, ret, "opening database");
+       return ret;
+    }
+    ret = context->db->hdb_fetch(context->context, context->db, 
+                                HDB_F_DECRYPT, &ent);
+    if(ret == HDB_ERR_NOENTRY)
+       goto out2;
+    if(ent.flags.immutable) {
+       ret = KADM5_PROTECT_PRINCIPAL;
+       goto out;
+    }
+    
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out;
+
+    kadm5_log_delete (context, princ);
+    
+    ret = context->db->hdb_remove(context->context, context->db, &ent);
+out:
+    hdb_free_entry(context->context, &ent);
+out2:
+    context->db->hdb_close(context->context, context->db);
+    return _kadm5_error_code(ret);
+}
diff --git a/src/kerberosV/src/lib/kadm5/destroy_c.c b/src/kerberosV/src/lib/kadm5/destroy_c.c
new file mode 100644 (file)
index 0000000..0a20190
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: destroy_c.c,v 1.4 2003/12/07 19:01:39 lha Exp $");
+
+kadm5_ret_t 
+kadm5_c_destroy(void *server_handle)
+{
+    kadm5_client_context *context = server_handle;
+
+    free(context->realm);
+    free(context->admin_server);
+    close(context->sock);
+    if (context->client_name)
+       free(context->client_name);
+    if (context->service_name)
+       free(context->service_name);
+    if (context->ac != NULL)
+       krb5_auth_con_free(context->context, context->ac);
+    if(context->my_context)
+       krb5_free_context(context->context);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/destroy_s.c b/src/kerberosV/src/lib/kadm5/destroy_s.c
new file mode 100644 (file)
index 0000000..b836073
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: destroy_s.c,v 1.7 2003/09/19 00:22:13 lha Exp $");
+
+/*
+ * dealloc a `kadm5_config_params'
+ */
+
+static void
+destroy_config (kadm5_config_params *c)
+{
+    free (c->realm);
+    free (c->dbname);
+    free (c->acl_file);
+    free (c->stash_file);
+}
+
+/*
+ * dealloc a kadm5_log_context
+ */
+
+static void
+destroy_kadm5_log_context (kadm5_log_context *c)
+{
+    free (c->log_file);
+    close (c->socket_fd);
+}
+
+/*
+ * destroy a kadm5 handle
+ */
+
+kadm5_ret_t 
+kadm5_s_destroy(void *server_handle)
+{
+    kadm5_ret_t ret;
+    kadm5_server_context *context = server_handle;
+    krb5_context kcontext = context->context;
+
+    ret = context->db->hdb_destroy(kcontext, context->db);
+    destroy_kadm5_log_context (&context->log_context);
+    destroy_config (&context->config);
+    krb5_free_principal (kcontext, context->caller);
+    if(context->my_context)
+       krb5_free_context(kcontext);
+    free (context);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kadm5/dump_log.c b/src/kerberosV/src/lib/kadm5/dump_log.c
new file mode 100644 (file)
index 0000000..8446bdb
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "iprop.h"
+#include "parse_time.h"
+
+RCSID("$KTH: dump_log.c,v 1.16 2005/04/25 18:17:51 lha Exp $");
+
+static char *op_names[] = {
+    "get",
+    "delete",
+    "create",
+    "rename",
+    "chpass",
+    "modify",
+    "randkey",
+    "get_privs",
+    "get_princs",
+    "chpass_with_key",
+    "nop"
+};
+
+static void
+print_entry(kadm5_server_context *server_context,
+           u_int32_t ver,
+           time_t timestamp,
+           enum kadm_ops op,
+           u_int32_t len,
+           krb5_storage *sp)
+{
+    char t[256];
+    int32_t mask;
+    hdb_entry ent;
+    krb5_principal source;
+    char *name1, *name2;
+    krb5_data data;
+    krb5_context context = server_context->context;
+
+    off_t end = krb5_storage_seek(sp, 0, SEEK_CUR) + len;
+    
+    krb5_error_code ret;
+
+    strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", localtime(&timestamp));
+
+    if(op < kadm_get || op > kadm_nop) {
+       printf("unknown op: %d\n", op);
+       krb5_storage_seek(sp, end, SEEK_SET);
+       return;
+    }
+
+    printf ("%s: ver = %u, timestamp = %s, len = %u\n",
+           op_names[op], ver, t, len);
+    switch(op) {
+    case kadm_delete:
+       krb5_ret_principal(sp, &source);
+       krb5_unparse_name(context, source, &name1);
+       printf("    %s\n", name1);
+       free(name1);
+       krb5_free_principal(context, source);
+       break;
+    case kadm_rename:
+       ret = krb5_data_alloc(&data, len);
+       if (ret)
+           krb5_err (context, 1, ret, "kadm_rename: data alloc: %d", len);
+       krb5_ret_principal(sp, &source);
+       krb5_storage_read(sp, data.data, data.length);
+       hdb_value2entry(context, &data, &ent);
+       krb5_unparse_name(context, source, &name1);
+       krb5_unparse_name(context, ent.principal, &name2);
+       printf("    %s -> %s\n", name1, name2);
+       free(name1);
+       free(name2);
+       krb5_free_principal(context, source);
+       hdb_free_entry(context, &ent);
+       break;
+    case kadm_create:
+       ret = krb5_data_alloc(&data, len);
+       if (ret)
+           krb5_err (context, 1, ret, "kadm_create: data alloc: %d", len);
+       krb5_storage_read(sp, data.data, data.length);
+       ret = hdb_value2entry(context, &data, &ent);
+       if(ret)
+           abort();
+       mask = ~0;
+       goto foo;
+    case kadm_modify:
+       ret = krb5_data_alloc(&data, len);
+       if (ret)
+           krb5_err (context, 1, ret, "kadm_modify: data alloc: %d", len);
+       krb5_ret_int32(sp, &mask);
+       krb5_storage_read(sp, data.data, data.length);
+       ret = hdb_value2entry(context, &data, &ent);
+       if(ret)
+           abort();
+    foo:
+       if(ent.principal /* mask & KADM5_PRINCIPAL */) {
+           krb5_unparse_name(context, ent.principal, &name1);
+           printf("    principal = %s\n", name1);
+           free(name1);
+       }
+       if(mask & KADM5_PRINC_EXPIRE_TIME) {
+           if(ent.valid_end == NULL) {
+               strlcpy(t, "never", sizeof(t));
+           } else {
+               strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", 
+                        localtime(ent.valid_end));
+           }
+           printf("    expires = %s\n", t);
+       }
+       if(mask & KADM5_PW_EXPIRATION) {
+           if(ent.pw_end == NULL) {
+               strlcpy(t, "never", sizeof(t));
+           } else {
+               strftime(t, sizeof(t), "%Y-%m-%d %H:%M:%S", 
+                        localtime(ent.pw_end));
+           }
+           printf("    password exp = %s\n", t);
+       }
+       if(mask & KADM5_LAST_PWD_CHANGE) {
+       }
+       if(mask & KADM5_ATTRIBUTES) {
+           unparse_flags(HDBFlags2int(ent.flags), 
+                         asn1_HDBFlags_units(), t, sizeof(t));
+           printf("    attributes = %s\n", t);
+       }
+       if(mask & KADM5_MAX_LIFE) {
+           if(ent.max_life == NULL)
+               strlcpy(t, "for ever", sizeof(t));
+           else
+               unparse_time(*ent.max_life, t, sizeof(t));
+           printf("    max life = %s\n", t);
+       }
+       if(mask & KADM5_MAX_RLIFE) {
+           if(ent.max_renew == NULL)
+               strlcpy(t, "for ever", sizeof(t));
+           else
+               unparse_time(*ent.max_renew, t, sizeof(t));
+           printf("    max rlife = %s\n", t);
+       }
+       if(mask & KADM5_MOD_TIME) {
+           printf("    mod time\n");
+       }
+       if(mask & KADM5_MOD_NAME) {
+           printf("    mod name\n");
+       }
+       if(mask & KADM5_KVNO) {
+           printf("    kvno = %d\n", ent.kvno);
+       }
+       if(mask & KADM5_MKVNO) {
+           printf("    mkvno\n");
+       }
+       if(mask & KADM5_AUX_ATTRIBUTES) {
+           printf("    aux attributes\n");
+       }
+       if(mask & KADM5_POLICY) {
+           printf("    policy\n");
+       }
+       if(mask & KADM5_POLICY_CLR) {
+           printf("    mod time\n");
+       }
+       if(mask & KADM5_LAST_SUCCESS) {
+           printf("    last success\n");
+       }
+       if(mask & KADM5_LAST_FAILED) {
+           printf("    last failed\n");
+       }
+       if(mask & KADM5_FAIL_AUTH_COUNT) {
+           printf("    fail auth count\n");
+       }
+       if(mask & KADM5_KEY_DATA) {
+           printf("    key data\n");
+       }
+       if(mask & KADM5_TL_DATA) {
+           printf("    tl data\n");
+       }
+       hdb_free_entry(context, &ent);
+       break;
+    case kadm_nop :
+       break;
+    default:
+       abort();
+    }
+    krb5_storage_seek(sp, end, SEEK_SET);
+}
+
+static char *realm;
+static char *config_file;
+static int version_flag;
+static int help_flag;
+
+static struct getargs args[] = {
+    { "config-file", 'c', arg_string, &config_file },
+    { "realm", 'r', arg_string, &realm },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    void *kadm_handle;
+    kadm5_server_context *server_context;
+    kadm5_config_params conf;
+    char **files;
+
+    krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+    
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if (ret)
+       krb5_err(context, 1, ret, "reading configuration files");
+
+    memset(&conf, 0, sizeof(conf));
+    if(realm) {
+       conf.mask |= KADM5_CONFIG_REALM;
+       conf.realm = realm;
+    }
+    ret = kadm5_init_with_password_ctx (context,
+                                       KADM5_ADMIN_SERVICE,
+                                       NULL,
+                                       KADM5_ADMIN_SERVICE,
+                                       &conf, 0, 0, 
+                                       &kadm_handle);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
+
+    server_context = (kadm5_server_context *)kadm_handle;
+
+    ret = kadm5_log_init (server_context);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_log_init");
+
+    ret = kadm5_log_foreach (server_context, print_entry);
+    if(ret)
+       krb5_warn(context, ret, "kadm5_log_foreach");
+
+    ret = kadm5_log_end (server_context);
+    if (ret)
+       krb5_warn(context, ret, "kadm5_log_end");
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/ent_setup.c b/src/kerberosV/src/lib/kadm5/ent_setup.c
new file mode 100644 (file)
index 0000000..736fb17
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: ent_setup.c,v 1.13 2005/05/30 20:44:54 lha Exp $");
+
+#define set_value(X, V) do { if((X) == NULL) (X) = malloc(sizeof(*(X))); *(X) = V; } while(0)
+#define set_null(X)     do { if((X) != NULL) free((X)); (X) = NULL; } while (0)
+
+static void
+attr_to_flags(unsigned attr, HDBFlags *flags)
+{
+    flags->postdate =          !(attr & KRB5_KDB_DISALLOW_POSTDATED);
+    flags->forwardable =       !(attr & KRB5_KDB_DISALLOW_FORWARDABLE);
+    flags->initial =          !!(attr & KRB5_KDB_DISALLOW_TGT_BASED);
+    flags->renewable =         !(attr & KRB5_KDB_DISALLOW_RENEWABLE);
+    flags->proxiable =         !(attr & KRB5_KDB_DISALLOW_PROXIABLE);
+    /* DUP_SKEY */
+    flags->invalid =          !!(attr & KRB5_KDB_DISALLOW_ALL_TIX);
+    flags->require_preauth =   !!(attr & KRB5_KDB_REQUIRES_PRE_AUTH);
+    /* HW_AUTH */
+    flags->server =            !(attr & KRB5_KDB_DISALLOW_SVR);
+    flags->change_pw =                !!(attr & KRB5_KDB_PWCHANGE_SERVICE);
+    flags->client =            1; /* XXX */
+    flags->ok_as_delegate =    !!(attr & KRB5_KDB_OK_AS_DELEGATE);
+}
+
+/*
+ * Create the hdb entry `ent' based on data from `princ' with
+ * `princ_mask' specifying what fields to be gotten from there and
+ * `mask' specifying what fields we want filled in.
+ */
+
+kadm5_ret_t
+_kadm5_setup_entry(kadm5_server_context *context,
+                  hdb_entry *ent,
+                  u_int32_t mask,
+                  kadm5_principal_ent_t princ, 
+                  u_int32_t princ_mask,
+                  kadm5_principal_ent_t def,
+                  u_int32_t def_mask)
+{
+    if(mask & KADM5_PRINC_EXPIRE_TIME
+       && princ_mask & KADM5_PRINC_EXPIRE_TIME) {
+       if (princ->princ_expire_time)
+           set_value(ent->valid_end, princ->princ_expire_time);
+       else
+           set_null(ent->valid_end);
+    }
+    if(mask & KADM5_PW_EXPIRATION
+       && princ_mask & KADM5_PW_EXPIRATION) {
+       if (princ->pw_expiration)
+           set_value(ent->pw_end, princ->pw_expiration);
+       else
+           set_null(ent->pw_end);
+    }
+    if(mask & KADM5_ATTRIBUTES) {
+       if (princ_mask & KADM5_ATTRIBUTES) {
+           attr_to_flags(princ->attributes, &ent->flags);
+       } else if(def_mask & KADM5_ATTRIBUTES) {
+           attr_to_flags(def->attributes, &ent->flags);
+           ent->flags.invalid = 0;
+       } else {
+           ent->flags.client      = 1;
+           ent->flags.server      = 1;
+           ent->flags.forwardable = 1;
+           ent->flags.proxiable   = 1;
+           ent->flags.renewable   = 1;
+           ent->flags.postdate    = 1;
+       }
+    }
+    if(mask & KADM5_MAX_LIFE) {
+       if(princ_mask & KADM5_MAX_LIFE) {
+           if(princ->max_life)
+             set_value(ent->max_life, princ->max_life);
+           else
+             set_null(ent->max_life);
+       } else if(def_mask & KADM5_MAX_LIFE) {
+           if(def->max_life)
+             set_value(ent->max_life, def->max_life);
+           else
+             set_null(ent->max_life);
+       }
+    }
+    if(mask & KADM5_KVNO
+       && princ_mask & KADM5_KVNO)
+       ent->kvno = princ->kvno;
+    if(mask & KADM5_MAX_RLIFE) {
+       if(princ_mask & KADM5_MAX_RLIFE) {
+         if(princ->max_renewable_life)
+           set_value(ent->max_renew, princ->max_renewable_life);
+         else
+           set_null(ent->max_renew);
+       } else if(def_mask & KADM5_MAX_RLIFE) {
+         if(def->max_renewable_life)
+           set_value(ent->max_renew, def->max_renewable_life);
+         else
+           set_null(ent->max_renew);
+       }
+    }
+    if(mask & KADM5_KEY_DATA
+       && princ_mask & KADM5_KEY_DATA) {
+       _kadm5_set_keys2(context, ent, princ->n_key_data, princ->key_data);
+    }
+    if(mask & KADM5_TL_DATA) {
+       /* XXX */
+    }
+    if(mask & KADM5_FAIL_AUTH_COUNT) {
+       /* XXX */
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/error.c b/src/kerberosV/src/lib/kadm5/error.c
new file mode 100644 (file)
index 0000000..8ac9c3c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: error.c,v 1.3 1999/12/02 17:05:06 joda Exp $");
+
+kadm5_ret_t
+_kadm5_error_code(kadm5_ret_t code)
+{
+    switch(code){
+    case HDB_ERR_EXISTS:
+       return KADM5_DUP;
+    case HDB_ERR_NOENTRY:
+       return KADM5_UNK_PRINC;
+    }
+    return code;
+}
diff --git a/src/kerberosV/src/lib/kadm5/flush.c b/src/kerberosV/src/lib/kadm5/flush.c
new file mode 100644 (file)
index 0000000..636c33c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: flush.c,v 1.2 1999/12/02 17:05:06 joda Exp $");
+
+kadm5_ret_t 
+kadm5_s_flush(void *server_handle)
+{
+    return 0;
+}
+
+kadm5_ret_t 
+kadm5_c_flush(void *server_handle)
+{
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/flush_c.c b/src/kerberosV/src/lib/kadm5/flush_c.c
new file mode 100644 (file)
index 0000000..1604c2c
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#include "kadm5_locl.h"
+
+RCSID("$KTH: flush_c.c,v 1.1 1999/03/23 18:23:36 joda Exp $");
+
+kadm5_ret_t 
+kadm5_c_flush(void *server_handle)
+{
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/flush_s.c b/src/kerberosV/src/lib/kadm5/flush_s.c
new file mode 100644 (file)
index 0000000..f7d983f
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#include "kadm5_locl.h"
+
+RCSID("$KTH: flush_s.c,v 1.1 1999/03/23 18:23:37 joda Exp $");
+
+kadm5_ret_t 
+kadm5_s_flush(void *server_handle)
+{
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/free.c b/src/kerberosV/src/lib/kadm5/free.c
new file mode 100644 (file)
index 0000000..8f64b42
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: free.c,v 1.4 1999/12/02 17:05:06 joda Exp $");
+
+void 
+kadm5_free_key_data(void *server_handle,
+                   int16_t *n_key_data, 
+                   krb5_key_data *key_data)
+{
+    int i;
+    for(i = 0; i < *n_key_data; i++){
+       if(key_data[i].key_data_contents[0]){
+           memset(key_data[i].key_data_contents[0], 
+                  0,
+                  key_data[i].key_data_length[0]);
+           free(key_data[i].key_data_contents[0]);
+       }
+       if(key_data[i].key_data_contents[1])
+           free(key_data[i].key_data_contents[1]);
+    }
+    *n_key_data = 0;
+}
+
+
+void 
+kadm5_free_principal_ent(void *server_handle,
+                        kadm5_principal_ent_t princ)
+{
+    kadm5_server_context *context = server_handle;
+    if(princ->principal)
+       krb5_free_principal(context->context, princ->principal);
+    if(princ->mod_name)
+       krb5_free_principal(context->context, princ->mod_name);
+    kadm5_free_key_data(server_handle, &princ->n_key_data, princ->key_data);
+    while(princ->n_tl_data && princ->tl_data) {
+       krb5_tl_data *tp;
+       tp = princ->tl_data;
+       princ->tl_data = tp->tl_data_next;
+       princ->n_tl_data--;
+       memset(tp->tl_data_contents, 0, tp->tl_data_length);
+       free(tp->tl_data_contents);
+       free(tp);
+    }
+    if (princ->key_data != NULL)
+       free (princ->key_data);
+}
+
+void 
+kadm5_free_name_list(void *server_handle,
+                    char **names, 
+                    int *count)
+{
+    int i;
+    for(i = 0; i < *count; i++)
+       free(names[i]);
+    free(names);
+    *count = 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/get_c.c b/src/kerberosV/src/lib/kadm5/get_c.c
new file mode 100644 (file)
index 0000000..a84984a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: get_c.c,v 1.6 2000/07/11 15:59:36 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_get_principal(void *server_handle, 
+                     krb5_principal princ, 
+                     kadm5_principal_ent_t out, 
+                     u_int32_t mask)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_get);
+    krb5_store_principal(sp, princ);
+    krb5_store_int32(sp, mask);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    if(ret)
+       return ret;
+    ret = _kadm5_client_recv(context, &reply);
+    if (ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    ret = tmp;
+    if(ret == 0)
+       kadm5_ret_principal_ent(sp, out);
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kadm5/get_princs_c.c b/src/kerberosV/src/lib/kadm5/get_princs_c.c
new file mode 100644 (file)
index 0000000..8a14dbb
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: get_princs_c.c,v 1.4 2000/07/11 16:00:19 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_get_principals(void *server_handle, 
+                      const char *exp,
+                      char ***princs, 
+                      int *count)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_get_princs);
+    krb5_store_int32(sp, exp != NULL);
+    if(exp)
+       krb5_store_string(sp, exp);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    ret = tmp;
+    if(ret == 0) {
+       int i;
+       krb5_ret_int32(sp, &tmp);
+       *princs = calloc(tmp + 1, sizeof(**princs));
+       if (*princs == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+       for(i = 0; i < tmp; i++)
+           krb5_ret_string(sp, &(*princs)[i]);
+       *count = tmp;
+    }
+out:
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kadm5/get_princs_s.c b/src/kerberosV/src/lib/kadm5/get_princs_s.c
new file mode 100644 (file)
index 0000000..7167987
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: get_princs_s.c,v 1.6 2003/09/19 00:22:35 lha Exp $");
+
+struct foreach_data {
+    const char *exp;
+    char *exp2;
+    char **princs;
+    int count;
+};
+
+static krb5_error_code
+add_princ(struct foreach_data *d, char *princ)
+{
+    char **tmp;
+    tmp = realloc(d->princs, (d->count + 1) * sizeof(*tmp));
+    if(tmp == NULL)
+       return ENOMEM;
+    d->princs = tmp;
+    d->princs[d->count++] = princ;
+    return 0;
+}
+
+static krb5_error_code
+foreach(krb5_context context, HDB *db, hdb_entry *ent, void *data)
+{
+    struct foreach_data *d = data;
+    char *princ;
+    krb5_error_code ret;
+    ret = krb5_unparse_name(context, ent->principal, &princ);
+    if(ret)
+       return ret;
+    if(d->exp){
+       if(fnmatch(d->exp, princ, 0) == 0 || fnmatch(d->exp2, princ, 0) == 0)
+           ret = add_princ(d, princ);
+       else
+           free(princ);
+    }else{
+       ret = add_princ(d, princ);
+    }
+    if(ret)
+       free(princ);
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_s_get_principals(void *server_handle, 
+                      const char *exp,
+                      char ***princs, 
+                      int *count)
+{
+    struct foreach_data d;
+    kadm5_server_context *context = server_handle;
+    kadm5_ret_t ret;
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret) {
+       krb5_warn(context->context, ret, "opening database");
+       return ret;
+    }
+    d.exp = exp;
+    {
+       krb5_realm r;
+       krb5_get_default_realm(context->context, &r);
+       asprintf(&d.exp2, "%s@%s", exp, r);
+       free(r);
+    }
+    d.princs = NULL;
+    d.count = 0;
+    ret = hdb_foreach(context->context, context->db, 0, foreach, &d);
+    context->db->hdb_close(context->context, context->db);
+    if(ret == 0)
+       ret = add_princ(&d, NULL);
+    if(ret == 0){
+       *princs = d.princs;
+       *count = d.count - 1;
+    }else
+       kadm5_free_name_list(context, d.princs, &d.count);
+    free(d.exp2);
+    return _kadm5_error_code(ret);
+}
diff --git a/src/kerberosV/src/lib/kadm5/get_s.c b/src/kerberosV/src/lib/kadm5/get_s.c
new file mode 100644 (file)
index 0000000..2054eb9
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: get_s.c,v 1.15 2005/05/30 20:43:14 lha Exp $");
+
+kadm5_ret_t
+kadm5_s_get_principal(void *server_handle, 
+                     krb5_principal princ, 
+                     kadm5_principal_ent_t out, 
+                     u_int32_t mask)
+{
+    kadm5_server_context *context = server_handle;
+    kadm5_ret_t ret;
+    hdb_entry ent;
+    
+    ent.principal = princ;
+    ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
+    if(ret)
+       return ret;
+    ret = context->db->hdb_fetch(context->context, context->db, 
+                                HDB_F_DECRYPT, &ent);
+    context->db->hdb_close(context->context, context->db);
+    if(ret)
+       return _kadm5_error_code(ret);
+
+    memset(out, 0, sizeof(*out));
+    if(mask & KADM5_PRINCIPAL)
+       ret  = krb5_copy_principal(context->context, ent.principal, 
+                                  &out->principal);
+    if(ret)
+       goto out;
+    if(mask & KADM5_PRINC_EXPIRE_TIME && ent.valid_end)
+       out->princ_expire_time = *ent.valid_end;
+    if(mask & KADM5_PW_EXPIRATION && ent.pw_end)
+       out->pw_expiration = *ent.pw_end;
+    if(mask & KADM5_LAST_PWD_CHANGE)
+       /* XXX implement */;
+    if(mask & KADM5_ATTRIBUTES){
+       out->attributes |= ent.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
+       out->attributes |= ent.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
+       out->attributes |= ent.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
+       out->attributes |= ent.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
+       out->attributes |= ent.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
+       out->attributes |= ent.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
+       out->attributes |= ent.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
+       out->attributes |= ent.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
+       out->attributes |= ent.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
+       out->attributes |= ent.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
+    }
+    if(mask & KADM5_MAX_LIFE) {
+       if(ent.max_life)
+           out->max_life = *ent.max_life;
+       else
+           out->max_life = INT_MAX;
+    }
+    if(mask & KADM5_MOD_TIME) {
+       if(ent.modified_by)
+           out->mod_date = ent.modified_by->time;
+       else
+           out->mod_date = ent.created_by.time;
+    }
+    if(mask & KADM5_MOD_NAME) {
+       if(ent.modified_by) {
+           if (ent.modified_by->principal != NULL)
+               ret = krb5_copy_principal(context->context, 
+                                         ent.modified_by->principal,
+                                         &out->mod_name);
+       } else if(ent.created_by.principal != NULL)
+           ret = krb5_copy_principal(context->context, 
+                                     ent.created_by.principal,
+                                     &out->mod_name);
+       else
+           out->mod_name = NULL;
+    }
+    if(ret)
+       goto out;
+
+    if(mask & KADM5_KVNO)
+       out->kvno = ent.kvno;
+    if(mask & KADM5_MKVNO) {
+       int n;
+       out->mkvno = 0; /* XXX */
+       for(n = 0; n < ent.keys.len; n++)
+           if(ent.keys.val[n].mkvno) {
+               out->mkvno = *ent.keys.val[n].mkvno; /* XXX this isn't right */
+               break;
+           }
+    }
+    if(mask & KADM5_AUX_ATTRIBUTES)
+       /* XXX implement */;
+    if(mask & KADM5_POLICY)
+       out->policy = NULL;
+    if(mask & KADM5_MAX_RLIFE) {
+       if(ent.max_renew)
+           out->max_renewable_life = *ent.max_renew;
+       else
+           out->max_renewable_life = INT_MAX;
+    }
+    if(mask & KADM5_LAST_SUCCESS)
+       /* XXX implement */;
+    if(mask & KADM5_LAST_FAILED)
+       /* XXX implement */;
+    if(mask & KADM5_FAIL_AUTH_COUNT)
+       /* XXX implement */;
+    if(mask & KADM5_KEY_DATA){
+       int i;
+       Key *key;
+       krb5_key_data *kd;
+       krb5_salt salt;
+       krb5_data *sp;
+       krb5_get_pw_salt(context->context, ent.principal, &salt);
+       out->key_data = malloc(ent.keys.len * sizeof(*out->key_data));
+       for(i = 0; i < ent.keys.len; i++){
+           key = &ent.keys.val[i];
+           kd = &out->key_data[i];
+           kd->key_data_ver = 2;
+           kd->key_data_kvno = ent.kvno;
+           kd->key_data_type[0] = key->key.keytype;
+           if(key->salt)
+               kd->key_data_type[1] = key->salt->type;
+           else
+               kd->key_data_type[1] = KRB5_PADATA_PW_SALT;
+           /* setup key */
+           kd->key_data_length[0] = key->key.keyvalue.length;
+           kd->key_data_contents[0] = malloc(kd->key_data_length[0]);
+           if(kd->key_data_contents[0] == NULL){
+               ret = ENOMEM;
+               break;
+           }
+           memcpy(kd->key_data_contents[0], key->key.keyvalue.data, 
+                  kd->key_data_length[0]);
+           /* setup salt */
+           if(key->salt)
+               sp = &key->salt->salt;
+           else
+               sp = &salt.saltvalue;
+           kd->key_data_length[1] = sp->length;
+           kd->key_data_contents[1] = malloc(kd->key_data_length[1]);
+           if(kd->key_data_length[1] != 0
+              && kd->key_data_contents[1] == NULL) {
+               memset(kd->key_data_contents[0], 0, kd->key_data_length[0]);
+               ret = ENOMEM;
+               break;
+           }
+           memcpy(kd->key_data_contents[1], sp->data, kd->key_data_length[1]);
+           out->n_key_data = i + 1;
+       }
+       krb5_free_salt(context->context, salt);
+    }
+    if(ret){
+       kadm5_free_principal_ent(context, out);
+       goto out;
+    }
+    if(mask & KADM5_TL_DATA)
+       /* XXX implement */;
+out:
+    hdb_free_entry(context->context, &ent);
+
+    return _kadm5_error_code(ret);
+}
diff --git a/src/kerberosV/src/lib/kadm5/init_c.c b/src/kerberosV/src/lib/kadm5/init_c.c
new file mode 100644 (file)
index 0000000..8b519a1
--- /dev/null
@@ -0,0 +1,732 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+RCSID("$KTH: init_c.c,v 1.51 2005/05/13 10:57:13 lha Exp $");
+
+static void
+set_funcs(kadm5_client_context *c)
+{
+#define SET(C, F) (C)->funcs.F = kadm5 ## _c_ ## F
+    SET(c, chpass_principal);
+    SET(c, chpass_principal_with_key);
+    SET(c, create_principal);
+    SET(c, delete_principal);
+    SET(c, destroy);
+    SET(c, flush);
+    SET(c, get_principal);
+    SET(c, get_principals);
+    SET(c, get_privs);
+    SET(c, modify_principal);
+    SET(c, randkey_principal);
+    SET(c, rename_principal);
+}
+
+kadm5_ret_t
+_kadm5_c_init_context(kadm5_client_context **ctx, 
+                     kadm5_config_params *params,
+                     krb5_context context)
+{
+    krb5_error_code ret;
+    char *colon;
+
+    *ctx = malloc(sizeof(**ctx));
+    if(*ctx == NULL)
+       return ENOMEM;
+    memset(*ctx, 0, sizeof(**ctx));
+    krb5_add_et_list (context, initialize_kadm5_error_table_r);
+    set_funcs(*ctx);
+    (*ctx)->context = context;
+    if(params->mask & KADM5_CONFIG_REALM) {
+       ret = 0;
+       (*ctx)->realm = strdup(params->realm);
+       if ((*ctx)->realm == NULL)
+           ret = ENOMEM;
+    } else
+       ret = krb5_get_default_realm((*ctx)->context, &(*ctx)->realm);
+    if (ret) {
+       free(*ctx);
+       return ret;
+    }
+    if(params->mask & KADM5_CONFIG_ADMIN_SERVER)
+       (*ctx)->admin_server = strdup(params->admin_server);
+    else {
+       char **hostlist;
+
+       ret = krb5_get_krb_admin_hst (context, &(*ctx)->realm, &hostlist);
+       if (ret) {
+           free((*ctx)->realm);
+           free(*ctx);
+           return ret;
+       }
+       (*ctx)->admin_server = strdup(*hostlist);
+       krb5_free_krbhst (context, hostlist);
+    }
+
+    if ((*ctx)->admin_server == NULL) {
+       free((*ctx)->realm);
+       free(*ctx);
+       return ENOMEM;
+    }
+    colon = strchr ((*ctx)->admin_server, ':');
+    if (colon != NULL)
+       *colon++ = '\0';
+
+    (*ctx)->kadmind_port = 0;
+
+    if(params->mask & KADM5_CONFIG_KADMIND_PORT)
+       (*ctx)->kadmind_port = params->kadmind_port;
+    else if (colon != NULL) {
+       char *end;
+
+       (*ctx)->kadmind_port = htons(strtol (colon, &end, 0));
+    }
+    if ((*ctx)->kadmind_port == 0)
+       (*ctx)->kadmind_port = krb5_getportbyname (context, "kerberos-adm", 
+                                                  "tcp", 749);
+    return 0;
+}
+
+static krb5_error_code
+get_kadm_ticket(krb5_context context,
+               krb5_ccache id,
+               krb5_principal client,
+               const char *server_name)
+{
+    krb5_error_code ret;
+    krb5_creds in, *out;
+    
+    memset(&in, 0, sizeof(in));
+    in.client = client;
+    ret = krb5_parse_name(context, server_name, &in.server);
+    if(ret) 
+       return ret;
+    ret = krb5_get_credentials(context, 0, id, &in, &out);
+    if(ret == 0)
+       krb5_free_creds(context, out);
+    krb5_free_principal(context, in.server);
+    return ret;
+}
+
+static krb5_error_code
+get_new_cache(krb5_context context,
+             krb5_principal client,
+             const char *password,
+             krb5_prompter_fct prompter,
+             const char *keytab,
+             const char *server_name,
+             krb5_ccache *ret_cache)
+{
+    krb5_error_code ret;
+    krb5_creds cred;
+    krb5_get_init_creds_opt *opt;
+    krb5_ccache id;
+    
+    ret = krb5_get_init_creds_opt_alloc (context, &opt);
+    if (ret)
+       return ret;
+
+    krb5_get_init_creds_opt_set_default_flags(context, "kadmin", 
+                                             krb5_principal_get_realm(context, 
+                                                                      client), 
+                                             opt);
+
+
+    krb5_get_init_creds_opt_set_forwardable (opt, FALSE);
+    krb5_get_init_creds_opt_set_proxiable (opt, FALSE);
+
+    if(password == NULL && prompter == NULL) {
+       krb5_keytab kt;
+       if(keytab == NULL)
+           ret = krb5_kt_default(context, &kt);
+       else
+           ret = krb5_kt_resolve(context, keytab, &kt);
+       if(ret) {
+           krb5_get_init_creds_opt_free(opt);
+           return ret;
+       }
+       ret = krb5_get_init_creds_keytab (context,
+                                         &cred,
+                                         client,
+                                         kt,
+                                         0,
+                                         server_name,
+                                         opt);
+       krb5_kt_close(context, kt);
+    } else {
+       ret = krb5_get_init_creds_password (context,
+                                           &cred,
+                                           client,
+                                           password,
+                                           prompter,
+                                           NULL,
+                                           0,
+                                           server_name,
+                                           opt);
+    }
+    krb5_get_init_creds_opt_free(opt);
+    switch(ret){
+    case 0:
+       break;
+    case KRB5_LIBOS_PWDINTR:   /* don't print anything if it was just C-c:ed */
+    case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+    case KRB5KRB_AP_ERR_MODIFIED:
+       return KADM5_BAD_PASSWORD;
+    default:
+       return ret;
+    }
+    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
+    if(ret)
+       return ret;
+    ret = krb5_cc_initialize (context, id, cred.client);
+    if (ret)
+       return ret;
+    ret = krb5_cc_store_cred (context, id, &cred);
+    if (ret)
+       return ret;
+    krb5_free_cred_contents (context, &cred);
+    *ret_cache = id;
+    return 0;
+}
+
+krb5_error_code
+_kadm5_c_get_cred_cache(krb5_context context,
+                       const char *client_name,
+                       const char *server_name,
+                       const char *password,
+                       krb5_prompter_fct prompter,
+                       const char *keytab,
+                       krb5_ccache ccache,
+                       krb5_ccache *ret_cache)
+{
+    krb5_error_code ret;
+    krb5_ccache id = NULL;
+    krb5_principal default_client = NULL, client = NULL;
+    
+    /* treat empty password as NULL */
+    if(password && *password == '\0')
+       password = NULL;
+    if(server_name == NULL)
+       server_name = KADM5_ADMIN_SERVICE;
+    
+    if(client_name != NULL) {
+       ret = krb5_parse_name(context, client_name, &client);
+       if(ret) 
+           return ret;
+    }
+
+    if(password != NULL || prompter != NULL) {
+       /* get principal from default cache, ok if this doesn't work */
+       ret = krb5_cc_default(context, &id);
+       if(ret == 0) {
+           ret = krb5_cc_get_principal(context, id, &default_client);
+           if(ret) {
+               krb5_cc_close(context, id);
+               id = NULL;
+           } else {
+               const char *name, *inst;
+               krb5_principal tmp;
+               name = krb5_principal_get_comp_string(context, 
+                                                     default_client, 0);
+               inst = krb5_principal_get_comp_string(context, 
+                                                     default_client, 1);
+               if(inst == NULL || strcmp(inst, "admin") != 0) {
+                   ret = krb5_make_principal(context, &tmp, NULL, 
+                                             name, "admin", NULL);
+                   if(ret != 0) {
+                       krb5_free_principal(context, default_client);
+                       if (client)
+                           krb5_free_principal(context, client);
+                       krb5_cc_close(context, id);
+                       return ret;
+                   }
+                   krb5_free_principal(context, default_client);
+                   default_client = tmp;
+                   krb5_cc_close(context, id);
+                   id = NULL;
+               }
+           }
+       }
+
+       if (client != NULL) {
+           /* A client was specified by the caller. */
+           if (default_client != NULL) {
+               krb5_free_principal(context, default_client);
+               default_client = NULL;
+           }
+       }
+       else if (default_client != NULL)
+           /* No client was specified by the caller, but we have a
+            * client from the default credentials cache.
+            */
+           client = default_client;
+       else {
+           /* No client was specified by the caller and we cannot determine
+            * the client from a credentials cache.
+            */
+           const char *user;
+
+           user = get_default_username ();
+
+           if(user == NULL)
+               return KADM5_FAILURE;
+           ret = krb5_make_principal(context, &client, 
+                                     NULL, user, "admin", NULL);
+           if(ret)
+               return ret;
+           if (id != NULL) {
+               krb5_cc_close(context, id);
+               id = NULL;
+           }
+       }
+    } else if(ccache != NULL) {
+       id = ccache;
+       ret = krb5_cc_get_principal(context, id, &client);
+       if(ret)
+           return ret;
+    }
+
+    
+    if(id && (default_client == NULL || 
+             krb5_principal_compare(context, client, default_client))) {
+       ret = get_kadm_ticket(context, id, client, server_name);
+       if(ret == 0) {
+           *ret_cache = id;
+           krb5_free_principal(context, default_client);
+           if (default_client != client)
+               krb5_free_principal(context, client);
+           return 0;
+       }
+       if(ccache != NULL)
+           /* couldn't get ticket from cache */
+           return -1;
+    }
+    /* get creds via AS request */
+    if(id && (id != ccache))
+       krb5_cc_close(context, id);
+    if (client != default_client)
+       krb5_free_principal(context, default_client);
+
+    ret = get_new_cache(context, client, password, prompter, keytab, 
+                       server_name, ret_cache);
+    krb5_free_principal(context, client);
+    return ret;
+}
+
+static kadm5_ret_t
+kadm_connect(kadm5_client_context *ctx)
+{
+    kadm5_ret_t ret;
+    krb5_principal server;
+    krb5_ccache cc;
+    int s;
+    struct addrinfo *ai, *a;
+    struct addrinfo hints;
+    int error;
+    char portstr[NI_MAXSERV];
+    char *hostname, *slash;
+    char *service_name;
+    krb5_context context = ctx->context;
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    
+    snprintf (portstr, sizeof(portstr), "%u", ntohs(ctx->kadmind_port));
+
+    hostname = ctx->admin_server;
+    slash = strchr (hostname, '/');
+    if (slash != NULL)
+       hostname = slash + 1;
+
+    error = getaddrinfo (hostname, portstr, &hints, &ai);
+    if (error) 
+       return KADM5_BAD_SERVER_NAME;
+    
+    for (a = ai; a != NULL; a = a->ai_next) {
+       s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (s < 0)
+           continue;
+       if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+           krb5_warn (context, errno, "connect(%s)", hostname);
+           close (s);
+           continue;
+       }
+       break;
+    }
+    if (a == NULL) {
+       freeaddrinfo (ai);
+       krb5_warnx (context, "failed to contact %s", hostname);
+       return KADM5_FAILURE;
+    }
+    ret = _kadm5_c_get_cred_cache(context,
+                                 ctx->client_name, 
+                                 ctx->service_name, 
+                                 NULL, ctx->prompter, ctx->keytab, 
+                                 ctx->ccache, &cc);
+    
+    if(ret) {
+       freeaddrinfo (ai);
+       close(s);
+       return ret;
+    }
+
+    if (ctx->realm)
+       asprintf(&service_name, "%s@%s", KADM5_ADMIN_SERVICE, ctx->realm);
+    else
+       asprintf(&service_name, "%s", KADM5_ADMIN_SERVICE);
+
+    if (service_name == NULL) {
+       freeaddrinfo (ai);
+       close(s);
+       return ENOMEM;
+    }
+
+    ret = krb5_parse_name(context, service_name, &server);
+    free(service_name);
+    if(ret) {
+       freeaddrinfo (ai);
+       if(ctx->ccache == NULL)
+           krb5_cc_close(context, cc);
+       close(s);
+       return ret;
+    }
+    ctx->ac = NULL;
+
+    ret = krb5_sendauth(context, &ctx->ac, &s, 
+                       KADMIN_APPL_VERSION, NULL, 
+                       server, AP_OPTS_MUTUAL_REQUIRED, 
+                       NULL, NULL, cc, NULL, NULL, NULL);
+    if(ret == 0) {
+       krb5_data params;
+       kadm5_config_params p;
+       memset(&p, 0, sizeof(p));
+       if(ctx->realm) {
+           p.mask |= KADM5_CONFIG_REALM;
+           p.realm = ctx->realm;
+       }
+       ret = _kadm5_marshal_params(context, &p, &params);
+       
+       ret = krb5_write_priv_message(context, ctx->ac, &s, &params);
+       krb5_data_free(&params);
+       if(ret) {
+           freeaddrinfo (ai);
+           close(s);
+           if(ctx->ccache == NULL)
+               krb5_cc_close(context, cc);
+           return ret;
+       }
+    } else if(ret == KRB5_SENDAUTH_BADAPPLVERS) {
+       close(s);
+
+       s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (s < 0) {
+           freeaddrinfo (ai);
+           return errno;
+       }
+       if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+           close (s);
+           freeaddrinfo (ai);
+           return errno;
+       }
+       ret = krb5_sendauth(context, &ctx->ac, &s, 
+                           KADMIN_OLD_APPL_VERSION, NULL, 
+                           server, AP_OPTS_MUTUAL_REQUIRED, 
+                           NULL, NULL, cc, NULL, NULL, NULL);
+    }
+    freeaddrinfo (ai);
+    if(ret) {
+       close(s);
+       return ret;
+    }
+    
+    krb5_free_principal(context, server);
+    if(ctx->ccache == NULL)
+       krb5_cc_close(context, cc);
+    if(ret) {
+       close(s);
+       return ret;
+    }
+    ctx->sock = s;
+    
+    return 0;
+}
+
+kadm5_ret_t
+_kadm5_connect(void *handle)
+{
+    kadm5_client_context *ctx = handle;
+    if(ctx->sock == -1)
+       return kadm_connect(ctx);
+    return 0;
+}
+
+static kadm5_ret_t 
+kadm5_c_init_with_context(krb5_context context,
+                         const char *client_name, 
+                         const char *password,
+                         krb5_prompter_fct prompter,
+                         const char *keytab,
+                         krb5_ccache ccache,
+                         const char *service_name,
+                         kadm5_config_params *realm_params,
+                         unsigned long struct_version,
+                         unsigned long api_version,
+                         void **server_handle)
+{
+    kadm5_ret_t ret;
+    kadm5_client_context *ctx;
+    krb5_ccache cc;
+
+    ret = _kadm5_c_init_context(&ctx, realm_params, context);
+    if(ret)
+       return ret;
+
+    if(password != NULL && *password != '\0') {
+       ret = _kadm5_c_get_cred_cache(context, 
+                                     client_name,
+                                     service_name, 
+                                     password, prompter, keytab, ccache, &cc);
+       if(ret)
+           return ret; /* XXX */
+       ccache = cc;
+    }
+    
+
+    if (client_name != NULL)
+       ctx->client_name = strdup(client_name);
+    else
+       ctx->client_name = NULL;
+    if (service_name != NULL)
+       ctx->service_name = strdup(service_name);
+    else
+       ctx->service_name = NULL;
+    ctx->prompter = prompter;
+    ctx->keytab = keytab;
+    ctx->ccache = ccache;
+    /* maybe we should copy the params here */
+    ctx->sock = -1;
+    
+    *server_handle = ctx;
+    return 0;
+}
+
+static kadm5_ret_t 
+init_context(const char *client_name, 
+            const char *password,
+            krb5_prompter_fct prompter,
+            const char *keytab,
+            krb5_ccache ccache,
+            const char *service_name,
+            kadm5_config_params *realm_params,
+            unsigned long struct_version,
+            unsigned long api_version,
+            void **server_handle)
+{
+    krb5_context context;
+    kadm5_ret_t ret;
+    kadm5_server_context *ctx;
+    
+    ret = krb5_init_context(&context);
+    if (ret)
+       return ret;
+    ret = kadm5_c_init_with_context(context,
+                                   client_name,
+                                   password,
+                                   prompter,
+                                   keytab,
+                                   ccache,
+                                   service_name,
+                                   realm_params,
+                                   struct_version,
+                                   api_version,
+                                   server_handle);
+    if(ret){
+       krb5_free_context(context);
+       return ret;
+    }
+    ctx = *server_handle;
+    ctx->my_context = 1;
+    return 0;
+}
+
+kadm5_ret_t 
+kadm5_c_init_with_password_ctx(krb5_context context,
+                              const char *client_name, 
+                              const char *password,
+                              const char *service_name,
+                              kadm5_config_params *realm_params,
+                              unsigned long struct_version,
+                              unsigned long api_version,
+                              void **server_handle)
+{
+    return kadm5_c_init_with_context(context,
+                                    client_name,
+                                    password,
+                                    krb5_prompter_posix,
+                                    NULL,
+                                    NULL,
+                                    service_name,
+                                    realm_params,
+                                    struct_version,
+                                    api_version,
+                                    server_handle);
+}
+
+kadm5_ret_t 
+kadm5_c_init_with_password(const char *client_name, 
+                          const char *password,
+                          const char *service_name,
+                          kadm5_config_params *realm_params,
+                          unsigned long struct_version,
+                          unsigned long api_version,
+                          void **server_handle)
+{
+    return init_context(client_name, 
+                       password, 
+                       krb5_prompter_posix,
+                       NULL,
+                       NULL,
+                       service_name, 
+                       realm_params, 
+                       struct_version, 
+                       api_version, 
+                       server_handle);
+}
+
+kadm5_ret_t 
+kadm5_c_init_with_skey_ctx(krb5_context context,
+                          const char *client_name, 
+                          const char *keytab,
+                          const char *service_name,
+                          kadm5_config_params *realm_params,
+                          unsigned long struct_version,
+                          unsigned long api_version,
+                          void **server_handle)
+{
+    return kadm5_c_init_with_context(context,
+                                    client_name,
+                                    NULL,
+                                    NULL,
+                                    keytab,
+                                    NULL,
+                                    service_name,
+                                    realm_params,
+                                    struct_version,
+                                    api_version,
+                                    server_handle);
+}
+
+
+kadm5_ret_t 
+kadm5_c_init_with_skey(const char *client_name, 
+                    const char *keytab,
+                    const char *service_name,
+                    kadm5_config_params *realm_params,
+                    unsigned long struct_version,
+                    unsigned long api_version,
+                    void **server_handle)
+{
+    return init_context(client_name, 
+                       NULL,
+                       NULL,
+                       keytab,
+                       NULL,
+                       service_name, 
+                       realm_params, 
+                       struct_version, 
+                       api_version, 
+                       server_handle);
+}
+
+kadm5_ret_t 
+kadm5_c_init_with_creds_ctx(krb5_context context,
+                           const char *client_name,
+                           krb5_ccache ccache,
+                           const char *service_name,
+                           kadm5_config_params *realm_params,
+                           unsigned long struct_version,
+                           unsigned long api_version,
+                           void **server_handle)
+{
+    return kadm5_c_init_with_context(context,
+                                    client_name,
+                                    NULL,
+                                    NULL,
+                                    NULL,
+                                    ccache,
+                                    service_name,
+                                    realm_params,
+                                    struct_version,
+                                    api_version,
+                                    server_handle);
+}
+
+kadm5_ret_t 
+kadm5_c_init_with_creds(const char *client_name,
+                       krb5_ccache ccache,
+                       const char *service_name,
+                       kadm5_config_params *realm_params,
+                       unsigned long struct_version,
+                       unsigned long api_version,
+                       void **server_handle)
+{
+    return init_context(client_name, 
+                       NULL,
+                       NULL,
+                       NULL,
+                       ccache,
+                       service_name, 
+                       realm_params, 
+                       struct_version, 
+                       api_version, 
+                       server_handle);
+}
+
+#if 0
+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)
+{
+}
+#endif
+
diff --git a/src/kerberosV/src/lib/kadm5/init_s.c b/src/kerberosV/src/lib/kadm5/init_s.c
new file mode 100644 (file)
index 0000000..d1dfeb4
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: init_s.c,v 1.10 2000/12/31 08:01:16 assar Exp $");
+
+
+static kadm5_ret_t 
+kadm5_s_init_with_context(krb5_context context,
+                         const char *client_name, 
+                         const char *service_name,
+                         kadm5_config_params *realm_params,
+                         unsigned long struct_version,
+                         unsigned long api_version,
+                         void **server_handle)
+{
+    kadm5_ret_t ret;
+    kadm5_server_context *ctx;
+    ret = _kadm5_s_init_context(&ctx, realm_params, context);
+    if(ret)
+       return ret;
+
+    assert(ctx->config.dbname != NULL);
+    assert(ctx->config.stash_file != NULL);
+    assert(ctx->config.acl_file != NULL);
+    assert(ctx->log_context.log_file != NULL);
+    assert(ctx->log_context.socket_name.sun_path[0] != '\0');
+
+    ret = hdb_create(ctx->context, &ctx->db, ctx->config.dbname);
+    if(ret)
+       return ret;
+    ret = hdb_set_master_keyfile (ctx->context, 
+                                 ctx->db, ctx->config.stash_file);
+    if(ret)
+       return ret;
+
+    ctx->log_context.log_fd   = -1;
+
+    ctx->log_context.socket_fd = socket (AF_UNIX, SOCK_DGRAM, 0);
+
+    ret = krb5_parse_name(ctx->context, client_name, &ctx->caller);
+    if(ret)
+       return ret;
+
+    ret = _kadm5_acl_init(ctx);
+    if(ret)
+       return ret;
+    
+    *server_handle = ctx;
+    return 0;
+}
+
+kadm5_ret_t 
+kadm5_s_init_with_password_ctx(krb5_context context,
+                              const char *client_name, 
+                              const char *password,
+                              const char *service_name,
+                              kadm5_config_params *realm_params,
+                              unsigned long struct_version,
+                              unsigned long api_version,
+                              void **server_handle)
+{
+    return kadm5_s_init_with_context(context,
+                                    client_name,
+                                    service_name,
+                                    realm_params,
+                                    struct_version,
+                                    api_version,
+                                    server_handle);
+}
+
+kadm5_ret_t 
+kadm5_s_init_with_password(const char *client_name, 
+                          const char *password,
+                          const char *service_name,
+                          kadm5_config_params *realm_params,
+                          unsigned long struct_version,
+                          unsigned long api_version,
+                          void **server_handle)
+{
+    krb5_context context;
+    kadm5_ret_t ret;
+    kadm5_server_context *ctx;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       return ret;
+    ret = kadm5_s_init_with_password_ctx(context, 
+                                        client_name, 
+                                        password, 
+                                        service_name, 
+                                        realm_params, 
+                                        struct_version, 
+                                        api_version, 
+                                        server_handle);
+    if(ret){
+       krb5_free_context(context);
+       return ret;
+    }
+    ctx = *server_handle;
+    ctx->my_context = 1;
+    return 0;
+}
+
+kadm5_ret_t 
+kadm5_s_init_with_skey_ctx(krb5_context context,
+                          const char *client_name, 
+                          const char *keytab,
+                          const char *service_name,
+                          kadm5_config_params *realm_params,
+                          unsigned long struct_version,
+                          unsigned long api_version,
+                          void **server_handle)
+{
+    return kadm5_s_init_with_context(context,
+                                    client_name,
+                                    service_name,
+                                    realm_params,
+                                    struct_version,
+                                    api_version,
+                                    server_handle);
+}
+
+kadm5_ret_t 
+kadm5_s_init_with_skey(const char *client_name,
+                      const char *keytab,
+                      const char *service_name,
+                      kadm5_config_params *realm_params,
+                      unsigned long struct_version,
+                      unsigned long api_version,
+                      void **server_handle)
+{
+    krb5_context context;
+    kadm5_ret_t ret;
+    kadm5_server_context *ctx;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       return ret;
+    ret = kadm5_s_init_with_skey_ctx(context, 
+                                    client_name, 
+                                    keytab, 
+                                    service_name, 
+                                    realm_params, 
+                                    struct_version, 
+                                    api_version, 
+                                    server_handle);
+    if(ret){
+       krb5_free_context(context);
+       return ret;
+    }
+    ctx = *server_handle;
+    ctx->my_context = 1;
+    return 0;
+}
+
+kadm5_ret_t 
+kadm5_s_init_with_creds_ctx(krb5_context context,
+                           const char *client_name,
+                           krb5_ccache ccache,
+                           const char *service_name,
+                           kadm5_config_params *realm_params,
+                           unsigned long struct_version,
+                           unsigned long api_version,
+                           void **server_handle)
+{
+    return kadm5_s_init_with_context(context,
+                                    client_name,
+                                    service_name,
+                                    realm_params,
+                                    struct_version,
+                                    api_version,
+                                    server_handle);
+}
+
+kadm5_ret_t 
+kadm5_s_init_with_creds(const char *client_name,
+                       krb5_ccache ccache,
+                       const char *service_name,
+                       kadm5_config_params *realm_params,
+                       unsigned long struct_version,
+                       unsigned long api_version,
+                       void **server_handle)
+{
+    krb5_context context;
+    kadm5_ret_t ret;
+    kadm5_server_context *ctx;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       return ret;
+    ret = kadm5_s_init_with_creds_ctx(context, 
+                                     client_name, 
+                                     ccache, 
+                                     service_name, 
+                                     realm_params, 
+                                     struct_version, 
+                                     api_version, 
+                                     server_handle);
+    if(ret){
+       krb5_free_context(context);
+       return ret;
+    }
+    ctx = *server_handle;
+    ctx->my_context = 1;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/iprop.8 b/src/kerberosV/src/lib/kadm5/iprop.8
new file mode 100644 (file)
index 0000000..18b58d5
--- /dev/null
@@ -0,0 +1,222 @@
+.\" $KTH: iprop.8,v 1.2 2005/05/24 14:22:38 lha Exp $
+.\" 
+.\" Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\"
+.Dd May 24, 2005
+.Dt IPROP 8
+.Os Heimdal
+.Sh NAME
+.Nm iprop ,
+.Nm ipropd-master ,
+.Nm ipropd-slave
+.Nd
+propagate changes to a Heimdal Kerberos master KDC to slave KDCs
+.Sh SYNOPSIS
+.Nm ipropd-master
+.Oo Fl c Ar string \*(Ba Xo
+.Fl -config-file= Ns Ar string
+.Xc
+.Oc
+.Oo Fl r Ar string \*(Ba Xo
+.Fl -realm= Ns Ar string
+.Xc
+.Oc
+.Oo Fl k Ar kspec \*(Ba Xo
+.Fl -keytab= Ns Ar kspec
+.Xc
+.Oc
+.Oo Fl d Ar file \*(Ba Xo
+.Fl -database= Ns Ar file
+.Xc
+.Oc
+.Op Fl -slave-stats-file= Ns Ar file
+.Op Fl -time-missing= Ns Ar time
+.Op Fl -time-gone= Ns Ar time
+.Op Fl -detach
+.Op Fl -version
+.Op Fl -help
+.Nm ipropd-slave
+.Oo Fl c Ar string \*(Ba Xo
+.Fl -config-file= Ns Ar string
+.Xc
+.Oc
+.Oo Fl r Ar string \*(Ba Xo
+.Fl -realm= Ns Ar string
+.Xc
+.Oc
+.Oo Fl k Ar kspec \*(Ba Xo
+.Fl -keytab= Ns Ar kspec
+.Xc
+.Oc
+.Op Fl -time-lost= Ns Ar time
+.Op Fl -detach
+.Op Fl -version
+.Op Fl -help
+.Ar master
+.Pp
+.Sh DESCRIPTION
+.Nm ipropd-master
+is used to propagate changes to a Heimdal Kerberos database from the
+master Kerberos server on which it runs to slave Kerberos servers
+running
+.Nm ipropd-slave .
+.Pp
+The slaves are specified by the contents of the
+.Pa slaves
+file in the KDC's database directory, e.g.\&
+.Pa /var/heimdal/slaves .
+This has principals one per-line of the form
+.Dl iprop/ Ns Ar slave Ns @ Ns Ar REALM
+where 
+.Ar slave 
+is the hostname of the slave server in the given 
+.Ar REALM ,
+e.g.\&
+.Dl iprop/kerberos-1.example.com@EXAMPLE.COM
+On a slave, the argument
+.Fa master
+specifies the hostname of the master server from which to receive updates.
+.Pp
+In contrast to
+.Xr hprop 8 ,
+which sends the whole database to the slaves regularly,
+.Nm
+normally sends only the changes as they happen on the master.  The
+master keeps track of all the changes by assigning a version number to
+every change to the database.  The slaves know which was the latest
+version they saw, and in this way it can be determined if they are in
+sync or not.  A log of all the changes is kept on the master.  When a
+slave is at an older version than the oldest one in the log, the whole
+database has to be sent.
+.Pp
+The changes are propagated over a secure channel (on port 2121 by
+default).  This should normally be defined as
+.Dq iprop/tcp
+in
+.Pa /etc/services
+or another source of the services database.  The master and slaves
+must each have access to a keytab with keys for the
+.Nm iprop
+service principal on the local host.
+.Pp
+There is a keep-alive feature logged in the master's
+.Pa slave-stats
+file (e.g.\&
+.Pa /var/heimdal/slave-stats ) .
+.Pp
+Supported options for
+.Nm ipropd-master :
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar string ,
+.Fl -config-file= Ns Ar string
+.Xc
+.It Xo
+.Fl r Ar string ,
+.Fl -realm= Ns Ar string
+.Xc
+.It Xo
+.Fl k Ar kspec ,
+.Fl -keytab= Ns Ar kspec
+.Xc
+keytab to get authentication from
+.It Xo
+.Fl d Ar file ,
+.Fl -database= Ns Ar file
+.Xc
+Database (default per KDC)
+.It Xo
+.Fl -slave-stats-file= Ns Ar file
+.Xc
+file for slave status information
+.It Xo
+.Fl -time-missing= Ns Ar time
+.Xc
+time before slave is polled for presence (default 2 min)
+.It Xo
+.Fl -time-gone= Ns Ar time
+.Xc
+time of inactivity after which a slave is considered gone (default 5 min)
+.It Xo
+.Fl -detach
+.Xc
+detach from console
+.It Xo
+.Fl -version
+.Xc
+.It Xo
+.Fl -help
+.Xc
+.El
+.Pp
+Supported options for
+.Nm ipropd-slave :
+.Bl -tag -width Ds
+.It Xo
+.Fl c Ar string ,
+.Fl -config-file= Ns Ar string
+.Xc
+.It Xo
+.Fl r Ar string ,
+.Fl -realm= Ns Ar string
+.Xc
+.It Xo
+.Fl k Ar kspec ,
+.Fl -keytab= Ns Ar kspec
+.Xc
+keytab to get authentication from
+.It Xo
+.Fl -time-lost= Ns Ar time
+.Xc
+time before server is considered lost (default 5 min)
+.It Xo
+.Fl -detach
+.Xc
+detach from console
+.It Xo
+.Fl -version
+.Xc
+.It Xo
+.Fl -help
+.Xc
+.El
+Time arguments for the relevant options above may be specified in forms
+like 5 min, 300 s, or simply a number of seconds.
+.Sh FILES
+.Pa slaves ,
+.Pa slave-stats
+in the database directory.
+.Sh SEE ALSO
+.Xr hpropd 8 ,
+.Xr hprop 8 ,
+.Xr krb5.conf 8 , 
+.Xr kdc 8 .
diff --git a/src/kerberosV/src/lib/kadm5/iprop.h b/src/kerberosV/src/lib/kadm5/iprop.h
new file mode 100644 (file)
index 0000000..5fb5c93
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1998-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: iprop.h,v 1.9 2003/11/23 06:24:16 lha Exp $ */
+
+#ifndef __IPROP_H__
+#define __IPROP_H__
+
+#include "kadm5_locl.h"
+#include <kerberosV/krb5-private.h>
+#include <getarg.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_UTIL_H
+#include <util.h>
+#endif
+
+#include <parse_time.h>
+
+#define IPROP_VERSION "iprop-0.0"
+
+#define KADM5_SLAVE_ACL HDB_DB_DIR "/slaves"
+
+#define KADM5_SLAVE_STATS HDB_DB_DIR "/slaves-stats"
+
+#define IPROP_NAME "iprop"
+
+#define IPROP_SERVICE "iprop"
+
+#define IPROP_PORT 2121
+
+enum iprop_cmd { I_HAVE = 1,
+                FOR_YOU = 2,
+                TELL_YOU_EVERYTHING = 3,
+                ONE_PRINC = 4,
+                NOW_YOU_HAVE = 5,
+                ARE_YOU_THERE = 6,
+                I_AM_HERE = 7
+};
+
+#endif /* __IPROP_H__ */
diff --git a/src/kerberosV/src/lib/kadm5/ipropd_master.c b/src/kerberosV/src/lib/kadm5/ipropd_master.c
new file mode 100644 (file)
index 0000000..3dd2ceb
--- /dev/null
@@ -0,0 +1,799 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "iprop.h"
+#include <rtbl.h>
+
+RCSID("$KTH: ipropd_master.c,v 1.42 2005/05/23 17:38:46 lha Exp $");
+
+static krb5_log_facility *log_facility;
+
+const char *slave_stats_file = KADM5_SLAVE_STATS;
+const char *slave_time_missing = "2 min";
+const char *slave_time_gone = "5 min";
+
+static int time_before_missing;
+static int time_before_gone;
+
+static int
+make_signal_socket (krb5_context context)
+{
+    struct sockaddr_un addr;
+    int fd;
+
+    fd = socket (AF_UNIX, SOCK_DGRAM, 0);
+    if (fd < 0)
+       krb5_err (context, 1, errno, "socket AF_UNIX");
+    memset (&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    strlcpy (addr.sun_path, KADM5_LOG_SIGNAL, sizeof(addr.sun_path));
+    unlink (addr.sun_path);
+    if (bind (fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+       krb5_err (context, 1, errno, "bind %s", addr.sun_path);
+    return fd;
+}
+
+static int
+make_listen_socket (krb5_context context, const char *port_str)
+{
+    int fd;
+    int one = 1;
+    struct sockaddr_in addr;
+
+    fd = socket (AF_INET, SOCK_STREAM, 0);
+    if (fd < 0)
+       krb5_err (context, 1, errno, "socket AF_INET");
+    setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(one));
+    memset (&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+
+    if (port_str) {
+       addr.sin_port = krb5_getportbyname (context,
+                                             port_str, "tcp", 
+                                             0);
+       if (addr.sin_port == 0) {
+           char *ptr;
+           long port;
+
+           port = strtol (port_str, &ptr, 10);
+           if (port == 0 && ptr == port_str)
+               krb5_errx (context, 1, "bad port `%s'", port_str);
+           addr.sin_port = htons(port);
+       }
+    } else {
+       addr.sin_port = krb5_getportbyname (context, IPROP_SERVICE, 
+                                           "tcp", IPROP_PORT);
+    }
+    if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+       krb5_err (context, 1, errno, "bind");
+    if (listen(fd, SOMAXCONN) < 0)
+       krb5_err (context, 1, errno, "listen");
+    return fd;
+}
+
+struct slave {
+    int fd;
+    struct sockaddr_in addr;
+    char *name;
+    krb5_auth_context ac;
+    u_int32_t version;
+    time_t seen;
+    unsigned long flags;
+#define SLAVE_F_DEAD   0x1
+#define SLAVE_F_AYT    0x2
+    struct slave *next;
+};
+
+typedef struct slave slave;
+
+static int
+check_acl (krb5_context context, const char *name)
+{
+    FILE *fp;
+    char buf[256];
+    int ret = 1;
+
+    fp = fopen (KADM5_SLAVE_ACL, "r");
+    if (fp == NULL)
+       return 1;
+    while (fgets(buf, sizeof(buf), fp) != NULL) {
+       buf[strcspn(buf, "\r\n")] = '\0';
+       if (strcmp (buf, name) == 0) {
+           ret = 0;
+           break;
+       }
+    }
+    fclose (fp);
+    return ret;
+}
+
+static void
+slave_seen(slave *s)
+{
+    s->flags &= ~SLAVE_F_AYT;
+    s->seen = time(NULL);
+}
+
+static int
+slave_missing_p (slave *s)
+{
+    if (time(NULL) > s->seen + time_before_missing)
+       return 1;
+    return 0;
+}
+
+static int
+slave_gone_p (slave *s)
+{
+    if (time(NULL) > s->seen + time_before_gone)
+       return 1;
+    return 0;
+}
+
+static void
+slave_dead(slave *s)
+{
+    if (s->fd >= 0) {
+       close (s->fd);
+       s->fd = -1;
+    }
+    s->flags |= SLAVE_F_DEAD;
+    slave_seen(s);
+}
+
+static void
+remove_slave (krb5_context context, slave *s, slave **root)
+{
+    slave **p;
+
+    if (s->fd >= 0)
+       close (s->fd);
+    if (s->name)
+       free (s->name);
+    if (s->ac)
+       krb5_auth_con_free (context, s->ac);
+
+    for (p = root; *p; p = &(*p)->next)
+       if (*p == s) {
+           *p = s->next;
+           break;
+       }
+    free (s);
+}
+
+static void
+add_slave (krb5_context context, krb5_keytab keytab, slave **root, int fd)
+{
+    krb5_principal server;
+    krb5_error_code ret;
+    slave *s;
+    socklen_t addr_len;
+    krb5_ticket *ticket = NULL;
+    char hostname[128];
+
+    s = malloc(sizeof(*s));
+    if (s == NULL) {
+       krb5_warnx (context, "add_slave: no memory");
+       return;
+    }
+    s->name = NULL;
+    s->ac = NULL;
+
+    addr_len = sizeof(s->addr);
+    s->fd = accept (fd, (struct sockaddr *)&s->addr, &addr_len);
+    if (s->fd < 0) {
+       krb5_warn (context, errno, "accept");
+       goto error;
+    }
+    gethostname(hostname, sizeof(hostname));
+    ret = krb5_sname_to_principal (context, hostname, IPROP_NAME,
+                                  KRB5_NT_SRV_HST, &server);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_sname_to_principal");
+       goto error;
+    }
+
+    ret = krb5_recvauth (context, &s->ac, &s->fd,
+                        IPROP_VERSION, server, 0, keytab, &ticket);
+    krb5_free_principal (context, server);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_recvauth");
+       goto error;
+    }
+    ret = krb5_unparse_name (context, ticket->client, &s->name);
+    if (ret) {
+       krb5_warn (context, ret, "krb5_unparse_name");
+       goto error;
+    }
+    if (check_acl (context, s->name)) {
+       krb5_warnx (context, "%s not in acl", s->name);
+       goto error;
+    }
+    krb5_free_ticket (context, ticket);
+    ticket = NULL;
+
+    {
+       slave *l = *root;
+
+       while (l) {
+           if (strcmp(l->name, s->name) == 0)
+               break;
+           l = l->next;
+       }
+       if (l) {
+           if (l->flags & SLAVE_F_DEAD) {
+               remove_slave(context, l, root);
+           } else {
+               krb5_warnx (context, "second connection from %s", s->name);
+               goto error;
+           }
+       }
+    }
+
+    krb5_warnx (context, "connection from %s", s->name);
+
+    s->version = 0;
+    s->flags = 0;
+    slave_seen(s);
+    s->next = *root;
+    *root = s;
+    return;
+error:
+    remove_slave(context, s, root);
+}
+
+struct prop_context {
+    krb5_auth_context auth_context;
+    int fd;
+};
+
+static int
+prop_one (krb5_context context, HDB *db, hdb_entry *entry, void *v)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+    krb5_data data;
+    struct slave *slave = (struct slave *)v;
+
+    ret = hdb_entry2value (context, entry, &data);
+    if (ret)
+       return ret;
+    ret = krb5_data_realloc (&data, data.length + 4);
+    if (ret) {
+       krb5_data_free (&data);
+       return ret;
+    }
+    memmove ((char *)data.data + 4, data.data, data.length - 4);
+    sp = krb5_storage_from_data(&data);
+    if (sp == NULL) {
+       krb5_data_free (&data);
+       return ENOMEM;
+    }
+    krb5_store_int32(sp, ONE_PRINC);
+    krb5_storage_free(sp);
+
+    ret = krb5_write_priv_message (context, slave->ac, &slave->fd, &data);
+    krb5_data_free (&data);
+    return ret;
+}
+
+static int
+send_complete (krb5_context context, slave *s,
+              const char *database, u_int32_t current_version)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+    HDB *db;
+    krb5_data data;
+    char buf[8];
+
+    ret = hdb_create (context, &db, database);
+    if (ret)
+       krb5_err (context, 1, ret, "hdb_create: %s", database);
+    ret = db->hdb_open (context, db, O_RDONLY, 0);
+    if (ret)
+       krb5_err (context, 1, ret, "db->open");
+
+    sp = krb5_storage_from_mem (buf, 4);
+    if (sp == NULL)
+       krb5_errx (context, 1, "krb5_storage_from_mem");
+    krb5_store_int32 (sp, TELL_YOU_EVERYTHING);
+    krb5_storage_free (sp);
+
+    data.data   = buf;
+    data.length = 4;
+
+    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
+
+    if (ret) {
+       krb5_warn (context, ret, "krb5_write_priv_message");
+       slave_dead(s);
+       return ret;
+    }
+
+    ret = hdb_foreach (context, db, 0, prop_one, s);
+    if (ret) {
+       krb5_warn (context, ret, "hdb_foreach");
+       slave_dead(s);
+       return ret;
+    }
+
+    (*db->hdb_close)(context, db);
+    (*db->hdb_destroy)(context, db);
+
+    sp = krb5_storage_from_mem (buf, 8);
+    if (sp == NULL)
+       krb5_errx (context, 1, "krb5_storage_from_mem");
+    krb5_store_int32 (sp, NOW_YOU_HAVE);
+    krb5_store_int32 (sp, current_version);
+    krb5_storage_free (sp);
+
+    data.length = 8;
+
+    s->version = current_version;
+
+    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
+    if (ret) {
+       slave_dead(s);
+       krb5_warn (context, ret, "krb5_write_priv_message");
+       return ret;
+    }
+
+    slave_seen(s);
+
+    return 0;
+}
+
+static int
+send_are_you_there (krb5_context context, slave *s)
+{
+    krb5_storage *sp;
+    krb5_data data;
+    char buf[4];
+    int ret;
+
+    if (s->flags & (SLAVE_F_DEAD|SLAVE_F_AYT))
+       return 0;
+
+    s->flags |= SLAVE_F_AYT;
+
+    data.data = buf;
+    data.length = 4;
+
+    sp = krb5_storage_from_mem (buf, 4);
+    if (sp == NULL) {
+       krb5_warnx (context, "are_you_there: krb5_data_alloc");
+       slave_dead(s);
+       return 1;
+    }
+    krb5_store_int32 (sp, ARE_YOU_THERE);
+    krb5_storage_free (sp);
+
+    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
+
+    if (ret) {
+       krb5_warn (context, ret, "are_you_there: krb5_write_priv_message");
+       slave_dead(s);
+       return 1;
+    }
+
+    return 0;
+}
+
+static int
+send_diffs (krb5_context context, slave *s, int log_fd,
+           const char *database, u_int32_t current_version)
+{
+    krb5_storage *sp;
+    u_int32_t ver;
+    time_t timestamp;
+    enum kadm_ops op;
+    u_int32_t len;
+    off_t right, left;
+    krb5_data data;
+    int ret = 0;
+
+    if (s->version == current_version)
+       return 0;
+
+    if (s->flags & SLAVE_F_DEAD)
+       return 0;
+
+    sp = kadm5_log_goto_end (log_fd);
+    right = krb5_storage_seek(sp, 0, SEEK_CUR);
+    for (;;) {
+       if (kadm5_log_previous (sp, &ver, &timestamp, &op, &len))
+           abort ();
+       left = krb5_storage_seek(sp, -16, SEEK_CUR);
+       if (ver == s->version)
+           return 0;
+       if (ver == s->version + 1)
+           break;
+       if (left == 0)
+           return send_complete (context, s, database, current_version);
+    }
+    ret = krb5_data_alloc (&data, right - left + 4);
+    if (ret) {
+       krb5_warn (context, ret, "send_diffs: krb5_data_alloc");
+       slave_dead(s);
+       return 1;
+    }
+    krb5_storage_read (sp, (char *)data.data + 4, data.length - 4);
+    krb5_storage_free(sp);
+
+    sp = krb5_storage_from_data (&data);
+    if (sp == NULL) {
+       krb5_warnx (context, "send_diffs: krb5_storage_from_data");
+       slave_dead(s);
+       return 1;
+    }
+    krb5_store_int32 (sp, FOR_YOU);
+    krb5_storage_free(sp);
+
+    ret = krb5_write_priv_message(context, s->ac, &s->fd, &data);
+    krb5_data_free(&data);
+
+    if (ret) {
+       krb5_warn (context, ret, "send_diffs: krb5_write_priv_message");
+       slave_dead(s);
+       return 1;
+    }
+    slave_seen(s);
+
+    return 0;
+}
+
+static int
+process_msg (krb5_context context, slave *s, int log_fd,
+            const char *database, u_int32_t current_version)
+{
+    int ret = 0;
+    krb5_data out;
+    krb5_storage *sp;
+    int32_t tmp;
+
+    ret = krb5_read_priv_message(context, s->ac, &s->fd, &out);
+    if(ret) {
+       krb5_warn (context, ret, "error reading message from %s", s->name);
+       return 1;
+    }
+
+    sp = krb5_storage_from_mem (out.data, out.length);
+    if (sp == NULL) {
+       krb5_warnx (context, "process_msg: no memory");
+       krb5_data_free (&out);
+       return 1;
+    }
+    if (krb5_ret_int32 (sp, &tmp) != 0) {
+       krb5_warnx (context, "process_msg: client send too short command");
+       krb5_data_free (&out);
+       return 1;
+    }
+    switch (tmp) {
+    case I_HAVE :
+       ret = krb5_ret_int32 (sp, &tmp);
+       if (ret != 0) {
+           krb5_warnx (context, "process_msg: client send too I_HAVE data");
+           break;
+       }
+       s->version = tmp;
+       ret = send_diffs (context, s, log_fd, database, current_version);
+       break;
+    case I_AM_HERE :
+       break;
+    case ARE_YOU_THERE:
+    case FOR_YOU :
+    default :
+       krb5_warnx (context, "Ignoring command %d", tmp);
+       break;
+    }
+
+    krb5_data_free (&out);
+
+    slave_seen(s);
+
+    return ret;
+}
+
+#define SLAVE_NAME     "Name"
+#define SLAVE_ADDRESS  "Address"
+#define SLAVE_VERSION  "Version"
+#define SLAVE_STATUS   "Status"
+#define SLAVE_SEEN     "Last Seen"
+
+static void
+write_stats(krb5_context context, slave *slaves, u_int32_t current_version)
+{
+    char str[100];
+    rtbl_t tbl;
+    time_t t = time(NULL);
+    FILE *fp;
+
+    fp = fopen(slave_stats_file, "w");
+    if (fp == NULL)
+       return;
+
+    krb5_format_time(context, t, str, sizeof(str), TRUE); 
+    fprintf(fp, "Status for slaves, last updated: %s\n\n", str);
+
+    fprintf(fp, "Master version: %lu\n\n", (unsigned long)current_version);
+
+    tbl = rtbl_create();
+    if (tbl == NULL) {
+       fclose(fp);
+       return;
+    }
+
+    rtbl_add_column(tbl, SLAVE_NAME, 0);
+    rtbl_add_column(tbl, SLAVE_ADDRESS, 0);
+    rtbl_add_column(tbl, SLAVE_VERSION, RTBL_ALIGN_RIGHT);
+    rtbl_add_column(tbl, SLAVE_STATUS, 0);
+    rtbl_add_column(tbl, SLAVE_SEEN, 0);
+
+    rtbl_set_prefix(tbl, "  ");
+    rtbl_set_column_prefix(tbl, SLAVE_NAME, "");
+
+    while (slaves) {
+       krb5_address addr;
+       krb5_error_code ret;
+       rtbl_add_column_entry(tbl, SLAVE_NAME, slaves->name);
+       ret = krb5_sockaddr2address (context, 
+                                    (struct sockaddr*)&slaves->addr, &addr);
+       if(ret == 0) {
+           krb5_print_address(&addr, str, sizeof(str), NULL);
+           krb5_free_address(context, &addr);
+           rtbl_add_column_entry(tbl, SLAVE_ADDRESS, str);
+       } else
+           rtbl_add_column_entry(tbl, SLAVE_ADDRESS, "<unknown>");
+       
+       snprintf(str, sizeof(str), "%u", (unsigned)slaves->version);
+       rtbl_add_column_entry(tbl, SLAVE_VERSION, str);
+
+       if (slaves->flags & SLAVE_F_DEAD)
+           rtbl_add_column_entry(tbl, SLAVE_STATUS, "Down");
+       else
+           rtbl_add_column_entry(tbl, SLAVE_STATUS, "Up");
+
+       ret = krb5_format_time(context, slaves->seen, str, sizeof(str), TRUE); 
+       rtbl_add_column_entry(tbl, SLAVE_SEEN, str);
+
+       slaves = slaves->next;
+    }
+
+    rtbl_format(tbl, fp);
+    rtbl_destroy(tbl);
+
+    fclose(fp);
+}
+
+
+static char *realm;
+static int version_flag;
+static int help_flag;
+static char *keytab_str = "HDB:";
+static char *database;
+static char *config_file;
+static char *port_str;
+static int detach_from_console = 0;
+
+static struct getargs args[] = {
+    { "config-file", 'c', arg_string, &config_file },
+    { "realm", 'r', arg_string, &realm },
+    { "keytab", 'k', arg_string, &keytab_str,
+      "keytab to get authentication from", "kspec" },
+    { "database", 'd', arg_string, &database, "database", "file"},
+    { "slave-stats-file", 0, arg_string, &slave_stats_file, 
+      "file for slave status information", "file"},
+    { "time-missing", 0, arg_string, &slave_time_missing, 
+      "time before slave is polled for presence", "time"},
+    { "time-gone", 0, arg_string, &slave_time_gone,
+      "time of inactivity after which a slave is considered gone", "time"},
+    { "port", 0, arg_string, &port_str,
+      "port ipropd will listen to", "port"},
+    { "detach", 0, arg_flag, &detach_from_console, 
+      "detach from console" },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    void *kadm_handle;
+    kadm5_server_context *server_context;
+    kadm5_config_params conf;
+    int signal_fd, listen_fd;
+    int log_fd;
+    slave *slaves = NULL;
+    u_int32_t current_version = 0, old_version = 0;
+    krb5_keytab keytab;
+    int optind;
+    char **files;
+    
+    optind = krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+    
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if (ret)
+       krb5_err(context, 1, ret, "reading configuration files");
+
+    time_before_gone = parse_time (slave_time_gone,  "s");
+    if (time_before_gone < 0)
+       krb5_errx (context, 1, "couldn't parse time: %s", slave_time_gone);
+    time_before_missing = parse_time (slave_time_missing,  "s");
+    if (time_before_missing < 0)
+       krb5_errx (context, 1, "couldn't parse time: %s", slave_time_missing);
+
+    if (detach_from_console)
+       daemon(0, 0);
+    pidfile (NULL);
+    krb5_openlog (context, "ipropd-master", &log_facility);
+    krb5_set_warn_dest(context, log_facility);
+
+    ret = krb5_kt_register(context, &hdb_kt_ops);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_kt_register");
+
+    ret = krb5_kt_resolve(context, keytab_str, &keytab);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_kt_resolve: %s", keytab_str);
+    
+    memset(&conf, 0, sizeof(conf));
+    if(realm) {
+       conf.mask |= KADM5_CONFIG_REALM;
+       conf.realm = realm;
+    }
+    ret = kadm5_init_with_skey_ctx (context,
+                                   KADM5_ADMIN_SERVICE,
+                                   NULL,
+                                   KADM5_ADMIN_SERVICE,
+                                   &conf, 0, 0, 
+                                   &kadm_handle);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
+
+    server_context = (kadm5_server_context *)kadm_handle;
+
+    log_fd = open (server_context->log_context.log_file, O_RDONLY, 0);
+    if (log_fd < 0)
+       krb5_err (context, 1, errno, "open %s",
+                 server_context->log_context.log_file);
+
+    signal_fd = make_signal_socket (context);
+    listen_fd = make_listen_socket (context, port_str);
+
+    signal (SIGPIPE, SIG_IGN);
+
+    for (;;) {
+       slave *p;
+       fd_set readset;
+       int max_fd = 0;
+       struct timeval to = {30, 0};
+       u_int32_t vers;
+
+       if (signal_fd >= FD_SETSIZE || listen_fd >= FD_SETSIZE)
+           krb5_errx (context, 1, "fd too large");
+
+       FD_ZERO(&readset);
+       FD_SET(signal_fd, &readset);
+       max_fd = max(max_fd, signal_fd);
+       FD_SET(listen_fd, &readset);
+       max_fd = max(max_fd, listen_fd);
+
+       for (p = slaves; p != NULL; p = p->next) {
+           if (p->flags & SLAVE_F_DEAD)
+               continue;
+           FD_SET(p->fd, &readset);
+           max_fd = max(max_fd, p->fd);
+       }
+
+       ret = select (max_fd + 1,
+                     &readset, NULL, NULL, &to);
+       if (ret < 0) {
+           if (errno == EINTR)
+               continue;
+           else
+               krb5_err (context, 1, errno, "select");
+       }
+
+       if (ret == 0) {
+           old_version = current_version;
+           kadm5_log_get_version_fd (log_fd, &current_version);
+
+           if (current_version > old_version) {
+               for (p = slaves; p != NULL; p = p->next) {
+                   if (p->flags & SLAVE_F_DEAD)
+                       continue;
+                   send_diffs (context, p, log_fd, database, current_version);
+               }
+           }
+       }
+
+       if (ret && FD_ISSET(signal_fd, &readset)) {
+           struct sockaddr_un peer_addr;
+           socklen_t peer_len = sizeof(peer_addr);
+
+           if(recvfrom(signal_fd, (void *)&vers, sizeof(vers), 0,
+                       (struct sockaddr *)&peer_addr, &peer_len) < 0) {
+               krb5_warn (context, errno, "recvfrom");
+               continue;
+           }
+           --ret;
+           assert(ret >= 0);
+           old_version = current_version;
+           kadm5_log_get_version_fd (log_fd, &current_version);
+           for (p = slaves; p != NULL; p = p->next)
+               send_diffs (context, p, log_fd, database, current_version);
+        }
+
+       for(p = slaves; p != NULL; p = p->next) {
+           if (p->flags & SLAVE_F_DEAD)
+               continue;
+           if (ret && FD_ISSET(p->fd, &readset)) {
+               --ret;
+               assert(ret >= 0);
+               if(process_msg (context, p, log_fd, database, current_version))
+                   slave_dead(p);
+           } else if (slave_gone_p (p))
+               slave_dead (p);
+           else if (slave_missing_p (p))
+               send_are_you_there (context, p);
+       }
+
+       if (ret && FD_ISSET(listen_fd, &readset)) {
+           add_slave (context, keytab, &slaves, listen_fd);
+           --ret;
+           assert(ret >= 0);
+       }
+       write_stats(context, slaves, current_version);
+    }
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/ipropd_slave.c b/src/kerberosV/src/lib/kadm5/ipropd_slave.c
new file mode 100644 (file)
index 0000000..9759c5a
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "iprop.h"
+#include <util.h>
+
+RCSID("$KTH: ipropd_slave.c,v 1.39 2005/05/23 17:39:35 lha Exp $");
+
+static krb5_log_facility *log_facility;
+static char *server_time_lost = "5 min";
+static int time_before_lost;
+
+static int
+connect_to_master (krb5_context context, const char *master,
+                  const char *port_str)
+{
+    int fd;
+    struct sockaddr_in addr;
+    struct hostent *he;
+
+    fd = socket (AF_INET, SOCK_STREAM, 0);
+    if (fd < 0)
+       krb5_err (context, 1, errno, "socket AF_INET");
+    memset (&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    if (port_str) {
+       addr.sin_port = krb5_getportbyname (context,
+                                           port_str, "tcp", 
+                                           0);
+       if (addr.sin_port == 0) {
+           char *ptr;
+           long port;
+           
+           port = strtol (port_str, &ptr, 10);
+           if (port == 0 && ptr == port_str)
+               krb5_errx (context, 1, "bad port `%s'", port_str);
+           addr.sin_port = htons(port);
+       }
+    } else {
+       addr.sin_port = krb5_getportbyname (context, IPROP_SERVICE, 
+                                           "tcp", IPROP_PORT);
+    }
+    he = roken_gethostbyname (master);
+    if (he == NULL)
+       krb5_errx (context, 1, "gethostbyname: %s", hstrerror(h_errno));
+    memcpy (&addr.sin_addr, he->h_addr, sizeof(addr.sin_addr));
+    if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+       krb5_err (context, 1, errno, "connect");
+    return fd;
+}
+
+static void
+get_creds(krb5_context context, const char *keytab_str,
+         krb5_ccache *cache, const char *host)
+{
+    krb5_keytab keytab;
+    krb5_principal client;
+    krb5_error_code ret;
+    krb5_get_init_creds_opt *init_opts;
+    krb5_creds creds;
+    char *server;
+    char keytab_buf[256];
+    
+    if (keytab_str == NULL) {
+       ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf));
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_kt_default_name");
+       keytab_str = keytab_buf;
+    }
+
+    ret = krb5_kt_resolve(context, keytab_str, &keytab);
+    if(ret)
+       krb5_err(context, 1, ret, "%s", keytab_str);
+    
+    ret = krb5_sname_to_principal (context, NULL, IPROP_NAME,
+                                  KRB5_NT_SRV_HST, &client);
+    if (ret) krb5_err(context, 1, ret, "krb5_sname_to_principal");
+
+    ret = krb5_get_init_creds_opt_alloc(context, &init_opts);
+    if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");
+
+    asprintf (&server, "%s/%s", IPROP_NAME, host);
+    if (server == NULL)
+       krb5_errx (context, 1, "malloc: no memory");
+
+    ret = krb5_get_init_creds_keytab(context, &creds, client, keytab,
+                                    0, server, init_opts);
+    free (server);
+    krb5_get_init_creds_opt_free(init_opts);
+    if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");
+    
+    ret = krb5_kt_close(context, keytab);
+    if(ret) krb5_err(context, 1, ret, "krb5_kt_close");
+    
+    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, cache);
+    if(ret) krb5_err(context, 1, ret, "krb5_cc_gen_new");
+
+    ret = krb5_cc_initialize(context, *cache, client);
+    if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+    ret = krb5_cc_store_cred(context, *cache, &creds);
+    if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");
+}
+
+static void
+ihave (krb5_context context, krb5_auth_context auth_context,
+       int fd, u_int32_t version)
+{
+    int ret;
+    u_char buf[8];
+    krb5_storage *sp;
+    krb5_data data;
+
+    sp = krb5_storage_from_mem (buf, 8);
+    krb5_store_int32 (sp, I_HAVE);
+    krb5_store_int32 (sp, version);
+    krb5_storage_free (sp);
+    data.length = 8;
+    data.data   = buf;
+    
+    ret = krb5_write_priv_message(context, auth_context, &fd, &data);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_write_priv_message");
+}
+
+static void
+receive_loop (krb5_context context,
+             krb5_storage *sp,
+             kadm5_server_context *server_context)
+{
+    int ret;
+    off_t left, right;
+    void *buf;
+    int32_t vers;
+
+    do {
+       int32_t len, timestamp, tmp;
+       enum kadm_ops op;
+
+       if(krb5_ret_int32 (sp, &vers) != 0)
+           return;
+       krb5_ret_int32 (sp, &timestamp);
+       krb5_ret_int32 (sp, &tmp);
+       op = tmp;
+       krb5_ret_int32 (sp, &len);
+       if (vers <= server_context->log_context.version)
+           krb5_storage_seek(sp, len + 8, SEEK_CUR);
+    } while(vers <= server_context->log_context.version);
+
+    left  = krb5_storage_seek (sp, -16, SEEK_CUR);
+    right = krb5_storage_seek (sp, 0, SEEK_END);
+    buf = malloc (right - left);
+    if (buf == NULL && (right - left) != 0) {
+       krb5_warnx (context, "malloc: no memory");
+       return;
+    }
+    krb5_storage_seek (sp, left, SEEK_SET);
+    krb5_storage_read (sp, buf, right - left);
+    write (server_context->log_context.log_fd, buf, right-left);
+    fsync (server_context->log_context.log_fd);
+    free (buf);
+
+    krb5_storage_seek (sp, left, SEEK_SET);
+
+    for(;;) {
+       int32_t len, timestamp, tmp;
+       enum kadm_ops op;
+
+       if(krb5_ret_int32 (sp, &vers) != 0)
+           break;
+       krb5_ret_int32 (sp, &timestamp);
+       krb5_ret_int32 (sp, &tmp);
+       op = tmp;
+       krb5_ret_int32 (sp, &len);
+
+       ret = kadm5_log_replay (server_context,
+                               op, vers, len, sp);
+       if (ret)
+           krb5_warn (context, ret, "kadm5_log_replay: %d", (int)vers);
+       else
+           server_context->log_context.version = vers;
+       krb5_storage_seek (sp, 8, SEEK_CUR);
+    }
+}
+
+static void
+receive (krb5_context context,
+        krb5_storage *sp,
+        kadm5_server_context *server_context)
+{
+    int ret;
+
+    ret = server_context->db->hdb_open(context,
+                                      server_context->db,
+                                      O_RDWR | O_CREAT, 0600);
+    if (ret)
+       krb5_err (context, 1, ret, "db->open");
+
+    receive_loop (context, sp, server_context);
+
+    ret = server_context->db->hdb_close (context, server_context->db);
+    if (ret)
+       krb5_err (context, 1, ret, "db->close");
+}
+
+static void
+send_im_here (krb5_context context, int fd,
+             krb5_auth_context auth_context)
+{
+    krb5_storage *sp;
+    krb5_data data;
+    int ret;
+
+    ret = krb5_data_alloc (&data, 4);
+    if (ret)
+       krb5_err (context, 1, ret, "send_im_here");
+
+    sp = krb5_storage_from_data (&data);
+    if (sp == NULL)
+       krb5_errx (context, 1, "krb5_storage_from_data");
+    krb5_store_int32(sp, I_AM_HERE);
+    krb5_storage_free(sp);
+
+    ret = krb5_write_priv_message(context, auth_context, &fd, &data);
+    krb5_data_free(&data);
+
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_write_priv_message");
+}
+
+static void
+receive_everything (krb5_context context, int fd,
+                   kadm5_server_context *server_context,
+                   krb5_auth_context auth_context)
+{
+    int ret;
+    krb5_data data;
+    int32_t vno;
+    int32_t opcode;
+    krb5_storage *sp;
+
+    char *dbname;
+    HDB *mydb;
+  
+    asprintf(&dbname, "%s-NEW", server_context->db->hdb_name);
+    ret = hdb_create(context, &mydb, dbname);
+    if(ret)
+       krb5_err(context,1, ret, "hdb_create");
+    free(dbname);
+    ret = hdb_set_master_keyfile (context,
+                                 mydb, server_context->config.stash_file);
+    if(ret)
+       krb5_err(context,1, ret, "hdb_set_master_keyfile");
+    /* I really want to use O_EXCL here, but given that I can't easily clean
+       up on error, I won't */
+    ret = mydb->hdb_open(context, mydb, O_RDWR | O_CREAT | O_TRUNC, 0600);
+
+    if (ret)
+       krb5_err (context, 1, ret, "db->open");
+
+    sp = NULL;
+    do {
+       ret = krb5_read_priv_message(context, auth_context, &fd, &data);
+
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_read_priv_message");
+
+       sp = krb5_storage_from_data (&data);
+       if (sp == NULL)
+           krb5_errx (context, 1, "krb5_storage_from_data");
+       krb5_ret_int32 (sp, &opcode);
+       if (opcode == ONE_PRINC) {
+           krb5_data fake_data;
+           hdb_entry entry;
+
+           krb5_storage_free(sp);
+
+           fake_data.data   = (char *)data.data + 4;
+           fake_data.length = data.length - 4;
+
+           ret = hdb_value2entry (context, &fake_data, &entry);
+           if (ret)
+               krb5_err (context, 1, ret, "hdb_value2entry");
+           ret = mydb->hdb_store(server_context->context,
+                                 mydb,
+                                 0, &entry);
+           if (ret)
+               krb5_err (context, 1, ret, "hdb_store");
+
+           hdb_free_entry (context, &entry);
+           krb5_data_free (&data);
+       } else if (opcode == NOW_YOU_HAVE)
+           ;
+       else
+           krb5_errx (context, 1, "strange opcode %d", opcode);
+    } while (opcode == ONE_PRINC);
+
+    if (opcode != NOW_YOU_HAVE)
+       krb5_errx (context, 1, "receive_everything: strange %d", opcode);
+
+    krb5_ret_int32 (sp, &vno);
+    krb5_storage_free(sp);
+
+    ret = kadm5_log_reinit (server_context);
+    if (ret)
+       krb5_err(context, 1, ret, "kadm5_log_reinit");
+
+    ret = kadm5_log_set_version (server_context, vno - 1);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_log_set_version");
+
+    ret = kadm5_log_nop (server_context);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_log_nop");
+
+    krb5_data_free (&data);
+
+    ret = mydb->hdb_rename (context, mydb, server_context->db->hdb_name);
+    if (ret)
+       krb5_err (context, 1, ret, "db->rename");
+
+    ret = mydb->hdb_close (context, mydb);
+    if (ret)
+       krb5_err (context, 1, ret, "db->close");
+
+    ret = mydb->hdb_destroy (context, mydb);
+    if (ret)
+       krb5_err (context, 1, ret, "db->destroy");
+}
+
+static char *config_file;
+static char *realm;
+static int version_flag;
+static int help_flag;
+static char *keytab_str;
+static char *port_str;
+static int detach_from_console = 0;
+
+static struct getargs args[] = {
+    { "config-file", 'c', arg_string, &config_file },
+    { "realm", 'r', arg_string, &realm },
+    { "keytab", 'k', arg_string, &keytab_str,
+      "keytab to get authentication from", "kspec" },
+    { "time-lost", 0, arg_string, &server_time_lost,
+      "time before server is considered lost", "time" },
+    { "port", 0, arg_string, &port_str,
+      "port ipropd-slave will connect to", "port"},
+    { "detach", 0, arg_flag, &detach_from_console, 
+      "detach from console" },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage (int code, struct getargs *args, int num_args)
+{
+    arg_printusage (args, num_args, NULL, "master");
+    exit (code);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_auth_context auth_context;
+    void *kadm_handle;
+    kadm5_server_context *server_context;
+    kadm5_config_params conf;
+    int master_fd;
+    krb5_ccache ccache;
+    krb5_principal server;
+    char **files;
+
+    int optind;
+    const char *master;
+    
+    optind = krb5_program_setup(&context, argc, argv, args, num_args, usage);
+    
+    if(help_flag)
+       usage (0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if (ret)
+       krb5_err(context, 1, ret, "reading configuration files");
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 1)
+       usage (1, args, num_args);
+
+    master = argv[0];
+
+    if (detach_from_console)
+       daemon(0, 0);
+    pidfile (NULL);
+    krb5_openlog (context, "ipropd-slave", &log_facility);
+    krb5_set_warn_dest(context, log_facility);
+
+    ret = krb5_kt_register(context, &hdb_kt_ops);
+    if(ret)
+       krb5_err(context, 1, ret, "krb5_kt_register");
+
+    time_before_lost = parse_time (server_time_lost,  "s");
+    if (time_before_lost < 0)
+       krb5_errx (context, 1, "couldn't parse time: %s", server_time_lost);
+
+    memset(&conf, 0, sizeof(conf));
+    if(realm) {
+       conf.mask |= KADM5_CONFIG_REALM;
+       conf.realm = realm;
+    }
+    ret = kadm5_init_with_password_ctx (context,
+                                       KADM5_ADMIN_SERVICE,
+                                       NULL,
+                                       KADM5_ADMIN_SERVICE,
+                                       &conf, 0, 0, 
+                                       &kadm_handle);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
+
+    server_context = (kadm5_server_context *)kadm_handle;
+
+    ret = kadm5_log_init (server_context);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_log_init");
+
+    get_creds(context, keytab_str, &ccache, master);
+
+    master_fd = connect_to_master (context, master, port_str);
+
+    ret = krb5_sname_to_principal (context, master, IPROP_NAME,
+                                  KRB5_NT_SRV_HST, &server);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_sname_to_principal");
+
+    auth_context = NULL;
+    ret = krb5_sendauth (context, &auth_context, &master_fd,
+                        IPROP_VERSION, NULL, server,
+                        AP_OPTS_MUTUAL_REQUIRED, NULL, NULL,
+                        ccache, NULL, NULL, NULL);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_sendauth");
+
+    ihave (context, auth_context, master_fd,
+          server_context->log_context.version);
+
+    for (;;) {
+       int ret;
+       krb5_data out;
+       krb5_storage *sp;
+       int32_t tmp;
+       fd_set readset;
+       struct timeval to;
+
+       if (master_fd >= FD_SETSIZE)
+           krb5_errx (context, 1, "fd too large");
+
+       FD_ZERO(&readset);
+       FD_SET(master_fd, &readset);
+
+       to.tv_sec = time_before_lost;
+       to.tv_usec = 0;
+
+       ret = select (master_fd + 1,
+                     &readset, NULL, NULL, &to);
+       if (ret < 0) {
+           if (errno == EINTR)
+               continue;
+           else
+               krb5_err (context, 1, errno, "select");
+       }
+       if (ret == 0)
+           krb5_errx (context, 1, "server didn't send a message "
+                      "in %d seconds", time_before_lost);
+
+       ret = krb5_read_priv_message(context, auth_context, &master_fd, &out);
+
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_read_priv_message");
+
+       sp = krb5_storage_from_mem (out.data, out.length);
+       krb5_ret_int32 (sp, &tmp);
+       switch (tmp) {
+       case FOR_YOU :
+           receive (context, sp, server_context);
+           ihave (context, auth_context, master_fd,
+                  server_context->log_context.version);
+           break;
+       case TELL_YOU_EVERYTHING :
+           receive_everything (context, master_fd, server_context,
+                               auth_context);
+           break;
+       case ARE_YOU_THERE :
+           send_im_here (context, master_fd, auth_context);
+           break;
+       case NOW_YOU_HAVE :
+       case I_HAVE :
+       case ONE_PRINC :
+       case I_AM_HERE :
+       default :
+           krb5_warnx (context, "Ignoring command %d", tmp);
+           break;
+       }
+       krb5_storage_free (sp);
+       krb5_data_free (&out);
+    }
+    
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/kadm5-private.h b/src/kerberosV/src/lib/kadm5/kadm5-private.h
new file mode 100644 (file)
index 0000000..1c40b92
--- /dev/null
@@ -0,0 +1,533 @@
+/* This is a generated file */
+#ifndef __kadm5_private_h__
+#define __kadm5_private_h__
+
+#include <stdarg.h>
+
+kadm5_ret_t
+_kadm5_acl_check_permission (
+       kadm5_server_context */*context*/,
+       unsigned /*op*/,
+       krb5_const_principal /*princ*/);
+
+kadm5_ret_t
+_kadm5_acl_init (kadm5_server_context */*context*/);
+
+kadm5_ret_t
+_kadm5_bump_pw_expire (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/);
+
+krb5_error_code
+_kadm5_c_get_cred_cache (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*server_name*/,
+       const char */*password*/,
+       krb5_prompter_fct /*prompter*/,
+       const char */*keytab*/,
+       krb5_ccache /*ccache*/,
+       krb5_ccache */*ret_cache*/);
+
+kadm5_ret_t
+_kadm5_c_init_context (
+       kadm5_client_context **/*ctx*/,
+       kadm5_config_params */*params*/,
+       krb5_context /*context*/);
+
+kadm5_ret_t
+_kadm5_client_recv (
+       kadm5_client_context */*context*/,
+       krb5_data */*reply*/);
+
+kadm5_ret_t
+_kadm5_client_send (
+       kadm5_client_context */*context*/,
+       krb5_storage */*sp*/);
+
+int
+_kadm5_cmp_keys (
+       Key */*keys1*/,
+       int /*len1*/,
+       Key */*keys2*/,
+       int /*len2*/);
+
+kadm5_ret_t
+_kadm5_connect (void */*handle*/);
+
+kadm5_ret_t
+_kadm5_error_code (kadm5_ret_t /*code*/);
+
+void
+_kadm5_free_keys (
+       krb5_context /*context*/,
+       int /*len*/,
+       Key */*keys*/);
+
+void
+_kadm5_init_keys (
+       Key */*keys*/,
+       int /*len*/);
+
+kadm5_ret_t
+_kadm5_marshal_params (
+       krb5_context /*context*/,
+       kadm5_config_params */*params*/,
+       krb5_data */*out*/);
+
+kadm5_ret_t
+_kadm5_privs_to_string (
+       u_int32_t /*privs*/,
+       char */*string*/,
+       size_t /*len*/);
+
+HDB *
+_kadm5_s_get_db (void */*server_handle*/);
+
+kadm5_ret_t
+_kadm5_s_init_context (
+       kadm5_server_context **/*ctx*/,
+       kadm5_config_params */*params*/,
+       krb5_context /*context*/);
+
+kadm5_ret_t
+_kadm5_set_keys (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/,
+       const char */*password*/);
+
+kadm5_ret_t
+_kadm5_set_keys2 (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/,
+       int16_t /*n_key_data*/,
+       krb5_key_data */*key_data*/);
+
+kadm5_ret_t
+_kadm5_set_keys3 (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/,
+       int /*n_keys*/,
+       krb5_keyblock */*keyblocks*/);
+
+kadm5_ret_t
+_kadm5_set_keys_randomly (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/,
+       krb5_keyblock **/*new_keys*/,
+       int */*n_keys*/);
+
+kadm5_ret_t
+_kadm5_set_modifier (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/);
+
+kadm5_ret_t
+_kadm5_setup_entry (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/,
+       u_int32_t /*mask*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*princ_mask*/,
+       kadm5_principal_ent_t /*def*/,
+       u_int32_t /*def_mask*/);
+
+kadm5_ret_t
+_kadm5_string_to_privs (
+       const char */*s*/,
+       u_int32_t* /*privs*/);
+
+kadm5_ret_t
+_kadm5_unmarshal_params (
+       krb5_context /*context*/,
+       krb5_data */*in*/,
+       kadm5_config_params */*params*/);
+
+kadm5_ret_t
+kadm5_c_chpass_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_c_chpass_principal_with_key (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       int /*n_key_data*/,
+       krb5_key_data */*key_data*/);
+
+kadm5_ret_t
+kadm5_c_create_principal (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_c_delete_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/);
+
+kadm5_ret_t
+kadm5_c_destroy (void */*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_flush (void */*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_get_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       kadm5_principal_ent_t /*out*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_c_get_principals (
+       void */*server_handle*/,
+       const char */*exp*/,
+       char ***/*princs*/,
+       int */*count*/);
+
+kadm5_ret_t
+kadm5_c_get_privs (
+       void */*server_handle*/,
+       u_int32_t */*privs*/);
+
+kadm5_ret_t
+kadm5_c_init_with_creds (
+       const char */*client_name*/,
+       krb5_ccache /*ccache*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_init_with_creds_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       krb5_ccache /*ccache*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_init_with_password (
+       const char */*client_name*/,
+       const char */*password*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_init_with_password_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*password*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_init_with_skey (
+       const char */*client_name*/,
+       const char */*keytab*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_init_with_skey_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*keytab*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_c_modify_principal (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_c_randkey_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       krb5_keyblock **/*new_keys*/,
+       int */*n_keys*/);
+
+kadm5_ret_t
+kadm5_c_rename_principal (
+       void */*server_handle*/,
+       krb5_principal /*source*/,
+       krb5_principal /*target*/);
+
+kadm5_ret_t
+kadm5_log_create (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/);
+
+kadm5_ret_t
+kadm5_log_delete (
+       kadm5_server_context */*context*/,
+       krb5_principal /*princ*/);
+
+kadm5_ret_t
+kadm5_log_end (kadm5_server_context */*context*/);
+
+kadm5_ret_t
+kadm5_log_foreach (
+       kadm5_server_context */*context*/,
+       void (*/*func*/)(kadm5_server_context *server_context, u_int32_t ver, time_t timestamp, enum kadm_ops op, u_int32_t len, krb5_storage *sp));
+
+kadm5_ret_t
+kadm5_log_get_version (
+       kadm5_server_context */*context*/,
+       u_int32_t */*ver*/);
+
+kadm5_ret_t
+kadm5_log_get_version_fd (
+       int /*fd*/,
+       u_int32_t */*ver*/);
+
+krb5_storage *
+kadm5_log_goto_end (int /*fd*/);
+
+kadm5_ret_t
+kadm5_log_init (kadm5_server_context */*context*/);
+
+kadm5_ret_t
+kadm5_log_modify (
+       kadm5_server_context */*context*/,
+       hdb_entry */*ent*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_log_nop (kadm5_server_context */*context*/);
+
+kadm5_ret_t
+kadm5_log_previous (
+       krb5_storage */*sp*/,
+       u_int32_t */*ver*/,
+       time_t */*timestamp*/,
+       enum kadm_ops */*op*/,
+       u_int32_t */*len*/);
+
+kadm5_ret_t
+kadm5_log_reinit (kadm5_server_context */*context*/);
+
+kadm5_ret_t
+kadm5_log_rename (
+       kadm5_server_context */*context*/,
+       krb5_principal /*source*/,
+       hdb_entry */*ent*/);
+
+kadm5_ret_t
+kadm5_log_replay (
+       kadm5_server_context */*context*/,
+       enum kadm_ops /*op*/,
+       u_int32_t /*ver*/,
+       u_int32_t /*len*/,
+       krb5_storage */*sp*/);
+
+kadm5_ret_t
+kadm5_log_replay_create (
+       kadm5_server_context */*context*/,
+       u_int32_t /*ver*/,
+       u_int32_t /*len*/,
+       krb5_storage */*sp*/);
+
+kadm5_ret_t
+kadm5_log_replay_delete (
+       kadm5_server_context */*context*/,
+       u_int32_t /*ver*/,
+       u_int32_t /*len*/,
+       krb5_storage */*sp*/);
+
+kadm5_ret_t
+kadm5_log_replay_modify (
+       kadm5_server_context */*context*/,
+       u_int32_t /*ver*/,
+       u_int32_t /*len*/,
+       krb5_storage */*sp*/);
+
+kadm5_ret_t
+kadm5_log_replay_nop (
+       kadm5_server_context */*context*/,
+       u_int32_t /*ver*/,
+       u_int32_t /*len*/,
+       krb5_storage */*sp*/);
+
+kadm5_ret_t
+kadm5_log_replay_rename (
+       kadm5_server_context */*context*/,
+       u_int32_t /*ver*/,
+       u_int32_t /*len*/,
+       krb5_storage */*sp*/);
+
+kadm5_ret_t
+kadm5_log_set_version (
+       kadm5_server_context */*context*/,
+       u_int32_t /*vno*/);
+
+kadm5_ret_t
+kadm5_log_truncate (kadm5_server_context */*server_context*/);
+
+kadm5_ret_t
+kadm5_s_chpass_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_s_chpass_principal_cond (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_s_chpass_principal_with_key (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       int /*n_key_data*/,
+       krb5_key_data */*key_data*/);
+
+kadm5_ret_t
+kadm5_s_create_principal (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_s_create_principal_with_key (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_s_delete_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/);
+
+kadm5_ret_t
+kadm5_s_destroy (void */*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_flush (void */*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_get_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       kadm5_principal_ent_t /*out*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_s_get_principals (
+       void */*server_handle*/,
+       const char */*exp*/,
+       char ***/*princs*/,
+       int */*count*/);
+
+kadm5_ret_t
+kadm5_s_get_privs (
+       void */*server_handle*/,
+       u_int32_t */*privs*/);
+
+kadm5_ret_t
+kadm5_s_init_with_creds (
+       const char */*client_name*/,
+       krb5_ccache /*ccache*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_init_with_creds_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       krb5_ccache /*ccache*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_init_with_password (
+       const char */*client_name*/,
+       const char */*password*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_init_with_password_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*password*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_init_with_skey (
+       const char */*client_name*/,
+       const char */*keytab*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_init_with_skey_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*keytab*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_s_modify_principal (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_s_randkey_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       krb5_keyblock **/*new_keys*/,
+       int */*n_keys*/);
+
+kadm5_ret_t
+kadm5_s_rename_principal (
+       void */*server_handle*/,
+       krb5_principal /*source*/,
+       krb5_principal /*target*/);
+
+#endif /* __kadm5_private_h__ */
diff --git a/src/kerberosV/src/lib/kadm5/kadm5-protos.h b/src/kerberosV/src/lib/kadm5/kadm5-protos.h
new file mode 100644 (file)
index 0000000..72c5d32
--- /dev/null
@@ -0,0 +1,244 @@
+/* This is a generated file */
+#ifndef __kadm5_protos_h__
+#define __kadm5_protos_h__
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+kadm5_ret_t
+kadm5_ad_init_with_password (
+       const char */*client_name*/,
+       const char */*password*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_ad_init_with_password_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*password*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+krb5_error_code
+kadm5_add_passwd_quality_verifier (
+       krb5_context /*context*/,
+       const char */*check_library*/);
+
+const char *
+kadm5_check_password_quality (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       krb5_data */*pwd_data*/);
+
+kadm5_ret_t
+kadm5_chpass_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_chpass_principal_with_key (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       int /*n_key_data*/,
+       krb5_key_data */*key_data*/);
+
+kadm5_ret_t
+kadm5_create_principal (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/,
+       char */*password*/);
+
+kadm5_ret_t
+kadm5_delete_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/);
+
+kadm5_ret_t
+kadm5_destroy (void */*server_handle*/);
+
+kadm5_ret_t
+kadm5_flush (void */*server_handle*/);
+
+void
+kadm5_free_key_data (
+       void */*server_handle*/,
+       int16_t */*n_key_data*/,
+       krb5_key_data */*key_data*/);
+
+void
+kadm5_free_name_list (
+       void */*server_handle*/,
+       char **/*names*/,
+       int */*count*/);
+
+void
+kadm5_free_principal_ent (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/);
+
+kadm5_ret_t
+kadm5_get_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       kadm5_principal_ent_t /*out*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_get_principals (
+       void */*server_handle*/,
+       const char */*exp*/,
+       char ***/*princs*/,
+       int */*count*/);
+
+kadm5_ret_t
+kadm5_get_privs (
+       void */*server_handle*/,
+       u_int32_t */*privs*/);
+
+kadm5_ret_t
+kadm5_init_with_creds (
+       const char */*client_name*/,
+       krb5_ccache /*ccache*/,
+       const 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_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       krb5_ccache /*ccache*/,
+       const 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_password (
+       const char */*client_name*/,
+       const char */*password*/,
+       const 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_password_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*password*/,
+       const 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 (
+       const char */*client_name*/,
+       const char */*keytab*/,
+       const 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_ctx (
+       krb5_context /*context*/,
+       const char */*client_name*/,
+       const char */*keytab*/,
+       const char */*service_name*/,
+       kadm5_config_params */*realm_params*/,
+       unsigned long /*struct_version*/,
+       unsigned long /*api_version*/,
+       void **/*server_handle*/);
+
+kadm5_ret_t
+kadm5_modify_principal (
+       void */*server_handle*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_randkey_principal (
+       void */*server_handle*/,
+       krb5_principal /*princ*/,
+       krb5_keyblock **/*new_keys*/,
+       int */*n_keys*/);
+
+kadm5_ret_t
+kadm5_rename_principal (
+       void */*server_handle*/,
+       krb5_principal /*source*/,
+       krb5_principal /*target*/);
+
+kadm5_ret_t
+kadm5_ret_key_data (
+       krb5_storage */*sp*/,
+       krb5_key_data */*key*/);
+
+kadm5_ret_t
+kadm5_ret_principal_ent (
+       krb5_storage */*sp*/,
+       kadm5_principal_ent_t /*princ*/);
+
+kadm5_ret_t
+kadm5_ret_principal_ent_mask (
+       krb5_storage */*sp*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t */*mask*/);
+
+kadm5_ret_t
+kadm5_ret_tl_data (
+       krb5_storage */*sp*/,
+       krb5_tl_data */*tl*/);
+
+void
+kadm5_setup_passwd_quality_check (
+       krb5_context /*context*/,
+       const char */*check_library*/,
+       const char */*check_function*/);
+
+kadm5_ret_t
+kadm5_store_key_data (
+       krb5_storage */*sp*/,
+       krb5_key_data */*key*/);
+
+kadm5_ret_t
+kadm5_store_principal_ent (
+       krb5_storage */*sp*/,
+       kadm5_principal_ent_t /*princ*/);
+
+kadm5_ret_t
+kadm5_store_principal_ent_mask (
+       krb5_storage */*sp*/,
+       kadm5_principal_ent_t /*princ*/,
+       u_int32_t /*mask*/);
+
+kadm5_ret_t
+kadm5_store_tl_data (
+       krb5_storage */*sp*/,
+       krb5_tl_data */*tl*/);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __kadm5_protos_h__ */
diff --git a/src/kerberosV/src/lib/kadm5/kadm5-pwcheck.h b/src/kerberosV/src/lib/kadm5/kadm5-pwcheck.h
new file mode 100644 (file)
index 0000000..ff5d21b
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: kadm5-pwcheck.h,v 1.1 2004/06/21 11:15:15 lha Exp $ */
+
+#ifndef KADM5_PWCHECK_H
+#define KADM5_PWCHECK_H 1
+
+
+#define KADM5_PASSWD_VERSION_V0 0
+#define KADM5_PASSWD_VERSION_V1 1
+
+typedef const char* (*kadm5_passwd_quality_check_func_v0)(krb5_context,
+                                                         krb5_principal,
+                                                         krb5_data*);
+
+/* 
+ * The 4th argument, is a tuning parameter for the quality check
+ * function, the lib/caller will providing it for the password quality
+ * module.
+ */
+
+typedef int
+(*kadm5_passwd_quality_check_func)(krb5_context context,
+                                  krb5_principal principal,
+                                  krb5_data *password,
+                                  const char *tuning,
+                                  char *message,
+                                  size_t length);
+
+struct kadm5_pw_policy_check_func {
+    char *name;
+    kadm5_passwd_quality_check_func func;
+};
+
+struct kadm5_pw_policy_verifier {
+    char *name;
+    int version;
+    char *vendor;
+    struct kadm5_pw_policy_check_func *funcs;
+};
+
+#endif /* KADM5_PWCHECK_H */
diff --git a/src/kerberosV/src/lib/kadm5/kadm5_err.et b/src/kerberosV/src/lib/kadm5/kadm5_err.et
new file mode 100644 (file)
index 0000000..1aa883a
--- /dev/null
@@ -0,0 +1,59 @@
+#
+# Error messages for the kadm5 library
+#
+# This might look like a com_err file, but is not
+#
+id "$KTH: kadm5_err.et,v 1.5.10.1 2006/02/02 13:12:48 lha Exp $"
+
+error_table ovk kadm5
+
+prefix KADM5
+error_code FAILURE,            "Operation failed for unspecified reason"
+error_code AUTH_GET,           "Operation requires `get' privilege"
+error_code AUTH_ADD,           "Operation requires `add' privilege"
+error_code AUTH_MODIFY,                "Operation requires `modify' privilege"
+error_code AUTH_DELETE,                "Operation requires `delete' privilege"
+error_code AUTH_INSUFFICIENT,  "Insufficient authorization for operation"
+error_code BAD_DB,             "Database inconsistency detected"
+error_code DUP,                        "Principal or policy already exists"
+error_code RPC_ERROR,          "Communication failure with server"
+error_code NO_SRV,             "No administration server found for realm"
+error_code BAD_HIST_KEY,       "Password history principal key version mismatch"
+error_code NOT_INIT,           "Connection to server not initialized"
+error_code UNK_PRINC,          "Principal does not exist"
+error_code UNK_POLICY,         "Policy does not exist"
+error_code BAD_MASK,           "Invalid field mask for operation"
+error_code BAD_CLASS,          "Invalid number of character classes"
+error_code BAD_LENGTH,         "Invalid password length"
+error_code BAD_POLICY,         "Invalid policy name"
+error_code BAD_PRINCIPAL,      "Invalid principal name."
+error_code BAD_AUX_ATTR,       "Invalid auxillary attributes"
+error_code BAD_HISTORY,                "Invalid password history count"
+error_code BAD_MIN_PASS_LIFE,  "Password minimum life is greater than password maximum life"
+error_code PASS_Q_TOOSHORT,    "Password is too short"
+error_code PASS_Q_CLASS,       "Password does not contain enough character classes"
+error_code PASS_Q_DICT,                "Password is in the password dictionary"
+error_code PASS_REUSE,         "Can't reuse password"
+error_code PASS_TOOSOON,       "Current password's minimum life has not expired"
+error_code POLICY_REF,         "Policy is in use"
+error_code INIT,               "Connection to server already initialized"
+error_code BAD_PASSWORD,       "Incorrect password"
+error_code PROTECT_PRINCIPAL,  "Can't change protected principal"
+error_code BAD_SERVER_HANDLE,  "Programmer error!  Bad Admin server handle"
+error_code BAD_STRUCT_VERSION, "Programmer error!  Bad API structure version"
+error_code OLD_STRUCT_VERSION, "API structure version specified by application is no longer supported"
+error_code NEW_STRUCT_VERSION, "API structure version specified by application is unknown to libraries"
+error_code BAD_API_VERSION,    "Programmer error!  Bad API version"
+error_code OLD_LIB_API_VERSION,        "API version specified by application is no longer supported by libraries"
+error_code OLD_SERVER_API_VERSION,"API version specified by application is no longer supported by server"
+error_code NEW_LIB_API_VERSION,        "API version specified by application is unknown to libraries"
+error_code NEW_SERVER_API_VERSION,"API version specified by application is unknown to server"
+error_code SECURE_PRINC_MISSING,"Database error! Required principal missing"
+error_code NO_RENAME_SALT,     "The salt type of the specified principal does not support renaming"
+error_code BAD_CLIENT_PARAMS,  "Invalid configuration parameter for remote KADM5 client"
+error_code BAD_SERVER_PARAMS,  "Invalid configuration parameter for local KADM5 client."
+error_code AUTH_LIST,          "Operation requires `list' privilege"
+error_code AUTH_CHANGEPW,      "Operation requires `change-password' privilege"
+error_code BAD_TL_TYPE,                "Programmer error!  Invalid tagged data list element type"
+error_code MISSING_CONF_PARAMS,        "Required parameters in kdc.conf missing"
+error_code BAD_SERVER_NAME,    "Bad krb5 admin server hostname"
diff --git a/src/kerberosV/src/lib/kadm5/kadm5_locl.h b/src/kerberosV/src/lib/kadm5/kadm5_locl.h
new file mode 100644 (file)
index 0000000..79f2f95
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1997-2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: kadm5_locl.h,v 1.23 2000/07/08 11:57:40 assar Exp $ */
+
+#ifndef __KADM5_LOCL_H__
+#define __KADM5_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#include <fnmatch.h>
+#include <kerberosV/kadm5/admin.h>
+#include <kerberosV/kadm5/kadm5_err.h>
+#include <hdb.h>
+#include <der.h>
+#include <roken.h>
+#include <parse_units.h>
+#include "private.h"
+
+#endif /* __KADM5_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/kadm5/kadm5_pwcheck.3 b/src/kerberosV/src/lib/kadm5/kadm5_pwcheck.3
new file mode 100644 (file)
index 0000000..fccafa7
--- /dev/null
@@ -0,0 +1,146 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: kadm5_pwcheck.3,v 1.3 2005/05/25 13:16:27 lha Exp $
+.\"
+.Dd February 29, 2004
+.Dt KADM5_PWCHECK 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_pwcheck ,
+.Nm kadm5_setup_passwd_quality_check ,
+.Nm kadm5_add_passwd_quality_verifier ,
+.Nm kadm5_check_password_quality
+.Nd Heimdal warning and error functions
+.Sh LIBRARY
+Kerberos 5 Library (libkadm5srv, -lkadm5srv)
+.Sh SYNOPSIS
+.In kadm5-protos.h
+.In kadm5-pwcheck.h
+.Ft void
+.Fo kadm5_setup_passwd_quality_check
+.Fa "krb5_context context"
+.Fa "const char *check_library"
+.Fa "const char *check_function"
+.Fc
+.Ft "krb5_error_code"
+.Fo kadm5_add_passwd_quality_verifier
+.Fa "krb5_context context"
+.Fa "const char *check_library"
+.Fc
+.Ft "const char *"
+.Fo kadm5_check_password_quality
+.Fa "krb5_context context"
+.Fa "krb5_principal principal"
+.Fa "krb5_data *pwd_data"
+.Fc
+.Ft int
+.Fo "(*kadm5_passwd_quality_check_func)"
+.Fa "krb5_context context"
+.Fa "krb5_principal principal"
+.Fa "krb5_data *password"
+.Fa "const char *tuning"
+.Fa "char *message"
+.Fa "size_t length"
+.Fc
+.Sh DESCRIPTION
+These functions perform the quality check for the heimdal database
+library.
+.Pp
+There are two versions of the shared object API; the old version (0)
+is deprecated, but still supported.  The new version (1) supports
+multiple password quality checking modules in the same shared object.
+See below for details.
+.Pp
+The password quality checker will run over all tests that are
+configured by the user.
+.Pp
+Module names are of the form
+.Ql vendor:test-name
+or, if the the test name is unique enough, just
+.Ql test-name .
+.Sh IMPLEMENTING A PASSWORD QUALITY CHECKING SHARED OBJECT
+(This refers to the version 1 API only.)
+.Pp
+Module shared objects may conveniently be compiled and linked with
+.Xr libtool 1 .
+An object needs to export a symbol called
+.Ql kadm5_password_verifier
+of the type
+.Ft "struct kadm5_pw_policy_verifier" .
+.Pp
+Its
+.Ft name
+and
+.Ft vendor
+fields should be contain the obvious information and
+.Ft version
+should be
+.Dv KADM5_PASSWD_VERSION_V1 .
+.Ft funcs
+contains an array of
+.Ft "struct kadm5_pw_policy_check_func"
+structures that is terminated with an entry whose
+.Ft name
+component is
+.Dv NULL .
+The
+.Ft func
+Fields of the array elements are functions that are exported by the
+module to be called to check the password.  They get the following
+arguments:  the Kerberos context, principal, password, a tuning parameter, and
+a pointer to a message buffer and its length.  The tuning parameter
+for the quality check function is currently always
+.Dv NULL .
+If the password is acceptable, the function returns zero.  Otherwise
+it returns non-zero and fills in the message buffer with an
+appropriate explanation.
+.Sh RUNNING THE CHECKS
+.Nm kadm5_setup_passwd_quality_check
+sets up type 0 checks.  It sets up all type 0 checks defined in
+.Xr krb5.conf 5
+if called with the last two arguments null.
+.Pp
+.Nm kadm5_add_passwd_quality_verifier
+sets up type 1 checks.  It sets up all type 1 tests defined in
+.Xr krb5.conf 5
+if called with a null second argument.
+.Nm kadm5_check_password_quality
+runs the checks in the order in which they are defined in
+.Xr krb5.conf 5
+and the order in which they occur in a
+module's
+.Ft funcs
+array until one returns non-zero.
+.Sh SEE ALSO
+.Xr libtool 1 ,
+.Xr krb5 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/kadm5/keys.c b/src/kerberosV/src/lib/kadm5/keys.c
new file mode 100644 (file)
index 0000000..449c57c
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: keys.c,v 1.3 2004/10/11 23:50:14 lha Exp $");
+
+/*
+ * free all the memory used by (len, keys)
+ */
+
+void
+_kadm5_free_keys (krb5_context context,
+                 int len, Key *keys)
+{
+    hdb_free_keys(context, len, keys);
+}
+
+/*
+ * null-ify `len', `keys'
+ */
+
+void
+_kadm5_init_keys (Key *keys, int len)
+{
+    int i;
+
+    for (i = 0; i < len; ++i) {
+       keys[i].mkvno               = NULL;
+       keys[i].salt                = NULL;
+       keys[i].key.keyvalue.length = 0;
+       keys[i].key.keyvalue.data   = NULL;
+    }
+}
+
+/*
+ * return 0 iff `keys1, len1' and `keys2, len2' are identical
+ */
+
+int
+_kadm5_cmp_keys(Key *keys1, int len1, Key *keys2, int len2)
+{
+    int i;
+
+    if (len1 != len2)
+       return 1;
+
+    for (i = 0; i < len1; ++i) {
+       if ((keys1[i].salt != NULL && keys2[i].salt == NULL)
+           || (keys1[i].salt == NULL && keys2[i].salt != NULL))
+           return 1;
+       if (keys1[i].salt != NULL) {
+           if (keys1[i].salt->type != keys2[i].salt->type)
+               return 1;
+           if (keys1[i].salt->salt.length != keys2[i].salt->salt.length)
+               return 1;
+           if (memcmp (keys1[i].salt->salt.data, keys2[i].salt->salt.data,
+                       keys1[i].salt->salt.length) != 0)
+               return 1;
+       }
+       if (keys1[i].key.keytype != keys2[i].key.keytype)
+           return 1;
+       if (keys1[i].key.keyvalue.length != keys2[i].key.keyvalue.length)
+           return 1;
+       if (memcmp (keys1[i].key.keyvalue.data, keys2[i].key.keyvalue.data,
+                   keys1[i].key.keyvalue.length) != 0)
+           return 1;
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/log.c b/src/kerberosV/src/lib/kadm5/log.c
new file mode 100644 (file)
index 0000000..24a517e
--- /dev/null
@@ -0,0 +1,830 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: log.c,v 1.21 2003/09/19 00:24:05 lha Exp $");
+
+/*
+ * A log record consists of:
+ *
+ * version number              4 bytes
+ * time in seconds             4 bytes
+ * operation (enum kadm_ops)   4 bytes
+ * length of record            4 bytes
+ * data...                     n bytes
+ * length of record            4 bytes
+ * version number              4 bytes
+ *
+ */
+
+kadm5_ret_t
+kadm5_log_get_version_fd (int fd,
+                         u_int32_t *ver)
+{
+    int ret;
+    krb5_storage *sp;
+    int32_t old_version;
+
+    ret = lseek (fd, 0, SEEK_END);
+    if(ret < 0)
+       return errno;
+    if(ret == 0) {
+       *ver = 0;
+       return 0;
+    }
+    sp = krb5_storage_from_fd (fd);
+    krb5_storage_seek(sp, -4, SEEK_CUR);
+    krb5_ret_int32 (sp, &old_version);
+    *ver = old_version;
+    krb5_storage_free(sp);
+    lseek (fd, 0, SEEK_END);
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_log_get_version (kadm5_server_context *context, u_int32_t *ver)
+{
+    return kadm5_log_get_version_fd (context->log_context.log_fd, ver);
+}
+
+kadm5_ret_t
+kadm5_log_set_version (kadm5_server_context *context, u_int32_t vno)
+{
+    kadm5_log_context *log_context = &context->log_context;
+
+    log_context->version = vno;
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_log_init (kadm5_server_context *context)
+{
+    int fd;
+    kadm5_ret_t ret;
+    kadm5_log_context *log_context = &context->log_context;
+
+    if (log_context->log_fd != -1)
+       return 0;
+    fd = open (log_context->log_file, O_RDWR | O_CREAT, 0600);
+    if (fd < 0)
+       return errno;
+    if (flock (fd, LOCK_EX) < 0) {
+       close (fd);
+       return errno;
+    }
+
+    ret = kadm5_log_get_version_fd (fd, &log_context->version);
+    if (ret)
+       return ret;
+
+    log_context->log_fd  = fd;
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_log_reinit (kadm5_server_context *context)
+{
+    int fd;
+    kadm5_log_context *log_context = &context->log_context;
+
+    if (log_context->log_fd != -1) {
+       close (log_context->log_fd);
+       log_context->log_fd = -1;
+    }
+    fd = open (log_context->log_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
+    if (fd < 0)
+       return errno;
+    if (flock (fd, LOCK_EX) < 0) {
+       close (fd);
+       return errno;
+    }
+
+    log_context->version = 0;
+    log_context->log_fd  = fd;
+    return 0;
+}
+
+
+kadm5_ret_t
+kadm5_log_end (kadm5_server_context *context)
+{
+    kadm5_log_context *log_context = &context->log_context;
+    int fd = log_context->log_fd;
+
+    flock (fd, LOCK_UN);
+    close(fd);
+    log_context->log_fd = -1;
+    return 0;
+}
+
+static kadm5_ret_t
+kadm5_log_preamble (kadm5_server_context *context,
+                   krb5_storage *sp,
+                   enum kadm_ops op)
+{
+    kadm5_log_context *log_context = &context->log_context;
+    kadm5_ret_t kadm_ret;
+
+    kadm_ret = kadm5_log_init (context);
+    if (kadm_ret)
+       return kadm_ret;
+
+    krb5_store_int32 (sp, ++log_context->version);
+    krb5_store_int32 (sp, time(NULL));
+    krb5_store_int32 (sp, op);
+    return 0;
+}
+
+static kadm5_ret_t
+kadm5_log_postamble (kadm5_log_context *context,
+                    krb5_storage *sp)
+{
+    krb5_store_int32 (sp, context->version);
+    return 0;
+}
+
+/*
+ * flush the log record in `sp'.
+ */
+
+static kadm5_ret_t
+kadm5_log_flush (kadm5_log_context *log_context,
+                krb5_storage *sp)
+{
+    krb5_data data;
+    size_t len;
+    int ret;
+
+    krb5_storage_to_data(sp, &data);
+    len = data.length;
+    ret = write (log_context->log_fd, data.data, len);
+    if (ret != len) {
+       krb5_data_free(&data);
+       return errno;
+    }
+    if (fsync (log_context->log_fd) < 0) {
+       krb5_data_free(&data);
+       return errno;
+    }
+    /*
+     * Try to send a signal to any running `ipropd-master'
+     */
+    sendto (log_context->socket_fd,
+           (void *)&log_context->version,
+           sizeof(log_context->version),
+           0,
+           (struct sockaddr *)&log_context->socket_name,
+           sizeof(log_context->socket_name));
+
+    krb5_data_free(&data);
+    return 0;
+}
+
+/*
+ * Add a `create' operation to the log.
+ */
+
+kadm5_ret_t
+kadm5_log_create (kadm5_server_context *context,
+                 hdb_entry *ent)
+{
+    krb5_storage *sp;
+    kadm5_ret_t ret;
+    krb5_data value;
+    kadm5_log_context *log_context = &context->log_context;
+
+    sp = krb5_storage_emem();
+    ret = hdb_entry2value (context->context, ent, &value);
+    if (ret) {
+       krb5_storage_free(sp);
+       return ret;
+    }
+    ret = kadm5_log_preamble (context, sp, kadm_create);
+    if (ret) {
+       krb5_data_free (&value);
+       krb5_storage_free(sp);
+       return ret;
+    }
+    krb5_store_int32 (sp, value.length);
+    krb5_storage_write(sp, value.data, value.length);
+    krb5_store_int32 (sp, value.length);
+    krb5_data_free (&value);
+    ret = kadm5_log_postamble (log_context, sp);
+    if (ret) {
+       krb5_storage_free (sp);
+       return ret;
+    }
+    ret = kadm5_log_flush (log_context, sp);
+    krb5_storage_free (sp);
+    if (ret)
+       return ret;
+    ret = kadm5_log_end (context);
+    return ret;
+}
+
+/*
+ * Read the data of a create log record from `sp' and change the
+ * database.
+ */
+
+kadm5_ret_t
+kadm5_log_replay_create (kadm5_server_context *context,
+                        u_int32_t ver,
+                        u_int32_t len,
+                        krb5_storage *sp)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    hdb_entry ent;
+
+    ret = krb5_data_alloc (&data, len);
+    if (ret)
+       return ret;
+    krb5_storage_read (sp, data.data, len);
+    ret = hdb_value2entry (context->context, &data, &ent);
+    krb5_data_free(&data);
+    if (ret)
+       return ret;
+    ret = context->db->hdb_store(context->context, context->db, 0, &ent);
+    hdb_free_entry (context->context, &ent);
+    return ret;
+}
+
+/*
+ * Add a `delete' operation to the log.
+ */
+
+kadm5_ret_t
+kadm5_log_delete (kadm5_server_context *context,
+                 krb5_principal princ)
+{
+    krb5_storage *sp;
+    kadm5_ret_t ret;
+    off_t off;
+    off_t len;
+    kadm5_log_context *log_context = &context->log_context;
+
+    sp = krb5_storage_emem();
+    if (sp == NULL)
+       return ENOMEM;
+    ret = kadm5_log_preamble (context, sp, kadm_delete);
+    if (ret)
+       goto out;
+    ret = krb5_store_int32 (sp, 0);
+    if (ret)
+       goto out;
+    off = krb5_storage_seek (sp, 0, SEEK_CUR);
+    ret = krb5_store_principal (sp, princ);
+    if (ret)
+       goto out;
+    len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
+    krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
+    ret = krb5_store_int32 (sp, len);
+    if (ret)
+       goto out;
+    krb5_storage_seek(sp, len, SEEK_CUR);
+    ret = krb5_store_int32 (sp, len);
+    if (ret)
+       goto out;
+    ret = kadm5_log_postamble (log_context, sp);
+    if (ret)
+       goto out;
+    ret = kadm5_log_flush (log_context, sp);
+    if (ret)
+       goto out;
+    ret = kadm5_log_end (context);
+out:
+    krb5_storage_free (sp);
+    return ret;
+}
+
+/*
+ * Read a `delete' log operation from `sp' and apply it.
+ */
+
+kadm5_ret_t
+kadm5_log_replay_delete (kadm5_server_context *context,
+                        u_int32_t ver,
+                        u_int32_t len,
+                        krb5_storage *sp)
+{
+    krb5_error_code ret;
+    hdb_entry ent;
+
+    krb5_ret_principal (sp, &ent.principal);
+
+    ret = context->db->hdb_remove(context->context, context->db, &ent);
+    krb5_free_principal (context->context, ent.principal);
+    return ret;
+}
+
+/*
+ * Add a `rename' operation to the log.
+ */
+
+kadm5_ret_t
+kadm5_log_rename (kadm5_server_context *context,
+                 krb5_principal source,
+                 hdb_entry *ent)
+{
+    krb5_storage *sp;
+    kadm5_ret_t ret;
+    off_t off;
+    off_t len;
+    krb5_data value;
+    kadm5_log_context *log_context = &context->log_context;
+
+    krb5_data_zero(&value);
+
+    sp = krb5_storage_emem();
+    ret = hdb_entry2value (context->context, ent, &value);
+    if (ret)
+       goto failed;
+
+    ret = kadm5_log_preamble (context, sp, kadm_rename);
+    if (ret)
+       goto failed;
+
+    ret = krb5_store_int32 (sp, 0);
+    if (ret)
+       goto failed;
+    off = krb5_storage_seek (sp, 0, SEEK_CUR);
+    ret = krb5_store_principal (sp, source);
+    if (ret)
+       goto failed;
+
+    krb5_storage_write(sp, value.data, value.length);
+    len = krb5_storage_seek (sp, 0, SEEK_CUR) - off;
+
+    krb5_storage_seek(sp, -(len + 4), SEEK_CUR);
+    ret = krb5_store_int32 (sp, len);
+    if (ret)
+       goto failed;
+
+    krb5_storage_seek(sp, len, SEEK_CUR);
+    ret = krb5_store_int32 (sp, len);
+    if (ret)
+       goto failed;
+
+    ret = kadm5_log_postamble (log_context, sp);
+    if (ret)
+       goto failed;
+
+    ret = kadm5_log_flush (log_context, sp);
+    if (ret)
+       goto failed;
+    krb5_storage_free (sp);
+    krb5_data_free (&value);
+
+    return kadm5_log_end (context);
+
+failed:
+    krb5_data_free(&value);
+    krb5_storage_free(sp);
+    return ret;
+}
+
+/*
+ * Read a `rename' log operation from `sp' and apply it.
+ */
+
+kadm5_ret_t
+kadm5_log_replay_rename (kadm5_server_context *context,
+                        u_int32_t ver,
+                        u_int32_t len,
+                        krb5_storage *sp)
+{
+    krb5_error_code ret;
+    krb5_principal source;
+    hdb_entry source_ent, target_ent;
+    krb5_data value;
+    off_t off;
+    size_t princ_len, data_len;
+
+    off = krb5_storage_seek(sp, 0, SEEK_CUR);
+    krb5_ret_principal (sp, &source);
+    princ_len = krb5_storage_seek(sp, 0, SEEK_CUR) - off;
+    data_len = len - princ_len;
+    ret = krb5_data_alloc (&value, data_len);
+    if (ret) {
+       krb5_free_principal (context->context, source);
+       return ret;
+    }
+    krb5_storage_read (sp, value.data, data_len);
+    ret = hdb_value2entry (context->context, &value, &target_ent);
+    krb5_data_free(&value);
+    if (ret) {
+       krb5_free_principal (context->context, source);
+       return ret;
+    }
+    ret = context->db->hdb_store (context->context, context->db, 
+                                 0, &target_ent);
+    hdb_free_entry (context->context, &target_ent);
+    if (ret) {
+       krb5_free_principal (context->context, source);
+       return ret;
+    }
+    source_ent.principal = source;
+    ret = context->db->hdb_remove (context->context, context->db, &source_ent);
+    krb5_free_principal (context->context, source);
+    return ret;
+}
+
+
+/*
+ * Add a `modify' operation to the log.
+ */
+
+kadm5_ret_t
+kadm5_log_modify (kadm5_server_context *context,
+                 hdb_entry *ent,
+                 u_int32_t mask)
+{
+    krb5_storage *sp;
+    kadm5_ret_t ret;
+    krb5_data value;
+    u_int32_t len;
+    kadm5_log_context *log_context = &context->log_context;
+
+    krb5_data_zero(&value);
+
+    sp = krb5_storage_emem();
+    ret = hdb_entry2value (context->context, ent, &value);
+    if (ret)
+       goto failed;
+
+    ret = kadm5_log_preamble (context, sp, kadm_modify);
+    if (ret)
+       goto failed;
+
+    len = value.length + 4;
+    ret = krb5_store_int32 (sp, len);
+    if (ret)
+       goto failed;
+    ret = krb5_store_int32 (sp, mask);
+    if (ret)
+       goto failed;
+    krb5_storage_write (sp, value.data, value.length);
+
+    ret = krb5_store_int32 (sp, len);
+    if (ret)
+       goto failed;
+    ret = kadm5_log_postamble (log_context, sp);
+    if (ret)
+       goto failed;
+    ret = kadm5_log_flush (log_context, sp);
+    if (ret)
+       goto failed;
+    krb5_data_free(&value);
+    krb5_storage_free (sp);
+    return kadm5_log_end (context);
+failed:
+    krb5_data_free(&value);
+    krb5_storage_free(sp);
+    return ret;
+}
+
+/*
+ * Read a `modify' log operation from `sp' and apply it.
+ */
+
+kadm5_ret_t
+kadm5_log_replay_modify (kadm5_server_context *context,
+                        u_int32_t ver,
+                        u_int32_t len,
+                        krb5_storage *sp)
+{
+    krb5_error_code ret;
+    int32_t mask;
+    krb5_data value;
+    hdb_entry ent, log_ent;
+
+    krb5_ret_int32 (sp, &mask);
+    len -= 4;
+    ret = krb5_data_alloc (&value, len);
+    if (ret)
+       return ret;
+    krb5_storage_read (sp, value.data, len);
+    ret = hdb_value2entry (context->context, &value, &log_ent);
+    krb5_data_free(&value);
+    if (ret)
+       return ret;
+    ent.principal = log_ent.principal;
+    log_ent.principal = NULL;
+    ret = context->db->hdb_fetch(context->context, context->db, 
+                                HDB_F_DECRYPT, &ent);
+    if (ret)
+       return ret;
+    if (mask & KADM5_PRINC_EXPIRE_TIME) {
+       if (log_ent.valid_end == NULL) {
+           ent.valid_end = NULL;
+       } else {
+           if (ent.valid_end == NULL)
+               ent.valid_end = malloc(sizeof(*ent.valid_end));
+           *ent.valid_end = *log_ent.valid_end;
+       }
+    }
+    if (mask & KADM5_PW_EXPIRATION) {
+       if (log_ent.pw_end == NULL) {
+           ent.pw_end = NULL;
+       } else {
+           if (ent.pw_end == NULL)
+               ent.pw_end = malloc(sizeof(*ent.pw_end));
+           *ent.pw_end = *log_ent.pw_end;
+       }
+    }
+    if (mask & KADM5_LAST_PWD_CHANGE) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_ATTRIBUTES) {
+       ent.flags = log_ent.flags;
+    }
+    if (mask & KADM5_MAX_LIFE) {
+       if (log_ent.max_life == NULL) {
+           ent.max_life = NULL;
+       } else {
+           if (ent.max_life == NULL)
+               ent.max_life = malloc (sizeof(*ent.max_life));
+           *ent.max_life = *log_ent.max_life;
+       }
+    }
+    if ((mask & KADM5_MOD_TIME) && (mask & KADM5_MOD_NAME)) {
+       if (ent.modified_by == NULL) {
+           ent.modified_by = malloc(sizeof(*ent.modified_by));
+       } else
+           free_Event(ent.modified_by);
+       copy_Event(log_ent.modified_by, ent.modified_by);
+    }
+    if (mask & KADM5_KVNO) {
+       ent.kvno = log_ent.kvno;
+    }
+    if (mask & KADM5_MKVNO) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_AUX_ATTRIBUTES) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_POLICY) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_POLICY_CLR) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_MAX_RLIFE) {
+       if (log_ent.max_renew == NULL) {
+           ent.max_renew = NULL;
+       } else {
+           if (ent.max_renew == NULL)
+               ent.max_renew = malloc (sizeof(*ent.max_renew));
+           *ent.max_renew = *log_ent.max_renew;
+       }
+    }
+    if (mask & KADM5_LAST_SUCCESS) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_LAST_FAILED) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_FAIL_AUTH_COUNT) {
+       abort ();               /* XXX */
+    }
+    if (mask & KADM5_KEY_DATA) {
+       size_t len;
+       int i;
+
+       for (i = 0; i < ent.keys.len; ++i)
+           free_Key(&ent.keys.val[i]);
+       free (ent.keys.val);
+
+       len = log_ent.keys.len;
+
+       ent.keys.len = len;
+       ent.keys.val = malloc(len * sizeof(*ent.keys.val));
+       for (i = 0; i < ent.keys.len; ++i)
+           copy_Key(&log_ent.keys.val[i],
+                    &ent.keys.val[i]);
+    }
+    ret = context->db->hdb_store(context->context, context->db, 
+                                HDB_F_REPLACE, &ent);
+    hdb_free_entry (context->context, &ent);
+    hdb_free_entry (context->context, &log_ent);
+    return ret;
+}
+
+/*
+ * Add a `nop' operation to the log.
+ */
+
+kadm5_ret_t
+kadm5_log_nop (kadm5_server_context *context)
+{
+    krb5_storage *sp;
+    kadm5_ret_t ret;
+    kadm5_log_context *log_context = &context->log_context;
+
+    sp = krb5_storage_emem();
+    ret = kadm5_log_preamble (context, sp, kadm_nop);
+    if (ret) {
+       krb5_storage_free (sp);
+       return ret;
+    }
+    krb5_store_int32 (sp, 0);
+    krb5_store_int32 (sp, 0);
+    ret = kadm5_log_postamble (log_context, sp);
+    if (ret) {
+       krb5_storage_free (sp);
+       return ret;
+    }
+    ret = kadm5_log_flush (log_context, sp);
+    krb5_storage_free (sp);
+    if (ret)
+       return ret;
+    ret = kadm5_log_end (context);
+    return ret;
+}
+
+/*
+ * Read a `nop' log operation from `sp' and apply it.
+ */
+
+kadm5_ret_t
+kadm5_log_replay_nop (kadm5_server_context *context,
+                     u_int32_t ver,
+                     u_int32_t len,
+                     krb5_storage *sp)
+{
+    return 0;
+}
+
+/*
+ * Call `func' for each log record in the log in `context'
+ */
+
+kadm5_ret_t
+kadm5_log_foreach (kadm5_server_context *context,
+                  void (*func)(kadm5_server_context *server_context,
+                               u_int32_t ver,
+                               time_t timestamp,
+                               enum kadm_ops op,
+                               u_int32_t len,
+                               krb5_storage *sp))
+{
+    int fd = context->log_context.log_fd;
+    krb5_storage *sp;
+
+    lseek (fd, 0, SEEK_SET);
+    sp = krb5_storage_from_fd (fd);
+    for (;;) {
+       int32_t ver, timestamp, op, len;
+
+       if(krb5_ret_int32 (sp, &ver) != 0)
+           break;
+       krb5_ret_int32 (sp, &timestamp);
+       krb5_ret_int32 (sp, &op);
+       krb5_ret_int32 (sp, &len);
+       (*func)(context, ver, timestamp, op, len, sp);
+       krb5_storage_seek(sp, 8, SEEK_CUR);
+    }
+    return 0;
+}
+
+/*
+ * Go to end of log.
+ */
+
+krb5_storage *
+kadm5_log_goto_end (int fd)
+{
+    krb5_storage *sp;
+
+    sp = krb5_storage_from_fd (fd);
+    krb5_storage_seek(sp, 0, SEEK_END);
+    return sp;
+}
+
+/*
+ * Return previous log entry.
+ */
+
+kadm5_ret_t
+kadm5_log_previous (krb5_storage *sp,
+                   u_int32_t *ver,
+                   time_t *timestamp,
+                   enum kadm_ops *op,
+                   u_int32_t *len)
+{
+    off_t off;
+    int32_t tmp;
+
+    krb5_storage_seek(sp, -8, SEEK_CUR);
+    krb5_ret_int32 (sp, &tmp);
+    *len = tmp;
+    krb5_ret_int32 (sp, &tmp);
+    *ver = tmp;
+    off = 24 + *len;
+    krb5_storage_seek(sp, -off, SEEK_CUR);
+    krb5_ret_int32 (sp, &tmp);
+    assert(tmp == *ver);
+    krb5_ret_int32 (sp, &tmp);
+    *timestamp = tmp;
+    krb5_ret_int32 (sp, &tmp);
+    *op = tmp;
+    krb5_ret_int32 (sp, &tmp);
+    assert(tmp == *len);
+    return 0;
+}
+
+/*
+ * Replay a record from the log
+ */
+
+kadm5_ret_t
+kadm5_log_replay (kadm5_server_context *context,
+                 enum kadm_ops op,
+                 u_int32_t ver,
+                 u_int32_t len,
+                 krb5_storage *sp)
+{
+    switch (op) {
+    case kadm_create :
+       return kadm5_log_replay_create (context, ver, len, sp);
+    case kadm_delete :
+       return kadm5_log_replay_delete (context, ver, len, sp);
+    case kadm_rename :
+       return kadm5_log_replay_rename (context, ver, len, sp);
+    case kadm_modify :
+       return kadm5_log_replay_modify (context, ver, len, sp);
+    case kadm_nop :
+       return kadm5_log_replay_nop (context, ver, len, sp);
+    default :
+       return KADM5_FAILURE;
+    }
+}
+
+/*
+ * truncate the log - i.e. create an empty file with just (nop vno + 2)
+ */
+
+kadm5_ret_t
+kadm5_log_truncate (kadm5_server_context *server_context)
+{
+    kadm5_ret_t ret;
+    u_int32_t vno;
+
+    ret = kadm5_log_init (server_context);
+    if (ret)
+       return ret;
+
+    ret = kadm5_log_get_version (server_context, &vno);
+    if (ret)
+       return ret;
+
+    ret = kadm5_log_reinit (server_context);
+    if (ret)
+       return ret;
+
+    ret = kadm5_log_set_version (server_context, vno + 1);
+    if (ret)
+       return ret;
+
+    ret = kadm5_log_nop (server_context);
+    if (ret)
+       return ret;
+
+    ret = kadm5_log_end (server_context);
+    if (ret)
+       return ret;
+    return 0;
+
+}
diff --git a/src/kerberosV/src/lib/kadm5/marshall.c b/src/kerberosV/src/lib/kadm5/marshall.c
new file mode 100644 (file)
index 0000000..e959843
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: marshall.c,v 1.6 1999/12/02 17:05:06 joda Exp $");
+
+kadm5_ret_t
+kadm5_store_key_data(krb5_storage *sp,
+                    krb5_key_data *key)
+{
+    krb5_data c;
+    krb5_store_int32(sp, key->key_data_ver);
+    krb5_store_int32(sp, key->key_data_kvno);
+    krb5_store_int32(sp, key->key_data_type[0]);
+    c.length = key->key_data_length[0];
+    c.data = key->key_data_contents[0];
+    krb5_store_data(sp, c);
+    krb5_store_int32(sp, key->key_data_type[1]);
+    c.length = key->key_data_length[1];
+    c.data = key->key_data_contents[1];
+    krb5_store_data(sp, c);
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_ret_key_data(krb5_storage *sp,
+                  krb5_key_data *key)
+{
+    krb5_data c;
+    int32_t tmp;
+    krb5_ret_int32(sp, &tmp);
+    key->key_data_ver = tmp;
+    krb5_ret_int32(sp, &tmp);
+    key->key_data_kvno = tmp;
+    krb5_ret_int32(sp, &tmp);
+    key->key_data_type[0] = tmp;
+    krb5_ret_data(sp, &c);
+    key->key_data_length[0] = c.length;
+    key->key_data_contents[0] = c.data;
+    krb5_ret_int32(sp, &tmp);
+    key->key_data_type[1] = tmp;
+    krb5_ret_data(sp, &c);
+    key->key_data_length[1] = c.length;
+    key->key_data_contents[1] = c.data;
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_store_tl_data(krb5_storage *sp,
+                   krb5_tl_data *tl)
+{
+    krb5_data c;
+    krb5_store_int32(sp, tl->tl_data_type);
+    c.length = tl->tl_data_length;
+    c.data = tl->tl_data_contents;
+    krb5_store_data(sp, c);
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_ret_tl_data(krb5_storage *sp,
+                 krb5_tl_data *tl)
+{
+    krb5_data c;
+    int32_t tmp;
+    krb5_ret_int32(sp, &tmp);
+    tl->tl_data_type = tmp;
+    krb5_ret_data(sp, &c);
+    tl->tl_data_length = c.length;
+    tl->tl_data_contents = c.data;
+    return 0;
+}
+
+static kadm5_ret_t
+store_principal_ent(krb5_storage *sp,
+                   kadm5_principal_ent_t princ,
+                   u_int32_t mask)
+{
+    int i;
+
+    if (mask & KADM5_PRINCIPAL)
+       krb5_store_principal(sp, princ->principal);
+    if (mask & KADM5_PRINC_EXPIRE_TIME)
+       krb5_store_int32(sp, princ->princ_expire_time);
+    if (mask & KADM5_PW_EXPIRATION)
+       krb5_store_int32(sp, princ->pw_expiration);
+    if (mask & KADM5_LAST_PWD_CHANGE)
+       krb5_store_int32(sp, princ->last_pwd_change);
+    if (mask & KADM5_MAX_LIFE)
+       krb5_store_int32(sp, princ->max_life);
+    if (mask & KADM5_MOD_NAME) {
+       krb5_store_int32(sp, princ->mod_name != NULL);
+       if(princ->mod_name)
+           krb5_store_principal(sp, princ->mod_name);
+    }
+    if (mask & KADM5_MOD_TIME)
+       krb5_store_int32(sp, princ->mod_date);
+    if (mask & KADM5_ATTRIBUTES)
+       krb5_store_int32(sp, princ->attributes);
+    if (mask & KADM5_KVNO)
+       krb5_store_int32(sp, princ->kvno);
+    if (mask & KADM5_MKVNO)
+       krb5_store_int32(sp, princ->mkvno);
+    if (mask & KADM5_POLICY) {
+       krb5_store_int32(sp, princ->policy != NULL);
+       if(princ->policy)
+           krb5_store_string(sp, princ->policy);
+    }
+    if (mask & KADM5_AUX_ATTRIBUTES)
+       krb5_store_int32(sp, princ->aux_attributes);
+    if (mask & KADM5_MAX_RLIFE)
+       krb5_store_int32(sp, princ->max_renewable_life);
+    if (mask & KADM5_LAST_SUCCESS)
+       krb5_store_int32(sp, princ->last_success);
+    if (mask & KADM5_LAST_FAILED)
+       krb5_store_int32(sp, princ->last_failed);
+    if (mask & KADM5_FAIL_AUTH_COUNT)
+       krb5_store_int32(sp, princ->fail_auth_count);
+    if (mask & KADM5_KEY_DATA) {
+       krb5_store_int32(sp, princ->n_key_data);
+       for(i = 0; i < princ->n_key_data; i++)
+           kadm5_store_key_data(sp, &princ->key_data[i]);
+    }
+    if (mask & KADM5_TL_DATA) {
+       krb5_tl_data *tp;
+
+       krb5_store_int32(sp, princ->n_tl_data);
+       for(tp = princ->tl_data; tp; tp = tp->tl_data_next)
+           kadm5_store_tl_data(sp, tp);
+    }
+    return 0;
+}
+
+
+kadm5_ret_t
+kadm5_store_principal_ent(krb5_storage *sp,
+                         kadm5_principal_ent_t princ)
+{
+    return store_principal_ent (sp, princ, ~0);
+}
+
+kadm5_ret_t
+kadm5_store_principal_ent_mask(krb5_storage *sp,
+                              kadm5_principal_ent_t princ,
+                              u_int32_t mask)
+{
+    krb5_store_int32(sp, mask);
+    return store_principal_ent (sp, princ, mask);
+}
+
+static kadm5_ret_t
+ret_principal_ent(krb5_storage *sp,
+                 kadm5_principal_ent_t princ,
+                 u_int32_t mask)
+{
+    int i;
+    int32_t tmp;
+
+    if (mask & KADM5_PRINCIPAL)
+       krb5_ret_principal(sp, &princ->principal);
+    
+    if (mask & KADM5_PRINC_EXPIRE_TIME) {
+       krb5_ret_int32(sp, &tmp);
+       princ->princ_expire_time = tmp;
+    }
+    if (mask & KADM5_PW_EXPIRATION) {
+       krb5_ret_int32(sp, &tmp);
+       princ->pw_expiration = tmp;
+    }
+    if (mask & KADM5_LAST_PWD_CHANGE) {
+       krb5_ret_int32(sp, &tmp);
+       princ->last_pwd_change = tmp;
+    }
+    if (mask & KADM5_MAX_LIFE) {
+       krb5_ret_int32(sp, &tmp);
+       princ->max_life = tmp;
+    }
+    if (mask & KADM5_MOD_NAME) {
+       krb5_ret_int32(sp, &tmp);
+       if(tmp)
+           krb5_ret_principal(sp, &princ->mod_name);
+       else
+           princ->mod_name = NULL;
+    }
+    if (mask & KADM5_MOD_TIME) {
+       krb5_ret_int32(sp, &tmp);
+       princ->mod_date = tmp;
+    }
+    if (mask & KADM5_ATTRIBUTES) {
+       krb5_ret_int32(sp, &tmp);
+       princ->attributes = tmp;
+    }
+    if (mask & KADM5_KVNO) {
+       krb5_ret_int32(sp, &tmp);
+       princ->kvno = tmp;
+    }
+    if (mask & KADM5_MKVNO) {
+       krb5_ret_int32(sp, &tmp);
+       princ->mkvno = tmp;
+    }
+    if (mask & KADM5_POLICY) {
+       krb5_ret_int32(sp, &tmp);
+       if(tmp)
+           krb5_ret_string(sp, &princ->policy);
+       else
+           princ->policy = NULL;
+    }
+    if (mask & KADM5_AUX_ATTRIBUTES) {
+       krb5_ret_int32(sp, &tmp);
+       princ->aux_attributes = tmp;
+    }
+    if (mask & KADM5_MAX_RLIFE) {
+       krb5_ret_int32(sp, &tmp);
+       princ->max_renewable_life = tmp;
+    }
+    if (mask & KADM5_LAST_SUCCESS) {
+       krb5_ret_int32(sp, &tmp);
+       princ->last_success = tmp;
+    }
+    if (mask & KADM5_LAST_FAILED) {
+       krb5_ret_int32(sp, &tmp);
+       princ->last_failed = tmp;
+    }
+    if (mask & KADM5_FAIL_AUTH_COUNT) {
+       krb5_ret_int32(sp, &tmp);
+       princ->fail_auth_count = tmp;
+    }
+    if (mask & KADM5_KEY_DATA) {
+       krb5_ret_int32(sp, &tmp);
+       princ->n_key_data = tmp;
+       princ->key_data = malloc(princ->n_key_data * sizeof(*princ->key_data));
+       for(i = 0; i < princ->n_key_data; i++)
+           kadm5_ret_key_data(sp, &princ->key_data[i]);
+    }
+    if (mask & KADM5_TL_DATA) {
+       krb5_ret_int32(sp, &tmp);
+       princ->n_tl_data = tmp;
+       princ->tl_data = NULL;
+       for(i = 0; i < princ->n_tl_data; i++){
+           krb5_tl_data *tp = malloc(sizeof(*tp));
+           kadm5_ret_tl_data(sp, tp);
+           tp->tl_data_next = princ->tl_data;
+           princ->tl_data = tp;
+       }
+    }
+    return 0;
+}
+
+kadm5_ret_t
+kadm5_ret_principal_ent(krb5_storage *sp,
+                       kadm5_principal_ent_t princ)
+{
+    return ret_principal_ent (sp, princ, ~0);
+}
+
+kadm5_ret_t
+kadm5_ret_principal_ent_mask(krb5_storage *sp,
+                            kadm5_principal_ent_t princ,
+                            u_int32_t *mask)
+{
+    int32_t tmp;
+
+    krb5_ret_int32 (sp, &tmp);
+    *mask = tmp;
+    return ret_principal_ent (sp, princ, *mask);
+}
+
+kadm5_ret_t
+_kadm5_marshal_params(krb5_context context, 
+                     kadm5_config_params *params, 
+                     krb5_data *out)
+{
+    krb5_storage *sp = krb5_storage_emem();
+    
+    krb5_store_int32(sp, params->mask & (KADM5_CONFIG_REALM));
+       
+    if(params->mask & KADM5_CONFIG_REALM)
+       krb5_store_string(sp, params->realm);
+    krb5_storage_to_data(sp, out);
+    krb5_storage_free(sp);
+
+    return 0;
+}
+
+kadm5_ret_t
+_kadm5_unmarshal_params(krb5_context context,
+                       krb5_data *in,
+                       kadm5_config_params *params)
+{
+    krb5_storage *sp = krb5_storage_from_data(in);
+    
+    krb5_ret_int32(sp, &params->mask);
+       
+    if(params->mask & KADM5_CONFIG_REALM)
+       krb5_ret_string(sp, &params->realm);
+    krb5_storage_free(sp);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/modify_c.c b/src/kerberosV/src/lib/kadm5/modify_c.c
new file mode 100644 (file)
index 0000000..8631c5d
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: modify_c.c,v 1.4 2000/07/11 15:59:46 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_modify_principal(void *server_handle,
+                        kadm5_principal_ent_t princ, 
+                        u_int32_t mask)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_modify);
+    kadm5_store_principal_ent(sp, princ);
+    krb5_store_int32(sp, mask);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    if(ret)
+       return ret;
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return tmp;
+}
+
diff --git a/src/kerberosV/src/lib/kadm5/modify_s.c b/src/kerberosV/src/lib/kadm5/modify_s.c
new file mode 100644 (file)
index 0000000..21b70f5
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: modify_s.c,v 1.13 2003/09/19 00:24:28 lha Exp $");
+
+static kadm5_ret_t
+modify_principal(void *server_handle,
+                kadm5_principal_ent_t princ, 
+                u_int32_t mask,
+                u_int32_t forbidden_mask)
+{
+    kadm5_server_context *context = server_handle;
+    hdb_entry ent;
+    kadm5_ret_t ret;
+    if((mask & forbidden_mask))
+       return KADM5_BAD_MASK;
+    if((mask & KADM5_POLICY) && strcmp(princ->policy, "default"))
+       return KADM5_UNK_POLICY;
+    
+    ent.principal = princ->principal;
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       return ret;
+    ret = context->db->hdb_fetch(context->context, context->db, 0, &ent);
+    if(ret)
+       goto out;
+    ret = _kadm5_setup_entry(context, &ent, mask, princ, mask, NULL, 0);
+    if(ret)
+       goto out2;
+    ret = _kadm5_set_modifier(context, &ent);
+    if(ret)
+       goto out2;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out2;
+
+    kadm5_log_modify (context,
+                     &ent,
+                     mask | KADM5_MOD_NAME | KADM5_MOD_TIME);
+                     
+    ret = context->db->hdb_store(context->context, context->db, 
+                            HDB_F_REPLACE, &ent);
+out2:
+    hdb_free_entry(context->context, &ent);
+out:
+    context->db->hdb_close(context->context, context->db);
+    return _kadm5_error_code(ret);
+}
+
+
+kadm5_ret_t
+kadm5_s_modify_principal(void *server_handle,
+                        kadm5_principal_ent_t princ, 
+                        u_int32_t mask)
+{
+    return modify_principal(server_handle, princ, mask, 
+                           KADM5_LAST_PWD_CHANGE | KADM5_MOD_TIME 
+                           | KADM5_MOD_NAME | KADM5_MKVNO 
+                           | KADM5_AUX_ATTRIBUTES | KADM5_LAST_SUCCESS
+                           | KADM5_LAST_FAILED);
+}
diff --git a/src/kerberosV/src/lib/kadm5/password_quality.c b/src/kerberosV/src/lib/kadm5/password_quality.c
new file mode 100644 (file)
index 0000000..7cd0d45
--- /dev/null
@@ -0,0 +1,496 @@
+/*
+ * Copyright (c) 1997-2000, 2003-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+#include "kadm5-pwcheck.h"
+
+RCSID("$KTH: password_quality.c,v 1.11 2005/05/09 19:17:34 lha Exp $");
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+static int
+min_length_passwd_quality (krb5_context context,
+                          krb5_principal principal,
+                          krb5_data *pwd,
+                          const char *opaque,
+                          char *message,
+                          size_t length)
+{
+    u_int32_t min_length = krb5_config_get_int_default(context, NULL, 6,
+                                                      "password_quality",
+                                                      "min_length",
+                                                      NULL);
+
+    if (pwd->length < min_length) {
+       strlcpy(message, "Password too short", length);
+       return 1;
+    } else
+       return 0;
+}
+
+static const char *
+min_length_passwd_quality_v0 (krb5_context context,
+                             krb5_principal principal,
+                             krb5_data *pwd)
+{
+    static char message[1024];
+    int ret;
+
+    message[0] = '\0';
+
+    ret = min_length_passwd_quality(context, principal, pwd, NULL,
+                                   message, sizeof(message));
+    if (ret)
+       return message;
+    return NULL;
+}
+
+
+static int
+char_class_passwd_quality (krb5_context context,
+                          krb5_principal principal,
+                          krb5_data *pwd,
+                          const char *opaque,
+                          char *message,
+                          size_t length)
+{
+    char *classes[] = {
+       "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+       "abcdefghijklmnopqrstuvwxyz",
+       "1234567890",
+       "!@#$%^&*()/?<>,.{[]}\\|'~`\" "
+    };
+    int i, counter = 0, req_classes;
+    size_t len;
+    char *pw;
+
+    req_classes = krb5_config_get_int_default(context, NULL, 3,
+                                             "password_quality",
+                                             "min_classes",
+                                             NULL);
+
+    len = pwd->length + 1;
+    pw = malloc(len);
+    if (pw == NULL) {
+       strlcpy(message, "out of memory", length);
+       return 1;
+    }
+    strlcpy(pw, pwd->data, len);
+    len = strlen(pw);
+
+    for (i = 0; i < sizeof(classes)/sizeof(classes[0]); i++) {
+       if (strcspn(pw, classes[i]) < len)
+           counter++;
+    }
+    memset(pw, 0, pwd->length + 1);
+    free(pw);
+    if (counter < req_classes) {
+       snprintf(message, length,
+           "Password doesn't meet complexity requirement.\n"
+           "Add more characters from the following classes:\n"
+           "1. English uppercase characters (A through Z)\n"
+           "2. English lowercase characters (a through z)\n"
+           "3. Base 10 digits (0 through 9)\n"
+           "4. Nonalphanumeric characters (e.g., !, $, #, %%)");
+       return 1;
+    }
+    return 0;
+}
+
+static int
+external_passwd_quality (krb5_context context,
+                        krb5_principal principal,
+                        krb5_data *pwd,
+                        const char *opaque,
+                        char *message,
+                        size_t length)
+{
+    krb5_error_code ret;
+    const char *program;
+    char *p;
+    pid_t child;
+    int status;
+    char reply[1024];
+    FILE *in = NULL, *out = NULL, *error = NULL;
+
+    if (memchr(pwd->data, pwd->length, '\n') != NULL) {
+       snprintf(message, length, "password contains newline, "
+                "not valid for external test");
+       return 1;
+    }
+
+    program = krb5_config_get_string(context, NULL,
+                                    "password_quality",
+                                    "external_program",
+                                    NULL);
+    if (program == NULL) {
+       snprintf(message, length, "external password quality "
+                "program not configured");
+       return 1;
+    }
+
+    ret = krb5_unparse_name(context, principal, &p);
+    if (ret) {
+       strlcpy(message, "out of memory", length);
+       return 1;
+    }
+
+    child = pipe_execv(&in, &out, &error, program, p, NULL);
+    if (child < 0) {
+       snprintf(message, length, "external password quality "
+                "program failed to execute for principal %s", p);
+       free(p);
+       return 1;
+    }
+
+    fprintf(in, "principal: %s\n"
+           "new-password: %.*s\n"
+           "end\n",
+           p, (int)pwd->length, (char *)pwd->data);
+    
+    fclose(in);
+
+    if (fgets(reply, sizeof(reply), out) == NULL) {
+
+       if (fgets(reply, sizeof(reply), error) == NULL) {
+           snprintf(message, length, "external password quality "
+                    "program failed without error");
+
+       } else {
+           reply[strcspn(reply, "\n")] = '\0';
+           snprintf(message, length, "External password quality "
+                    "program failed: %s", reply);
+       }
+
+       fclose(out);
+       fclose(error);
+       waitpid(child, &status, 0);
+       return 1;
+    }
+    reply[strcspn(reply, "\n")] = '\0';
+
+    fclose(out);
+    fclose(error);
+
+    if (waitpid(child, &status, 0) < 0) {
+       snprintf(message, length, "external program failed: %s", reply);
+       free(p);
+       return 1;
+    }
+    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
+       snprintf(message, length, "external program failed: %s", reply);
+       free(p);
+       return 1;
+    }
+
+    if (strcmp(reply, "APPROVED") != 0) {
+       snprintf(message, length, "%s", reply);
+       free(p);
+       return 1;
+    }
+
+    free(p);
+
+    return 0;
+}
+
+
+static kadm5_passwd_quality_check_func_v0 passwd_quality_check = 
+       min_length_passwd_quality_v0;
+
+struct kadm5_pw_policy_check_func builtin_funcs[] = {
+    { "minimum-length", min_length_passwd_quality },
+    { "character-class", char_class_passwd_quality },
+    { "external-check", external_passwd_quality },
+    { NULL }
+};
+struct kadm5_pw_policy_verifier builtin_verifier = {
+    "builtin", 
+    KADM5_PASSWD_VERSION_V1, 
+    "Heimdal builtin",
+    builtin_funcs
+};
+
+static struct kadm5_pw_policy_verifier **verifiers;
+static int num_verifiers;
+
+/*
+ * setup the password quality hook
+ */
+
+#ifndef RTLD_NOW
+#define RTLD_NOW 0
+#endif
+
+void
+kadm5_setup_passwd_quality_check(krb5_context context,
+                                const char *check_library,
+                                const char *check_function)
+{
+#ifdef HAVE_DLOPEN
+    void *handle;
+    void *sym;
+    int *version;
+    const char *tmp;
+
+    if(check_library == NULL) {
+       tmp = krb5_config_get_string(context, NULL, 
+                                    "password_quality", 
+                                    "check_library", 
+                                    NULL);
+       if(tmp != NULL)
+           check_library = tmp;
+    }
+    if(check_function == NULL) {
+       tmp = krb5_config_get_string(context, NULL, 
+                                    "password_quality", 
+                                    "check_function", 
+                                    NULL);
+       if(tmp != NULL)
+           check_function = tmp;
+    }
+    if(check_library != NULL && check_function == NULL)
+       check_function = "passwd_check";
+
+    if(check_library == NULL)
+       return;
+    handle = dlopen(check_library, RTLD_NOW);
+    if(handle == NULL) {
+       krb5_warnx(context, "failed to open `%s'", check_library);
+       return;
+    }
+    version = dlsym(handle, "version");
+    if(version == NULL) {
+       krb5_warnx(context,
+                  "didn't find `version' symbol in `%s'", check_library);
+       dlclose(handle);
+       return;
+    }
+    if(*version != KADM5_PASSWD_VERSION_V0) {
+       krb5_warnx(context,
+                  "version of loaded library is %d (expected %d)",
+                  *version, KADM5_PASSWD_VERSION_V0);
+       dlclose(handle);
+       return;
+    }
+    sym = dlsym(handle, check_function);
+    if(sym == NULL) {
+       krb5_warnx(context, 
+                  "didn't find `%s' symbol in `%s'", 
+                  check_function, check_library);
+       dlclose(handle);
+       return;
+    }
+    passwd_quality_check = (kadm5_passwd_quality_check_func_v0) sym;
+#endif /* HAVE_DLOPEN */
+}
+
+#ifdef HAVE_DLOPEN
+
+static krb5_error_code
+add_verifier(krb5_context context, const char *check_library)
+{
+    struct kadm5_pw_policy_verifier *v, **tmp;
+    void *handle;
+    int i;
+
+    handle = dlopen(check_library, RTLD_NOW);
+    if(handle == NULL) {
+       krb5_warnx(context, "failed to open `%s'", check_library);
+       return ENOENT;
+    }
+    v = dlsym(handle, "kadm5_password_verifier");
+    if(v == NULL) {
+       krb5_warnx(context,
+                  "didn't find `kadm5_password_verifier' symbol "
+                  "in `%s'", check_library);
+       dlclose(handle);
+       return ENOENT;
+    }
+    if(v->version != KADM5_PASSWD_VERSION_V1) {
+       krb5_warnx(context,
+                  "version of loaded library is %d (expected %d)",
+                  v->version, KADM5_PASSWD_VERSION_V1);
+       dlclose(handle);
+       return EINVAL;
+    }
+    for (i = 0; i < num_verifiers; i++) {
+       if (strcmp(v->name, verifiers[i]->name) == 0)
+           break;
+    }
+    if (i < num_verifiers) {
+       krb5_warnx(context, "password verifier library `%s' is already loaded",
+                  v->name);
+       dlclose(handle);
+       return 0;
+    }
+
+    tmp = realloc(verifiers, (num_verifiers + 1) * sizeof(*verifiers));
+    if (tmp == NULL) {
+       krb5_warnx(context, "out of memory");
+       dlclose(handle);
+       return 0;
+    }
+    verifiers = tmp;
+    verifiers[num_verifiers] = v;
+    num_verifiers++;
+
+    return 0;
+}
+
+#endif
+
+krb5_error_code
+kadm5_add_passwd_quality_verifier(krb5_context context,
+                                 const char *check_library)
+{
+#ifdef HAVE_DLOPEN
+
+    if(check_library == NULL) {
+       krb5_error_code ret;
+       char **tmp;
+
+       tmp = krb5_config_get_strings(context, NULL, 
+                                     "password_quality", 
+                                     "policy_libraries", 
+                                     NULL);
+       if(tmp == NULL)
+           return 0;
+
+       while(tmp) {
+           ret = add_verifier(context, *tmp);
+           if (ret)
+               return ret;
+           tmp++;
+       }
+    }
+    return add_verifier(context, check_library);
+#else
+    return 0;
+#endif /* HAVE_DLOPEN */
+}
+
+/*
+ *
+ */
+
+static struct kadm5_pw_policy_check_func *
+find_func(krb5_context context, const char *name)
+{
+    struct kadm5_pw_policy_check_func *f;
+    char *module = NULL;
+    const char *p, *func;
+    int i;
+
+    p = strchr(name, ':');
+    if (p) {
+       func = p + 1;
+       module = strndup(name, p - name);
+       if (module == NULL)
+           return NULL;
+    } else
+       func = name;
+
+    /* Find module in loaded modules first */
+    for (i = 0; i < num_verifiers; i++) {
+       if (module && strcmp(module, verifiers[i]->name) != 0)
+           continue;
+       for (f = verifiers[i]->funcs; f->name ; f++)
+           if (strcmp(name, f->name) == 0) {
+               if (module)
+                   free(module);
+               return f;
+           }
+    }
+    /* Lets try try the builtin modules */
+    if (module == NULL || strcmp(module, "builtin") == 0) {
+       for (f = builtin_verifier.funcs; f->name ; f++)
+           if (strcmp(func, f->name) == 0) {
+               if (module)
+                   free(module);
+               return f;
+           }
+    }
+    if (module)
+       free(module);
+    return NULL;
+}
+
+const char *
+kadm5_check_password_quality (krb5_context context,
+                             krb5_principal principal,
+                             krb5_data *pwd_data)
+{
+    struct kadm5_pw_policy_check_func *proc;
+    static char error_msg[1024];
+    const char *msg;
+    char **v, **vp;
+    int ret;
+
+    v = krb5_config_get_strings(context, NULL, 
+                               "password_quality", 
+                               "policies", 
+                               NULL);
+    if (v == NULL)
+       return (*passwd_quality_check) (context, principal, pwd_data);
+
+    error_msg[0] = '\0';
+
+    msg = NULL;
+    for(vp = v; *vp; vp++) {
+       proc = find_func(context, *vp);
+       if (proc == NULL) {
+           msg = "failed to find password verifier function";
+           break;
+       }
+       ret = (proc->func)(context, principal, pwd_data, NULL,
+                          error_msg, sizeof(error_msg));
+       if (ret) {
+           msg = error_msg;
+           break;
+       }
+    }
+    krb5_config_free_strings(v);
+
+    /* If the default quality check isn't used, lets check that the
+     * old quality function the user have set too */
+    if (msg == NULL && passwd_quality_check != min_length_passwd_quality_v0)
+       msg = (*passwd_quality_check) (context, principal, pwd_data);
+
+    return msg;
+}
diff --git a/src/kerberosV/src/lib/kadm5/private.h b/src/kerberosV/src/lib/kadm5/private.h
new file mode 100644 (file)
index 0000000..df442fb
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 1997-2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: private.h,v 1.16 2004/05/26 16:55:25 lha Exp $ */
+
+#ifndef __kadm5_privatex_h__
+#define __kadm5_privatex_h__
+
+struct kadm_func {
+    kadm5_ret_t (*chpass_principal) (void *, krb5_principal, char*);
+    kadm5_ret_t (*create_principal) (void*, kadm5_principal_ent_t, 
+                                    u_int32_t, char*);
+    kadm5_ret_t (*delete_principal) (void*, krb5_principal);
+    kadm5_ret_t (*destroy) (void*);
+    kadm5_ret_t (*flush) (void*);
+    kadm5_ret_t (*get_principal) (void*, krb5_principal, 
+                                 kadm5_principal_ent_t, u_int32_t);
+    kadm5_ret_t (*get_principals) (void*, const char*, char***, int*);
+    kadm5_ret_t (*get_privs) (void*, u_int32_t*);
+    kadm5_ret_t (*modify_principal) (void*, kadm5_principal_ent_t, u_int32_t);
+    kadm5_ret_t (*randkey_principal) (void*, krb5_principal, 
+                                     krb5_keyblock**, int*);
+    kadm5_ret_t (*rename_principal) (void*, krb5_principal, krb5_principal);
+    kadm5_ret_t (*chpass_principal_with_key) (void *, krb5_principal,
+                                             int, krb5_key_data *);
+};
+
+/* XXX should be integrated */
+typedef struct kadm5_common_context {
+    krb5_context context;
+    krb5_boolean my_context;
+    struct kadm_func funcs;
+    void *data;
+}kadm5_common_context;
+
+typedef struct kadm5_log_peer {
+    int fd;
+    char *name;
+    krb5_auth_context ac;
+    struct kadm5_log_peer *next;
+} kadm5_log_peer;
+
+typedef struct kadm5_log_context {
+    char *log_file;
+    int log_fd;
+    u_int32_t version;
+    struct sockaddr_un socket_name;
+    int socket_fd;
+} kadm5_log_context;
+
+typedef struct kadm5_server_context {
+    krb5_context context;
+    krb5_boolean my_context;
+    struct kadm_func funcs;
+    /* */
+    kadm5_config_params config;
+    HDB *db;
+    krb5_principal caller;
+    unsigned acl_flags;
+    kadm5_log_context log_context;
+} kadm5_server_context;
+
+typedef struct kadm5_client_context {
+    krb5_context context;
+    krb5_boolean my_context;
+    struct kadm_func funcs;
+    /* */
+    krb5_auth_context ac;
+    char *realm;
+    char *admin_server;
+    int kadmind_port;
+    int sock;
+    char *client_name;
+    char *service_name;
+    krb5_prompter_fct prompter;
+    const char *keytab;
+    krb5_ccache ccache;
+    kadm5_config_params *realm_params;
+}kadm5_client_context;
+
+typedef struct kadm5_ad_context {
+    krb5_context context;
+    krb5_boolean my_context;
+    struct kadm_func funcs;
+    /* */
+    kadm5_config_params config;
+    krb5_principal caller;
+    krb5_ccache ccache;
+    char *client_name;
+    char *realm;
+    void *ldap_conn;
+    char *base_dn;
+} kadm5_ad_context;
+
+enum kadm_ops {
+    kadm_get,
+    kadm_delete,
+    kadm_create,
+    kadm_rename,
+    kadm_chpass,
+    kadm_modify,
+    kadm_randkey,
+    kadm_get_privs,
+    kadm_get_princs,
+    kadm_chpass_with_key,
+    kadm_nop
+};
+
+#define KADMIN_APPL_VERSION "KADM0.1"
+#define KADMIN_OLD_APPL_VERSION "KADM0.0"
+
+#define KADM5_LOG_SIGNAL HDB_DB_DIR "/signal"
+
+#include "kadm5-private.h"
+
+#endif /* __kadm5_privatex_h__ */
diff --git a/src/kerberosV/src/lib/kadm5/privs_c.c b/src/kerberosV/src/lib/kadm5/privs_c.c
new file mode 100644 (file)
index 0000000..349a16e
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: privs_c.c,v 1.4 2000/07/11 15:59:54 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_get_privs(void *server_handle, u_int32_t *privs)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_get_privs);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    if(ret)
+       return ret;
+    ret = _kadm5_client_recv(context, &reply);
+    if (ret)
+       return ret;
+    sp = krb5_storage_from_data(&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    ret = tmp;
+    if(ret == 0){
+       krb5_ret_int32(sp, &tmp);
+       *privs = tmp;
+    }
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kadm5/privs_s.c b/src/kerberosV/src/lib/kadm5/privs_s.c
new file mode 100644 (file)
index 0000000..85afa78
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: privs_s.c,v 1.2 1999/12/02 17:05:07 joda Exp $");
+
+kadm5_ret_t
+kadm5_s_get_privs(void *server_handle, u_int32_t *privs)
+{
+    kadm5_server_context *context = server_handle;
+    *privs = context->acl_flags;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/randkey_c.c b/src/kerberosV/src/lib/kadm5/randkey_c.c
new file mode 100644 (file)
index 0000000..67e35d4
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: randkey_c.c,v 1.4 2000/07/11 16:00:02 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_randkey_principal(void *server_handle, 
+                         krb5_principal princ,
+                         krb5_keyblock **new_keys, 
+                         int *n_keys)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_randkey);
+    krb5_store_principal(sp, princ);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    if (ret)
+       return ret;
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data(&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    ret = tmp;
+    if(ret == 0){
+       krb5_keyblock *k;
+       int i;
+
+       krb5_ret_int32(sp, &tmp);
+       k = malloc(tmp * sizeof(*k));
+       if (k == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+       for(i = 0; i < tmp; i++)
+           krb5_ret_keyblock(sp, &k[i]);
+       *n_keys = tmp;
+       *new_keys = k;
+    }
+out:
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kadm5/randkey_s.c b/src/kerberosV/src/lib/kadm5/randkey_s.c
new file mode 100644 (file)
index 0000000..2001268
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: randkey_s.c,v 1.15 2004/02/29 05:59:22 lha Exp $");
+
+/*
+ * Set the keys of `princ' to random values, returning the random keys
+ * in `new_keys', `n_keys'.
+ */
+
+kadm5_ret_t
+kadm5_s_randkey_principal(void *server_handle, 
+                         krb5_principal princ,
+                         krb5_keyblock **new_keys, 
+                         int *n_keys)
+{
+    kadm5_server_context *context = server_handle;
+    hdb_entry ent;
+    kadm5_ret_t ret;
+
+    ent.principal = princ;
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       return ret;
+    ret = context->db->hdb_fetch(context->context, context->db, 0, &ent);
+    if(ret)
+       goto out;
+
+    ret = _kadm5_set_keys_randomly (context,
+                                   &ent,
+                                   new_keys,
+                                   n_keys);
+    if (ret)
+       goto out2;
+    ent.kvno++;
+
+    ret = _kadm5_set_modifier(context, &ent);
+    if(ret)
+       goto out3;
+    ret = _kadm5_bump_pw_expire(context, &ent);
+    if (ret)
+       goto out2;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret)
+       goto out2;
+
+    kadm5_log_modify (context,
+                     &ent,
+                     KADM5_PRINCIPAL | KADM5_MOD_NAME | KADM5_MOD_TIME |
+                     KADM5_KEY_DATA | KADM5_KVNO | KADM5_PW_EXPIRATION);
+
+    ret = context->db->hdb_store(context->context, context->db, 
+                                HDB_F_REPLACE, &ent);
+out3:
+    if (ret) {
+       int i;
+
+       for (i = 0; i < *n_keys; ++i)
+           krb5_free_keyblock_contents (context->context, &(*new_keys)[i]);
+       free (*new_keys);
+       *new_keys = NULL;
+       *n_keys = 0;
+    }
+out2:
+    hdb_free_entry(context->context, &ent);
+out:
+    context->db->hdb_close(context->context, context->db);
+    return _kadm5_error_code(ret);
+}
diff --git a/src/kerberosV/src/lib/kadm5/rename_c.c b/src/kerberosV/src/lib/kadm5/rename_c.c
new file mode 100644 (file)
index 0000000..0210014
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: rename_c.c,v 1.4 2000/07/11 16:00:08 joda Exp $");
+
+kadm5_ret_t
+kadm5_c_rename_principal(void *server_handle, 
+                        krb5_principal source,
+                        krb5_principal target)
+{
+    kadm5_client_context *context = server_handle;
+    kadm5_ret_t ret;
+    krb5_storage *sp;
+    unsigned char buf[1024];
+    int32_t tmp;
+    krb5_data reply;
+
+    ret = _kadm5_connect(server_handle);
+    if(ret)
+       return ret;
+
+    sp = krb5_storage_from_mem(buf, sizeof(buf));
+    if (sp == NULL)
+       return ENOMEM;
+    krb5_store_int32(sp, kadm_rename);
+    krb5_store_principal(sp, source);
+    krb5_store_principal(sp, target);
+    ret = _kadm5_client_send(context, sp);
+    krb5_storage_free(sp);
+    if (ret)
+       return ret;
+    ret = _kadm5_client_recv(context, &reply);
+    if(ret)
+       return ret;
+    sp = krb5_storage_from_data (&reply);
+    if (sp == NULL) {
+       krb5_data_free (&reply);
+       return ENOMEM;
+    }
+    krb5_ret_int32(sp, &tmp);
+    ret = tmp;
+    krb5_storage_free(sp);
+    krb5_data_free (&reply);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kadm5/rename_s.c b/src/kerberosV/src/lib/kadm5/rename_s.c
new file mode 100644 (file)
index 0000000..bba1cdb
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: rename_s.c,v 1.13 2003/12/08 14:29:22 lha Exp $");
+
+kadm5_ret_t
+kadm5_s_rename_principal(void *server_handle, 
+                        krb5_principal source,
+                        krb5_principal target)
+{
+    kadm5_server_context *context = server_handle;
+    kadm5_ret_t ret;
+    hdb_entry ent, ent2;
+    ent.principal = source;
+    if(krb5_principal_compare(context->context, source, target))
+       return KADM5_DUP; /* XXX is this right? */
+    ret = context->db->hdb_open(context->context, context->db, O_RDWR, 0);
+    if(ret)
+       return ret;
+    ret = context->db->hdb_fetch(context->context, context->db, 0, &ent);
+    if(ret){
+       context->db->hdb_close(context->context, context->db);
+       goto out;
+    }
+    ret = _kadm5_set_modifier(context, &ent);
+    if(ret)
+       goto out2;
+    {
+       /* fix salt */
+       int i;
+       Salt salt;
+       krb5_salt salt2;
+       krb5_get_pw_salt(context->context, source, &salt2);
+       salt.type = hdb_pw_salt;
+       salt.salt = salt2.saltvalue;
+       for(i = 0; i < ent.keys.len; i++){
+           if(ent.keys.val[i].salt == NULL){
+               ent.keys.val[i].salt = malloc(sizeof(*ent.keys.val[i].salt));
+               ret = copy_Salt(&salt, ent.keys.val[i].salt);
+               if(ret)
+                   break;
+           }
+       }
+       krb5_free_salt(context->context, salt2);
+    }
+    if(ret)
+       goto out2;
+    ent2.principal = ent.principal;
+    ent.principal = target;
+
+    ret = hdb_seal_keys(context->context, context->db, &ent);
+    if (ret) {
+       ent.principal = ent2.principal;
+       goto out2;
+    }
+
+    kadm5_log_rename (context,
+                     source,
+                     &ent);
+
+    ret = context->db->hdb_store(context->context, context->db, 0, &ent);
+    if(ret){
+       ent.principal = ent2.principal;
+       goto out2;
+    }
+    ret = context->db->hdb_remove(context->context, context->db, &ent2);
+    ent.principal = ent2.principal;
+out2:
+    context->db->hdb_close(context->context, context->db);
+    hdb_free_entry(context->context, &ent);
+out:
+    return _kadm5_error_code(ret);
+}
+
diff --git a/src/kerberosV/src/lib/kadm5/replay_log.c b/src/kerberosV/src/lib/kadm5/replay_log.c
new file mode 100644 (file)
index 0000000..6b6bc86
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "iprop.h"
+
+RCSID("$KTH: replay_log.c,v 1.11 2003/11/18 23:19:22 lha Exp $");
+
+int start_version = -1;
+int end_version = -1;
+
+static void
+apply_entry(kadm5_server_context *server_context,
+           u_int32_t ver,
+           time_t timestamp,
+           enum kadm_ops op,
+           u_int32_t len,
+           krb5_storage *sp)
+{
+    krb5_error_code ret;
+
+    if((start_version != -1 && ver < start_version) ||
+       (end_version != -1 && ver > end_version)) {
+       /* XXX skip this entry */
+       krb5_storage_seek(sp, len, SEEK_CUR);
+       return;
+    }
+    printf ("ver %u... ", ver);
+    fflush (stdout);
+
+    ret = kadm5_log_replay (server_context,
+                           op, ver, len, sp);
+    if (ret)
+       krb5_warn (server_context->context, ret, "kadm5_log_replay");
+
+    
+    printf ("done\n");
+}
+
+static char *config_file;
+int version_flag;
+int help_flag;
+
+struct getargs args[] = {
+    { "config-file", 'c', arg_string, &config_file },
+    { "start-version", 0, arg_integer, &start_version, "start replay with this version" },
+    { "end-version", 0, arg_integer, &end_version, "end replay with this version" },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    void *kadm_handle;
+    kadm5_config_params conf;
+    kadm5_server_context *server_context;
+    char **files;
+
+    krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+    
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if (ret)
+       krb5_err(context, 1, ret, "reading configuration files");
+
+    memset(&conf, 0, sizeof(conf));
+    ret = kadm5_init_with_password_ctx (context,
+                                       KADM5_ADMIN_SERVICE,
+                                       NULL,
+                                       KADM5_ADMIN_SERVICE,
+                                       &conf, 0, 0, 
+                                       &kadm_handle);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
+
+    server_context = (kadm5_server_context *)kadm_handle;
+
+    ret = server_context->db->hdb_open(context,
+                                      server_context->db,
+                                      O_RDWR | O_CREAT, 0);
+    if (ret)
+       krb5_err (context, 1, ret, "db->open");
+
+    ret = kadm5_log_init (server_context);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_log_init");
+
+    ret = kadm5_log_foreach (server_context, apply_entry);
+    if(ret)
+       krb5_warn(context, ret, "kadm5_log_foreach");
+    ret = kadm5_log_end (server_context);
+    if (ret)
+       krb5_warn(context, ret, "kadm5_log_end");
+    ret = server_context->db->hdb_close (context, server_context->db);
+    if (ret)
+       krb5_err (context, 1, ret, "db->close");
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/sample_passwd_check.c b/src/kerberosV/src/lib/kadm5/sample_passwd_check.c
new file mode 100644 (file)
index 0000000..dbbe5a0
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1999 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. */
+
+/* $KTH: sample_passwd_check.c,v 1.1 1999/09/10 10:11:03 assar Exp $ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <krb5.h>
+
+/* specify the api-version this library conforms to */
+
+int version = 0;
+
+/* just check the length of the password, this is what the default
+   check does, but this lets you specify the minimum length in
+   krb5.conf */
+const char*
+check_length(krb5_context context,
+             krb5_principal prinipal,
+             krb5_data *password)
+{
+    int min_length = krb5_config_get_int_default(context, NULL, 6,
+                                                "password_quality",
+                                                "min_length",
+                                                NULL);
+    if(password->length < min_length)
+       return "Password too short";
+    return NULL;
+}
+
+#ifdef DICTPATH
+
+/* use cracklib to check password quality; this requires a patch for
+   cracklib that can be found at
+   ftp://ftp.pdc.kth.se/pub/krb/src/cracklib.patch */
+
+const char*
+check_cracklib(krb5_context context,
+              krb5_principal principal,
+              krb5_data *password)
+{
+    char *s = malloc(password->length + 1);
+    char *msg;
+    char *strings[2];
+    if(s == NULL)
+       return NULL; /* XXX */
+    strings[0] = principal->name.name_string.val[0]; /* XXX */
+    strings[1] = NULL;
+    memcpy(s, password->data, password->length);
+    s[password->length] = '\0';
+    msg = FascistCheck(s, DICTPATH, strings);
+    memset(s, 0, password->length);
+    free(s);
+    return msg;
+}
+#endif
diff --git a/src/kerberosV/src/lib/kadm5/send_recv.c b/src/kerberosV/src/lib/kadm5/send_recv.c
new file mode 100644 (file)
index 0000000..b4fb4fb
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: send_recv.c,v 1.10 2003/04/16 17:58:59 lha Exp $");
+
+kadm5_ret_t 
+_kadm5_client_send(kadm5_client_context *context, krb5_storage *sp)
+{
+    krb5_data msg, out;
+    krb5_error_code ret;
+    size_t len;
+    krb5_storage *sock;
+
+    assert(context->sock != -1);
+
+    len = krb5_storage_seek(sp, 0, SEEK_CUR);
+    ret = krb5_data_alloc(&msg, len);
+    if (ret)
+       return ret;
+    krb5_storage_seek(sp, 0, SEEK_SET);
+    krb5_storage_read(sp, msg.data, msg.length);
+    
+    ret = krb5_mk_priv(context->context, context->ac, &msg, &out, NULL);
+    krb5_data_free(&msg);
+    if(ret)
+       return ret;
+    
+    sock = krb5_storage_from_fd(context->sock);
+    if(sock == NULL) {
+       krb5_data_free(&out);
+       return ENOMEM;
+    }
+    
+    ret = krb5_store_data(sock, out);
+    krb5_storage_free(sock);
+    krb5_data_free(&out);
+    return ret;
+}
+
+kadm5_ret_t
+_kadm5_client_recv(kadm5_client_context *context, krb5_data *reply)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    krb5_storage *sock;
+
+    sock = krb5_storage_from_fd(context->sock);
+    if(sock == NULL)
+       return ENOMEM;
+    ret = krb5_ret_data(sock, &data);
+    krb5_storage_free(sock);
+    if(ret == KRB5_CC_END)
+       return KADM5_RPC_ERROR;
+    else if(ret)
+       return ret;
+
+    ret = krb5_rd_priv(context->context, context->ac, &data, reply, NULL);
+    krb5_data_free(&data);
+    return ret;
+}
+
diff --git a/src/kerberosV/src/lib/kadm5/server_glue.c b/src/kerberosV/src/lib/kadm5/server_glue.c
new file mode 100644 (file)
index 0000000..a953af8
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: server_glue.c,v 1.6 1999/12/02 17:05:07 joda Exp $");
+
+kadm5_ret_t
+kadm5_init_with_password(const char *client_name,
+                        const char *password,
+                        const char *service_name,
+                        kadm5_config_params *realm_params,
+                        unsigned long struct_version,
+                        unsigned long api_version,
+                        void **server_handle)
+{
+    return kadm5_s_init_with_password(client_name,
+                                     password,
+                                     service_name,
+                                     realm_params,
+                                     struct_version,
+                                     api_version,
+                                     server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_password_ctx(krb5_context context,
+                            const char *client_name,
+                            const char *password,
+                            const char *service_name,
+                            kadm5_config_params *realm_params,
+                            unsigned long struct_version,
+                            unsigned long api_version,
+                            void **server_handle)
+{
+    return kadm5_s_init_with_password_ctx(context,
+                                         client_name,
+                                         password,
+                                         service_name,
+                                         realm_params,
+                                         struct_version,
+                                         api_version,
+                                         server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_skey(const char *client_name,
+                    const char *keytab,
+                    const char *service_name,
+                    kadm5_config_params *realm_params,
+                    unsigned long struct_version,
+                    unsigned long api_version,
+                    void **server_handle)
+{
+    return kadm5_s_init_with_skey(client_name,
+                                 keytab,
+                                 service_name,
+                                 realm_params,
+                                 struct_version,
+                                 api_version,
+                                 server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_skey_ctx(krb5_context context,
+                        const char *client_name,
+                        const char *keytab,
+                        const char *service_name,
+                        kadm5_config_params *realm_params,
+                        unsigned long struct_version,
+                        unsigned long api_version,
+                        void **server_handle)
+{
+    return kadm5_s_init_with_skey_ctx(context,
+                                     client_name,
+                                     keytab,
+                                     service_name,
+                                     realm_params,
+                                     struct_version,
+                                     api_version,
+                                     server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_creds(const char *client_name,
+                     krb5_ccache ccache,
+                     const char *service_name,
+                     kadm5_config_params *realm_params,
+                     unsigned long struct_version,
+                     unsigned long api_version,
+                     void **server_handle)
+{
+    return kadm5_s_init_with_creds(client_name,
+                                  ccache,
+                                  service_name,
+                                  realm_params,
+                                  struct_version,
+                                  api_version,
+                                  server_handle);
+}
+
+kadm5_ret_t
+kadm5_init_with_creds_ctx(krb5_context context,
+                         const char *client_name,
+                         krb5_ccache ccache,
+                         const char *service_name,
+                         kadm5_config_params *realm_params,
+                         unsigned long struct_version,
+                         unsigned long api_version,
+                         void **server_handle)
+{
+    return kadm5_s_init_with_creds_ctx(context,
+                                      client_name,
+                                      ccache,
+                                      service_name,
+                                      realm_params,
+                                      struct_version,
+                                      api_version,
+                                      server_handle);
+}
diff --git a/src/kerberosV/src/lib/kadm5/set_keys.c b/src/kerberosV/src/lib/kadm5/set_keys.c
new file mode 100644 (file)
index 0000000..99230d0
--- /dev/null
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: set_keys.c,v 1.37 2004/10/11 23:50:25 lha Exp $");
+
+/*
+ * Set the keys of `ent' to the string-to-key of `password'
+ */
+
+kadm5_ret_t
+_kadm5_set_keys(kadm5_server_context *context,
+               hdb_entry *ent, 
+               const char *password)
+{
+    Key *keys;
+    size_t num_keys;
+    kadm5_ret_t ret;
+
+    ret = hdb_generate_key_set_password(context->context,
+                                       ent->principal, 
+                                       password, &keys, &num_keys);
+    if (ret)
+       return ret;
+
+    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
+    ent->keys.val = keys;
+    ent->keys.len = num_keys;
+    return 0;
+}
+
+/*
+ * Set the keys of `ent' to (`n_key_data', `key_data')
+ */
+
+kadm5_ret_t
+_kadm5_set_keys2(kadm5_server_context *context,
+                hdb_entry *ent, 
+                int16_t n_key_data, 
+                krb5_key_data *key_data)
+{
+    krb5_error_code ret;
+    int i;
+    unsigned len;
+    Key *keys;
+
+    len  = n_key_data;
+    keys = malloc (len * sizeof(*keys));
+    if (keys == NULL)
+       return ENOMEM;
+
+    _kadm5_init_keys (keys, len);
+
+    for(i = 0; i < n_key_data; i++) {
+       keys[i].mkvno = NULL;
+       keys[i].key.keytype = key_data[i].key_data_type[0];
+       ret = krb5_data_copy(&keys[i].key.keyvalue,
+                            key_data[i].key_data_contents[0],
+                            key_data[i].key_data_length[0]);
+       if(ret)
+           goto out;
+       if(key_data[i].key_data_ver == 2) {
+           Salt *salt;
+
+           salt = malloc(sizeof(*salt));
+           if(salt == NULL) {
+               ret = ENOMEM;
+               goto out;
+           }
+           keys[i].salt = salt;
+           salt->type = key_data[i].key_data_type[1];
+           krb5_data_copy(&salt->salt, 
+                          key_data[i].key_data_contents[1],
+                          key_data[i].key_data_length[1]);
+       } else
+           keys[i].salt = NULL;
+    }
+    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
+    ent->keys.len = len;
+    ent->keys.val = keys;
+    return 0;
+ out:
+    _kadm5_free_keys (context->context, len, keys);
+    return ret;
+}
+
+/*
+ * Set the keys of `ent' to `n_keys, keys'
+ */
+
+kadm5_ret_t
+_kadm5_set_keys3(kadm5_server_context *context,
+                hdb_entry *ent,
+                int n_keys,
+                krb5_keyblock *keyblocks)
+{
+    krb5_error_code ret;
+    int i;
+    unsigned len;
+    Key *keys;
+
+    len  = n_keys;
+    keys = malloc (len * sizeof(*keys));
+    if (keys == NULL)
+       return ENOMEM;
+
+    _kadm5_init_keys (keys, len);
+
+    for(i = 0; i < n_keys; i++) {
+       keys[i].mkvno = NULL;
+       ret = krb5_copy_keyblock_contents (context->context,
+                                          &keyblocks[i],
+                                          &keys[i].key);
+       if(ret)
+           goto out;
+       keys[i].salt = NULL;
+    }
+    _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
+    ent->keys.len = len;
+    ent->keys.val = keys;
+    return 0;
+ out:
+    _kadm5_free_keys (context->context, len, keys);
+    return ret;
+}
+
+/*
+ *
+ */
+
+static int
+is_des_key_p(int keytype)
+{
+    return keytype == ETYPE_DES_CBC_CRC ||
+       keytype == ETYPE_DES_CBC_MD4 ||
+       keytype == ETYPE_DES_CBC_MD5;
+}
+
+
+/*
+ * Set the keys of `ent' to random keys and return them in `n_keys'
+ * and `new_keys'.
+ */
+
+kadm5_ret_t
+_kadm5_set_keys_randomly (kadm5_server_context *context,
+                         hdb_entry *ent,
+                         krb5_keyblock **new_keys,
+                         int *n_keys)
+{
+   krb5_keyblock *kblock = NULL;
+   kadm5_ret_t ret = 0;
+   int i, des_keyblock;
+   size_t num_keys;
+   Key *keys;
+
+   ret = hdb_generate_key_set(context->context, ent->principal,
+                              &keys, &num_keys, 1);
+   if (ret)
+       return ret;
+
+   kblock = malloc(num_keys * sizeof(kblock[0]));
+   if (kblock == NULL) {
+       ret = ENOMEM;
+       _kadm5_free_keys (context->context, num_keys, keys);
+       return ret;
+   }
+   memset(kblock, 0, num_keys * sizeof(kblock[0]));
+
+   des_keyblock = -1;
+   for (i = 0; i < num_keys; i++) {
+
+       /* 
+        * To make sure all des keys are the the same we generate only
+        * the first one and then copy key to all other des keys.
+        */
+
+       if (des_keyblock != -1 && is_des_key_p(keys[i].key.keytype)) {
+           ret = krb5_copy_keyblock_contents (context->context,
+                                              &kblock[des_keyblock],
+                                              &kblock[i]);
+           if (ret)
+               goto out;
+           kblock[i].keytype = keys[i].key.keytype;
+       } else {
+           ret = krb5_generate_random_keyblock (context->context,
+                                                keys[i].key.keytype,
+                                                &kblock[i]);
+           if (ret)
+               goto out;
+
+           if (is_des_key_p(keys[i].key.keytype))
+               des_keyblock = i;
+       }
+
+       ret = krb5_copy_keyblock_contents (context->context,
+                                          &kblock[i],
+                                          &keys[i].key);
+       if (ret)
+           goto out;
+   }
+
+out:
+   if(ret) {
+       for (i = 0; i < num_keys; ++i)
+           krb5_free_keyblock_contents (context->context, &kblock[i]);
+       free(kblock);
+       _kadm5_free_keys (context->context, num_keys, keys);
+       return ret;
+   }
+   
+   _kadm5_free_keys (context->context, ent->keys.len, ent->keys.val);
+   ent->keys.val = keys;
+   ent->keys.len = num_keys;
+   *new_keys     = kblock;
+   *n_keys       = num_keys;
+
+   return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/set_modifier.c b/src/kerberosV/src/lib/kadm5/set_modifier.c
new file mode 100644 (file)
index 0000000..cde752f
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+
+RCSID("$KTH: set_modifier.c,v 1.2 1999/12/02 17:05:07 joda Exp $");
+
+kadm5_ret_t
+_kadm5_set_modifier(kadm5_server_context *context,
+                   hdb_entry *ent)
+{
+    kadm5_ret_t ret;
+    if(ent->modified_by == NULL){
+       ent->modified_by = malloc(sizeof(*ent->modified_by));
+       if(ent->modified_by == NULL)
+           return ENOMEM;
+    } else
+       free_Event(ent->modified_by);
+    ent->modified_by->time = time(NULL);
+    ret = krb5_copy_principal(context->context, context->caller, 
+                             &ent->modified_by->principal);
+    return ret;
+}
+
diff --git a/src/kerberosV/src/lib/kadm5/test_pw_quality.c b/src/kerberosV/src/lib/kadm5/test_pw_quality.c
new file mode 100644 (file)
index 0000000..4b9bbf5
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2003, 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kadm5_locl.h"
+#include <getarg.h>
+
+RCSID("$KTH: test_pw_quality.c,v 1.2 2005/05/09 19:13:29 lha Exp $");
+
+static int version_flag;
+static int help_flag;
+static char *principal;
+static char *password;
+
+static struct getargs args[] = {
+    { "principal", 0, arg_string, &principal },
+    { "password", 0, arg_string, &password },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    krb5_principal p;
+    const char *s;
+    krb5_data pw_data;
+
+    krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+    
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (principal == NULL)
+       krb5_errx(context, 1, "no principal given");
+    if (password == NULL)
+       krb5_errx(context, 1, "no password given");
+
+    ret = krb5_parse_name(context, principal, &p);
+    if (ret)
+       krb5_errx(context, 1, "krb5_parse_name: %s", principal);
+
+    pw_data.data = password;
+    pw_data.length = strlen(password);
+
+    kadm5_setup_passwd_quality_check (context, NULL, NULL);
+    ret = kadm5_add_passwd_quality_verifier(context, NULL);
+    if (ret)
+       krb5_errx(context, 1, "kadm5_add_passwd_quality_verifier");
+
+    s = kadm5_check_password_quality (context, p, &pw_data);
+    if (s)
+       krb5_errx(context, 1, "kadm5_check_password_quality:\n%s", s);
+
+    krb5_free_principal(context, p);
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kadm5/truncate_log.c b/src/kerberosV/src/lib/kadm5/truncate_log.c
new file mode 100644 (file)
index 0000000..9634da3
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "iprop.h"
+
+RCSID("$KTH: truncate_log.c,v 1.3 2003/11/18 23:19:26 lha Exp $");
+
+static char *config_file;
+static char *realm;
+static int version_flag;
+static int help_flag;
+
+static struct getargs args[] = {
+    { "config-file", 'c', arg_string, &config_file },
+    { "realm", 'r', arg_string, &realm },
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+
+static int num_args = sizeof(args) / sizeof(args[0]);
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    void *kadm_handle;
+    kadm5_server_context *server_context;
+    kadm5_config_params conf;
+    char **files;
+
+    krb5_program_setup(&context, argc, argv, args, num_args, NULL);
+    
+    if(help_flag)
+       krb5_std_usage(0, args, num_args);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+
+    if (config_file == NULL)
+       config_file = HDB_DB_DIR "/kdc.conf";
+
+    ret = krb5_prepend_config_files_default(config_file, &files);
+    if (ret)
+       krb5_err(context, 1, ret, "getting configuration files");
+
+    ret = krb5_set_config_files(context, files);
+    krb5_free_config_files(files);
+    if (ret)
+       krb5_err(context, 1, ret, "reading configuration files");
+
+    memset(&conf, 0, sizeof(conf));
+    if(realm) {
+       conf.mask |= KADM5_CONFIG_REALM;
+       conf.realm = realm;
+    }
+
+    ret = kadm5_init_with_password_ctx (context,
+                                       KADM5_ADMIN_SERVICE,
+                                       NULL,
+                                       KADM5_ADMIN_SERVICE,
+                                       &conf, 0, 0, 
+                                       &kadm_handle);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_init_with_password_ctx");
+
+    server_context = (kadm5_server_context *)kadm_handle;
+
+    ret = kadm5_log_truncate (server_context);
+    if (ret)
+       krb5_err (context, 1, ret, "kadm5_log_truncate");
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/kafs/CVS/Entries b/src/kerberosV/src/lib/kafs/CVS/Entries
new file mode 100644 (file)
index 0000000..989fb3d
--- /dev/null
@@ -0,0 +1,17 @@
+/ChangeLog/1.1.1.6/Fri Apr 14 07:33:56 2006//
+/README.dlfcn/1.1.1.1/Fri May 25 07:52:25 2001//
+/afskrb.c/1.1.1.3/Fri Apr 14 07:33:56 2006//
+/afskrb5.c/1.1.1.4/Fri Apr 14 07:33:56 2006//
+/afsl.exp/1.1.1.1/Fri May 25 07:52:25 2001//
+/afslib.c/1.1.1.1/Fri May 25 07:52:25 2001//
+/afslib.exp/1.1.1.1/Fri May 25 07:52:25 2001//
+/afssys.c/1.5/Fri Apr 14 08:15:04 2006//
+/afssysdefs.h/1.1.1.3/Fri Apr 14 07:33:56 2006//
+/common.c/1.6/Fri Apr 14 08:15:04 2006//
+/dlfcn.c/1.1.1.1/Fri May 25 07:52:27 2001//
+/dlfcn.h/1.1.1.2/Sun May 11 02:16:14 2003//
+/kafs.3/1.5/Sun Apr 30 10:31:18 2006//
+/kafs.h/1.8/Wed Jun  3 14:45:46 2009//
+/kafs_locl.h/1.1.1.3/Fri Apr 14 07:33:57 2006//
+/roken_rename.h/1.1.1.4/Fri Apr 14 07:33:57 2006//
+D
diff --git a/src/kerberosV/src/lib/kafs/CVS/Repository b/src/kerberosV/src/lib/kafs/CVS/Repository
new file mode 100644 (file)
index 0000000..8191f65
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/kafs
diff --git a/src/kerberosV/src/lib/kafs/CVS/Root b/src/kerberosV/src/lib/kafs/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/kafs/ChangeLog b/src/kerberosV/src/lib/kafs/ChangeLog
new file mode 100644 (file)
index 0000000..4f7b2dd
--- /dev/null
@@ -0,0 +1,488 @@
+2005-06-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * use struct kafs_data everywhere, don't mix with the typedef
+       kafs_data
+
+       * roken_rename.h: rename more resolve.c symbols
+       
+       * afssys.c: Don't building map_syscall_name_to_number where its
+       not used.
+
+2005-02-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: bump version to 4:1:4
+
+2005-02-03  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kafs.h: de-__P
+       
+2004-12-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afskrb5.c: s/KEYTYPE_DES/ETYPE_DES_CBC_CRC/
+       
+2004-08-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afssysdefs.h: ifdef protect AFS_SYSCALL for DragonFly since they
+       still define __FreeBSD__ (and __FreeBSD_version), but claim that
+       they will stop doing it some time...
+       
+       * afssysdefs.h: dragonflybsd uses 339 just like freebsd5
+       
+2004-06-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afssys.c: s/arla/nnpfs/
+       
+       * afssys.c: support the linux /proc/fs/mumel/afs_ioctl afs
+       "syscall" interface
+
+2004-01-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * common.c: search paths for AFS configuration files for the
+       OpenAFS MacOS X, fix comment
+       
+       * kafs.h: search paths for AFS configuration files for the OpenAFS
+       MacOS X
+
+2003-12-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * common.c: add _PATH_ARLA_OPENBSD & c/o
+       
+       * kafs.h: add _PATH_ARLA_OPENBSD & c/o
+       
+2003-11-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * common.c: typo, Bruno Rohee <bruno@rohee.com>
+       
+2003-11-08  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kafs.3: spelling, partly from jmc <jmc@prioris.mini.pw.edu.pl>
+       
+2003-09-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afskrb5.c (krb5_afslog_uid_home): be even more friendly to the
+       user and fetch context and id ourself
+       
+2003-09-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afskrb5.c (afslog_uid_int): just belive that realm hint the user
+       passed us
+
+2003-07-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: always include v4 symbols
+       
+       * afskrb.c: provide dummy krb_ function to there is no need to
+       bump major
+
+2003-06-22  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afskrb5.c (v5_convert): rename one of the two c to cred4
+       
+2003-04-23  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * common.c, kafs.h: drop the int argument (the error code) from
+       the logging function
+
+2003-04-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * afskrb5.c (v5_convert): better match what other functions do
+       with values from krb5.conf, like case insensitivity
+
+2003-04-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kafs.3: Change .Fd #include <header.h> to .In header.h
+       from Thomas Klausner <wiz@netbsd.org>
+
+2003-04-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: (libkafs_la_LDFLAGS): update version
+       
+       * Makefile.am (ROKEN_SRCS): drop strupr.c
+       
+       * kafs.3: document kafs_set_verbose
+       
+       * common.c (kafs_set_verbose): add function that (re)sets the
+       logging function
+       (_kafs_try_get_cred): add function that does (krb_data->get_cred) to
+       make logging easier (that is now done in this function)
+       (*): use _kafs_try_get_cred
+
+       * afskrb5.c (get_cred): handle that inst can be the empty string too
+       (v5_convert): use _kafs_foldup
+       (krb5_afslog_uid_home): set name
+       (krb5_afslog_uid_home): ditto
+
+       * afskrb.c (krb_afslog_uid_home): set name
+       (krb_afslog_uid_home): ditto
+
+       * kafs_locl.h (kafs_data): add name
+       (_kafs_foldup): internally export
+
+2003-04-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kafs.3: tell that cell-name is uppercased
+       
+       * Makefile.am: add INCLUDE_krb4 when using krb4, add INCLUDE_des
+       when using krb5, add strupr.c
+       
+       * afskrb5.c: Check the cell part of the name, not the realm part
+       when checking if 2b should be used. The reson is afs@REALM might
+       have updated their servers but not afs/cell@REALM. Add constant
+       KAFS_RXKAD_2B_KVNO.
+
+2003-04-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kafs.3: s/kerberos/Kerberos/
+       
+2003-03-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * kafs.3: spelling, from <jmc@prioris.mini.pw.edu.pl>
+       
+       * kafs.3: document the kafs_settoken functions write about the
+       krb5_appdefault option for kerberos 5 afs tokens fix prototypes
+       
+2003-03-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afskrb5.c (kafs_settoken5): change signature to include a
+       krb5_context, use v5_convert
+       (v5_convert): new function, converts a krb5_ccreds to a kafs_token in
+       three diffrent ways, not at all, local 524/2b, and using 524
+       (v5_to_kt): add code to do local 524/2b
+       (get_cred): use v5_convert
+
+
+       * kafs.h (kafs_settoken5): change signature to include a
+       krb5_context
+
+       * Makefile.am: always build the libkafs library now that the
+       kerberos 5 can stand on their own
+       
+       * kafs.3: expose the krb5 functions
+       
+       * common.c (kafs_settoken_rxkad): move all content kerberos
+       version from kafs_settoken to kafs_settoken_rxkad
+       (_kafs_fixup_viceid): move the fixup the timestamp to make client
+       happy code here.
+       (_kafs_v4_to_kt): move all the kerberos 4 dependant parts from
+       kafs_settoken here.
+       (*): adapt to kafs_token
+
+       * afskrb5.c (kafs_settoken5): new function, inserts a krb5_creds
+       into kernel
+       (v5_to_kt): new function, stores a krb5_creds in struct kafs_token
+       (get_cred): add a appdefault boolean ("libkafs", realm, "afs-use-524")
+       that can used to toggle if there should v5 token should be used
+       directly or converted via 524 first.
+
+       * afskrb.c: move kafs_settoken here, use struct kafs_token
+       
+       * kafs_locl.h: include krb5-v4compat.h if needed, define an
+       internal structure struct kafs_token that carries around for rxkad
+       data that is independant of kerberos version
+       
+2003-02-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * dlfcn.h: s/intialize/initialize, from
+       <jmc@prioris.mini.pw.edu.pl>
+
+2003-02-08  Assar Westerlund  <assar@kth.se>
+
+       * afssysdefs.h: fix FreeBSD section
+
+2003-02-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * afssysdefs.h: use syscall 208 on openbsd (all version) use
+       syscall 339 on freebsd 5.0 and later, use 210 on 4.x and earlier
+       
+2002-08-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * kafs.3: move around sections (from NetBSD)
+
+2002-05-31  Assar Westerlund  <assar@pdc.kth.se>
+
+       * common.c: remove the trial of afs@REALM for cell != realm, it
+       tries to use the wrong key for foreign cells
+
+2002-05-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: version number
+
+2002-04-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * common.c (find_cells): make file parameter const
+
+2001-11-01  Assar Westerlund  <assar@sics.se>
+
+       * add strsep, and bump version to 3:3:3
+
+2001-10-27  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkafs_la_LDFLAGS): set version to 3:2:3
+
+2001-10-24  Assar Westerlund  <assar@sics.se>
+
+       * afskrb.c (afslog_uid_int): handle krb_get_tf_fullname that
+       cannot take NULLs
+       (such as the MIT one)
+
+2001-10-22  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (ROKEN_SRCS): add strlcpy.c
+
+2001-10-09  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (ROKEN_SRCS): add strtok_r.c
+       * roken_rename.h (dns_srv_order): rename correctly
+       (strtok_r): add renaming
+
+2001-09-10  Assar Westerlund  <assar@sics.se>
+
+       * kafs.h, common.c: look for configuration files in /etc/arla (the
+       location in debian's arla package)
+
+2001-08-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: handle both krb5 and krb4 cases
+
+2001-07-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkafs_la_LDFLAGS): set version to 3:0:3
+
+2001-07-12  Assar Westerlund  <assar@sics.se>
+
+       * common.c: look in /etc/openafs for debian openafs
+       * kafs.h: add paths for openafs debian (/etc/openafs)
+
+       * Makefile.am: add required library dependencies
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkafs_la_LDFLAGS): set versoin to 2:4:2
+
+2001-06-19  Assar Westerlund  <assar@sics.se>
+
+       * common.c (_kafs_realm_of_cell): changed to first try exact match
+       in CellServDB, then exact match in DNS, and finally in-exact match
+       in CellServDB
+
+2001-05-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: only build resolve.c if doing renaming
+
+2001-02-12  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am, roken_rename.h: add rename of dns functions
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkafs_la_LDFLAGS): set version to 2:3:2
+
+2000-11-17  Assar Westerlund  <assar@sics.se>
+
+       * afssysdefs.h: solaris 8 apperently uses 65
+
+2000-09-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libkafs_la_LDFLAGS): bump version to 2:2:2
+
+2000-09-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * dlfcn.c: correct arguments to some snprintf:s
+
+2000-07-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: bump version to 2:1:2
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 2:0:2
+
+2000-03-20  Assar Westerlund  <assar@sics.se>
+
+       * afssysdefs.h: make versions later than 5.7 of solaris also use
+       73
+
+2000-03-16  Assar Westerlund  <assar@sics.se>
+
+       * afskrb.c (afslog_uid_int): use krb_get_tf_fullname instead of
+       krb_get_default_principal
+
+2000-03-15  Assar Westerlund  <assar@sics.se>
+
+       * afssys.c (map_syscall_name_to_number): ignore # at
+       beginning-of-line
+
+2000-03-13  Assar Westerlund  <assar@sics.se>
+
+       * afssysdefs.h: add 230 for MacOS X per information from
+       <warner.c@apple.com>
+
+1999-12-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 1:2:1
+
+1999-11-22  Assar Westerlund  <assar@sics.se>
+
+       * afskrb5.c (afslog_uid_int): handle d->realm == NULL
+       
+1999-11-17  Assar Westerlund  <assar@sics.se>
+
+       * afskrb5.c (afslog_uid_int): don't look at the local realm at
+       all.  just use the realm from the ticket file.
+
+1999-10-20  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 1:1:1
+
+       * afskrb5.c (get_cred): always request a DES key
+
+Mon Oct 18 17:40:21 1999  Bjoern Groenvall  <bg@mummel.sics.se>
+
+       * common.c (find_cells): Trim trailing whitespace from
+       cellname. Lines starting with # are regarded as comments.
+
+Fri Oct  8 18:17:22 1999  Bjoern Groenvall  <bg@mummel.sics.se>
+
+       * afskrb.c, common.c : Change code to make a clear distinction
+       between hinted realm and ticket realm.
+
+       * kafs_locl.h: Added argument realm_hint.
+
+       * common.c (_kafs_get_cred): Change code to acquire the ``best''
+       possible ticket. Use cross-cell authentication only as method of
+       last resort.
+
+       * afskrb.c (afslog_uid_int): Add realm_hint argument and extract
+       realm from ticket file.
+
+       * afskrb5.c (afslog_uid_int): Added argument realm_hint.
+
+1999-10-03  Assar Westerlund  <assar@sics.se>
+
+       * afskrb5.c (get_cred): update to new krb524_convert_creds_kdc
+
+1999-08-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: ignore the comlicated aix construct if !krb4
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 1:0:1
+
+1999-07-22  Assar Westerlund  <assar@sics.se>
+
+       * afssysdefs.h: define AFS_SYSCALL to 73 for Solaris 2.7
+
+1999-07-07  Assar Westerlund  <assar@sics.se>
+
+       * afskrb5.c (krb5_realm_of_cell): new function
+
+       * afskrb.c (krb_realm_of_cell): new function
+       (afslog_uid_int): call krb_get_lrealm correctly
+
+1999-06-15  Assar Westerlund  <assar@sics.se>
+
+       * common.c (realm_of_cell): rename to _kafs_realm_of_cell and
+       un-staticize
+
+Fri Mar 19 14:52:29 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: add version-info
+
+Thu Mar 18 11:24:02 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: include Makefile.am.common
+
+Sat Feb 27 19:46:21 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: remove EXTRA_DATA (as of autoconf 2.13/automake
+       1.4)
+
+Thu Feb 11 22:57:37 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: set AIX_SRC also if !AIX
+
+Tue Dec  1 14:45:15 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: fix AIX linkage
+
+Sun Nov 22 10:40:44 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (WFLAGS): set
+
+Sat Nov 21 16:55:19 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * afskrb5.c: add homedir support
+
+Sun Sep  6 20:16:27 1998  Assar Westerlund  <assar@sics.se>
+
+       * add new functionality for specifying the homedir to krb_afslog
+       et al
+
+Thu Jul 16 01:27:19 1998  Assar Westerlund  <assar@sics.se>
+
+       * afssys.c: reorganize order of definitions.
+       (try_one, try_two): conditionalize
+
+Thu Jul  9 18:31:52 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * common.c (realm_of_cell): make the dns fallback work
+
+Wed Jul  8 01:39:44 1998  Assar Westerlund  <assar@sics.se>
+
+       * afssys.c (map_syscall_name_to_number): new function for finding
+       the number of a syscall given the name on solaris
+       (k_hasafs): try using map_syscall_name_to_number
+
+Tue Jun 30 17:19:00 1998  Assar Westerlund  <assar@sics.se>
+
+       * afssys.c: rewrite and add support for environment variable
+       AFS_SYSCALL
+
+       * Makefile.in (distclean): don't remove roken_rename.h
+
+Fri May 29 19:03:20 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (roken_rename.h): remove dependency
+
+Mon May 25 05:25:54 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (clean): try to remove shared library debris
+
+Sun Apr 19 09:58:40 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in: add symlink magic for linux
+
+Sat Apr  4 15:08:48 1998  Assar Westerlund  <assar@sics.se>
+
+       * kafs.h: add arla paths
+
+       * common.c (_kafs_afslog_all_local_cells): Try _PATH_ARLA_*
+       (_realm_of_cell): Try _PATH_ARLA_CELLSERVDB
+
+Thu Feb 19 14:50:22 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * common.c: Don't store expired tokens (this broke when using
+       pag-less rsh-sessions, and `non-standard' ticket files).
+
+Thu Feb 12 11:20:15 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Makefile.in: Install/uninstall one library at a time.
+
+Thu Feb 12 05:38:58 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (install): one library at a time.
+
+Mon Feb  9 23:40:32 1998  Assar Westerlund  <assar@sics.se>
+
+       * common.c (find_cells): ignore empty lines
+
+Tue Jan  6 04:25:58 1998  Assar Westerlund  <assar@sics.se>
+
+       * afssysdefs.h (AFS_SYSCALL): add FreeBSD
+
+Fri Jan  2 17:08:24 1998  Assar Westerlund  <assar@sics.se>
+
+       * kafs.h: new VICEIOCTL's.  From <rb@stacken.kth.se>
+
+       * afssysdefs.h: Add OpenBSD
diff --git a/src/kerberosV/src/lib/kafs/README.dlfcn b/src/kerberosV/src/lib/kafs/README.dlfcn
new file mode 100644 (file)
index 0000000..cee1b75
--- /dev/null
@@ -0,0 +1,246 @@
+Copyright (c) 1992,1993,1995,1996, Jens-Uwe Mager, Helios Software GmbH
+Not derived from licensed software.
+
+Permission is granted to freely use, copy, modify, and redistribute
+this software, provided that the author is not construed to be liable
+for any results of using the software, alterations are clearly marked
+as such, and this notice is not modified.
+
+libdl.a
+-------
+
+This is an emulation library to emulate the SunOS/System V.4 functions
+to access the runtime linker. The functions are emulated by using the
+AIX load() function and by reading the .loader section of the loaded
+module to find the exports. The to be loaded module should be linked as
+follows (if using AIX 3):
+
+       cc -o module.so -bM:SRE -bE:module.exp -e _nostart $(OBJS)
+
+For AIX 4:
+
+       cc -o module.so -bM:SRE -bE:module.exp -bnoentry $(OBJS)
+
+If you want to reference symbols from the main part of the program in a
+loaded module, you will have to link against the export file of the
+main part:
+
+       cc -o main -bE:main.exp $(MAIN_OBJS)
+       cc -o module.so -bM:SRE -bI:main.exp -bE:module.exp -bnoentry $(OBJS)
+
+Note that you explicitely have to specify what functions are supposed
+to be accessible from your loaded modules, this is different from
+SunOS/System V.4 where any global is automatically exported. If you
+want to export all globals, the following script might be of help:
+
+#!/bin/sh
+/usr/ucb/nm -g $* | awk '$2 == "B" || $2 == "D" { print $3 }'
+
+The module export file contains the symbols to be exported. Because
+this library uses the loader section, the final module.so file can be
+stripped. C++ users should build their shared objects using the script
+makeC++SharedLib (part of the IBM C++ compiler), this will make sure
+that constructors and destructors for static and global objects will be
+called upon loading and unloading the module. GNU C++ users should use
+the -shared option to g++ to link the shared object:
+
+       g++ -o module.so -shared $(OBJS)
+
+If the shared object does have permissions for anybody, the shared
+object will be loaded into the shared library segment and it will stay
+there even if the main application terminates. If you rebuild your
+shared object after a bugfix and you want to make sure that you really
+get the newest version you will have to use the "slibclean" command
+before starting the application again to garbage collect the shared
+library segment. If the performance utilities (bosperf) are installed
+you can use the following command to see what shared objects are
+loaded:
+
+/usr/lpp/bosperf/genkld | sort | uniq
+
+For easier debugging you can avoid loading the shared object into the
+shared library segment alltogether by removing permissions for others
+from the module.so file:
+
+chmod o-rwx module.so
+
+This will ensure you get a fresh copy of the shared object for every
+dlopen() call which is loaded into the application's data segment.
+
+Usage
+-----
+
+void *dlopen(const char *path, int mode);
+
+This routine loads the module pointed to by path and reads its export
+table. If the path does not contain a '/' character, dlopen will search
+for the module using the LIBPATH environment variable. It returns an
+opaque handle to the module or NULL on error. The mode parameter can be
+either RTLD_LAZY (for lazy function binding) or RTLD_NOW for immediate
+function binding. The AIX implementation currently does treat RTLD_NOW
+the same as RTLD_LAZY. The flag RTLD_GLOBAL might be or'ed into the
+mode parameter to allow loaded modules to bind to global variables or
+functions in other loaded modules loaded by dlopen(). If RTLD_GLOBAL is
+not specified, only globals from the main part of the executable or
+shared libraries are used to look for undefined symbols in loaded
+modules.
+
+
+void *dlsym(void *handle, const char *symbol);
+
+This routine searches for the symbol in the module referred to by
+handle and returns its address. If the symbol could not be found, the
+function returns NULL. The return value must be casted to a proper
+function pointer before it can be used. SunOS/System V.4 allows handle
+to be a NULL pointer to refer to the module the call is made from, this
+is not implemented.
+
+int dlclose(void *handle);
+
+This routine unloads the module referred to by the handle and disposes
+of any local storage. this function returns -1 on failure. Any function
+pointers obtained through dlsym() should be considered invalid after
+closing a module.
+
+As AIX caches shared objects in the shared library segment, function
+pointers obtained through dlsym() might still work even though the
+module has been unloaded. This can introduce subtle bugs that will
+segment fault later if AIX garbage collects or immediatly on
+SunOS/System V.4 as the text segment is unmapped.
+
+char *dlerror(void);
+
+This routine can be used to retrieve a text message describing the most
+recent error that occured on on of the above routines. This function
+returns NULL if there is no error information.
+
+Initialization and termination handlers
+---------------------------------------
+
+The emulation provides for an initialization and a termination
+handler.  The dlfcn.h file contains a structure declaration named
+dl_info with following members:
+
+       void (*init)(void);
+       void (*fini)(void);
+
+The init function is called upon first referencing the library. The
+fini function is called at dlclose() time or when the process exits.
+The module should declare a variable named dl_info that contains this
+structure which must be exported.  These functions correspond to the
+documented _init() and _fini() functions of SunOS 4.x, but these are
+appearently not implemented in SunOS.  When using SunOS 5.0, these
+correspond to #pragma init and #pragma fini respectively. At the same
+time any static or global C++ object's constructors or destructors will
+be called.
+
+BUGS
+----
+
+Please note that there is currently a problem with implicitely loaded
+shared C++ libaries: if you refer to a shared C++ library from a loaded
+module that is not yet used by the main program, the dlopen() emulator
+does not notice this and does not call the static constructors for the
+implicitely loaded library. This can be easily demonstrated by
+referencing the C++ standard streams from a loaded module if the main
+program is a plain C program.
+
+Jens-Uwe Mager
+
+HELIOS Software GmbH
+Lavesstr. 80
+30159 Hannover
+Germany
+
+Phone:         +49 511 36482-0
+FAX:           +49 511 36482-69
+AppleLink:     helios.de/jum
+Internet:      jum@helios.de
+
+Revison History
+---------------
+
+SCCS/s.dlfcn.h:
+
+D 1.4 95/04/25 09:36:52 jum 4 3        00018/00004/00028
+MRs:
+COMMENTS:
+added RTLD_GLOBAL, include and C++ guards
+
+D 1.3 92/12/27 20:58:32 jum 3 2        00001/00001/00031
+MRs:
+COMMENTS:
+we always have prototypes on RS/6000
+
+D 1.2 92/08/16 17:45:11 jum 2 1        00009/00000/00023
+MRs:
+COMMENTS:
+added dl_info structure to implement initialize and terminate functions
+
+D 1.1 92/08/02 18:08:45 jum 1 0        00023/00000/00000
+MRs:
+COMMENTS:
+Erstellungsdatum und -uhrzeit 92/08/02 18:08:45 von jum
+
+SCCS/s.dlfcn.c:
+
+D 1.11 96/04/10 20:12:51 jum 13 12     00037/00000/00533
+MRs:
+COMMENTS:
+Integrated the changes from John W. Eaton <jwe@bevo.che.wisc.edu> to initialize
+g++ generated shared objects.
+
+D 1.10 96/02/15 17:42:44 jum 12 10     00012/00007/00521
+MRs:
+COMMENTS:
+the C++ constructor and destructor chains are now called properly for either
+xlC 2 or xlC 3 (CSet++).
+
+D 1.9 95/09/22 11:09:38 markus 10 9    00001/00008/00527
+MRs:
+COMMENTS:
+Fix version number
+
+D 1.8 95/09/22 10:14:34 markus 9 8     00008/00001/00527
+MRs:
+COMMENTS:
+Added version number for dl lib
+
+D 1.7 95/08/14 19:08:38 jum 8 6        00026/00004/00502
+MRs:
+COMMENTS:
+Integrated the fixes from Kirk Benell (kirk@rsinc.com) to allow loading of
+shared objects generated under AIX 4. Fixed bug that symbols with exactly
+8 characters would use garbage characters from the following symbol value.
+
+D 1.6 95/04/25 09:38:03 jum 6 5        00046/00006/00460
+MRs:
+COMMENTS:
+added handling of C++ static constructors and destructors, added RTLD_GLOBAL to bind against other loaded modules
+
+D 1.5 93/02/14 20:14:17 jum 5 4        00002/00000/00464
+MRs:
+COMMENTS:
+added path to dlopen error message to make clear where there error occured.
+
+D 1.4 93/01/03 19:13:56 jum 4 3        00061/00005/00403
+MRs:
+COMMENTS:
+to allow calling symbols in the main module call load with L_NOAUTODEFER and 
+do a loadbind later with the main module.
+
+D 1.3 92/12/27 20:59:55 jum 3 2        00066/00008/00342
+MRs:
+COMMENTS:
+added search by L_GETINFO if module got loaded by LIBPATH
+
+D 1.2 92/08/16 17:45:43 jum 2 1        00074/00006/00276
+MRs:
+COMMENTS:
+implemented initialize and terminate functions, added reference counting to avoid multiple loads of the same library
+
+D 1.1 92/08/02 18:08:45 jum 1 0        00282/00000/00000
+MRs:
+COMMENTS:
+Erstellungsdatum und -uhrzeit 92/08/02 18:08:45 von jum
+
diff --git a/src/kerberosV/src/lib/kafs/afskrb.c b/src/kerberosV/src/lib/kafs/afskrb.c
new file mode 100644 (file)
index 0000000..5de2d6e
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 1995 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kafs_locl.h"
+
+RCSID("$KTH: afskrb.c,v 1.19 2005/06/02 07:37:35 lha Exp $");
+
+#ifdef KRB4
+
+struct krb_kafs_data {
+    const char *realm;
+};
+
+static int
+get_cred(struct kafs_data *data, const char *name, const char *inst, 
+        const char *realm, uid_t uid, struct kafs_token *kt)
+{
+    CREDENTIALS c;
+    KTEXT_ST tkt;
+    int ret = krb_get_cred((char*)name, (char*)inst, (char*)realm, &c);
+    
+    if (ret) {
+       ret = krb_mk_req(&tkt, (char*)name, (char*)inst, (char*)realm, 0);
+       if (ret == KSUCCESS)
+           ret = krb_get_cred((char*)name, (char*)inst, (char*)realm, &c);
+    }
+    if (ret == 0)
+       ret = _kafs_v4_to_kt(&c, uid, kt);
+    return ret;
+}
+
+static int
+afslog_uid_int(struct kafs_data *data,
+              const char *cell,
+              const char *realm_hint,
+              uid_t uid,
+              const char *homedir)
+{
+    int ret;
+    struct kafs_token kt;
+    char name[ANAME_SZ];
+    char inst[INST_SZ];
+    char realm[REALM_SZ];
+    
+    kt.ticket = NULL;
+
+    if (cell == 0 || cell[0] == 0)
+       return _kafs_afslog_all_local_cells (data, uid, homedir);
+
+    /* Extract realm from ticket file. */
+    ret = krb_get_tf_fullname(tkt_string(), name, inst, realm);
+    if (ret != KSUCCESS)
+       return ret;
+
+    kt.ticket = NULL;
+    ret = _kafs_get_cred(data, cell, realm_hint, realm, uid, &kt);
+    
+    if (ret == 0) {
+       ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);
+       free(kt.ticket);
+    }
+    return ret;
+}
+
+static char *
+get_realm(struct kafs_data *data, const char *host)
+{
+    char *r = krb_realmofhost(host);
+    if(r != NULL)
+       return strdup(r);
+    else
+       return NULL;
+}
+
+int
+krb_afslog_uid_home(const char *cell, const char *realm_hint, uid_t uid,
+                   const char *homedir)
+{
+    struct kafs_data kd;
+
+    kd.name = "krb4";
+    kd.afslog_uid = afslog_uid_int;
+    kd.get_cred = get_cred;
+    kd.get_realm = get_realm;
+    kd.data = 0;
+    return afslog_uid_int(&kd, cell, realm_hint, uid, homedir);
+}
+
+int
+krb_afslog_uid(const char *cell, const char *realm_hint, uid_t uid)
+{
+    return krb_afslog_uid_home(cell, realm_hint, uid, NULL);
+}
+
+int
+krb_afslog(const char *cell, const char *realm_hint)
+{
+    return krb_afslog_uid(cell, realm_hint, getuid());
+}
+
+int
+krb_afslog_home(const char *cell, const char *realm_hint, const char *homedir)
+{
+    return krb_afslog_uid_home(cell, realm_hint, getuid(), homedir);
+}
+
+/*
+ *
+ */
+
+int
+krb_realm_of_cell(const char *cell, char **realm)
+{
+    struct kafs_data kd;
+
+    kd.name = "krb4";
+    kd.get_realm = get_realm;
+    return _kafs_realm_of_cell(&kd, cell, realm);
+}
+
+int
+kafs_settoken(const char *cell, uid_t uid, CREDENTIALS *c)
+{
+    struct kafs_token kt;
+    int ret;
+
+    kt.ticket = NULL;
+
+    ret = _kafs_v4_to_kt(c, uid, &kt);
+    if (ret)
+       return ret;
+
+    if (kt.ct.EndTimestamp < time(NULL)) {
+       free(kt.ticket);
+       return 0;
+    }
+
+    ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);
+    free(kt.ticket);
+    return ret;
+}
+
+#else /* KRB4 */
+
+#define KAFS_KRBET_KDC_SERVICE_EXP 39525378
+
+int
+krb_afslog_uid_home(const char *cell, const char *realm_hint, uid_t uid,
+                   const char *homedir)
+{
+    return KAFS_KRBET_KDC_SERVICE_EXP;
+}
+
+int
+krb_afslog_uid(const char *cell, const char *realm_hint, uid_t uid)
+{
+    return KAFS_KRBET_KDC_SERVICE_EXP;
+}
+
+int
+krb_afslog_home(const char *cell, const char *realm_hint, const char *homedir)
+{
+    return KAFS_KRBET_KDC_SERVICE_EXP;
+}
+
+int
+krb_afslog(const char *cell, const char *realm_hint)
+{
+    return KAFS_KRBET_KDC_SERVICE_EXP;
+}
+
+int
+krb_realm_of_cell(const char *cell, char **realm)
+{
+    *realm = NULL;
+    return KAFS_KRBET_KDC_SERVICE_EXP;
+}
+
+int kafs_settoken (const char*, uid_t, struct credentials *);
+
+int
+kafs_settoken(const char *cell, uid_t uid, struct credentials *c)
+{
+    return KAFS_KRBET_KDC_SERVICE_EXP;
+}
+
+#endif /* KRB4 */
diff --git a/src/kerberosV/src/lib/kafs/afskrb5.c b/src/kerberosV/src/lib/kafs/afskrb5.c
new file mode 100644 (file)
index 0000000..ffd4307
--- /dev/null
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 1995-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kafs_locl.h"
+
+RCSID("$KTH: afskrb5.c,v 1.24 2005/06/02 07:37:51 lha Exp $");
+
+struct krb5_kafs_data {
+    krb5_context context;
+    krb5_ccache id;
+    krb5_const_realm realm;
+};
+
+enum { 
+    KAFS_RXKAD_2B_KVNO = 213,
+    KAFS_RXKAD_K5_KVNO = 256
+};
+
+static int
+v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524)
+{
+    int kvno, ret;
+
+    kt->ticket = NULL;
+
+    /* check if des key */
+    if (cred->session.keyvalue.length != 8)
+       return EINVAL;
+
+    if (local524) {
+       Ticket t;
+       unsigned char *buf;
+       size_t buf_len;
+       size_t len;
+
+       kvno = KAFS_RXKAD_2B_KVNO;
+
+       ret = decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
+       if (ret)
+           return ret;
+       if (t.tkt_vno != 5)
+           return -1;
+
+       ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_len, &t.enc_part,
+                          &len, ret);
+       free_Ticket(&t);
+       if (ret)
+           return ret;
+       if(buf_len != len) {
+           free(buf);
+           return KRB5KRB_ERR_GENERIC;
+       }
+
+       kt->ticket = buf;
+       kt->ticket_len = buf_len;
+
+    } else {
+       kvno = KAFS_RXKAD_K5_KVNO;
+       kt->ticket = malloc(cred->ticket.length);
+       if (kt->ticket == NULL)
+           return ENOMEM;
+       kt->ticket_len = cred->ticket.length;
+       memcpy(kt->ticket, cred->ticket.data, kt->ticket_len);
+
+       ret = 0;
+    }
+
+
+    /*
+     * Build a struct ClearToken
+     */
+
+    kt->ct.AuthHandle = kvno;
+    memcpy(kt->ct.HandShakeKey, cred->session.keyvalue.data, 8);
+    kt->ct.ViceId = uid;
+    kt->ct.BeginTimestamp = cred->times.starttime;
+    kt->ct.EndTimestamp = cred->times.endtime;
+
+    _kafs_fixup_viceid(&kt->ct, uid);
+
+    return 0;
+}
+
+static krb5_error_code
+v5_convert(krb5_context context, krb5_ccache id,
+          krb5_creds *cred, uid_t uid, 
+          const char *cell,
+          struct kafs_token *kt)
+{
+    krb5_error_code ret;
+    char *c, *val;
+
+    c = strdup(cell);
+    if (c == NULL)
+       return ENOMEM;
+    _kafs_foldup(c, c);
+    krb5_appdefault_string (context, "libkafs",
+                           c,
+                           "afs-use-524", "yes", &val);
+    free(c);
+
+    if (strcasecmp(val, "local") == 0 || 
+       strcasecmp(val, "2b") == 0)
+       ret = v5_to_kt(cred, uid, kt, 1);
+    else if(strcasecmp(val, "yes") == 0 ||
+           strcasecmp(val, "true") == 0 ||
+           atoi(val)) {
+       struct credentials cred4;
+       
+       if (id == NULL)
+           ret = krb524_convert_creds_kdc(context, cred, &cred4);
+       else
+           ret = krb524_convert_creds_kdc_ccache(context, id, cred, &cred4);
+       if (ret)
+           goto out;
+
+       ret = _kafs_v4_to_kt(&cred4, uid, kt);
+    } else 
+       ret = v5_to_kt(cred, uid, kt, 0);
+
+ out:
+    free(val);
+    return ret;
+}
+
+
+/*
+ *
+ */
+
+static int
+get_cred(struct kafs_data *data, const char *name, const char *inst, 
+        const char *realm, uid_t uid, struct kafs_token *kt)
+{
+    krb5_error_code ret;
+    krb5_creds in_creds, *out_creds;
+    struct krb5_kafs_data *d = data->data;
+
+    memset(&in_creds, 0, sizeof(in_creds));
+    ret = krb5_425_conv_principal(d->context, name, inst, realm, 
+                                 &in_creds.server);
+    if(ret)
+       return ret;
+    ret = krb5_cc_get_principal(d->context, d->id, &in_creds.client);
+    if(ret){
+       krb5_free_principal(d->context, in_creds.server);
+       return ret;
+    }
+    in_creds.session.keytype = ETYPE_DES_CBC_CRC;
+    ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds);
+    krb5_free_principal(d->context, in_creds.server);
+    krb5_free_principal(d->context, in_creds.client);
+    if(ret)
+       return ret;
+
+    ret = v5_convert(d->context, d->id, out_creds, uid, 
+                    (inst != NULL && inst[0] != '\0') ? inst : realm, kt);
+    krb5_free_creds(d->context, out_creds);
+
+    return ret;
+}
+
+static krb5_error_code
+afslog_uid_int(struct kafs_data *data, const char *cell, const char *rh,
+              uid_t uid, const char *homedir)
+{
+    krb5_error_code ret;
+    struct kafs_token kt;
+    krb5_principal princ;
+    krb5_realm *trealm; /* ticket realm */
+    struct krb5_kafs_data *d = data->data;
+    
+    if (cell == 0 || cell[0] == 0)
+       return _kafs_afslog_all_local_cells (data, uid, homedir);
+
+    ret = krb5_cc_get_principal (d->context, d->id, &princ);
+    if (ret)
+       return ret;
+
+    trealm = krb5_princ_realm (d->context, princ);
+
+    kt.ticket = NULL;
+    ret = _kafs_get_cred(data, cell, d->realm, *trealm, uid, &kt);
+    krb5_free_principal (d->context, princ);
+    
+    if(ret == 0) {
+       ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);
+       free(kt.ticket);
+    }
+    return ret;
+}
+
+static char *
+get_realm(struct kafs_data *data, const char *host)
+{
+    struct krb5_kafs_data *d = data->data;
+    krb5_realm *realms;
+    char *r;
+    if(krb5_get_host_realm(d->context, host, &realms))
+       return NULL;
+    r = strdup(realms[0]);
+    krb5_free_host_realm(d->context, realms);
+    return r;
+}
+
+krb5_error_code
+krb5_afslog_uid_home(krb5_context context,
+                    krb5_ccache id,
+                    const char *cell,
+                    krb5_const_realm realm,
+                    uid_t uid,
+                    const char *homedir)
+{
+    struct kafs_data kd;
+    struct krb5_kafs_data d;
+    krb5_error_code ret;
+
+    kd.name = "krb5";
+    kd.afslog_uid = afslog_uid_int;
+    kd.get_cred = get_cred;
+    kd.get_realm = get_realm;
+    kd.data = &d;
+    if (context == NULL) {
+       ret = krb5_init_context(&d.context);
+       if (ret)
+           return ret;
+    } else
+       d.context = context;
+    if (id == NULL) {
+       ret = krb5_cc_default(d.context, &d.id);
+       if (ret)
+           goto out;
+    } else
+       d.id = id;
+    d.realm = realm;
+    ret = afslog_uid_int(&kd, cell, 0, uid, homedir);
+    if (id == NULL)
+       krb5_cc_close(context, d.id);
+ out:
+    if (context == NULL)
+       krb5_free_context(d.context);
+    return ret;
+}
+
+krb5_error_code
+krb5_afslog_uid(krb5_context context,
+               krb5_ccache id,
+               const char *cell,
+               krb5_const_realm realm,
+               uid_t uid)
+{
+    return krb5_afslog_uid_home (context, id, cell, realm, uid, NULL);
+}
+
+krb5_error_code
+krb5_afslog(krb5_context context,
+           krb5_ccache id, 
+           const char *cell,
+           krb5_const_realm realm)
+{
+    return krb5_afslog_uid (context, id, cell, realm, getuid());
+}
+
+krb5_error_code
+krb5_afslog_home(krb5_context context,
+                krb5_ccache id, 
+                const char *cell,
+                krb5_const_realm realm,
+                const char *homedir)
+{
+    return krb5_afslog_uid_home (context, id, cell, realm, getuid(), homedir);
+}
+
+/*
+ *
+ */
+
+krb5_error_code
+krb5_realm_of_cell(const char *cell, char **realm)
+{
+    struct kafs_data kd;
+
+    kd.name = "krb5";
+    kd.get_realm = get_realm;
+    return _kafs_realm_of_cell(&kd, cell, realm);
+}
+
+/*
+ *
+ */
+
+int
+kafs_settoken5(krb5_context context, const char *cell, uid_t uid,
+              krb5_creds *cred)
+{
+    struct kafs_token kt;
+    int ret;
+
+    ret = v5_convert(context, NULL, cred, uid, cell, &kt);
+    if (ret)
+       return ret;
+
+    ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);
+
+    free(kt.ticket);
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kafs/afsl.exp b/src/kerberosV/src/lib/kafs/afsl.exp
new file mode 100644 (file)
index 0000000..4d2b00e
--- /dev/null
@@ -0,0 +1,6 @@
+#!/unix
+
+* This mumbo jumbo creates entry points to syscalls in _AIX
+
+lpioctl        syscall
+lsetpag        syscall
diff --git a/src/kerberosV/src/lib/kafs/afslib.c b/src/kerberosV/src/lib/kafs/afslib.c
new file mode 100644 (file)
index 0000000..9c729b2
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* 
+ * This file is only used with AIX 
+ */
+
+#include "kafs_locl.h"
+
+RCSID("$KTH: afslib.c,v 1.6 1999/12/02 16:58:40 joda Exp $");
+
+int
+aix_pioctl(char *a_path,
+          int o_opcode,
+          struct ViceIoctl *a_paramsP,
+          int a_followSymlinks)
+{
+    return lpioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
+}
+
+int
+aix_setpag(void)
+{
+    return lsetpag();
+}
diff --git a/src/kerberosV/src/lib/kafs/afslib.exp b/src/kerberosV/src/lib/kafs/afslib.exp
new file mode 100644 (file)
index 0000000..f288717
--- /dev/null
@@ -0,0 +1,3 @@
+#!
+aix_pioctl
+aix_setpag
diff --git a/src/kerberosV/src/lib/kafs/afssys.c b/src/kerberosV/src/lib/kafs/afssys.c
new file mode 100644 (file)
index 0000000..bcac984
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 1995 - 2000, 2002, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "kafs_locl.h"
+
+RCSID("$KTH: afssys.c,v 1.73 2005/06/02 07:25:58 lha Exp $");
+
+struct procdata {
+    unsigned long param4;
+    unsigned long param3;
+    unsigned long param2;
+    unsigned long param1;
+    unsigned long syscall;
+};
+#define VIOC_SYSCALL _IOW('C', 1, void *)
+
+
+int _kafs_debug; /* this should be done in a better way */
+
+#define NO_ENTRY_POINT         0
+#define SINGLE_ENTRY_POINT     1
+#define MULTIPLE_ENTRY_POINT   2
+#define SINGLE_ENTRY_POINT2    3
+#define SINGLE_ENTRY_POINT3    4
+#define LINUX_PROC_POINT       5
+#define AIX_ENTRY_POINTS       6
+#define UNKNOWN_ENTRY_POINT    7
+static int afs_entry_point = UNKNOWN_ENTRY_POINT;
+static int afs_syscalls[2];
+static char *afs_procpath;
+
+/* Magic to get AIX syscalls to work */
+#ifdef _AIX
+
+static int (*Pioctl)(char*, int, struct ViceIoctl*, int);
+static int (*Setpag)(void);
+
+#include "dlfcn.h"
+
+/*
+ *
+ */
+
+static int
+try_aix(void)
+{
+#ifdef STATIC_AFS_SYSCALLS
+    Pioctl = aix_pioctl;
+    Setpag = aix_setpag;
+#else
+    void *ptr;
+    char path[MaxPathLen], *p;
+    /*
+     * If we are root or running setuid don't trust AFSLIBPATH!
+     */
+    if (getuid() != 0 && !issetugid() && (p = getenv("AFSLIBPATH")) != NULL)
+       strlcpy(path, p, sizeof(path));
+    else
+       snprintf(path, sizeof(path), "%s/afslib.so", LIBDIR);
+       
+    ptr = dlopen(path, RTLD_NOW);
+    if(ptr == NULL) {
+       if(_kafs_debug) {
+           if(errno == ENOEXEC && (p = dlerror()) != NULL)
+               fprintf(stderr, "dlopen(%s): %s\n", path, p);
+           else if (errno != ENOENT)
+               fprintf(stderr, "dlopen(%s): %s\n", path, strerror(errno));
+       }
+       return 1;
+    }
+    Setpag = (int (*)(void))dlsym(ptr, "aix_setpag");
+    Pioctl = (int (*)(char*, int, 
+                     struct ViceIoctl*, int))dlsym(ptr, "aix_pioctl");
+#endif
+    afs_entry_point = AIX_ENTRY_POINTS;
+    return 0;
+}
+#endif /* _AIX */
+
+/* 
+ * This probably only works under Solaris and could get confused if
+ * there's a /etc/name_to_sysnum file.  
+ */
+
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
+
+#define _PATH_ETC_NAME_TO_SYSNUM "/etc/name_to_sysnum"
+
+static int
+map_syscall_name_to_number (const char *str, int *res)
+{
+    FILE *f;
+    char buf[256];
+    size_t str_len = strlen (str);
+
+    f = fopen (_PATH_ETC_NAME_TO_SYSNUM, "r");
+    if (f == NULL)
+       return -1;
+    while (fgets (buf, sizeof(buf), f) != NULL) {
+       if (buf[0] == '#')
+           continue;
+
+       if (strncmp (str, buf, str_len) == 0) {
+           char *begptr = buf + str_len;
+           char *endptr;
+           long val = strtol (begptr, &endptr, 0);
+
+           if (val != 0 && endptr != begptr) {
+               fclose (f);
+               *res = val;
+               return 0;
+           }
+       }
+    }
+    fclose (f);
+    return -1;
+}
+#endif
+
+static int 
+try_proc(const char *path)
+{
+    int fd;
+    fd = open(path, O_RDWR);
+    if (fd < 0)
+       return 1;
+    close(fd);
+    afs_procpath = strdup(path);
+    if (afs_procpath == NULL)
+       return 1;
+    afs_entry_point = LINUX_PROC_POINT;
+    return 0;
+}
+
+static int
+do_proc(struct procdata *data)
+{
+    int fd, ret, saved_errno;
+    fd = open(afs_procpath, O_RDWR);
+    if (fd < 0) {
+       errno = EINVAL;
+       return -1;
+    }
+    ret = ioctl(fd, VIOC_SYSCALL, data);
+    saved_errno = errno;
+    close(fd);
+    errno = saved_errno;
+    return ret;
+}
+
+int
+k_pioctl(char *a_path,
+        int o_opcode,
+        struct ViceIoctl *a_paramsP,
+        int a_followSymlinks)
+{
+#ifndef NO_AFS
+    switch(afs_entry_point){
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
+    case SINGLE_ENTRY_POINT:
+    case SINGLE_ENTRY_POINT2:
+    case SINGLE_ENTRY_POINT3:
+       return syscall(afs_syscalls[0], AFSCALL_PIOCTL,
+                      a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+#if defined(AFS_PIOCTL)
+    case MULTIPLE_ENTRY_POINT:
+       return syscall(afs_syscalls[0],
+                      a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+    case LINUX_PROC_POINT: {
+       struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
+       data.param1 = (unsigned long)a_path;
+       data.param2 = (unsigned long)o_opcode;
+       data.param3 = (unsigned long)a_paramsP;
+       data.param4 = (unsigned long)a_followSymlinks;
+       return do_proc(&data);
+    }
+#ifdef _AIX
+    case AIX_ENTRY_POINTS:
+       return Pioctl(a_path, o_opcode, a_paramsP, a_followSymlinks);
+#endif
+    }    
+    errno = ENOSYS;
+#ifdef SIGSYS
+    kill(getpid(), SIGSYS);    /* You lose! */
+#endif
+#endif /* NO_AFS */
+    return -1;
+}
+
+int
+k_afs_cell_of_file(const char *path, char *cell, int len)
+{
+    struct ViceIoctl parms;
+    parms.in = NULL;
+    parms.in_size = 0;
+    parms.out = cell;
+    parms.out_size = len;
+    return k_pioctl((char*)path, VIOC_FILE_CELL_NAME, &parms, 1);
+}
+
+int
+k_unlog(void)
+{
+    struct ViceIoctl parms;
+    memset(&parms, 0, sizeof(parms));
+    return k_pioctl(0, VIOCUNLOG, &parms, 0);
+}
+
+int
+k_setpag(void)
+{
+#ifndef NO_AFS
+    switch(afs_entry_point){
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
+    case SINGLE_ENTRY_POINT:
+    case SINGLE_ENTRY_POINT2:
+    case SINGLE_ENTRY_POINT3:
+       return syscall(afs_syscalls[0], AFSCALL_SETPAG);
+#endif
+#if defined(AFS_PIOCTL)
+    case MULTIPLE_ENTRY_POINT:
+       return syscall(afs_syscalls[1]);
+#endif
+    case LINUX_PROC_POINT: {
+       struct procdata data = { 0, 0, 0, 0, AFSCALL_SETPAG };
+       return do_proc(&data);
+    }
+#ifdef _AIX
+    case AIX_ENTRY_POINTS:
+       return Setpag();
+#endif
+    }
+    
+    errno = ENOSYS;
+#ifdef SIGSYS
+    kill(getpid(), SIGSYS);    /* You lose! */
+#endif
+#endif /* NO_AFS */
+    return -1;
+}
+
+static jmp_buf catch_SIGSYS;
+
+#ifdef SIGSYS
+
+static RETSIGTYPE
+SIGSYS_handler(int sig)
+{
+    errno = 0;
+    signal(SIGSYS, SIGSYS_handler); /* Need to reinstall handler on SYSV */
+    longjmp(catch_SIGSYS, 1);
+}
+
+#endif
+
+/*
+ * Try to see if `syscall' is a pioctl.  Return 0 iff succesful.
+ */
+
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
+static int
+try_one (int syscall_num)
+{
+    struct ViceIoctl parms;
+    memset(&parms, 0, sizeof(parms));
+
+    if (setjmp(catch_SIGSYS) == 0) {
+       syscall(syscall_num, AFSCALL_PIOCTL,
+               0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+       if (errno == EINVAL) {
+           afs_entry_point = SINGLE_ENTRY_POINT;
+           afs_syscalls[0] = syscall_num;
+           return 0;
+       }
+    }
+    return 1;
+}
+#endif
+
+/*
+ * Try to see if `syscall_pioctl' is a pioctl syscall.  Return 0 iff
+ * succesful.
+ *
+ */
+
+#ifdef AFS_PIOCTL
+static int
+try_two (int syscall_pioctl, int syscall_setpag)
+{
+    struct ViceIoctl parms;
+    memset(&parms, 0, sizeof(parms));
+
+    if (setjmp(catch_SIGSYS) == 0) {
+       syscall(syscall_pioctl,
+               0, VIOCSETTOK, &parms, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
+       if (errno == EINVAL) {
+           afs_entry_point = MULTIPLE_ENTRY_POINT;
+           afs_syscalls[0] = syscall_pioctl;
+           afs_syscalls[1] = syscall_setpag;
+           return 0;
+       }
+    }
+    return 1;
+}
+#endif
+
+int
+k_hasafs(void)
+{
+#if !defined(NO_AFS) && defined(SIGSYS)
+    RETSIGTYPE (*saved_func)(int);
+#endif
+    int saved_errno;
+    char *env = getenv ("AFS_SYSCALL");
+  
+    /*
+     * Already checked presence of AFS syscalls?
+     */
+    if (afs_entry_point != UNKNOWN_ENTRY_POINT)
+       return afs_entry_point != NO_ENTRY_POINT;
+
+    /*
+     * Probe kernel for AFS specific syscalls,
+     * they (currently) come in two flavors.
+     * If the syscall is absent we recive a SIGSYS.
+     */
+    afs_entry_point = NO_ENTRY_POINT;
+  
+    saved_errno = errno;
+#ifndef NO_AFS
+#ifdef SIGSYS
+    saved_func = signal(SIGSYS, SIGSYS_handler);
+#endif
+
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3)
+    {
+       int tmp;
+
+       if (env != NULL) {
+           if (sscanf (env, "%d", &tmp) == 1) {
+               if (try_one (tmp) == 0)
+                   goto done;
+           } else {
+               char *end = NULL;
+               char *p;
+               char *s = strdup (env);
+
+               if (s != NULL) {
+                   for (p = strtok_r (s, ",", &end);
+                        p != NULL;
+                        p = strtok_r (NULL, ",", &end)) {
+                       if (map_syscall_name_to_number (p, &tmp) == 0)
+                           if (try_one (tmp) == 0) {
+                               free (s);
+                               goto done;
+                           }
+                   }
+                   free (s);
+               }
+           }
+       }
+    }
+#endif /* AFS_SYSCALL || AFS_SYSCALL2 || AFS_SYSCALL3 */
+
+#ifdef AFS_SYSCALL
+    if (try_one (AFS_SYSCALL) == 0)
+       goto done;
+#endif /* AFS_SYSCALL */
+
+#ifdef AFS_PIOCTL
+    {
+       int tmp[2];
+
+       if (env != NULL && sscanf (env, "%d%d", &tmp[0], &tmp[1]) == 2)
+           if (try_two (tmp[0], tmp[1]) == 2)
+               goto done;
+    }
+#endif /* AFS_PIOCTL */
+
+#ifdef AFS_PIOCTL
+    if (try_two (AFS_PIOCTL, AFS_SETPAG) == 0)
+       goto done;
+#endif /* AFS_PIOCTL */
+
+#ifdef AFS_SYSCALL2
+    if (try_one (AFS_SYSCALL2) == 0)
+       goto done;
+#endif /* AFS_SYSCALL2 */
+
+#ifdef AFS_SYSCALL3
+    if (try_one (AFS_SYSCALL3) == 0)
+       goto done;
+#endif /* AFS_SYSCALL3 */
+
+#ifdef _AIX
+#if 0
+    if (env != NULL) {
+       char *pos = NULL;
+       char *pioctl_name;
+       char *setpag_name;
+
+       pioctl_name = strtok_r (env, ", \t", &pos);
+       if (pioctl_name != NULL) {
+           setpag_name = strtok_r (NULL, ", \t", &pos);
+           if (setpag_name != NULL)
+               if (try_aix (pioctl_name, setpag_name) == 0)
+                   goto done;
+       }
+    }
+#endif
+
+    if(try_aix() == 0)
+       goto done;
+#endif
+
+    if (try_proc("/proc/fs/openafs/afs_ioctl") == 0)
+       goto done;
+    if (try_proc("/proc/fs/nnpfs/afs_ioctl") == 0)
+       goto done;
+    if (env && try_proc(env) == 0)
+       goto done;
+
+done:
+#ifdef SIGSYS
+    signal(SIGSYS, saved_func);
+#endif
+#endif /* NO_AFS */
+    errno = saved_errno;
+    return afs_entry_point != NO_ENTRY_POINT;
+}
diff --git a/src/kerberosV/src/lib/kafs/afssysdefs.h b/src/kerberosV/src/lib/kafs/afssysdefs.h
new file mode 100644 (file)
index 0000000..5aa6831
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1995 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: afssysdefs.h,v 1.28 2004/08/09 13:41:32 lha Exp $ */
+
+/*
+ * This section is for machines using single entry point AFS syscalls!
+ * and/or
+ * This section is for machines using multiple entry point AFS syscalls!
+ *
+ * SunOS 4 is an example of single entry point and sgi of multiple
+ * entry point syscalls.
+ */
+
+#if SunOS == 40
+#define AFS_SYSCALL    31
+#endif
+
+#if SunOS >= 50 && SunOS < 57
+#define AFS_SYSCALL    105
+#endif
+
+#if SunOS == 57
+#define AFS_SYSCALL    73
+#endif
+
+#if SunOS >= 58
+#define AFS_SYSCALL    65
+#endif
+
+#if defined(__hpux)
+#define AFS_SYSCALL    50
+#define AFS_SYSCALL2   49
+#define AFS_SYSCALL3   48
+#endif
+
+#if defined(_AIX)
+/* _AIX is too weird */
+#endif
+
+#if defined(__sgi)
+#define AFS_PIOCTL      (64+1000)
+#define AFS_SETPAG      (65+1000)
+#endif
+
+#if defined(__osf__)
+#define AFS_SYSCALL    232
+#define AFS_SYSCALL2   258
+#endif
+
+#if defined(__ultrix)
+#define AFS_SYSCALL    31
+#endif
+
+#if defined(__FreeBSD__)
+#if __FreeBSD_version >= 500000
+#define AFS_SYSCALL 339
+#else
+#define AFS_SYSCALL 210
+#endif
+#endif /* __FreeBSD__ */
+
+#ifdef __DragonFly__
+#ifndef AFS_SYSCALL
+#define AFS_SYSCALL 339
+#endif
+#endif
+
+#ifdef __OpenBSD__
+#define AFS_SYSCALL 208
+#endif
+
+#if defined(__NetBSD__)
+#define AFS_SYSCALL 210
+#endif
+
+#ifdef __APPLE__               /* MacOS X */
+#define AFS_SYSCALL 230
+#endif
+
+#ifdef SYS_afs_syscall
+#define AFS_SYSCALL3   SYS_afs_syscall
+#endif
diff --git a/src/kerberosV/src/lib/kafs/common.c b/src/kerberosV/src/lib/kafs/common.c
new file mode 100644 (file)
index 0000000..5d6d77d
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "kafs_locl.h"
+
+RCSID("$KTH: common.c,v 1.31 2005/06/02 07:38:06 lha Exp $");
+
+#define AUTH_SUPERUSER "afs"
+
+/*
+ * Here only ASCII characters are relevant.
+ */
+
+#define IsAsciiLower(c) ('a' <= (c) && (c) <= 'z')
+
+#define ToAsciiUpper(c) ((c) - 'a' + 'A')
+
+static void (*kafs_verbose)(void *, const char *);
+static void *kafs_verbose_ctx;
+
+void
+_kafs_foldup(char *a, const char *b)
+{
+  for (; *b; a++, b++)
+    if (IsAsciiLower(*b))
+      *a = ToAsciiUpper(*b);
+    else
+      *a = *b;
+  *a = '\0';
+}
+
+void
+kafs_set_verbose(void (*f)(void *, const char *), void *ctx)
+{
+    if (f) {
+       kafs_verbose = f;
+       kafs_verbose_ctx = ctx;
+    }
+}
+
+int
+kafs_settoken_rxkad(const char *cell, struct ClearToken *ct,
+                   void *ticket, size_t ticket_len)
+{
+    struct ViceIoctl parms;
+    char buf[2048], *t;
+    int32_t sizeof_x;
+    
+    t = buf;
+    /*
+     * length of secret token followed by secret token
+     */
+    sizeof_x = ticket_len;
+    memcpy(t, &sizeof_x, sizeof(sizeof_x));
+    t += sizeof(sizeof_x);
+    memcpy(t, ticket, sizeof_x);
+    t += sizeof_x;
+    /*
+     * length of clear token followed by clear token
+     */
+    sizeof_x = sizeof(*ct);
+    memcpy(t, &sizeof_x, sizeof(sizeof_x));
+    t += sizeof(sizeof_x);
+    memcpy(t, ct, sizeof_x);
+    t += sizeof_x;
+
+    /*
+     * do *not* mark as primary cell
+     */
+    sizeof_x = 0;
+    memcpy(t, &sizeof_x, sizeof(sizeof_x));
+    t += sizeof(sizeof_x);
+    /*
+     * follow with cell name
+     */
+    sizeof_x = strlen(cell) + 1;
+    memcpy(t, cell, sizeof_x);
+    t += sizeof_x;
+
+    /*
+     * Build argument block
+     */
+    parms.in = buf;
+    parms.in_size = t - buf;
+    parms.out = 0;
+    parms.out_size = 0;
+
+    return k_pioctl(0, VIOCSETTOK, &parms, 0);
+}
+
+void
+_kafs_fixup_viceid(struct ClearToken *ct, uid_t uid)
+{
+#define ODD(x) ((x) & 1)
+    /* According to Transarc conventions ViceId is valid iff
+     * (EndTimestamp - BeginTimestamp) is odd. By decrementing EndTime
+     * the transformations:
+     *
+     * (issue_date, life) -> (StartTime, EndTime) -> (issue_date, life)
+     * preserves the original values.
+     */
+    if (uid != 0)              /* valid ViceId */
+    {
+       if (!ODD(ct->EndTimestamp - ct->BeginTimestamp))
+           ct->EndTimestamp--;
+    }
+    else                       /* not valid ViceId */
+    {
+       if (ODD(ct->EndTimestamp - ct->BeginTimestamp))
+           ct->EndTimestamp--;
+    }
+}
+
+
+int
+_kafs_v4_to_kt(CREDENTIALS *c, uid_t uid, struct kafs_token *kt)
+{
+    kt->ticket = NULL;
+
+    if (c->ticket_st.length > MAX_KTXT_LEN)
+       return EINVAL;
+
+    kt->ticket = malloc(c->ticket_st.length);
+    if (kt->ticket == NULL)
+       return ENOMEM;
+    kt->ticket_len = c->ticket_st.length;
+    memcpy(kt->ticket, c->ticket_st.dat, kt->ticket_len);
+    
+    /*
+     * Build a struct ClearToken
+     */
+    kt->ct.AuthHandle = c->kvno;
+    memcpy (kt->ct.HandShakeKey, c->session, sizeof(c->session));
+    kt->ct.ViceId = uid;
+    kt->ct.BeginTimestamp = c->issue_date;
+    kt->ct.EndTimestamp = krb_life_to_time(c->issue_date, c->lifetime);
+
+    _kafs_fixup_viceid(&kt->ct, uid);
+
+    return 0;
+}
+
+/* Try to get a db-server for an AFS cell from a AFSDB record */
+
+static int
+dns_find_cell(const char *cell, char *dbserver, size_t len)
+{
+    struct dns_reply *r;
+    int ok = -1;
+    r = dns_lookup(cell, "afsdb");
+    if(r){
+       struct resource_record *rr = r->head;
+       while(rr){
+           if(rr->type == T_AFSDB && rr->u.afsdb->preference == 1){
+               strlcpy(dbserver,
+                               rr->u.afsdb->domain,
+                               len);
+               ok = 0;
+               break;
+           }
+           rr = rr->next;
+       }
+       dns_free_data(r);
+    }
+    return ok;
+}
+
+
+/*
+ * Try to find the cells we should try to klog to in "file".
+ */
+static void
+find_cells(const char *file, char ***cells, int *index)
+{
+    FILE *f;
+    char cell[64];
+    int i;
+    int ind = *index;
+
+    f = fopen(file, "r");
+    if (f == NULL)
+       return;
+    while (fgets(cell, sizeof(cell), f)) {
+       char *t;
+       t = cell + strlen(cell);
+       for (; t >= cell; t--)
+         if (*t == '\n' || *t == '\t' || *t == ' ')
+           *t = 0;
+       if (cell[0] == '\0' || cell[0] == '#')
+           continue;
+       for(i = 0; i < ind; i++)
+           if(strcmp((*cells)[i], cell) == 0)
+               break;
+       if(i == ind){
+           char **tmp;
+
+           tmp = realloc(*cells, (ind + 1) * sizeof(**cells));
+           if (tmp == NULL)
+               break;
+           *cells = tmp;
+           (*cells)[ind] = strdup(cell);
+           if ((*cells)[ind] == NULL)
+               break;
+           ++ind;
+       }
+    }
+    fclose(f);
+    *index = ind;
+}
+
+/*
+ * Get tokens for all cells[]
+ */
+static int
+afslog_cells(struct kafs_data *data, char **cells, int max, uid_t uid,
+            const char *homedir)
+{
+    int ret = 0;
+    int i;
+    for (i = 0; i < max; i++) {
+        int er = (*data->afslog_uid)(data, cells[i], 0, uid, homedir);
+       if (er)
+           ret = er;
+    }
+    return ret;
+}
+
+int
+_kafs_afslog_all_local_cells(struct kafs_data *data,
+                            uid_t uid, const char *homedir)
+{
+    int ret;
+    char **cells = NULL;
+    int index = 0;
+
+    if (homedir == NULL)
+       homedir = getenv("HOME");
+    if (homedir != NULL) {
+       char home[MaxPathLen];
+       snprintf(home, sizeof(home), "%s/.TheseCells", homedir);
+       find_cells(home, &cells, &index);
+    }
+#if 0
+    find_cells(_PATH_THESECELLS, &cells, &index);
+    find_cells(_PATH_THISCELL, &cells, &index);
+#endif
+    find_cells(_PATH_ARLA_THESECELLS, &cells, &index);
+    find_cells(_PATH_ARLA_THISCELL, &cells, &index);
+#if 0
+    find_cells(_PATH_OPENAFS_DEBIAN_THESECELLS, &cells, &index);
+    find_cells(_PATH_OPENAFS_DEBIAN_THISCELL, &cells, &index);
+    find_cells(_PATH_OPENAFS_MACOSX_THESECELLS, &cells, &index);
+    find_cells(_PATH_OPENAFS_MACOSX_THISCELL, &cells, &index);
+    find_cells(_PATH_ARLA_DEBIAN_THESECELLS, &cells, &index);
+    find_cells(_PATH_ARLA_DEBIAN_THISCELL, &cells, &index);
+    find_cells(_PATH_ARLA_OPENBSD_THESECELLS, &cells, &index);
+    find_cells(_PATH_ARLA_OPENBSD_THISCELL, &cells, &index);
+#endif    
+    
+    ret = afslog_cells(data, cells, index, uid, homedir);
+    while(index > 0)
+       free(cells[--index]);
+    free(cells);
+    return ret;
+}
+
+
+static int
+file_find_cell(struct kafs_data *data, 
+              const char *cell, char **realm, int exact)
+{
+    FILE *F;
+    char buf[1024];
+    char *p;
+    int ret = -1;
+
+    if ((F = fopen(_PATH_ARLA_CELLSERVDB, "r"))) {
+       while (fgets(buf, sizeof(buf), F)) {
+           int cmp;
+
+           if (buf[0] != '>')
+               continue; /* Not a cell name line, try next line */
+           p = buf;
+           strsep(&p, " \t\n#");
+
+           if (exact)
+               cmp = strcmp(buf + 1, cell);
+           else
+               cmp = strncmp(buf + 1, cell, strlen(cell));
+
+           if (cmp == 0) {
+               /*
+                * We found the cell name we're looking for.
+                * Read next line on the form ip-address '#' hostname
+                */
+               if (fgets(buf, sizeof(buf), F) == NULL)
+                   break;      /* Read failed, give up */
+               p = strchr(buf, '#');
+               if (p == NULL)
+                   break;      /* No '#', give up */
+               p++;
+               if (buf[strlen(buf) - 1] == '\n')
+                   buf[strlen(buf) - 1] = '\0';
+               *realm = (*data->get_realm)(data, p);
+               if (*realm && **realm != '\0')
+                   ret = 0;
+               break;          /* Won't try any more */
+           }
+       }
+       fclose(F);
+    }
+    return ret;
+}
+
+/* Find the realm associated with cell. Do this by opening CellServDB
+   file and getting the realm-of-host for the first VL-server for the
+   cell.
+
+   This does not work when the VL-server is living in one realm, but
+   the cell it is serving is living in another realm.
+
+   Return 0 on success, -1 otherwise.
+   */
+
+int
+_kafs_realm_of_cell(struct kafs_data *data,
+                   const char *cell, char **realm)
+{
+    char buf[1024];
+    int ret;
+
+    ret = file_find_cell(data, cell, realm, 1);
+    if (ret == 0)
+       return ret;
+    if (dns_find_cell(cell, buf, sizeof(buf)) == 0) {
+       *realm = (*data->get_realm)(data, buf);
+       if(*realm != NULL)
+           return 0;
+    }
+    return file_find_cell(data, cell, realm, 0);
+}
+
+static int
+_kafs_try_get_cred(struct kafs_data *data, const char *user, const char *cell,
+                  const char *realm, uid_t uid, struct kafs_token *kt)
+{
+    int ret;
+
+    ret = (*data->get_cred)(data, user, cell, realm, uid, kt);
+    if (kafs_verbose) {
+       char *str;
+       asprintf(&str, "%s tried afs%s%s@%s -> %d",
+                data->name, cell[0] == '\0' ? "" : "/", 
+                cell, realm, ret);
+       (*kafs_verbose)(kafs_verbose_ctx, str);
+       free(str);
+    }
+
+    return ret;
+}
+
+
+int
+_kafs_get_cred(struct kafs_data *data,
+              const char *cell, 
+              const char *realm_hint,
+              const char *realm,
+              uid_t uid,
+              struct kafs_token *kt)
+{
+    int ret = -1;
+    char *vl_realm;
+    char CELL[64];
+
+    /* We're about to find the realm that holds the key for afs in
+     * the specified cell. The problem is that null-instance
+     * afs-principals are common and that hitting the wrong realm might
+     * yield the wrong afs key. The following assumptions were made.
+     *
+     * Any realm passed to us is preferred.
+     *
+     * If there is a realm with the same name as the cell, it is most
+     * likely the correct realm to talk to.
+     *
+     * In most (maybe even all) cases the database servers of the cell
+     * will live in the realm we are looking for.
+     *
+     * Try the local realm, but if the previous cases fail, this is
+     * really a long shot.
+     *
+     */
+  
+    /* comments on the ordering of these tests */
+
+    /* If the user passes a realm, she probably knows something we don't
+     * know and we should try afs@realm_hint.
+     */
+  
+    if (realm_hint) {
+       ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
+                                cell, realm_hint, uid, kt);
+       if (ret == 0) return 0;
+       ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
+                                "", realm_hint, uid, kt);
+       if (ret == 0) return 0;
+    }
+
+    _kafs_foldup(CELL, cell);
+
+    /*
+     * If cell == realm we don't need no cross-cell authentication.
+     * Try afs@REALM.
+     */
+    if (strcmp(CELL, realm) == 0) {
+        ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
+                                "", realm, uid, kt);
+       if (ret == 0) return 0;
+       /* Try afs.cell@REALM below. */
+    }
+
+    /*
+     * If the AFS servers have a file /usr/afs/etc/krb.conf containing
+     * REALM we still don't have to resort to cross-cell authentication.
+     * Try afs.cell@REALM.
+     */
+    ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 
+                            cell, realm, uid, kt);
+    if (ret == 0) return 0;
+
+    /*
+     * We failed to get ``first class tickets'' for afs,
+     * fall back to cross-cell authentication.
+     * Try afs@CELL.
+     * Try afs.cell@CELL.
+     */
+    ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
+                            "", CELL, uid, kt);
+    if (ret == 0) return 0;
+    ret = _kafs_try_get_cred(data, AUTH_SUPERUSER, 
+                            cell, CELL, uid, kt);
+    if (ret == 0) return 0;
+
+    /*
+     * Perhaps the cell doesn't correspond to any realm?
+     * Use realm of first volume location DB server.
+     * Try afs.cell@VL_REALM.
+     * Try afs@VL_REALM???
+     */
+    if (_kafs_realm_of_cell(data, cell, &vl_realm) == 0
+       && strcmp(vl_realm, realm) != 0
+       && strcmp(vl_realm, CELL) != 0) {
+       ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
+                                cell, vl_realm, uid, kt);
+       if (ret)
+           ret = _kafs_try_get_cred(data, AUTH_SUPERUSER,
+                                    "", vl_realm, uid, kt);
+       free(vl_realm);
+       if (ret == 0) return 0;
+    }
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/kafs/dlfcn.c b/src/kerberosV/src/lib/kafs/dlfcn.c
new file mode 100644 (file)
index 0000000..728cf5c
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * @(#)dlfcn.c 1.11 revision of 96/04/10  20:12:51
+ * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
+ * 30159 Hannover, Germany
+ */
+
+/*
+ * Changes marked with `--jwe' were made on April 7 1996 by John W. Eaton
+ * <jwe@bevo.che.wisc.edu> to support g++ and/or use with Octave.
+ */
+
+/*
+ * This makes my life easier with Octave.  --jwe
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ldr.h>
+#include <a.out.h>
+#include <ldfcn.h>
+#include "dlfcn.h"
+
+/*
+ * We simulate dlopen() et al. through a call to load. Because AIX has
+ * no call to find an exported symbol we read the loader section of the
+ * loaded module and build a list of exported symbols and their virtual
+ * address.
+ */
+
+typedef struct {
+       char            *name;          /* the symbols's name */
+       void            *addr;          /* its relocated virtual address */
+} Export, *ExportPtr;
+
+/*
+ * xlC uses the following structure to list its constructors and
+ * destructors. This is gleaned from the output of munch.
+ */
+typedef struct {
+       void (*init)(void);             /* call static constructors */
+       void (*term)(void);             /* call static destructors */
+} Cdtor, *CdtorPtr;
+
+typedef void (*GccCDtorPtr)(void);
+
+/*
+ * The void * handle returned from dlopen is actually a ModulePtr.
+ */
+typedef struct Module {
+       struct Module   *next;
+       char            *name;          /* module name for refcounting */
+       int             refCnt;         /* the number of references */
+       void            *entry;         /* entry point from load */
+       struct dl_info  *info;          /* optional init/terminate functions */
+       CdtorPtr        cdtors;         /* optional C++ constructors */
+       GccCDtorPtr     gcc_ctor;       /* g++ constructors  --jwe */
+       GccCDtorPtr     gcc_dtor;       /* g++ destructors  --jwe */
+       int             nExports;       /* the number of exports found */
+       ExportPtr       exports;        /* the array of exports */
+} Module, *ModulePtr;
+
+/*
+ * We keep a list of all loaded modules to be able to call the fini
+ * handlers and destructors at atexit() time.
+ */
+static ModulePtr modList;
+
+/*
+ * The last error from one of the dl* routines is kept in static
+ * variables here. Each error is returned only once to the caller.
+ */
+static char errbuf[BUFSIZ];
+static int errvalid;
+
+/*
+ * The `fixed' gcc header files on AIX 3.2.5 provide a prototype for
+ * strdup().  --jwe
+ */
+#ifndef HAVE_STRDUP
+extern char *strdup(const char *);
+#endif
+static void caterr(char *);
+static int readExports(ModulePtr);
+static void terminate(void);
+static void *findMain(void);
+
+void *dlopen(const char *path, int mode)
+{
+       ModulePtr mp;
+       static void *mainModule;
+
+       /*
+        * Upon the first call register a terminate handler that will
+        * close all libraries. Also get a reference to the main module
+        * for use with loadbind.
+        */
+       if (!mainModule) {
+               if ((mainModule = findMain()) == NULL)
+                       return NULL;
+               atexit(terminate);
+       }
+       /*
+        * Scan the list of modules if we have the module already loaded.
+        */
+       for (mp = modList; mp; mp = mp->next)
+               if (strcmp(mp->name, path) == 0) {
+                       mp->refCnt++;
+                       return mp;
+               }
+       if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf), "calloc: %s", strerror(errno));
+               return NULL;
+       }
+       if ((mp->name = strdup(path)) == NULL) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf), "strdup: %s", strerror(errno));
+               free(mp);
+               return NULL;
+       }
+       /*
+        * load should be declared load(const char *...). Thus we
+        * cast the path to a normal char *. Ugly.
+        */
+       if ((mp->entry = (void *)load((char *)path, L_NOAUTODEFER, NULL)) == NULL) {
+               free(mp->name);
+               free(mp);
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "dlopen: %s: ", path);
+               /*
+                * If AIX says the file is not executable, the error
+                * can be further described by querying the loader about
+                * the last error.
+                */
+               if (errno == ENOEXEC) {
+                       char *tmp[BUFSIZ/sizeof(char *)];
+                       if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
+                               strlcpy(errbuf,
+                                               strerror(errno),
+                                               sizeof(errbuf));
+                       else {
+                               char **p;
+                               for (p = tmp; *p; p++)
+                                       caterr(*p);
+                       }
+               } else
+                       strlcat(errbuf,
+                                       strerror(errno),
+                                       sizeof(errbuf));
+               return NULL;
+       }
+       mp->refCnt = 1;
+       mp->next = modList;
+       modList = mp;
+       if (loadbind(0, mainModule, mp->entry) == -1) {
+               dlclose(mp);
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "loadbind: %s", strerror(errno));
+               return NULL;
+       }
+       /*
+        * If the user wants global binding, loadbind against all other
+        * loaded modules.
+        */
+       if (mode & RTLD_GLOBAL) {
+               ModulePtr mp1;
+               for (mp1 = mp->next; mp1; mp1 = mp1->next)
+                       if (loadbind(0, mp1->entry, mp->entry) == -1) {
+                               dlclose(mp);
+                               errvalid++;
+                               snprintf (errbuf, sizeof(errbuf),
+                                         "loadbind: %s",
+                                         strerror(errno));
+                               return NULL;
+                       }
+       }
+       if (readExports(mp) == -1) {
+               dlclose(mp);
+               return NULL;
+       }
+       /*
+        * If there is a dl_info structure, call the init function.
+        */
+       if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
+               if (mp->info->init)
+                       (*mp->info->init)();
+       } else
+               errvalid = 0;
+       /*
+        * If the shared object was compiled using xlC we will need
+        * to call static constructors (and later on dlclose destructors).
+        */
+       if (mp->cdtors = (CdtorPtr)dlsym(mp, "__cdtors")) {
+               CdtorPtr cp = mp->cdtors;
+               while (cp->init || cp->term) {
+                       if (cp->init && cp->init != (void (*)(void))0xffffffff)
+                               (*cp->init)();
+                       cp++;
+               }
+       /*
+        * If the shared object was compiled using g++, we will need
+        * to call global constructors using the _GLOBAL__DI function,
+        * and later, global destructors using the _GLOBAL_DD
+        * funciton.  --jwe
+        */
+       } else if (mp->gcc_ctor = (GccCDtorPtr)dlsym(mp, "_GLOBAL__DI")) {
+               (*mp->gcc_ctor)();
+               mp->gcc_dtor = (GccCDtorPtr)dlsym(mp, "_GLOBAL__DD"); 
+       } else
+               errvalid = 0;
+       return mp;
+}
+
+/*
+ * Attempt to decipher an AIX loader error message and append it
+ * to our static error message buffer.
+ */
+static void caterr(char *s)
+{
+       char *p = s;
+
+       while (*p >= '0' && *p <= '9')
+               p++;
+       switch(atoi(s)) {
+       case L_ERROR_TOOMANY:
+               strlcat(errbuf, "to many errors", sizeof(errbuf));
+               break;
+       case L_ERROR_NOLIB:
+               strlcat(errbuf, "can't load library", sizeof(errbuf));
+               strlcat(errbuf, p, sizeof(errbuf));
+               break;
+       case L_ERROR_UNDEF:
+               strlcat(errbuf, "can't find symbol", sizeof(errbuf));
+               strlcat(errbuf, p, sizeof(errbuf));
+               break;
+       case L_ERROR_RLDBAD:
+               strlcat(errbuf, "bad RLD", sizeof(errbuf));
+               strlcat(errbuf, p, sizeof(errbuf));
+               break;
+       case L_ERROR_FORMAT:
+               strlcat(errbuf, "bad exec format in", sizeof(errbuf));
+               strlcat(errbuf, p, sizeof(errbuf));
+               break;
+       case L_ERROR_ERRNO:
+               strlcat(errbuf, strerror(atoi(++p)), sizeof(errbuf));
+               break;
+       default:
+               strlcat(errbuf, s, sizeof(errbuf));
+               break;
+       }
+}
+
+void *dlsym(void *handle, const char *symbol)
+{
+       ModulePtr mp = (ModulePtr)handle;
+       ExportPtr ep;
+       int i;
+
+       /*
+        * Could speed up the search, but I assume that one assigns
+        * the result to function pointers anyways.
+        */
+       for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
+               if (strcmp(ep->name, symbol) == 0)
+                       return ep->addr;
+       errvalid++;
+       snprintf (errbuf, sizeof(errbuf),
+                 "dlsym: undefined symbol %s", symbol);                  
+       return NULL;
+}
+
+char *dlerror(void)
+{
+       if (errvalid) {
+               errvalid = 0;
+               return errbuf;
+       }
+       return NULL;
+}
+
+int dlclose(void *handle)
+{
+       ModulePtr mp = (ModulePtr)handle;
+       int result;
+       ModulePtr mp1;
+
+       if (--mp->refCnt > 0)
+               return 0;
+       if (mp->info && mp->info->fini)
+               (*mp->info->fini)();
+       if (mp->cdtors) {
+               CdtorPtr cp = mp->cdtors;
+               while (cp->init || cp->term) {
+                       if (cp->term && cp->init != (void (*)(void))0xffffffff)
+                               (*cp->term)();
+                       cp++;
+               }
+       /*
+        * If the function to handle global destructors for g++
+        * exists, call it.  --jwe
+        */
+       } else if (mp->gcc_dtor) {
+               (*mp->gcc_dtor)();
+       }
+       result = unload(mp->entry);
+       if (result == -1) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "%s", strerror(errno));
+       }
+       if (mp->exports) {
+               ExportPtr ep;
+               int i;
+               for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
+                       if (ep->name)
+                               free(ep->name);
+               free(mp->exports);
+       }
+       if (mp == modList)
+               modList = mp->next;
+       else {
+               for (mp1 = modList; mp1; mp1 = mp1->next)
+                       if (mp1->next == mp) {
+                               mp1->next = mp->next;
+                               break;
+                       }
+       }
+       free(mp->name);
+       free(mp);
+       return result;
+}
+
+static void terminate(void)
+{
+       while (modList)
+               dlclose(modList);
+}
+
+/*
+ * Build the export table from the XCOFF .loader section.
+ */
+static int readExports(ModulePtr mp)
+{
+       LDFILE *ldp = NULL;
+       SCNHDR sh, shdata;
+       LDHDR *lhp;
+       char *ldbuf;
+       LDSYM *ls;
+       int i;
+       ExportPtr ep;
+
+       if ((ldp = ldopen(mp->name, ldp)) == NULL) {
+               struct ld_info *lp;
+               char *buf;
+               int size = 4*1024;
+               if (errno != ENOENT) {
+                       errvalid++;
+                       snprintf(errbuf, sizeof(errbuf),
+                                "readExports: %s",
+                                strerror(errno));
+                       return -1;
+               }
+               /*
+                * The module might be loaded due to the LIBPATH
+                * environment variable. Search for the loaded
+                * module using L_GETINFO.
+                */
+               if ((buf = malloc(size)) == NULL) {
+                       errvalid++;
+                       snprintf(errbuf, sizeof(errbuf),
+                                "readExports: %s",
+                                strerror(errno));
+                       return -1;
+               }
+               while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
+                       free(buf);
+                       size += 4*1024;
+                       if ((buf = malloc(size)) == NULL) {
+                               errvalid++;
+                               snprintf(errbuf, sizeof(errbuf),
+                                        "readExports: %s",
+                                        strerror(errno));
+                               return -1;
+                       }
+               }
+               if (i == -1) {
+                       errvalid++;
+                       snprintf(errbuf, sizeof(errbuf),
+                                "readExports: %s",
+                                strerror(errno));
+                       free(buf);
+                       return -1;
+               }
+               /*
+                * Traverse the list of loaded modules. The entry point
+                * returned by load() does actually point to the data
+                * segment origin.
+                */
+               lp = (struct ld_info *)buf;
+               while (lp) {
+                       if (lp->ldinfo_dataorg == mp->entry) {
+                               ldp = ldopen(lp->ldinfo_filename, ldp);
+                               break;
+                       }
+                       if (lp->ldinfo_next == 0)
+                               lp = NULL;
+                       else
+                               lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
+               }
+               free(buf);
+               if (!ldp) {
+                       errvalid++;
+                       snprintf (errbuf, sizeof(errbuf),
+                                 "readExports: %s", strerror(errno));
+                       return -1;
+               }
+       }
+       if (TYPE(ldp) != U802TOCMAGIC) {
+               errvalid++;
+               snprintf(errbuf, sizeof(errbuf), "readExports: bad magic");
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       /*
+        * Get the padding for the data section. This is needed for
+        * AIX 4.1 compilers. This is used when building the final
+        * function pointer to the exported symbol.
+        */
+       if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) {
+               errvalid++;
+               snprintf(errbuf, sizeof(errbuf),
+                        "readExports: cannot read data section header");
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
+               errvalid++;
+               snprintf(errbuf, sizeof(errbuf),
+                        "readExports: cannot read loader section header");
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       /*
+        * We read the complete loader section in one chunk, this makes
+        * finding long symbol names residing in the string table easier.
+        */
+       if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "readExports: %s", strerror(errno));
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
+               errvalid++;
+               snprintf(errbuf, sizeof(errbuf),
+                        "readExports: cannot seek to loader section");
+               free(ldbuf);
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
+               errvalid++;
+               snprintf(errbuf, sizeof(errbuf),
+                        "readExports: cannot read loader section");
+               free(ldbuf);
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       lhp = (LDHDR *)ldbuf;
+       ls = (LDSYM *)(ldbuf+LDHDRSZ);
+       /*
+        * Count the number of exports to include in our export table.
+        */
+       for (i = lhp->l_nsyms; i; i--, ls++) {
+               if (!LDR_EXPORT(*ls))
+                       continue;
+               mp->nExports++;
+       }
+       if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "readExports: %s", strerror(errno));
+               free(ldbuf);
+               while(ldclose(ldp) == FAILURE)
+                       ;
+               return -1;
+       }
+       /*
+        * Fill in the export table. All entries are relative to
+        * the entry point we got from load.
+        */
+       ep = mp->exports;
+       ls = (LDSYM *)(ldbuf+LDHDRSZ);
+       for (i = lhp->l_nsyms; i; i--, ls++) {
+               char *symname;
+               char tmpsym[SYMNMLEN+1];
+               if (!LDR_EXPORT(*ls))
+                       continue;
+               if (ls->l_zeroes == 0)
+                       symname = ls->l_offset+lhp->l_stoff+ldbuf;
+               else {
+                       /*
+                        * The l_name member is not zero terminated, we
+                        * must copy the first SYMNMLEN chars and make
+                        * sure we have a zero byte at the end.
+                        */
+                       strlcpy (tmpsym, ls->l_name,
+                                        SYMNMLEN + 1);
+                       symname = tmpsym;
+               }
+               ep->name = strdup(symname);
+               ep->addr = (void *)((unsigned long)mp->entry +
+                                       ls->l_value - shdata.s_vaddr);
+               ep++;
+       }
+       free(ldbuf);
+       while(ldclose(ldp) == FAILURE)
+               ;
+       return 0;
+}
+
+/*
+ * Find the main modules entry point. This is used as export pointer
+ * for loadbind() to be able to resolve references to the main part.
+ */
+static void * findMain(void)
+{
+       struct ld_info *lp;
+       char *buf;
+       int size = 4*1024;
+       int i;
+       void *ret;
+
+       if ((buf = malloc(size)) == NULL) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "findMail: %s", strerror(errno));
+               return NULL;
+       }
+       while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
+               free(buf);
+               size += 4*1024;
+               if ((buf = malloc(size)) == NULL) {
+                       errvalid++;
+                       snprintf (errbuf, sizeof(errbuf),
+                                 "findMail: %s", strerror(errno));
+                       return NULL;
+               }
+       }
+       if (i == -1) {
+               errvalid++;
+               snprintf (errbuf, sizeof(errbuf),
+                         "findMail: %s", strerror(errno));
+               free(buf);
+               return NULL;
+       }
+       /*
+        * The first entry is the main module. The entry point
+        * returned by load() does actually point to the data
+        * segment origin.
+        */
+       lp = (struct ld_info *)buf;
+       ret = lp->ldinfo_dataorg;
+       free(buf);
+       return ret;
+}
diff --git a/src/kerberosV/src/lib/kafs/dlfcn.h b/src/kerberosV/src/lib/kafs/dlfcn.h
new file mode 100644 (file)
index 0000000..b8dfd98
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * @(#)dlfcn.h 1.4 revision of 95/04/25  09:36:52
+ * This is an unpublished work copyright (c) 1992 HELIOS Software GmbH
+ * 30159 Hannover, Germany
+ */
+
+#ifndef __dlfcn_h__
+#define __dlfcn_h__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Mode flags for the dlopen routine.
+ */
+#define RTLD_LAZY      1       /* lazy function call binding */
+#define RTLD_NOW       2       /* immediate function call binding */
+#define RTLD_GLOBAL    0x100   /* allow symbols to be global */
+
+/*
+ * To be able to initialize, a library may provide a dl_info structure
+ * that contains functions to be called to initialize and terminate.
+ */
+struct dl_info {
+       void (*init)(void);
+       void (*fini)(void);
+};
+
+#if __STDC__ || defined(_IBMR2)
+void *dlopen(const char *path, int mode);
+void *dlsym(void *handle, const char *symbol);
+char *dlerror(void);
+int dlclose(void *handle);
+#else
+void *dlopen();
+void *dlsym();
+char *dlerror();
+int dlclose();
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __dlfcn_h__ */
diff --git a/src/kerberosV/src/lib/kafs/kafs.3 b/src/kerberosV/src/lib/kafs/kafs.3
new file mode 100644 (file)
index 0000000..a1558c2
--- /dev/null
@@ -0,0 +1,274 @@
+.\" Copyright (c) 1998 - 1999, 2001 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\"    $KTH: kafs.3,v 1.17 2003/11/07 23:18:02 lha Exp $
+.\"
+.Dd March 17, 2003
+.Os HEIMDAL
+.Dt KAFS 3
+.Sh NAME
+.Nm k_hasafs ,
+.Nm k_pioctl ,
+.Nm k_unlog ,
+.Nm k_setpag ,
+.Nm k_afs_cell_of_file ,
+.Nm kafs_set_verbose ,
+.Nm kafs_settoken_rxkad ,
+.Nm kafs_settoken ,
+.Nm krb_afslog ,
+.Nm krb_afslog_uid ,
+.Nm kafs_settoken5 ,
+.Nm krb5_afslog ,
+.Nm krb5_afslog_uid
+.Nd AFS library
+.Sh LIBRARY
+AFS cache manager access library (libkafs, -lkafs)
+.Sh SYNOPSIS
+.In kafs.h
+.Ft int
+.Fn k_afs_cell_of_file "const char *path" "char *cell" "int len"
+.Ft int
+.Fn k_hasafs "void"
+.Ft int
+.Fn k_pioctl "char *a_path" "int o_opcode" "struct ViceIoctl *a_paramsP" "int a_followSymlinks"
+.Ft int
+.Fn k_setpag "void"
+.Ft int
+.Fn k_unlog "void"
+.Ft void
+.Fn kafs_set_verbose "void (*func)(void *, const char *, int)" "void *"
+.Ft int
+.Fn kafs_settoken_rxkad "const char *cell" "struct ClearToken *token" "void *ticket" "size_t ticket_len"
+.Ft int
+.Fn kafs_settoken "const char *cell" "uid_t uid" "CREDENTIALS *c"
+.Fn krb_afslog "char *cell" "char *realm"
+.Ft int
+.Fn krb_afslog_uid "char *cell" "char *realm" "uid_t uid"
+.Ft krb5_error_code
+.Fn krb5_afslog_uid "krb5_context context" "krb5_ccache id" "const char *cell" "krb5_const_realm realm" "uid_t uid"
+.Ft int
+.Fn kafs_settoken5 "const char *cell" "uid_t uid" "krb5_creds *c"
+.Ft krb5_error_code
+.Fn krb5_afslog "krb5_context context" "krb5_ccache id" "const char *cell" "krb5_const_realm realm"
+.Sh DESCRIPTION
+.Fn k_hasafs
+initializes some library internal structures, and tests for the
+presence of AFS in the kernel, none of the other functions should be
+called before
+.Fn k_hasafs
+is called, or if it fails.
+.Pp
+.Fn kafs_set_verbose
+set a log function that will be called each time the kafs library does
+something important so that the application using libkafs can output
+verbose logging.
+Calling the function
+.Fa kafs_set_verbose
+with the function argument set to
+.Dv NULL
+will stop libkafs from calling the logging function (if set).
+.Pp
+.Fn kafs_settoken_rxkad
+set
+.Li rxkad
+with the
+.Fa token
+and
+.Fa ticket
+(that have the length
+.Fa ticket_len )
+for a given
+.Fa cell .
+.Pp
+.Fn kafs_settoken
+and
+.Fn kafs_settoken5
+work the same way as
+.Fn kafs_settoken_rxkad
+but internally converts the Kerberos 4 or 5 credential to a afs
+cleartoken and ticket.
+.Pp
+.Fn krb_afslog ,
+and
+.Fn krb_afslog_uid
+obtains new tokens (and possibly tickets) for the specified
+.Fa cell
+and
+.Fa realm .
+If
+.Fa cell
+is
+.Dv NULL ,
+the local cell is used. If
+.Fa realm
+is
+.Dv NULL ,
+the function tries to guess what realm to use. Unless you  have some good knowledge of what cell or realm to use, you should pass
+.Dv NULL .
+.Fn krb_afslog
+will use the real user-id for the
+.Dv ViceId
+field in the token,
+.Fn krb_afslog_uid
+will use
+.Fa uid .
+.Pp
+.Fn krb5_afslog ,
+and
+.Fn krb5_afslog_uid
+are the Kerberos 5 equivalents of
+.Fn krb_afslog ,
+and
+.Fn krb_afslog_uid .
+.Pp
+.Fn krb5_afslog ,
+.Fn kafs_settoken5
+can be configured to behave differently via a 
+.Nm krb5_appdefault
+option
+.Li afs-use-524
+in
+.Pa krb5.conf .
+Possible values for
+.Li afs-use-524
+are:
+.Bl -tag -width local
+.It yes
+use the 524 server in the realm to convert the ticket
+.It no
+use the Kerberos 5 ticket directly, can be used with if the afs cell
+support 2b token.
+.It local, 2b
+convert the Kerberos 5 credential to a 2b token locally (the same work
+as a 2b 524 server should have done).
+.El
+.Pp
+Example:
+.Pp
+.Bd -literal
+[appdefaults]
+       SU.SE = { afs-use-524 = local }
+       PDC.KTH.SE = { afs-use-524 = yes }
+       afs-use-524 = yes
+.Ed
+.Pp
+libkafs will use the
+.Li libkafs
+as application name when running the
+.Nm krb5_appdefault
+function call.
+.Pp
+The (uppercased) cell name is used as the realm to the
+.Nm krb5_appdefault function.
+.Pp
+.\" The extra arguments are the ubiquitous context, and the cache id where
+.\" to store any obtained tickets. Since AFS servers normally can't handle
+.\" Kerberos 5 tickets directly, these functions will first obtain version
+.\" 5 tickets for the requested cells, and then convert them to version 4
+.\" tickets, that can be stashed in the kernel. To convert tickets the
+.\" .Fn krb524_convert_creds_kdc
+.\" function will be used.
+.\" .Pp
+.Fn k_afs_cell_of_file
+will in
+.Fa cell
+return the cell of a specified file, no more than
+.Fa len
+characters is put in
+.Fa cell .
+.Pp
+.Fn k_pioctl
+does a
+.Fn pioctl
+system call with the specified arguments. This function is equivalent to
+.Fn lpioctl .
+.Pp
+.Fn k_setpag
+initializes a new PAG.
+.Pp
+.Fn k_unlog
+removes destroys all tokens in the current PAG.
+.Sh RETURN VALUES
+.Fn k_hasafs
+returns 1 if AFS is present in the kernel, 0 otherwise.
+.Fn krb_afslog
+and
+.Fn krb_afslog_uid
+returns 0 on success, or a Kerberos error number on failure.
+.Fn k_afs_cell_of_file ,
+.Fn k_pioctl ,
+.Fn k_setpag ,
+and
+.Fn k_unlog
+all return the value of the underlaying system call, 0 on success.
+.Sh ENVIRONMENT
+The following environment variable affect the mode of operation of
+.Nm kafs :
+.Bl -tag -width AFS_SYSCALL
+.It Ev AFS_SYSCALL
+Normally,
+.Nm kafs
+will try to figure out the correct system call(s) that are used by AFS
+by itself.  If it does not manage to do that, or does it incorrectly,
+you can set this variable to the system call number or list of system
+call numbers that should be used.
+.El
+.Sh EXAMPLES
+The following code from
+.Nm login
+will obtain a new PAG and tokens for the local cell and the cell of
+the users home directory.
+.Bd -literal
+if (k_hasafs()) {
+       char cell[64];
+       k_setpag();
+       if(k_afs_cell_of_file(pwd->pw_dir, cell, sizeof(cell)) == 0)
+               krb_afslog(cell, NULL);
+       krb_afslog(NULL, NULL);
+}
+.Ed
+.Sh ERRORS
+If any of these functions (apart from
+.Fn k_hasafs )
+is called without AFS being present in the kernel, the process will
+usually (depending on the operating system) receive a SIGSYS signal.
+.Sh SEE ALSO
+.Xr krb5_appdefaults 3 ,
+.Xr krb5.conf 5
+.Rs
+.%A Transarc Corporation
+.%J AFS-3 Programmer's Reference
+.%T File Server/Cache Manager Interface
+.%D 1991
+.Re
+.Sh BUGS
+.Ev AFS_SYSCALL
+has no effect under AIX.
diff --git a/src/kerberosV/src/lib/kafs/kafs.h b/src/kerberosV/src/lib/kafs/kafs.h
new file mode 100644 (file)
index 0000000..e6e58d1
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1995 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: kafs.h,v 1.43 2005/02/03 08:45:13 lha Exp $ */
+
+#ifndef __KAFS_H
+#define __KAFS_H
+
+/* XXX must include krb5.h or krb.h */
+
+/* sys/ioctl.h must be included manually before kafs.h */
+
+/*
+ */
+
+#include<nnpfs/nnpfs_pioctl.h>
+
+/* Use k_hasafs() to probe if the machine supports AFS syscalls.
+   The other functions will generate a SIGSYS if AFS is not supported */
+
+int k_hasafs (void);
+
+int krb_afslog (const char *cell, const char *realm);
+int krb_afslog_uid (const char *cell, const char *realm, uid_t uid);
+int krb_afslog_home (const char *cell, const char *realm,
+                        const char *homedir);
+int krb_afslog_uid_home (const char *cell, const char *realm, uid_t uid,
+                            const char *homedir);
+
+int krb_realm_of_cell (const char *cell, char **realm);
+
+/* compat */
+#define k_afsklog krb_afslog
+#define k_afsklog_uid krb_afslog_uid
+
+int k_pioctl (char *a_path,
+                 int o_opcode,
+                 struct ViceIoctl *a_paramsP,
+                 int a_followSymlinks);
+int k_unlog (void);
+int k_setpag (void);
+int k_afs_cell_of_file (const char *path, char *cell, int len);
+
+
+
+/* XXX */
+#ifdef KFAILURE
+#define KRB_H_INCLUDED
+#endif
+
+#ifdef KRB5_RECVAUTH_IGNORE_VERSION
+#define KRB5_H_INCLUDED
+#endif
+
+void kafs_set_verbose (void (*kafs_verbose)(void *, const char *), void *);
+int kafs_settoken_rxkad (const char *, struct ClearToken *,
+                            void *ticket, size_t ticket_len);
+#ifdef KRB_H_INCLUDED
+int kafs_settoken (const char*, uid_t, CREDENTIALS*);
+#endif
+#ifdef KRB5_H_INCLUDED
+int kafs_settoken5 (krb5_context, const char*, uid_t, krb5_creds*);
+#endif
+
+
+#ifdef KRB5_H_INCLUDED
+krb5_error_code krb5_afslog_uid (krb5_context context,
+                                    krb5_ccache id,
+                                    const char *cell,
+                                    krb5_const_realm realm,
+                                    uid_t uid);
+krb5_error_code krb5_afslog (krb5_context context,
+                                krb5_ccache id, 
+                                const char *cell,
+                                krb5_const_realm realm);
+krb5_error_code krb5_afslog_uid_home (krb5_context context,
+                                         krb5_ccache id,
+                                         const char *cell,
+                                         krb5_const_realm realm,
+                                         uid_t uid,
+                                         const char *homedir);
+
+krb5_error_code krb5_afslog_home (krb5_context context,
+                                     krb5_ccache id,
+                                     const char *cell,
+                                     krb5_const_realm realm,
+                                     const char *homedir);
+
+krb5_error_code krb5_realm_of_cell (const char *cell, char **realm);
+
+#endif
+
+#define _PATH_VICE             "/etc/afs/"
+#define _PATH_THISCELL                 _PATH_VICE "ThisCell"
+#define _PATH_CELLSERVDB       _PATH_VICE "CellServDB"
+#define _PATH_THESECELLS       _PATH_VICE "TheseCells"
+
+#define _PATH_ARLA_VICE                "/etc/afs/"
+#define _PATH_ARLA_THISCELL    _PATH_ARLA_VICE "ThisCell"
+#define _PATH_ARLA_CELLSERVDB  _PATH_ARLA_VICE "CellServDB"
+#define _PATH_ARLA_THESECELLS  _PATH_ARLA_VICE "TheseCells"
+
+#if 0
+#define _PATH_OPENAFS_DEBIAN_VICE              "/etc/openafs/"
+#define _PATH_OPENAFS_DEBIAN_THISCELL          _PATH_OPENAFS_DEBIAN_VICE "ThisCell"
+#define _PATH_OPENAFS_DEBIAN_CELLSERVDB        _PATH_OPENAFS_DEBIAN_VICE "CellServDB"
+#define _PATH_OPENAFS_DEBIAN_THESECELLS                _PATH_OPENAFS_DEBIAN_VICE "TheseCells"
+#endif
+
+#define _PATH_OPENAFS_MACOSX_VICE              "/var/db/openafs/etc/"
+#define _PATH_OPENAFS_MACOSX_THISCELL          _PATH_OPENAFS_MACOSX_VICE "ThisCell"
+#define _PATH_OPENAFS_MACOSX_CELLSERVDB                _PATH_OPENAFS_MACOSX_VICE "CellServDB"
+#define _PATH_OPENAFS_MACOSX_THESECELLS                _PATH_OPENAFS_MACOSX_VICE "TheseCells"
+
+#define _PATH_ARLA_DEBIAN_VICE                 "/etc/arla/"
+#define _PATH_ARLA_DEBIAN_THISCELL             _PATH_ARLA_DEBIAN_VICE "ThisCell"
+#define _PATH_ARLA_DEBIAN_CELLSERVDB           _PATH_ARLA_DEBIAN_VICE "CellServDB"
+#define _PATH_ARLA_DEBIAN_THESECELLS           _PATH_ARLA_DEBIAN_VICE "TheseCells"
+
+#define _PATH_ARLA_OPENBSD_VICE                        "/etc/afs/"
+#define _PATH_ARLA_OPENBSD_THISCELL            _PATH_ARLA_OPENBSD_VICE "ThisCell"
+#define _PATH_ARLA_OPENBSD_CELLSERVDB          _PATH_ARLA_OPENBSD_VICE "CellServDB"
+#define _PATH_ARLA_OPENBSD_THESECELLS          _PATH_ARLA_OPENBSD_VICE "TheseCells"
+
+extern int _kafs_debug;
+
+#endif /* __KAFS_H */
diff --git a/src/kerberosV/src/lib/kafs/kafs_locl.h b/src/kerberosV/src/lib/kafs/kafs_locl.h
new file mode 100644 (file)
index 0000000..45bf7fc
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: kafs_locl.h,v 1.18 2005/06/02 07:38:22 lha Exp $ */
+
+#ifndef __KAFS_LOCL_H__
+#define __KAFS_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+
+#ifdef HAVE_SYS_SYSCALL_H
+#include <sys/syscall.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#include <roken.h>
+
+#ifdef KRB5
+#include <krb5.h>
+#endif
+#ifdef KRB4
+#include <krb.h>
+#else
+#ifdef KRB5
+#include "crypto-headers.h"
+#include <krb5-v4compat.h>
+typedef struct credentials CREDENTIALS;
+#endif /* KRB5 */
+#endif /* KRB4 */
+#include <kafs.h>
+
+#include <resolve.h>
+
+#include "afssysdefs.h"
+
+struct kafs_data;
+struct kafs_token;
+typedef int (*afslog_uid_func_t)(struct kafs_data *,
+                                const char *,
+                                const char *,
+                                uid_t,
+                                const char *);
+
+typedef int (*get_cred_func_t)(struct kafs_data*, const char*, const char*, 
+                              const char*, uid_t, struct kafs_token *);
+
+typedef char* (*get_realm_func_t)(struct kafs_data*, const char*);
+
+struct kafs_data {
+    const char *name;
+    afslog_uid_func_t afslog_uid;
+    get_cred_func_t get_cred;
+    get_realm_func_t get_realm;
+    void *data;
+};
+
+struct kafs_token {
+    struct ClearToken ct;
+    void *ticket;
+    size_t ticket_len;
+};
+
+void _kafs_foldup(char *, const char *);
+
+int _kafs_afslog_all_local_cells(struct kafs_data*, uid_t, const char*);
+
+int _kafs_get_cred(struct kafs_data*, const char*, const char*, const char *, 
+                  uid_t, struct kafs_token *);
+
+int
+_kafs_realm_of_cell(struct kafs_data *, const char *, char **);
+
+int
+_kafs_v4_to_kt(CREDENTIALS *, uid_t, struct kafs_token *);
+
+void
+_kafs_fixup_viceid(struct ClearToken *, uid_t);
+
+#ifdef _AIX
+int aix_pioctl(char*, int, struct ViceIoctl*, int);
+int aix_setpag(void);
+#endif
+
+#endif /* __KAFS_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/kafs/roken_rename.h b/src/kerberosV/src/lib/kafs/roken_rename.h
new file mode 100644 (file)
index 0000000..9e70112
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: roken_rename.h,v 1.7 2005/06/02 07:35:45 lha Exp $ */
+
+#ifndef __roken_rename_h__
+#define __roken_rename_h__
+
+/*
+ * Libroken routines that are added libkafs
+ */
+
+#define _resolve_debug _kafs_resolve_debug
+
+#define rk_dns_free_data _kafs_dns_free_data
+#define rk_dns_lookup _kafs_dns_lookup
+#define rk_dns_string_to_type _kafs_dns_string_to_type
+#define rk_dns_type_to_string _kafs_dns_type_to_string
+#define rk_dns_srv_order _kafs_dns_srv_order
+#define rk_dns_make_query _kafs_dns_make_query
+#define rk_dns_free_query _kafs_dns_free_query
+#define rk_dns_parse_reply _kafs_dns_parse_reply
+
+#ifndef HAVE_STRTOK_R
+#define strtok_r _kafs_strtok_r
+#endif
+#ifndef HAVE_STRLCPY
+#define strlcpy _kafs_strlcpy
+#endif
+#ifndef HAVE_STRSEP
+#define strsep _kafs_strsep
+#endif
+
+#endif /* __roken_rename_h__ */
diff --git a/src/kerberosV/src/lib/krb5/CVS/Entries b/src/kerberosV/src/lib/krb5/CVS/Entries
new file mode 100644 (file)
index 0000000..6562436
--- /dev/null
@@ -0,0 +1,189 @@
+/acache.c/1.1.1.1/Fri Apr 14 07:33:12 2006//
+/add_et_list.c/1.1.1.2/Fri Apr 14 07:33:12 2006//
+/addr_families.c/1.4/Fri Oct  6 07:09:10 2006//
+/address.c/1.1.1.2/Fri Jun 22 21:23:19 2001//
+/aes-test.c/1.1.1.2/Fri Apr 14 07:33:13 2006//
+/aname_to_localname.c/1.4/Fri Apr 14 08:15:04 2006//
+/appdefault.c/1.4/Fri Apr 14 08:15:04 2006//
+/asn1_glue.c/1.1.1.2/Fri Apr 14 07:33:13 2006//
+/auth_context.c/1.1.1.5/Fri Apr 14 07:33:13 2006//
+/build_ap_req.c/1.1.1.4/Fri Apr 14 07:33:13 2006//
+/build_auth.c/1.2/Fri Oct  6 07:09:10 2006//
+/cache.c/1.1.1.4/Fri Apr 14 07:33:14 2006//
+/changepw.c/1.1.1.6/Fri Apr 14 07:33:14 2006//
+/codec.c/1.1.1.3/Fri Apr 14 07:33:14 2006//
+/config_file.c/1.7/Mon Dec 18 21:08:28 2006//
+/config_file_netinfo.c/1.1.1.3/Fri Apr 14 07:33:15 2006//
+/constants.c/1.5/Wed Jun 14 17:03:07 2006//
+/context.c/1.5/Fri Apr 14 08:15:04 2006//
+/convert_creds.c/1.1.1.5/Fri Apr 14 07:33:15 2006//
+/copy_host_realm.c/1.1.1.3/Fri Apr 14 07:33:15 2006//
+/crc.c/1.1.1.1/Fri May 25 07:50:38 2001//
+/creds.c/1.1.1.3/Fri Apr 14 07:33:15 2006//
+/data.c/1.1.1.4/Fri Apr 14 07:33:17 2006//
+/derived-key-test.c/1.1.1.2/Fri Apr 14 07:33:17 2006//
+/dump_config.c/1.1.1.2/Fri Apr 14 07:33:17 2006//
+/eai_to_heim_errno.c/1.1.1.4/Fri Apr 14 07:33:17 2006//
+/error_string.c/1.1.1.2/Fri Apr 14 07:33:17 2006//
+/expand_hostname.c/1.1.1.4/Fri Apr 14 07:33:17 2006//
+/fcache.c/1.4/Fri Apr 14 08:15:04 2006//
+/free.c/1.1.1.2/Fri Apr 14 07:33:17 2006//
+/free_host_realm.c/1.1.1.2/Fri Apr 14 07:33:17 2006//
+/generate_seq_number.c/1.1.1.3/Fri Apr 14 07:33:17 2006//
+/generate_subkey.c/1.1.1.3/Fri Apr 14 07:33:17 2006//
+/get_addrs.c/1.1.1.5/Fri Apr 14 07:33:17 2006//
+/get_cred.c/1.1.1.6/Fri Apr 14 07:33:18 2006//
+/get_default_principal.c/1.1.1.3/Fri Apr 14 07:33:18 2006//
+/get_default_realm.c/1.1.1.4/Fri Apr 14 07:33:18 2006//
+/get_for_creds.c/1.1.1.6/Fri Apr 14 07:33:18 2006//
+/get_host_realm.c/1.3/Fri Apr 14 08:15:04 2006//
+/get_in_tkt.c/1.1.1.6/Fri Apr 14 07:33:18 2006//
+/get_in_tkt_pw.c/1.1.1.3/Fri Apr 14 07:33:18 2006//
+/get_in_tkt_with_keytab.c/1.1.1.3/Fri Apr 14 07:33:19 2006//
+/get_in_tkt_with_skey.c/1.1.1.2/Fri Apr 14 07:33:19 2006//
+/get_port.c/1.1.1.2/Fri Apr 14 07:33:19 2006//
+/heim_err.et/1.1.1.3/Fri Apr 14 07:33:19 2006//
+/heim_threads.h/1.1.1.1/Fri Apr 14 07:33:19 2006//
+/init_creds.c/1.4/Fri Apr 14 08:15:04 2006//
+/init_creds_pw.c/1.1.1.6/Fri Apr 14 07:33:19 2006//
+/k524_err.et/1.1.1.1/Wed Feb  6 08:55:30 2002//
+/kcm.c/1.1.1.1/Fri Apr 14 07:33:20 2006//
+/kcm.h/1.1.1.1/Fri Apr 14 07:33:20 2006//
+/kerberos.8/1.5/Mon May  7 18:04:03 2007//
+/keyblock.c/1.1.1.3/Fri Apr 14 07:33:20 2006//
+/keytab.c/1.1.1.4/Fri Apr 14 07:33:20 2006//
+/keytab_any.c/1.5/Fri Oct  6 07:09:10 2006//
+/keytab_file.c/1.2/Fri Oct  6 07:09:10 2006//
+/keytab_keyfile.c/1.1.1.4/Fri Apr 14 07:33:21 2006//
+/keytab_krb4.c/1.2/Fri Oct  6 07:09:10 2006//
+/keytab_memory.c/1.1.1.3/Fri Apr 14 07:33:21 2006//
+/krb5-private.h/1.1.1.4/Fri Apr 14 07:33:34 2006//
+/krb5-protos.h/1.4/Fri Apr 14 08:15:04 2006//
+/krb5-v4compat.h/1.1.1.2/Fri Apr 14 07:33:21 2006//
+/krb5.3/1.4/Sun Apr 30 09:20:00 2006//
+/krb5.conf.5/1.11/Fri Apr 14 08:15:04 2006//
+/krb5.h/1.8/Fri Apr 14 08:15:04 2006//
+/krb524_convert_creds_kdc.3/1.1.1.1/Fri Apr 14 07:33:22 2006//
+/krb5_425_conv_principal.3/1.1.1.4/Fri Apr 14 07:33:22 2006//
+/krb5_acl_match_file.3/1.2/Tue Jun 13 07:07:21 2006//
+/krb5_address.3/1.6/Mon Jul 14 07:39:34 2008//
+/krb5_aname_to_localname.3/1.4/Fri Apr 14 08:15:04 2006//
+/krb5_appdefault.3/1.1.1.5/Fri Apr 14 07:33:22 2006//
+/krb5_auth_context.3/1.1.1.4/Fri Apr 14 07:33:22 2006//
+/krb5_c_make_checksum.3/1.3/Tue Jun 13 07:07:21 2006//
+/krb5_ccache.3/1.4/Mon Jul 14 07:50:05 2008//
+/krb5_ccapi.h/1.1.1.1/Fri Apr 14 07:33:23 2006//
+/krb5_check_transited.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_compare_creds.3/1.1.1.1/Fri Apr 14 07:33:23 2006//
+/krb5_config.3/1.2/Tue Jun 13 07:07:21 2006//
+/krb5_context.3/1.5/Fri Apr 14 08:15:04 2006//
+/krb5_create_checksum.3/1.3/Fri Apr 14 08:15:04 2006//
+/krb5_creds.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_crypto_init.3/1.3/Fri Apr 14 08:15:04 2006//
+/krb5_data.3/1.4/Fri Apr 14 08:15:04 2006//
+/krb5_eai_to_heim_errno.3/1.1.1.1/Fri Apr 14 07:33:23 2006//
+/krb5_encrypt.3/1.4/Sun Apr 30 10:14:43 2006//
+/krb5_err.et/1.1.1.2/Fri Apr 14 07:33:24 2006//
+/krb5_expand_hostname.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_find_padata.3/1.1.1.1/Fri Apr 14 07:33:24 2006//
+/krb5_generate_random_block.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_get_all_client_addrs.3/1.3/Fri Apr 14 08:15:04 2006//
+/krb5_get_credentials.3/1.1.1.1/Fri Apr 14 07:33:24 2006//
+/krb5_get_forwarded_creds.3/1.1.1.1/Fri Apr 14 07:33:24 2006//
+/krb5_get_in_cred.3/1.3/Tue Jun 13 07:07:21 2006//
+/krb5_get_init_creds.3/1.4/Wed Sep 20 19:58:40 2006//
+/krb5_get_krbhst.3/1.3/Fri Apr 14 08:15:04 2006//
+/krb5_getportbyname.3/1.1.1.1/Fri Apr 14 07:33:24 2006//
+/krb5_init_context.3/1.10/Thu Sep  7 21:19:57 2006//
+/krb5_is_thread_safe.3/1.4/Tue Jun 13 07:07:21 2006//
+/krb5_keyblock.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_keytab.3/1.5/Fri Apr 14 08:15:04 2006//
+/krb5_krbhst_init.3/1.3/Fri Apr 14 08:15:04 2006//
+/krb5_kuserok.3/1.4/Fri Apr 14 08:15:04 2006//
+/krb5_locl.h/1.8/Wed Jun 14 17:01:31 2006//
+/krb5_mk_safe.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_openlog.3/1.1.1.3/Fri Apr 14 07:33:25 2006//
+/krb5_parse_name.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_principal.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_rcache.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_rd_error.3/1.1.1.1/Fri Apr 14 07:33:25 2006//
+/krb5_rd_safe.3/1.2/Sun Apr 30 09:20:00 2006//
+/krb5_set_default_realm.3/1.4/Fri Apr 14 08:15:04 2006//
+/krb5_set_password.3/1.3/Fri Apr 14 08:15:04 2006//
+/krb5_storage.3/1.1.1.1/Fri Apr 14 07:33:25 2006//
+/krb5_string_to_key.3/1.2/Sat Jul  8 20:17:46 2006//
+/krb5_ticket.3/1.3/Tue Jun 13 07:07:21 2006//
+/krb5_timeofday.3/1.5/Wed Sep 20 19:58:40 2006//
+/krb5_unparse_name.3/1.1.1.4/Fri Apr 14 07:33:26 2006//
+/krb5_verify_init_creds.3/1.3/Sun Apr 30 10:14:43 2006//
+/krb5_verify_user.3/1.6/Sun Apr 30 09:20:00 2006//
+/krb5_warn.3/1.2/Sun Apr 30 09:20:00 2006//
+/krbhst-test.c/1.1.1.2/Sun May 11 02:15:57 2003//
+/krbhst.c/1.6/Fri Apr 14 08:15:04 2006//
+/kuserok.c/1.1.1.3/Fri Apr 14 07:33:26 2006//
+/log.c/1.5/Fri Oct  6 07:09:10 2006//
+/mcache.c/1.1.1.6/Fri Apr 14 07:33:27 2006//
+/misc.c/1.1.1.1/Fri May 25 07:50:53 2001//
+/mit_glue.c/1.1.1.1/Fri Apr 14 07:33:27 2006//
+/mk_error.c/1.1.1.4/Fri Apr 14 07:33:27 2006//
+/mk_priv.c/1.1.1.5/Fri Apr 14 07:33:27 2006//
+/mk_rep.c/1.1.1.4/Fri Apr 14 07:33:27 2006//
+/mk_req.c/1.1.1.4/Fri Apr 14 07:33:27 2006//
+/mk_req_ext.c/1.2/Fri Oct  6 07:09:10 2006//
+/mk_safe.c/1.1.1.6/Fri Apr 14 07:33:27 2006//
+/n-fold-test.c/1.1.1.3/Fri Apr 14 07:33:27 2006//
+/n-fold.c/1.1.1.2/Fri Apr 14 07:33:27 2006//
+/name-45-test.c/1.3/Fri Apr 14 08:15:05 2006//
+/net_read.c/1.1.1.3/Fri Apr 14 07:33:28 2006//
+/net_write.c/1.1.1.3/Fri Apr 14 07:33:28 2006//
+/padata.c/1.1.1.2/Fri Apr 14 07:33:28 2006//
+/parse-name-test.c/1.1.1.3/Fri Apr 14 07:33:28 2006//
+/pkinit.c/1.2/Wed Jan 14 22:08:53 2009//
+/principal.c/1.2/Fri Oct  6 07:09:10 2006//
+/prog_setup.c/1.3/Fri Apr 14 08:15:05 2006//
+/prompter_posix.c/1.1.1.4/Fri Apr 14 07:33:29 2006//
+/rd_cred.c/1.1.1.5/Fri Apr 14 07:33:29 2006//
+/rd_error.c/1.1.1.3/Fri Apr 14 07:33:29 2006//
+/rd_priv.c/1.1.1.4/Fri Apr 14 07:33:29 2006//
+/rd_rep.c/1.1.1.4/Fri Apr 14 07:33:30 2006//
+/rd_req.c/1.5/Fri Oct  6 07:09:10 2006//
+/rd_safe.c/1.1.1.5/Fri Apr 14 07:33:30 2006//
+/read_message.c/1.1.1.3/Fri Apr 14 07:33:30 2006//
+/recvauth.c/1.1.1.4/Fri Apr 14 07:33:30 2006//
+/replay.c/1.1.1.4/Fri Apr 14 07:33:30 2006//
+/send_to_kdc.c/1.1.1.5/Fri Apr 14 07:33:30 2006//
+/sendauth.c/1.1.1.4/Fri Apr 14 07:33:30 2006//
+/set_default_realm.c/1.1.1.4/Fri Apr 14 07:33:30 2006//
+/sock_principal.c/1.1.1.4/Fri Apr 14 07:33:30 2006//
+/store-int.h/1.1.1.1/Sun May 11 02:15:59 2003//
+/store-test.c/1.1.1.1/Fri Jun 22 21:24:41 2001//
+/store.c/1.2/Fri Oct  6 07:09:10 2006//
+/store_emem.c/1.1.1.3/Fri Apr 14 07:33:31 2006//
+/store_fd.c/1.1.1.4/Fri Apr 14 07:33:31 2006//
+/store_mem.c/1.1.1.3/Fri Apr 14 07:33:31 2006//
+/string-to-key-test.c/1.1.1.3/Fri Apr 14 07:33:31 2006//
+/test_acl.c/1.1.1.1/Fri Apr 14 07:33:31 2006//
+/test_addr.c/1.1.1.1/Fri Apr 14 07:33:31 2006//
+/test_alname.c/1.1.1.2/Fri Apr 14 07:33:31 2006//
+/test_cc.c/1.1.1.2/Fri Apr 14 07:33:31 2006//
+/test_config.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/test_crypto.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/test_get_addrs.c/1.1.1.2/Sun May 11 02:16:00 2003//
+/test_keytab.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/test_kuserok.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/test_mem.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/test_time.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/ticket.c/1.1.1.4/Fri Apr 14 07:33:32 2006//
+/time.c/1.1.1.3/Fri Apr 14 07:33:32 2006//
+/transited.c/1.9/Fri Oct  6 07:09:10 2006//
+/v4_glue.c/1.1.1.1/Fri Apr 14 07:33:32 2006//
+/verify_init.c/1.1.1.4/Fri Apr 14 07:33:33 2006//
+/verify_krb5_conf.8/1.5/Fri Apr 14 08:15:05 2006//
+/verify_krb5_conf.c/1.6/Fri Apr 14 08:15:05 2006//
+/verify_user.c/1.1.1.4/Fri Apr 14 07:33:33 2006//
+/version.c/1.1.1.1/Fri May 25 07:51:02 2001//
+/warn.c/1.7/Fri Apr 14 08:15:05 2006//
+/write_message.c/1.1.1.4/Fri Apr 14 07:33:33 2006//
+/acl.c/1.2/Sat Jan  2 15:00:40 2010//
+/crypto.c/1.12/Mon Apr  5 23:11:33 2010//
+D
diff --git a/src/kerberosV/src/lib/krb5/CVS/Repository b/src/kerberosV/src/lib/krb5/CVS/Repository
new file mode 100644 (file)
index 0000000..bade8cd
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/krb5
diff --git a/src/kerberosV/src/lib/krb5/CVS/Root b/src/kerberosV/src/lib/krb5/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/krb5/acache.c b/src/kerberosV/src/lib/krb5/acache.c
new file mode 100644 (file)
index 0000000..47fb521
--- /dev/null
@@ -0,0 +1,778 @@
+/*
+ * Copyright (c) 2004 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <krb5_ccapi.h>
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+
+RCSID("$KTH: acache.c,v 1.10 2005/04/24 21:54:01 lha Exp $");
+
+/* XXX should we fetch these for each open ? */
+static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static void *cc_handle; 
+static cc_initialize_func init_func;
+
+typedef struct krb5_acc {
+    char *cache_name;
+    cc_context_t context;
+    cc_ccache_t ccache;
+} krb5_acc;
+
+static krb5_error_code acc_close(krb5_context, krb5_ccache);
+
+#define ACACHE(X) ((krb5_acc *)(X)->data.data)
+
+static const struct {
+    cc_int32 error;
+    krb5_error_code ret;
+} cc_errors[] = {
+    { ccErrBadName,            KRB5_CC_BADNAME },
+    { ccErrCredentialsNotFound,        KRB5_CC_NOTFOUND },
+    { ccErrCCacheNotFound,     KRB5_FCC_NOFILE },
+    { ccErrContextNotFound,    KRB5_CC_NOTFOUND },
+    { ccIteratorEnd,           KRB5_CC_END },
+    { ccErrNoMem,              KRB5_CC_NOMEM },
+    { ccErrServerUnavailable,  KRB5_CC_BADNAME },
+    { ccNoError,               0 }
+};
+
+static krb5_error_code
+translate_cc_error(krb5_context context, cc_int32 error)
+{
+    int i;
+    krb5_clear_error_string(context);
+    for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++)
+       if (cc_errors[i].error == error)
+           return cc_errors[i].ret;
+    return KRB5_FCC_INTERNAL;
+}
+
+static krb5_error_code
+init_ccapi(krb5_context context)
+{
+    const char *lib;
+
+    HEIMDAL_MUTEX_lock(&acc_mutex);
+    if (init_func) {
+       HEIMDAL_MUTEX_unlock(&acc_mutex);
+       krb5_clear_error_string(context);
+       return 0;
+    }
+
+    lib = krb5_config_get_string(context, NULL,
+                                "libdefaults", "ccapi_library", 
+                                NULL);
+    if (lib == NULL) {
+#ifdef __APPLE__
+       lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos";
+#else
+       lib = "/usr/lib/libkrb5_cc.so";
+#endif
+    }
+
+#ifdef HAVE_DLOPEN
+    cc_handle = dlopen(lib, 0);
+    if (cc_handle == NULL) {
+       HEIMDAL_MUTEX_unlock(&acc_mutex);
+       krb5_set_error_string(context, "Failed to load %s", lib);
+       return ccErrServerUnavailable;
+    }
+
+    init_func = dlsym(cc_handle, "cc_initialize");
+    HEIMDAL_MUTEX_unlock(&acc_mutex);
+    if (init_func == NULL) {
+       krb5_set_error_string(context, "Failed to find cc_initialize"
+                             "in %s: %s", lib, dlerror());
+       dlclose(cc_handle);
+       return ccErrServerUnavailable;
+    }
+
+    return 0;
+#else
+    HEIMDAL_MUTEX_unlock(&acc_mutex);
+    krb5_set_error_string(context, "no support for shared object");
+    return ccErrServerUnavailable;
+#endif
+}    
+
+static krb5_error_code
+make_cred_from_ccred(krb5_context context,
+                    const cc_credentials_v5_t *incred,
+                    krb5_creds *cred)
+{
+    krb5_error_code ret;
+    int i;
+
+    memset(cred, 0, sizeof(*cred));
+
+    ret = krb5_parse_name(context, incred->client, &cred->client);
+    if (ret)
+       goto fail;
+
+    ret = krb5_parse_name(context, incred->server, &cred->server);
+    if (ret)
+       goto fail;
+
+    cred->session.keytype = incred->keyblock.type;
+    cred->session.keyvalue.length = incred->keyblock.length;
+    cred->session.keyvalue.data = malloc(incred->keyblock.length);
+    if (cred->session.keyvalue.data == NULL)
+       goto nomem;
+    memcpy(cred->session.keyvalue.data, incred->keyblock.data,
+          incred->keyblock.length);
+
+    cred->times.authtime = incred->authtime;
+    cred->times.starttime = incred->starttime;
+    cred->times.endtime = incred->endtime;
+    cred->times.renew_till = incred->renew_till;
+
+    ret = krb5_data_copy(&cred->ticket,
+                        incred->ticket.data,
+                        incred->ticket.length);
+    if (ret)
+       goto nomem;
+
+    ret = krb5_data_copy(&cred->second_ticket,
+                        incred->second_ticket.data,
+                        incred->second_ticket.length);
+    if (ret)
+       goto nomem;
+
+    cred->authdata.val = NULL;
+    cred->authdata.len = 0;
+    
+    cred->addresses.val = NULL;
+    cred->addresses.len = 0;
+    
+    for (i = 0; incred->authdata && incred->authdata[i]; i++)
+       ;
+    
+    if (i) {
+       cred->authdata.val = malloc(sizeof(cred->authdata.val[0]) * i);
+       if (cred->authdata.val == NULL)
+           goto nomem;
+       cred->authdata.len = i;
+       memset(cred->authdata.val, 0, sizeof(cred->authdata.val[0]) * i);
+       for (i = 0; i < cred->authdata.len; i++) {
+           cred->authdata.val[i].ad_type = incred->authdata[i]->type;
+           ret = krb5_data_copy(&cred->authdata.val[i].ad_data,
+                                incred->authdata[i]->data,
+                                incred->authdata[i]->length);
+           if (ret)
+               goto nomem;
+       }
+    }
+    
+    for (i = 0; incred->addresses && incred->addresses[i]; i++)
+       ;
+    
+    if (i) {
+       cred->addresses.val = malloc(sizeof(cred->addresses.val[0]) * i);
+       if (cred->addresses.val == NULL)
+           goto nomem;
+       cred->addresses.len = i;
+       memset(cred->addresses.val, 0, sizeof(cred->addresses.val[0]) * i);
+       
+       for (i = 0; i < cred->addresses.len; i++) {
+           cred->addresses.val[i].addr_type = incred->addresses[i]->type;
+           ret = krb5_data_copy(&cred->addresses.val[i].address,
+                                incred->addresses[i]->data,
+                                incred->addresses[i]->length);
+           if (ret)
+               goto nomem;
+       }
+    }
+    
+    cred->flags.b = int2TicketFlags(incred->ticket_flags); /* XXX */
+    return 0;
+    
+nomem:
+    ret = ENOMEM;
+    krb5_set_error_string(context, "malloc - out of memory");
+    
+fail:
+    krb5_free_creds_contents(context, cred);
+    return ret;
+}
+
+static void
+free_ccred(cc_credentials_v5_t *cred)
+{
+    int i;
+
+    if (cred->addresses) {
+       for (i = 0; cred->addresses[i] != 0; i++) {
+           if (cred->addresses[i]->data)
+               free(cred->addresses[i]->data);
+           free(cred->addresses[i]);
+       }
+       free(cred->addresses);
+    }
+    if (cred->server)
+       free(cred->server);
+    if (cred->client)
+       free(cred->client);
+    memset(cred, 0, sizeof(*cred));
+}
+
+static krb5_error_code
+make_ccred_from_cred(krb5_context context,
+                    const krb5_creds *incred,
+                    cc_credentials_v5_t *cred)
+{
+    krb5_error_code ret;
+    int i;
+
+    memset(cred, 0, sizeof(*cred));
+
+    ret = krb5_unparse_name(context, incred->client, &cred->client);
+    if (ret)
+       goto fail;
+
+    ret = krb5_unparse_name(context, incred->server, &cred->server);
+    if (ret)
+       goto fail;
+
+    cred->keyblock.type = incred->session.keytype;
+    cred->keyblock.length = incred->session.keyvalue.length;
+    cred->keyblock.data = incred->session.keyvalue.data;
+
+    cred->authtime = incred->times.authtime;
+    cred->starttime = incred->times.starttime;
+    cred->endtime = incred->times.endtime;
+    cred->renew_till = incred->times.renew_till;
+
+    cred->ticket.length = incred->ticket.length;
+    cred->ticket.data = incred->ticket.data;
+
+    cred->second_ticket.length = incred->second_ticket.length;
+    cred->second_ticket.data = incred->second_ticket.data;
+
+    /* XXX this one should also be filled in */
+    cred->authdata = NULL;
+    
+    cred->addresses = calloc(incred->addresses.len + 1, 
+                            sizeof(cred->addresses[0]));
+    if (cred->addresses == NULL) {
+
+       ret = ENOMEM;
+       goto fail;
+    }
+
+    for (i = 0; i < incred->addresses.len; i++) {
+       cc_data *addr;
+       addr = malloc(sizeof(*addr));
+       addr->type = incred->addresses.val[i].addr_type;
+       addr->length = incred->addresses.val[i].address.length;
+       addr->data = malloc(addr->length);
+       if (addr->data == NULL) {
+           ret = ENOMEM;
+           goto fail;
+       }
+       memcpy(addr->data, incred->addresses.val[i].address.data, 
+              addr->length);
+       cred->addresses[i] = addr;
+    }
+    cred->addresses[i] = NULL;
+
+    cred->ticket_flags = TicketFlags2int(incred->flags.b); /* XXX */
+    return 0;
+
+fail:    
+    free_ccred(cred);
+
+    krb5_clear_error_string(context);
+    return ret;
+}
+
+static char *
+get_cc_name(cc_ccache_t cache)
+{
+    cc_string_t name;
+    cc_int32 error;
+    char *str;
+
+    error = (*cache->func->get_name)(cache, &name);
+    if (error)
+       return NULL;
+
+    str = strdup(name->data);
+    (*name->func->release)(name);
+    return str;
+}
+
+
+static const char*
+acc_get_name(krb5_context context,
+            krb5_ccache id)
+{
+    krb5_acc *a = ACACHE(id);
+    static char n[255];
+    char *name;
+
+    name = get_cc_name(a->ccache);
+    if (name == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return NULL;
+    }
+    strlcpy(n, name, sizeof(n));
+    free(name);
+    return n;
+}
+
+static krb5_error_code
+acc_alloc(krb5_context context, krb5_ccache *id)
+{
+    krb5_error_code ret;
+    cc_int32 error;
+    krb5_acc *a;
+
+    ret = init_ccapi(context);
+    if (ret)
+       return ret;
+
+    ret = krb5_data_alloc(&(*id)->data, sizeof(*a));
+    if (ret) {
+       krb5_clear_error_string(context);
+       return ret;
+    }
+    
+    a = ACACHE(*id);
+
+    error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL);
+    if (error) {
+       krb5_data_free(&(*id)->data);
+       return translate_cc_error(context, error);
+    }
+
+    a->cache_name = NULL;
+
+    return 0;
+}
+
+static krb5_error_code
+get_default_principal(krb5_context context, char **p)
+{
+    krb5_error_code ret;
+    krb5_principal principal;
+
+    *p = NULL;
+
+    ret = _krb5_get_default_principal_local(context, &principal);
+    if (ret)
+       return ret;
+
+    ret = krb5_unparse_name(context, principal, p);
+    krb5_free_principal(context, principal);
+    return ret;
+}
+
+static krb5_error_code
+acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
+{
+    krb5_error_code ret;
+    cc_int32 error;
+    krb5_acc *a;
+
+    ret = acc_alloc(context, id);
+    if (ret)
+       return ret;
+
+    a = ACACHE(*id);
+
+    if (res == NULL || res[0] == '\0') {    
+       error = (*a->context->func->open_default_ccache)(a->context,
+                                                        &a->ccache);
+       if (error == ccErrCCacheNotFound) {
+           char *p;
+
+           ret = get_default_principal(context, &p);
+           if (ret == 0) {
+               error = (*a->context->func->create_default_ccache)(a->context,
+                                                                  cc_credentials_v5,
+                                                                  p,
+                                                                  &a->ccache);
+               free(p);
+           }
+       }
+       if (error == 0)
+           a->cache_name = get_cc_name(a->ccache);
+    } else {
+       error = (*a->context->func->open_ccache)(a->context, res, &a->ccache);
+       if (error == 0)
+           a->cache_name = strdup(res);
+    }
+    if (error != 0) {
+       *id = NULL;
+       return translate_cc_error(context, error);
+    }
+    if (a->cache_name == NULL) {
+       acc_close(context, *id);
+       *id = NULL;
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+acc_gen_new(krb5_context context, krb5_ccache *id)
+{
+    krb5_error_code ret;
+    cc_int32 error;
+    krb5_acc *a;
+    char *p;
+
+    ret = get_default_principal(context, &p);
+
+    ret = acc_alloc(context, id);
+    if (ret) {
+       free(p);
+       return ret;
+    }
+
+    a = ACACHE(*id);
+
+    error = (*a->context->func->create_new_ccache)(a->context,
+                                                  cc_credentials_v5,
+                                                  p, &a->ccache);
+    free(p);
+    if (error) {
+       *id = NULL;
+       return translate_cc_error(context, error);
+    }
+    a->cache_name = get_cc_name(a->ccache);
+    if (a->cache_name == NULL) {
+       acc_close(context, *id);
+       *id = NULL;
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }  
+    return 0;
+}
+
+static krb5_error_code
+acc_initialize(krb5_context context,
+              krb5_ccache id,
+              krb5_principal primary_principal)
+{
+    cc_credentials_iterator_t iter;
+    krb5_acc *a = ACACHE(id);
+    cc_credentials_t ccred;
+    krb5_error_code ret;
+    int32_t error;
+    char *name;
+
+    ret = krb5_unparse_name(context, primary_principal, &name);
+    if (ret)
+       return ret;
+
+    if (a->ccache == NULL) {
+       error = (*a->context->func->create_new_ccache)(a->context,
+                                                      cc_credentials_v5,
+                                                      name,
+                                                      &a->ccache);
+    } else {    
+
+       error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
+       if (error) {
+           free(name);
+           return translate_cc_error(context, error);
+       }
+
+       while (1) {
+           error = (*iter->func->next)(iter, &ccred);
+           if (error)
+               break;
+           (*a->ccache->func->remove_credentials)(a->ccache, ccred);
+           (*ccred->func->release)(ccred);
+       }
+       (*iter->func->release)(iter);
+
+       error = (*a->ccache->func->set_principal)(a->ccache,
+                                                 cc_credentials_v5,
+                                                 name);
+    }
+
+    free(name);
+
+    return translate_cc_error(context, error);
+}
+
+static krb5_error_code
+acc_close(krb5_context context,
+         krb5_ccache id)
+{
+    krb5_acc *a = ACACHE(id);
+
+    if (a->ccache) {
+       (*a->ccache->func->release)(a->ccache);
+       a->ccache = NULL;
+    }
+    if (a->cache_name) {
+       free(a->cache_name);
+       a->cache_name = NULL;
+    }
+    (*a->context->func->release)(a->context);
+    a->context = NULL;
+    krb5_data_free(&id->data);
+    return 0;
+}
+
+static krb5_error_code
+acc_destroy(krb5_context context,
+           krb5_ccache id)
+{
+    krb5_acc *a = ACACHE(id);
+    cc_int32 error = 0;
+
+    if (a->ccache) {
+       error = (*a->ccache->func->destroy)(a->ccache);
+       a->ccache = NULL;
+    }
+    return translate_cc_error(context, error);
+}
+
+static krb5_error_code
+acc_store_cred(krb5_context context,
+              krb5_ccache id,
+              krb5_creds *creds)
+{
+    krb5_acc *a = ACACHE(id);
+    cc_credentials_union cred;
+    cc_credentials_v5_t v5cred;
+    krb5_error_code ret;
+    cc_int32 error;
+    
+    cred.version = cc_credentials_v5;
+    cred.credentials.credentials_v5 = &v5cred;
+
+    ret = make_ccred_from_cred(context, 
+                              creds,
+                              &v5cred);
+    if (ret)
+       return ret;
+
+    error = (*a->ccache->func->store_credentials)(a->ccache, &cred);
+    if (error)
+       ret = translate_cc_error(context, error);
+
+    free_ccred(&v5cred);
+
+    return ret;
+}
+
+static krb5_error_code
+acc_get_principal(krb5_context context,
+                 krb5_ccache id,
+                 krb5_principal *principal)
+{
+    krb5_acc *a = ACACHE(id);
+    krb5_error_code ret;
+    int32_t error;
+    cc_string_t name;
+
+    if (a->ccache == NULL)
+       return ENOENT;
+
+    error = (*a->ccache->func->get_principal)(a->ccache,
+                                             cc_credentials_v5,
+                                             &name);
+    if (error)
+       return translate_cc_error(context, error);
+    
+    ret = krb5_parse_name(context, name->data, principal);
+    
+    (*name->func->release)(name);
+    return ret;
+}
+
+static krb5_error_code
+acc_get_first (krb5_context context,
+              krb5_ccache id,
+              krb5_cc_cursor *cursor)
+{
+    cc_credentials_iterator_t iter;
+    krb5_acc *a = ACACHE(id);
+    int32_t error;
+    
+    error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
+    if (error)
+       return ENOENT;
+    *cursor = iter;
+    return 0;
+}
+
+
+static krb5_error_code
+acc_get_next (krb5_context context,
+             krb5_ccache id,
+             krb5_cc_cursor *cursor,
+             krb5_creds *creds)
+{
+    cc_credentials_iterator_t iter = *cursor;
+    cc_credentials_t cred;
+    krb5_error_code ret;
+    int32_t error;
+
+    while (1) {
+       error = (*iter->func->next)(iter, &cred);
+       if (error)
+           return translate_cc_error(context, error);
+       if (cred->data->version == cc_credentials_v5)
+           break;
+       (*cred->func->release)(cred);
+    }
+
+    ret = make_cred_from_ccred(context, 
+                              cred->data->credentials.credentials_v5,
+                              creds);
+    (*cred->func->release)(cred);
+    return ret;
+}
+
+static krb5_error_code
+acc_end_get (krb5_context context,
+            krb5_ccache id,
+            krb5_cc_cursor *cursor)
+{
+    cc_credentials_iterator_t iter = *cursor;
+    (*iter->func->release)(iter);
+    return 0;
+}
+
+static krb5_error_code
+acc_remove_cred(krb5_context context,
+               krb5_ccache id,
+               krb5_flags which,
+               krb5_creds *cred)
+{
+    cc_credentials_iterator_t iter;
+    krb5_acc *a = ACACHE(id);
+    cc_credentials_t ccred;
+    krb5_error_code ret;
+    cc_int32 error;
+    char *client, *server;
+    
+    if (cred->client) {
+       ret = krb5_unparse_name(context, cred->client, &client);
+       if (ret)
+           return ret;
+    } else
+       client = NULL;
+
+    ret = krb5_unparse_name(context, cred->server, &server);
+    if (ret) {
+       free(client);
+       return ret;
+    }
+
+    error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter);
+    if (error) {
+       free(server);
+       free(client);
+       return translate_cc_error(context, error);
+    }
+
+    ret = KRB5_CC_NOTFOUND;
+    while (1) {
+       cc_credentials_v5_t *v5cred;
+
+       error = (*iter->func->next)(iter, &ccred);
+       if (error)
+           break;
+
+       if (ccred->data->version != cc_credentials_v5)
+           goto next;
+
+       v5cred = ccred->data->credentials.credentials_v5;
+
+       if (client && strcmp(v5cred->client, client) != 0)
+           goto next;
+
+       if (strcmp(v5cred->server, server) != 0)
+           goto next;
+
+       (*a->ccache->func->remove_credentials)(a->ccache, ccred);
+       ret = 0;
+    next:
+       (*ccred->func->release)(ccred);
+    }
+
+    (*iter->func->release)(iter);
+
+    if (ret)
+       krb5_set_error_string(context, "Can't find credential %s in cache", 
+                             server);
+    free(server);
+    free(client);
+
+    return ret;
+}
+
+static krb5_error_code
+acc_set_flags(krb5_context context,
+             krb5_ccache id,
+             krb5_flags flags)
+{
+    return 0;
+}
+
+static krb5_error_code
+acc_get_version(krb5_context context,
+               krb5_ccache id)
+{
+    return 0;
+}
+                   
+const krb5_cc_ops krb5_acc_ops = {
+    "API",
+    acc_get_name,
+    acc_resolve,
+    acc_gen_new,
+    acc_initialize,
+    acc_destroy,
+    acc_close,
+    acc_store_cred,
+    NULL, /* acc_retrieve */
+    acc_get_principal,
+    acc_get_first,
+    acc_get_next,
+    acc_end_get,
+    acc_remove_cred,
+    acc_set_flags,
+    acc_get_version
+};
diff --git a/src/kerberosV/src/lib/krb5/acl.c b/src/kerberosV/src/lib/krb5/acl.c
new file mode 100644 (file)
index 0000000..20c4aee
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2000 - 2002, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <fnmatch.h>
+
+RCSID("$KTH: acl.c,v 1.5 2004/05/25 21:15:58 lha Exp $");
+
+struct acl_field {
+    enum { acl_string, acl_fnmatch, acl_retval } type;
+    union {
+       const char *cstr;
+       char **retv;
+    } u;
+    struct acl_field *next, **last;
+};
+
+static void
+free_retv(struct acl_field *acl)
+{
+    while(acl != NULL) {
+       if (acl->type == acl_retval) {
+           if (*acl->u.retv)
+               free(*acl->u.retv);
+           *acl->u.retv = NULL;
+       }
+       acl = acl->next;
+    }
+}
+
+static void
+acl_free_list(struct acl_field *acl, int retv)
+{
+    struct acl_field *next;
+    if (retv)
+       free_retv(acl);
+    while(acl != NULL) {
+       next = acl->next;
+       free(acl);
+       acl = next;
+    }
+}
+
+static krb5_error_code
+acl_parse_format(krb5_context context,
+                struct acl_field **acl_ret,
+                const char *format,
+                va_list ap)
+{
+    const char *p;
+    struct acl_field *acl = NULL, *tmp;
+
+    for(p = format; *p != '\0'; p++) {
+       tmp = malloc(sizeof(*tmp));
+       if(tmp == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           acl_free_list(acl, 0);
+           return ENOMEM;
+       }
+       if(*p == 's') {
+           tmp->type = acl_string;
+           tmp->u.cstr = va_arg(ap, const char*);
+       } else if(*p == 'f') {
+           tmp->type = acl_fnmatch;
+           tmp->u.cstr = va_arg(ap, const char*);
+       } else if(*p == 'r') {
+           tmp->type = acl_retval;
+           tmp->u.retv = va_arg(ap, char **);
+           *tmp->u.retv = NULL;
+       } else {
+           krb5_set_error_string(context, "acl_parse_format: "
+                                 "unknown format specifier %c", *p);
+           acl_free_list(acl, 0);
+           free(tmp);
+           return EINVAL;
+       }
+       tmp->next = NULL;
+       if(acl == NULL)
+           acl = tmp;
+       else
+           *acl->last = tmp;
+       acl->last = &tmp->next;
+    }
+    *acl_ret = acl;
+    return 0;
+}
+
+static krb5_boolean
+acl_match_field(krb5_context context,
+               const char *string,
+               struct acl_field *field)
+{
+    if(field->type == acl_string) {
+       return !strcmp(field->u.cstr, string);
+    } else if(field->type == acl_fnmatch) {
+       return !fnmatch(field->u.cstr, string, 0);
+    } else if(field->type == acl_retval) {
+       *field->u.retv = strdup(string);
+       return TRUE;
+    }
+    return FALSE;
+}
+
+static krb5_boolean
+acl_match_acl(krb5_context context,
+             struct acl_field *acl,
+             const char *string)
+{
+    char buf[256];
+    while(strsep_copy(&string, " \t", buf, sizeof(buf)) != -1) {
+       if(buf[0] == '\0')
+           continue; /* skip ws */
+       if (acl == NULL)
+           return FALSE;
+       if(!acl_match_field(context, buf, acl)) {
+           return FALSE;
+       }
+       acl = acl->next;
+    }
+    if (acl)
+       return FALSE;
+    return TRUE;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_acl_match_string(krb5_context context,
+                     const char *string,
+                     const char *format,
+                     ...)
+{
+    krb5_error_code ret;
+    krb5_boolean found;
+    struct acl_field *acl;
+
+    va_list ap;
+    va_start(ap, format);
+    ret = acl_parse_format(context, &acl, format, ap);
+    va_end(ap);
+    if(ret)
+       return ret;
+
+    found = acl_match_acl(context, acl, string);
+    acl_free_list(acl, !found);
+    if (found) {
+       return 0;
+    } else {
+       krb5_set_error_string(context, "ACL did not match");
+       return EACCES;
+    }
+}
+              
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_acl_match_file(krb5_context context,
+                   const char *file,
+                   const char *format,
+                   ...)
+{
+    krb5_error_code ret;
+    struct acl_field *acl;
+    char buf[256];
+    va_list ap;
+    FILE *f;
+    krb5_boolean found;
+
+    f = fopen(file, "r");
+    if(f == NULL) {
+       int save_errno = errno;
+
+       krb5_set_error_string(context, "open(%s): %s", file,
+                             strerror(save_errno));
+       return save_errno;
+    }
+
+    va_start(ap, format);
+    ret = acl_parse_format(context, &acl, format, ap);
+    va_end(ap);
+    if(ret) {
+       fclose(f);
+       return ret;
+    }
+
+    found = FALSE;
+    while(fgets(buf, sizeof(buf), f)) {
+       if(buf[0] == '#')
+           continue;
+       if(acl_match_acl(context, acl, buf)) {
+           found = TRUE;
+           break;
+       }
+       free_retv(acl);
+    }
+
+    fclose(f);
+    acl_free_list(acl, !found);
+    if (found) {
+       return 0;
+    } else {
+       krb5_set_error_string(context, "ACL did not match");
+       return EACCES;
+    }
+}
diff --git a/src/kerberosV/src/lib/krb5/add_et_list.c b/src/kerberosV/src/lib/krb5/add_et_list.c
new file mode 100644 (file)
index 0000000..415c068
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: add_et_list.c,v 1.3 2004/04/13 14:33:45 lha Exp $");
+
+/*
+ * Add a specified list of error messages to the et list in context.
+ * Call func (probably a comerr-generated function) with a pointer to
+ * the current et_list.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_add_et_list (krb5_context context,
+                 void (*func)(struct et_list **))
+{
+    (*func)(&context->et_list);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/addr_families.c b/src/kerberosV/src/lib/krb5/addr_families.c
new file mode 100644 (file)
index 0000000..8daeb6a
--- /dev/null
@@ -0,0 +1,1187 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: addr_families.c,v 1.47 2005/05/18 04:20:36 lha Exp $");
+
+struct addr_operations {
+    int af;
+    krb5_address_type atype;
+    size_t max_sockaddr_size;
+    krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *);
+    krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *);
+    void (*addr2sockaddr)(const krb5_address *, struct sockaddr *,
+                         krb5_socklen_t *sa_size, int port);
+    void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int);
+    krb5_error_code (*h_addr2addr)(const char *, krb5_address *);
+    krb5_boolean (*uninteresting)(const struct sockaddr *);
+    void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int);
+    int (*print_addr)(const krb5_address *, char *, size_t);
+    int (*parse_addr)(krb5_context, const char*, krb5_address *);
+    int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*);
+    int (*free_addr)(krb5_context, krb5_address*);
+    int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*);
+    int (*mask_boundary)(krb5_context, const krb5_address*, unsigned long, 
+                                    krb5_address*, krb5_address*);
+};
+
+/*
+ * AF_INET - aka IPv4 implementation
+ */
+
+static krb5_error_code
+ipv4_sockaddr2addr (const struct sockaddr *sa, krb5_address *a)
+{
+    const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
+    unsigned char buf[4];
+
+    a->addr_type = KRB5_ADDRESS_INET;
+    memcpy (buf, &sin->sin_addr, 4);
+    return krb5_data_copy(&a->address, buf, 4);
+}
+
+static krb5_error_code
+ipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port)
+{
+    const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
+
+    *port = sin->sin_port;
+    return 0;
+}
+
+static void
+ipv4_addr2sockaddr (const krb5_address *a,
+                   struct sockaddr *sa,
+                   krb5_socklen_t *sa_size,
+                   int port)
+{
+    struct sockaddr_in tmp;
+
+    memset (&tmp, 0, sizeof(tmp));
+    tmp.sin_family = AF_INET;
+    memcpy (&tmp.sin_addr, a->address.data, 4);
+    tmp.sin_port = port;
+    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+    *sa_size = sizeof(tmp);
+}
+
+static void
+ipv4_h_addr2sockaddr(const char *addr,
+                    struct sockaddr *sa,
+                    krb5_socklen_t *sa_size,
+                    int port)
+{
+    struct sockaddr_in tmp;
+
+    memset (&tmp, 0, sizeof(tmp));
+    tmp.sin_family = AF_INET;
+    tmp.sin_port   = port;
+    tmp.sin_addr   = *((const struct in_addr *)addr);
+    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+    *sa_size = sizeof(tmp);
+}
+
+static krb5_error_code
+ipv4_h_addr2addr (const char *addr,
+                 krb5_address *a)
+{
+    unsigned char buf[4];
+
+    a->addr_type = KRB5_ADDRESS_INET;
+    memcpy(buf, addr, 4);
+    return krb5_data_copy(&a->address, buf, 4);
+}
+
+/*
+ * Are there any addresses that should be considered `uninteresting'?
+ */
+
+static krb5_boolean
+ipv4_uninteresting (const struct sockaddr *sa)
+{
+    const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
+
+    if (sin->sin_addr.s_addr == INADDR_ANY)
+       return TRUE;
+
+    return FALSE;
+}
+
+static void
+ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port)
+{
+    struct sockaddr_in tmp;
+
+    memset (&tmp, 0, sizeof(tmp));
+    tmp.sin_family = AF_INET;
+    tmp.sin_port   = port;
+    tmp.sin_addr.s_addr = INADDR_ANY;
+    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+    *sa_size = sizeof(tmp);
+}
+
+static int
+ipv4_print_addr (const krb5_address *addr, char *str, size_t len)
+{
+    struct in_addr ia;
+
+    memcpy (&ia, addr->address.data, 4);
+
+    return snprintf (str, len, "IPv4:%s", inet_ntoa(ia));
+}
+
+static int
+ipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr)
+{
+    const char *p;
+    struct in_addr a;
+
+    p = strchr(address, ':');
+    if(p) {
+       p++;
+       if(strncasecmp(address, "ip:", p - address) != 0 &&
+          strncasecmp(address, "ip4:", p - address) != 0 &&
+          strncasecmp(address, "ipv4:", p - address) != 0 &&
+          strncasecmp(address, "inet:", p - address) != 0)
+           return -1;
+    } else
+       p = address;
+#ifdef HAVE_INET_ATON
+    if(inet_aton(p, &a) == 0)
+       return -1;
+#elif defined(HAVE_INET_ADDR)
+    a.s_addr = inet_addr(p);
+    if(a.s_addr == INADDR_NONE)
+       return -1;
+#else
+    return -1;
+#endif
+    addr->addr_type = KRB5_ADDRESS_INET;
+    if(krb5_data_alloc(&addr->address, 4) != 0)
+       return -1;
+    _krb5_put_int(addr->address.data, ntohl(a.s_addr), addr->address.length);
+    return 0;
+}
+
+static int
+ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr,
+                  unsigned long len, krb5_address *low, krb5_address *high)
+{
+    unsigned long ia;
+    u_int32_t l, h, m = 0xffffffff;
+
+    if (len > 32) {
+       krb5_set_error_string(context, "IPv4 prefix too large (%ld)", len);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    m = m << (32 - len);
+
+    _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length);
+
+    l = ia & m;
+    h = l | ~m;
+
+    low->addr_type = KRB5_ADDRESS_INET;
+    if(krb5_data_alloc(&low->address, 4) != 0)
+       return -1;
+    _krb5_put_int(low->address.data, l, low->address.length);
+
+    high->addr_type = KRB5_ADDRESS_INET;
+    if(krb5_data_alloc(&high->address, 4) != 0) {
+       krb5_free_address(context, low);
+       return -1;
+    }
+    _krb5_put_int(high->address.data, h, high->address.length);
+
+    return 0;
+}
+
+
+/*
+ * AF_INET6 - aka IPv6 implementation
+ */
+
+#ifdef HAVE_IPV6
+
+static krb5_error_code
+ipv6_sockaddr2addr (const struct sockaddr *sa, krb5_address *a)
+{
+    const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+
+    if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+       unsigned char buf[4];
+
+       a->addr_type      = KRB5_ADDRESS_INET;
+#ifndef IN6_ADDR_V6_TO_V4
+#ifdef IN6_EXTRACT_V4ADDR
+#define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x))
+#else
+#define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12])
+#endif
+#endif
+       memcpy (buf, IN6_ADDR_V6_TO_V4(&sin6->sin6_addr), 4);
+       return krb5_data_copy(&a->address, buf, 4);
+    } else {
+       a->addr_type = KRB5_ADDRESS_INET6;
+       return krb5_data_copy(&a->address,
+                             &sin6->sin6_addr,
+                             sizeof(sin6->sin6_addr));
+    }
+}
+
+static krb5_error_code
+ipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port)
+{
+    const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+
+    *port = sin6->sin6_port;
+    return 0;
+}
+
+static void
+ipv6_addr2sockaddr (const krb5_address *a,
+                   struct sockaddr *sa,
+                   krb5_socklen_t *sa_size,
+                   int port)
+{
+    struct sockaddr_in6 tmp;
+
+    memset (&tmp, 0, sizeof(tmp));
+    tmp.sin6_family = AF_INET6;
+    memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr));
+    tmp.sin6_port = port;
+    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+    *sa_size = sizeof(tmp);
+}
+
+static void
+ipv6_h_addr2sockaddr(const char *addr,
+                    struct sockaddr *sa,
+                    krb5_socklen_t *sa_size,
+                    int port)
+{
+    struct sockaddr_in6 tmp;
+
+    memset (&tmp, 0, sizeof(tmp));
+    tmp.sin6_family = AF_INET6;
+    tmp.sin6_port   = port;
+    tmp.sin6_addr   = *((const struct in6_addr *)addr);
+    memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+    *sa_size = sizeof(tmp);
+}
+
+static krb5_error_code
+ipv6_h_addr2addr (const char *addr,
+                 krb5_address *a)
+{
+    a->addr_type = KRB5_ADDRESS_INET6;
+    return krb5_data_copy(&a->address, addr, sizeof(struct in6_addr));
+}
+
+/*
+ * 
+ */
+
+static krb5_boolean
+ipv6_uninteresting (const struct sockaddr *sa)
+{
+    const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+    const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr;
+    
+    return
+       IN6_IS_ADDR_LINKLOCAL(in6)
+       || IN6_IS_ADDR_V4COMPAT(in6);
+}
+
+static void
+ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port)
+{
+    struct sockaddr_in6 tmp;
+
+    memset (&tmp, 0, sizeof(tmp));
+    tmp.sin6_family = AF_INET6;
+    tmp.sin6_port   = port;
+    tmp.sin6_addr   = in6addr_any;
+    *sa_size = sizeof(tmp);
+}
+
+static int
+ipv6_print_addr (const krb5_address *addr, char *str, size_t len)
+{
+    char buf[128], buf2[3];
+#ifdef HAVE_INET_NTOP
+    if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL)
+#endif
+       {
+           /* XXX this is pretty ugly, but better than abort() */
+           int i;
+           unsigned char *p = addr->address.data;
+           buf[0] = '\0';
+           for(i = 0; i < addr->address.length; i++) {
+               snprintf(buf2, sizeof(buf2), "%02x", p[i]);
+               if(i > 0 && (i & 1) == 0)
+                   strlcat(buf, ":", sizeof(buf));
+               strlcat(buf, buf2, sizeof(buf));
+           }
+       }
+    return snprintf(str, len, "IPv6:%s", buf);
+}
+
+static int
+ipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr)
+{
+    int ret;
+    struct in6_addr in6;
+    const char *p;
+
+    p = strchr(address, ':');
+    if(p) {
+       p++;
+       if(strncasecmp(address, "ip6:", p - address) == 0 ||
+          strncasecmp(address, "ipv6:", p - address) == 0 ||
+          strncasecmp(address, "inet6:", p - address) == 0)
+           address = p;
+    }
+
+    ret = inet_pton(AF_INET6, address, &in6.s6_addr);
+    if(ret == 1) {
+       addr->addr_type = KRB5_ADDRESS_INET6;
+       ret = krb5_data_alloc(&addr->address, sizeof(in6.s6_addr));
+       if (ret)
+           return -1;
+       memcpy(addr->address.data, in6.s6_addr, sizeof(in6.s6_addr));
+       return 0;
+    }
+    return -1;
+}
+
+static int
+ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr,
+                  unsigned long len, krb5_address *low, krb5_address *high)
+{
+    struct in6_addr addr, laddr, haddr;
+    u_int32_t m;
+    int i, sub_len;
+
+    if (len > 128) {
+       krb5_set_error_string(context, "IPv6 prefix too large (%ld)", len);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+
+    if (inaddr->address.length != sizeof(addr)) {
+       krb5_set_error_string(context, "IPv6 addr bad length");
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+
+    memcpy(&addr, inaddr->address.data, inaddr->address.length);
+
+    for (i = 0; i < 16; i++) {
+       sub_len = min(8, len);
+
+       m = 0xff << (8 - sub_len);
+       
+       laddr.s6_addr[i] = addr.s6_addr[i] & m;
+       haddr.s6_addr[i] = (addr.s6_addr[i] & m) | ~m;
+
+       if (len > 8)
+           len -= 8;
+       else
+           len = 0;
+    }
+
+    low->addr_type = KRB5_ADDRESS_INET6;
+    if (krb5_data_alloc(&low->address, sizeof(laddr.s6_addr)) != 0)
+       return -1;
+    memcpy(low->address.data, laddr.s6_addr, sizeof(laddr.s6_addr));
+
+    high->addr_type = KRB5_ADDRESS_INET6;
+    if (krb5_data_alloc(&high->address, sizeof(haddr.s6_addr)) != 0) {
+       krb5_free_address(context, low);
+       return -1;
+    }
+    memcpy(high->address.data, haddr.s6_addr, sizeof(haddr.s6_addr));
+
+    return 0;
+}
+
+#endif /* IPv6 */
+
+/*
+ * table
+ */
+
+#define KRB5_ADDRESS_ARANGE    (-100)
+
+struct arange {
+    krb5_address low;
+    krb5_address high;
+};
+
+static int
+arange_parse_addr (krb5_context context, 
+                  const char *address, krb5_address *addr)
+{
+    char buf[1024], *p;
+    krb5_address low0, high0;
+    struct arange *a;
+    krb5_error_code ret;
+    
+    if(strncasecmp(address, "RANGE:", 6) != 0)
+       return -1;
+    
+    address += 6;
+
+    p = strrchr(address, '/');
+    if (p) {
+       krb5_addresses addrmask;
+       char *q;
+       long num;
+
+       if (strlcpy(buf, address, sizeof(buf)) > sizeof(buf))
+           return -1;
+       buf[p - address] = '\0';
+       ret = krb5_parse_address(context, buf, &addrmask);
+       if (ret)
+           return ret;
+       if(addrmask.len != 1) {
+           krb5_free_addresses(context, &addrmask);
+           return -1;
+       }
+       
+       address += p - address + 1;
+
+       num = strtol(address, &q, 10);
+       if (q == address || *q != '\0' || num < 0) {
+           krb5_free_addresses(context, &addrmask);
+           return -1;
+       }
+
+       ret = krb5_address_prefixlen_boundary(context, &addrmask.val[0], num,
+                                             &low0, &high0);
+       krb5_free_addresses(context, &addrmask);
+       if (ret)
+           return ret;
+
+    } else {
+       krb5_addresses low, high;
+       
+       strsep_copy(&address, "-", buf, sizeof(buf));
+       ret = krb5_parse_address(context, buf, &low);
+       if(ret)
+           return ret;
+       if(low.len != 1) {
+           krb5_free_addresses(context, &low);
+           return -1;
+       }
+       
+       strsep_copy(&address, "-", buf, sizeof(buf));
+       ret = krb5_parse_address(context, buf, &high);
+       if(ret) {
+           krb5_free_addresses(context, &low);
+           return ret;
+       }
+       
+       if(high.len != 1 && high.val[0].addr_type != low.val[0].addr_type) {
+           krb5_free_addresses(context, &low);
+           krb5_free_addresses(context, &high);
+           return -1;
+       }
+
+       ret = krb5_copy_address(context, &high.val[0], &high0);
+       if (ret == 0) {
+           ret = krb5_copy_address(context, &low.val[0], &low0);
+           if (ret)
+               krb5_free_address(context, &high0);
+       }
+       krb5_free_addresses(context, &low);
+       krb5_free_addresses(context, &high);
+       if (ret)
+           return ret;
+    }
+
+    krb5_data_alloc(&addr->address, sizeof(*a));
+    addr->addr_type = KRB5_ADDRESS_ARANGE;
+    a = addr->address.data;
+
+    if(krb5_address_order(context, &low0, &high0) < 0) {
+       a->low = low0;
+       a->high = high0;
+    } else {
+       a->low = high0;
+       a->high = low0;
+    }
+    return 0;
+}
+
+static int
+arange_free (krb5_context context, krb5_address *addr)
+{
+    struct arange *a;
+    a = addr->address.data;
+    krb5_free_address(context, &a->low);
+    krb5_free_address(context, &a->high);
+    return 0;
+}
+
+
+static int
+arange_copy (krb5_context context, const krb5_address *inaddr, 
+            krb5_address *outaddr)
+{
+    krb5_error_code ret;
+    struct arange *i, *o;
+
+    outaddr->addr_type = KRB5_ADDRESS_ARANGE;
+    ret = krb5_data_alloc(&outaddr->address, sizeof(*o));
+    if(ret)
+       return ret;
+    i = inaddr->address.data;
+    o = outaddr->address.data;
+    ret = krb5_copy_address(context, &i->low, &o->low);
+    if(ret) {
+       krb5_data_free(&outaddr->address);
+       return ret;
+    }
+    ret = krb5_copy_address(context, &i->high, &o->high);
+    if(ret) {
+       krb5_free_address(context, &o->low);
+       krb5_data_free(&outaddr->address);
+       return ret;
+    }
+    return 0;
+}
+
+static int
+arange_print_addr (const krb5_address *addr, char *str, size_t len)
+{
+    struct arange *a;
+    krb5_error_code ret;
+    size_t l, size, ret_len;
+
+    a = addr->address.data;
+
+    l = strlcpy(str, "RANGE:", len);
+    ret_len = l;
+    if (l > len)
+       l = len;
+    size = l;
+       
+    ret = krb5_print_address (&a->low, str + size, len - size, &l);
+    if (ret)
+       return ret;
+    ret_len += l;
+    if (len - size > l)
+       size += l;
+    else
+       size = len;
+
+    l = strlcat(str + size, "-", len - size);
+    ret_len += l;
+    if (len - size > l)
+       size += l;
+    else
+       size = len;
+
+    ret = krb5_print_address (&a->high, str + size, len - size, &l);
+    if (ret)
+       return ret;
+    ret_len += l;
+
+    return ret_len;
+}
+
+static int
+arange_order_addr(krb5_context context, 
+                 const krb5_address *addr1, 
+                 const krb5_address *addr2)
+{
+    int tmp1, tmp2, sign;
+    struct arange *a;
+    const krb5_address *a2;
+
+    if(addr1->addr_type == KRB5_ADDRESS_ARANGE) {
+       a = addr1->address.data;
+       a2 = addr2;
+       sign = 1;
+    } else if(addr2->addr_type == KRB5_ADDRESS_ARANGE) {
+       a = addr2->address.data;
+       a2 = addr1;
+       sign = -1;
+    } else
+       abort();
+       
+    if(a2->addr_type == KRB5_ADDRESS_ARANGE) {
+       struct arange *b = a2->address.data;
+       tmp1 = krb5_address_order(context, &a->low, &b->low);
+       if(tmp1 != 0)
+           return sign * tmp1;
+       return sign * krb5_address_order(context, &a->high, &b->high);
+    } else if(a2->addr_type == a->low.addr_type) {
+       tmp1 = krb5_address_order(context, &a->low, a2);
+       if(tmp1 > 0)
+           return sign;
+       tmp2 = krb5_address_order(context, &a->high, a2);
+       if(tmp2 < 0)
+           return -sign;
+       return 0;
+    } else {
+       return sign * (addr1->addr_type - addr2->addr_type);
+    }
+}
+
+static int
+addrport_print_addr (const krb5_address *addr, char *str, size_t len)
+{
+    krb5_error_code ret;
+    krb5_address addr1, addr2;
+    uint16_t port = 0;
+    size_t ret_len = 0, l, size = 0;
+    krb5_storage *sp = krb5_storage_from_data((krb5_data*)&addr->address);
+    /* for totally obscure reasons, these are not in network byteorder */
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+    krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */
+    krb5_ret_address(sp, &addr1);
+
+    krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */
+    krb5_ret_address(sp, &addr2);
+    krb5_storage_free(sp);
+    if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) {
+       unsigned long value;
+       _krb5_get_int(addr2.address.data, &value, 2);
+       port = value;
+    }
+    l = strlcpy(str, "ADDRPORT:", len);
+    ret_len += l;
+    if (len > l)
+       size += l;
+    else
+       size = len;
+
+    ret = krb5_print_address(&addr1, str + size, len - size, &l);
+    if (ret)
+       return ret;
+    ret_len += l;
+    if (len - size > l)
+       size += l;
+    else
+       size = len;
+
+    ret = snprintf(str + size, len - size, ",PORT=%u", port);
+    if (ret < 0)
+       return EINVAL;
+    ret_len += ret;
+    return ret_len;
+}
+
+static struct addr_operations at[] = {
+    {AF_INET,  KRB5_ADDRESS_INET, sizeof(struct sockaddr_in),
+     ipv4_sockaddr2addr, 
+     ipv4_sockaddr2port,
+     ipv4_addr2sockaddr,
+     ipv4_h_addr2sockaddr,
+     ipv4_h_addr2addr,
+     ipv4_uninteresting, ipv4_anyaddr, ipv4_print_addr, ipv4_parse_addr,
+     NULL, NULL, NULL, ipv4_mask_boundary },
+#ifdef HAVE_IPV6
+    {AF_INET6, KRB5_ADDRESS_INET6, sizeof(struct sockaddr_in6),
+     ipv6_sockaddr2addr, 
+     ipv6_sockaddr2port,
+     ipv6_addr2sockaddr,
+     ipv6_h_addr2sockaddr,
+     ipv6_h_addr2addr,
+     ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr,
+     NULL, NULL, NULL, ipv6_mask_boundary } ,
+#endif
+    {KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0,
+     NULL, NULL, NULL, NULL, NULL, 
+     NULL, NULL, addrport_print_addr, NULL, NULL, NULL, NULL },
+    /* fake address type */
+    {KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange),
+     NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+     arange_print_addr, arange_parse_addr, 
+     arange_order_addr, arange_free, arange_copy }
+};
+
+static int num_addrs = sizeof(at) / sizeof(at[0]);
+
+static size_t max_sockaddr_size = 0;
+
+/*
+ * generic functions
+ */
+
+static struct addr_operations *
+find_af(int af)
+{
+    struct addr_operations *a;
+
+    for (a = at; a < at + num_addrs; ++a)
+       if (af == a->af)
+           return a;
+    return NULL;
+}
+
+static struct addr_operations *
+find_atype(int atype)
+{
+    struct addr_operations *a;
+
+    for (a = at; a < at + num_addrs; ++a)
+       if (atype == a->atype)
+           return a;
+    return NULL;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sockaddr2address (krb5_context context,
+                      const struct sockaddr *sa, krb5_address *addr)
+{
+    struct addr_operations *a = find_af(sa->sa_family);
+    if (a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported",
+                              sa->sa_family);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    return (*a->sockaddr2addr)(sa, addr);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sockaddr2port (krb5_context context,
+                   const struct sockaddr *sa, int16_t *port)
+{
+    struct addr_operations *a = find_af(sa->sa_family);
+    if (a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported",
+                              sa->sa_family);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    return (*a->sockaddr2port)(sa, port);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_addr2sockaddr (krb5_context context,
+                   const krb5_address *addr,
+                   struct sockaddr *sa,
+                   krb5_socklen_t *sa_size,
+                   int port)
+{
+    struct addr_operations *a = find_atype(addr->addr_type);
+
+    if (a == NULL) {
+       krb5_set_error_string (context, "Address type %d not supported",
+                              addr->addr_type);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    if (a->addr2sockaddr == NULL) {
+       krb5_set_error_string (context, "Can't convert address type %d to sockaddr",
+                              addr->addr_type);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    (*a->addr2sockaddr)(addr, sa, sa_size, port);
+    return 0;
+}
+
+size_t KRB5_LIB_FUNCTION
+krb5_max_sockaddr_size (void)
+{
+    if (max_sockaddr_size == 0) {
+       struct addr_operations *a;
+
+       for(a = at; a < at + num_addrs; ++a)
+           max_sockaddr_size = max(max_sockaddr_size, a->max_sockaddr_size);
+    }
+    return max_sockaddr_size;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_sockaddr_uninteresting(const struct sockaddr *sa)
+{
+    struct addr_operations *a = find_af(sa->sa_family);
+    if (a == NULL || a->uninteresting == NULL)
+       return TRUE;
+    return (*a->uninteresting)(sa);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_h_addr2sockaddr (krb5_context context,
+                     int af,
+                     const char *addr, struct sockaddr *sa,
+                     krb5_socklen_t *sa_size,
+                     int port)
+{
+    struct addr_operations *a = find_af(af);
+    if (a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported", af);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    (*a->h_addr2sockaddr)(addr, sa, sa_size, port);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_h_addr2addr (krb5_context context,
+                 int af,
+                 const char *haddr, krb5_address *addr)
+{
+    struct addr_operations *a = find_af(af);
+    if (a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported", af);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    return (*a->h_addr2addr)(haddr, addr);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_anyaddr (krb5_context context,
+             int af,
+             struct sockaddr *sa,
+             krb5_socklen_t *sa_size,
+             int port)
+{
+    struct addr_operations *a = find_af (af);
+
+    if (a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported", af);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+
+    (*a->anyaddr)(sa, sa_size, port);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_print_address (const krb5_address *addr, 
+                   char *str, size_t len, size_t *ret_len)
+{
+    struct addr_operations *a = find_atype(addr->addr_type);
+    int ret;
+
+    if (a == NULL || a->print_addr == NULL) {
+       char *s;
+       int l;
+       int i;
+
+       s = str;
+       l = snprintf(s, len, "TYPE_%d:", addr->addr_type);
+       if (l < 0 || l >= len)
+           return EINVAL;
+       s += l;
+       len -= l;
+       for(i = 0; i < addr->address.length; i++) {
+           l = snprintf(s, len, "%02x", ((char*)addr->address.data)[i]);
+           if (l < 0 || l >= len)
+               return EINVAL;
+           len -= l;
+           s += l;
+       }
+       if(ret_len != NULL)
+           *ret_len = s - str;
+       return 0;
+    }
+    ret = (*a->print_addr)(addr, str, len);
+    if (ret < 0)
+       return EINVAL;
+    if(ret_len != NULL)
+       *ret_len = ret;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_parse_address(krb5_context context,
+                  const char *string,
+                  krb5_addresses *addresses)
+{
+    int i, n;
+    struct addrinfo *ai, *a;
+    int error;
+    int save_errno;
+
+    addresses->len = 0;
+    addresses->val = NULL;
+
+    for(i = 0; i < num_addrs; i++) {
+       if(at[i].parse_addr) {
+           krb5_address addr;
+           if((*at[i].parse_addr)(context, string, &addr) == 0) {
+               ALLOC_SEQ(addresses, 1);
+               if (addresses->val == NULL) {
+                   krb5_set_error_string(context, "malloc: out of memory");
+                   return ENOMEM;
+               }
+               addresses->val[0] = addr;
+               return 0;
+           }
+       }
+    }
+
+    error = getaddrinfo (string, NULL, NULL, &ai);
+    if (error) {
+       save_errno = errno;
+       krb5_set_error_string (context, "%s: %s", string, gai_strerror(error));
+       return krb5_eai_to_heim_errno(error, save_errno);
+    }
+    
+    n = 0;
+    for (a = ai; a != NULL; a = a->ai_next)
+       ++n;
+
+    ALLOC_SEQ(addresses, n);
+    if (addresses->val == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       freeaddrinfo(ai);
+       return ENOMEM;
+    }
+
+    addresses->len = 0;
+    for (a = ai, i = 0; a != NULL; a = a->ai_next) {
+       if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i]))
+           continue;
+       if(krb5_address_search(context, &addresses->val[i], addresses))
+           continue;
+       addresses->len = i;
+       i++;
+    }
+    freeaddrinfo (ai);
+    return 0;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_address_order(krb5_context context,
+                  const krb5_address *addr1,
+                  const krb5_address *addr2)
+{
+    /* this sucks; what if both addresses have order functions, which
+       should we call? this works for now, though */
+    struct addr_operations *a;
+    a = find_atype(addr1->addr_type); 
+    if(a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported", 
+                              addr1->addr_type);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    if(a->order_addr != NULL) 
+       return (*a->order_addr)(context, addr1, addr2); 
+    a = find_atype(addr2->addr_type); 
+    if(a == NULL) {
+       krb5_set_error_string (context, "Address family %d not supported", 
+                              addr2->addr_type);
+       return KRB5_PROG_ATYPE_NOSUPP;
+    }
+    if(a->order_addr != NULL) 
+       return (*a->order_addr)(context, addr1, addr2);
+
+    if(addr1->addr_type != addr2->addr_type)
+       return addr1->addr_type - addr2->addr_type;
+    if(addr1->address.length != addr2->address.length)
+       return addr1->address.length - addr2->address.length;
+    return memcmp (addr1->address.data,
+                  addr2->address.data,
+                  addr1->address.length);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_address_compare(krb5_context context,
+                    const krb5_address *addr1,
+                    const krb5_address *addr2)
+{
+    return krb5_address_order (context, addr1, addr2) == 0;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_address_search(krb5_context context,
+                   const krb5_address *addr,
+                   const krb5_addresses *addrlist)
+{
+    int i;
+
+    for (i = 0; i < addrlist->len; ++i)
+       if (krb5_address_compare (context, addr, &addrlist->val[i]))
+           return TRUE;
+    return FALSE;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_address(krb5_context context,
+                 krb5_address *address)
+{
+    struct addr_operations *a = find_atype (address->addr_type);
+    if(a != NULL && a->free_addr != NULL)
+       return (*a->free_addr)(context, address);
+    krb5_data_free (&address->address);
+    memset(address, 0, sizeof(*address));
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_addresses(krb5_context context,
+                   krb5_addresses *addresses)
+{
+    int i;
+    for(i = 0; i < addresses->len; i++)
+       krb5_free_address(context, &addresses->val[i]);
+    free(addresses->val);
+    addresses->len = 0;
+    addresses->val = NULL;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_address(krb5_context context,
+                 const krb5_address *inaddr,
+                 krb5_address *outaddr)
+{
+    struct addr_operations *a = find_af (inaddr->addr_type);
+    if(a != NULL && a->copy_addr != NULL)
+       return (*a->copy_addr)(context, inaddr, outaddr);
+    return copy_HostAddress(inaddr, outaddr);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_addresses(krb5_context context,
+                   const krb5_addresses *inaddr,
+                   krb5_addresses *outaddr)
+{
+    int i;
+    ALLOC_SEQ(outaddr, inaddr->len);
+    if(inaddr->len > 0 && outaddr->val == NULL)
+       return ENOMEM;
+    for(i = 0; i < inaddr->len; i++)
+       krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_append_addresses(krb5_context context,
+                     krb5_addresses *dest,
+                     const krb5_addresses *source)
+{
+    krb5_address *tmp;
+    krb5_error_code ret;
+    int i;
+    if(source->len > 0) {
+       tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp));
+       if(tmp == NULL) {
+           krb5_set_error_string(context, "realloc: out of memory");
+           return ENOMEM;
+       }
+       dest->val = tmp;
+       for(i = 0; i < source->len; i++) {
+           /* skip duplicates */
+           if(krb5_address_search(context, &source->val[i], dest))
+               continue;
+           ret = krb5_copy_address(context, 
+                                   &source->val[i], 
+                                   &dest->val[dest->len]);
+           if(ret)
+               return ret;
+           dest->len++;
+       }
+    }
+    return 0;
+}
+
+/*
+ * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port)
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_make_addrport (krb5_context context,
+                   krb5_address **res, const krb5_address *addr, int16_t port)
+{
+    krb5_error_code ret;
+    size_t len = addr->address.length + 2 + 4 * 4;
+    u_char *p;
+
+    *res = malloc (sizeof(**res));
+    if (*res == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    (*res)->addr_type = KRB5_ADDRESS_ADDRPORT;
+    ret = krb5_data_alloc (&(*res)->address, len);
+    if (ret) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free (*res);
+       return ret;
+    }
+    p = (*res)->address.data;
+    *p++ = 0;
+    *p++ = 0;
+    *p++ = (addr->addr_type     ) & 0xFF;
+    *p++ = (addr->addr_type >> 8) & 0xFF;
+
+    *p++ = (addr->address.length      ) & 0xFF;
+    *p++ = (addr->address.length >>  8) & 0xFF;
+    *p++ = (addr->address.length >> 16) & 0xFF;
+    *p++ = (addr->address.length >> 24) & 0xFF;
+
+    memcpy (p, addr->address.data, addr->address.length);
+    p += addr->address.length;
+
+    *p++ = 0;
+    *p++ = 0;
+    *p++ = (KRB5_ADDRESS_IPPORT     ) & 0xFF;
+    *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF;
+
+    *p++ = (2      ) & 0xFF;
+    *p++ = (2 >>  8) & 0xFF;
+    *p++ = (2 >> 16) & 0xFF;
+    *p++ = (2 >> 24) & 0xFF;
+
+    memcpy (p, &port, 2);
+    p += 2;
+
+    return 0;
+}
+
+/*
+ * Calculate the boundary addresses of `inaddr'/`prefixlen' and store
+ * them in `low' and `high'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_address_prefixlen_boundary(krb5_context context,
+                               const krb5_address *inaddr,
+                               unsigned long prefixlen,
+                               krb5_address *low,
+                               krb5_address *high)
+{
+    struct addr_operations *a = find_atype (inaddr->addr_type);
+    if(a != NULL && a->mask_boundary != NULL)
+       return (*a->mask_boundary)(context, inaddr, prefixlen, low, high);
+    krb5_set_error_string(context, "Address family %d doesn't support "
+                         "address mask operation", inaddr->addr_type);
+    return KRB5_PROG_ATYPE_NOSUPP;
+}
diff --git a/src/kerberosV/src/lib/krb5/address.c b/src/kerberosV/src/lib/krb5/address.c
new file mode 100644 (file)
index 0000000..7f5828c
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: address.c,v 1.15 2001/05/14 06:14:44 assar Exp $");
+
+#if 0
+/* This is the supposedly MIT-api version */
+
+krb5_boolean
+krb5_address_search(krb5_context context,
+                   const krb5_address *addr,
+                   krb5_address *const *addrlist)
+{
+  krb5_address *a;
+
+  while((a = *addrlist++))
+    if (krb5_address_compare (context, addr, a))
+      return TRUE;
+  return FALSE;
+}
+#endif
+
+krb5_boolean
+krb5_address_search(krb5_context context,
+                   const krb5_address *addr,
+                   const krb5_addresses *addrlist)
+{
+    int i;
+
+    for (i = 0; i < addrlist->len; ++i)
+       if (krb5_address_compare (context, addr, &addrlist->val[i]))
+           return TRUE;
+    return FALSE;
+}
+
+int
+krb5_address_order(krb5_context context,
+                  const krb5_address *addr1,
+                  const krb5_address *addr2)
+{
+    return (addr1->addr_type - addr2->addr_type)
+       || memcmp (addr1->address.data,
+                  addr2->address.data,
+                  addr1->address.length);
+}
+
+krb5_boolean
+krb5_address_compare(krb5_context context,
+                    const krb5_address *addr1,
+                    const krb5_address *addr2)
+{
+    return krb5_address_order (context, addr1, addr2) == 0;
+}
+
+krb5_error_code
+krb5_copy_address(krb5_context context,
+                 const krb5_address *inaddr,
+                 krb5_address *outaddr)
+{
+    copy_HostAddress(inaddr, outaddr);
+    return 0;
+}
+
+krb5_error_code
+krb5_copy_addresses(krb5_context context,
+                   const krb5_addresses *inaddr,
+                   krb5_addresses *outaddr)
+{
+    copy_HostAddresses(inaddr, outaddr);
+    return 0;
+}
+
+krb5_error_code
+krb5_free_address(krb5_context context,
+                 krb5_address *address)
+{
+    krb5_data_free (&address->address);
+    return 0;
+}
+
+krb5_error_code
+krb5_free_addresses(krb5_context context,
+                   krb5_addresses *addresses)
+{
+    free_HostAddresses(addresses);
+    return 0;
+}
+
+krb5_error_code
+krb5_append_addresses(krb5_context context,
+                     krb5_addresses *dest,
+                     const krb5_addresses *source)
+{
+    krb5_address *tmp;
+    krb5_error_code ret;
+    int i;
+    if(source->len > 0) {
+       tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp));
+       if(tmp == NULL) {
+           krb5_set_error_string(context, "realloc: out of memory");
+           return ENOMEM;
+       }
+       dest->val = tmp;
+       for(i = 0; i < source->len; i++) {
+           /* skip duplicates */
+           if(krb5_address_search(context, &source->val[i], dest))
+               continue;
+           ret = krb5_copy_address(context, 
+                                   &source->val[i], 
+                                   &dest->val[dest->len]);
+           if(ret)
+               return ret;
+           dest->len++;
+       }
+    }
+    return 0;
+}
+
+/*
+ * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port)
+ */
+
+krb5_error_code
+krb5_make_addrport (krb5_context context,
+                   krb5_address **res, const krb5_address *addr, int16_t port)
+{
+    krb5_error_code ret;
+    size_t len = addr->address.length + 2 + 4 * 4;
+    u_char *p;
+
+    *res = malloc (sizeof(**res));
+    if (*res == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    (*res)->addr_type = KRB5_ADDRESS_ADDRPORT;
+    ret = krb5_data_alloc (&(*res)->address, len);
+    if (ret) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free (*res);
+       return ret;
+    }
+    p = (*res)->address.data;
+    *p++ = 0;
+    *p++ = 0;
+    *p++ = (addr->addr_type     ) & 0xFF;
+    *p++ = (addr->addr_type >> 8) & 0xFF;
+
+    *p++ = (addr->address.length      ) & 0xFF;
+    *p++ = (addr->address.length >>  8) & 0xFF;
+    *p++ = (addr->address.length >> 16) & 0xFF;
+    *p++ = (addr->address.length >> 24) & 0xFF;
+
+    memcpy (p, addr->address.data, addr->address.length);
+    p += addr->address.length;
+
+    *p++ = 0;
+    *p++ = 0;
+    *p++ = (KRB5_ADDRESS_IPPORT     ) & 0xFF;
+    *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF;
+
+    *p++ = (2      ) & 0xFF;
+    *p++ = (2 >>  8) & 0xFF;
+    *p++ = (2 >> 16) & 0xFF;
+    *p++ = (2 >> 24) & 0xFF;
+
+    memcpy (p, &port, 2);
+    p += 2;
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/aes-test.c b/src/kerberosV/src/lib/krb5/aes-test.c
new file mode 100644 (file)
index 0000000..8a986a0
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * Copyright (c) 2003 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. */
+
+#include "krb5_locl.h"
+#include <hex.h>
+#include <err.h>
+
+#ifdef HAVE_OPENSSL
+#include <openssl/evp.h>
+#endif
+
+RCSID("$KTH: aes-test.c,v 1.15 2005/04/30 15:19:46 lha Exp $");
+
+static int verbose = 0;
+
+static void
+hex_dump_data(krb5_data *data)
+{
+    char *p;
+
+    hex_encode(data->data, data->length, &p);
+    printf("%s\n", p);
+    free(p);
+}
+
+struct {
+    char *password;
+    char *salt;
+    int saltlen;
+    int iterations;
+    krb5_enctype enctype;
+    size_t keylen;
+    char *pbkdf2;
+    char *key;
+} keys[] = {
+    { 
+       "password", "ATHENA.MIT.EDUraeburn", -1,
+       1, 
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15",
+       "\x42\x26\x3c\x6e\x89\xf4\xfc\x28\xb8\xdf\x68\xee\x09\x79\x9f\x15"
+    },
+    {
+       "password", "ATHENA.MIT.EDUraeburn", -1,
+       1, 
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\xcd\xed\xb5\x28\x1b\xb2\xf8\x01\x56\x5a\x11\x22\xb2\x56\x35\x15"
+       "\x0a\xd1\xf7\xa0\x4b\xb9\xf3\xa3\x33\xec\xc0\xe2\xe1\xf7\x08\x37",
+       "\xfe\x69\x7b\x52\xbc\x0d\x3c\xe1\x44\x32\xba\x03\x6a\x92\xe6\x5b"
+       "\xbb\x52\x28\x09\x90\xa2\xfa\x27\x88\x39\x98\xd7\x2a\xf3\x01\x61"
+    },
+    {
+       "password", "ATHENA.MIT.EDUraeburn", -1,
+       2,
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d",
+       "\xc6\x51\xbf\x29\xe2\x30\x0a\xc2\x7f\xa4\x69\xd6\x93\xbd\xda\x13"
+    },
+    {
+       "password", "ATHENA.MIT.EDUraeburn", -1,
+       2, 
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\x01\xdb\xee\x7f\x4a\x9e\x24\x3e\x98\x8b\x62\xc7\x3c\xda\x93\x5d"
+       "\xa0\x53\x78\xb9\x32\x44\xec\x8f\x48\xa9\x9e\x61\xad\x79\x9d\x86",
+       "\xa2\xe1\x6d\x16\xb3\x60\x69\xc1\x35\xd5\xe9\xd2\xe2\x5f\x89\x61"
+       "\x02\x68\x56\x18\xb9\x59\x14\xb4\x67\xc6\x76\x22\x22\x58\x24\xff"
+    },
+    {
+       "password", "ATHENA.MIT.EDUraeburn", -1,
+       1200, 
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b",
+       "\x4c\x01\xcd\x46\xd6\x32\xd0\x1e\x6d\xbe\x23\x0a\x01\xed\x64\x2a"
+    },
+    {
+       "password", "ATHENA.MIT.EDUraeburn", -1,
+       1200, 
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\x5c\x08\xeb\x61\xfd\xf7\x1e\x4e\x4e\xc3\xcf\x6b\xa1\xf5\x51\x2b"
+       "\xa7\xe5\x2d\xdb\xc5\xe5\x14\x2f\x70\x8a\x31\xe2\xe6\x2b\x1e\x13",
+       "\x55\xa6\xac\x74\x0a\xd1\x7b\x48\x46\x94\x10\x51\xe1\xe8\xb0\xa7"
+       "\x54\x8d\x93\xb0\xab\x30\xa8\xbc\x3f\xf1\x62\x80\x38\x2b\x8c\x2a"
+    },
+    {
+       "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8,
+       5,
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49",
+       "\xe9\xb2\x3d\x52\x27\x37\x47\xdd\x5c\x35\xcb\x55\xbe\x61\x9d\x8e"
+    },
+    {
+       "password", "\x12\x34\x56\x78\x78\x56\x34\x12", 8,
+       5,
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\xd1\xda\xa7\x86\x15\xf2\x87\xe6\xa1\xc8\xb1\x20\xd7\x06\x2a\x49"
+       "\x3f\x98\xd2\x03\xe6\xbe\x49\xa6\xad\xf4\xfa\x57\x4b\x6e\x64\xee",
+       "\x97\xa4\xe7\x86\xbe\x20\xd8\x1a\x38\x2d\x5e\xbc\x96\xd5\x90\x9c"
+       "\xab\xcd\xad\xc8\x7c\xa4\x8f\x57\x45\x04\x15\x9f\x16\xc3\x6e\x31"
+    },
+    {
+       "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+       "pass phrase equals block size", -1,
+       1200,
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9",
+       "\x59\xd1\xbb\x78\x9a\x82\x8b\x1a\xa5\x4e\xf9\xc2\x88\x3f\x69\xed"
+    },
+    {
+       "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+       "pass phrase equals block size", -1,
+       1200,
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\x13\x9c\x30\xc0\x96\x6b\xc3\x2b\xa5\x5f\xdb\xf2\x12\x53\x0a\xc9"
+       "\xc5\xec\x59\xf1\xa4\x52\xf5\xcc\x9a\xd9\x40\xfe\xa0\x59\x8e\xd1",
+       "\x89\xad\xee\x36\x08\xdb\x8b\xc7\x1f\x1b\xfb\xfe\x45\x94\x86\xb0"
+       "\x56\x18\xb7\x0c\xba\xe2\x20\x92\x53\x4e\x56\xc5\x53\xba\x4b\x34"
+    },
+    {
+       "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+       "pass phrase exceeds block size", -1,
+       1200,
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61",
+       "\xcb\x80\x05\xdc\x5f\x90\x17\x9a\x7f\x02\x10\x4c\x00\x18\x75\x1d"
+    },
+    {
+       "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
+       "pass phrase exceeds block size", -1,
+       1200,
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\x9c\xca\xd6\xd4\x68\x77\x0c\xd5\x1b\x10\xe6\xa6\x87\x21\xbe\x61"
+       "\x1a\x8b\x4d\x28\x26\x01\xdb\x3b\x36\xbe\x92\x46\x91\x5e\xc8\x2a",
+       "\xd7\x8c\x5c\x9c\xb8\x72\xa8\xc9\xda\xd4\x69\x7f\x0b\xb5\xb2\xd2"
+       "\x14\x96\xc8\x2b\xeb\x2c\xae\xda\x21\x12\xfc\xee\xa0\x57\x40\x1b"
+
+    },
+    {
+       "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1,
+       50,
+       ETYPE_AES128_CTS_HMAC_SHA1_96, 16,
+       "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39",
+       "\xf1\x49\xc1\xf2\xe1\x54\xa7\x34\x52\xd4\x3e\x7f\xe6\x2a\x56\xe5"
+    },
+    {
+       "\xf0\x9d\x84\x9e" /* g-clef */, "EXAMPLE.COMpianist", -1,
+       50,
+       ETYPE_AES256_CTS_HMAC_SHA1_96, 32,
+       "\x6b\x9c\xf2\x6d\x45\x45\x5a\x43\xa5\xb8\xbb\x27\x6a\x40\x3b\x39"
+       "\xe7\xfe\x37\xa0\xc4\x1e\x02\xc2\x81\xff\x30\x69\xe1\xe9\x4f\x52",
+       "\x4b\x6d\x98\x39\xf8\x44\x06\xdf\x1f\x09\xcc\x16\x6d\xb4\xb8\x3c"
+       "\x57\x18\x48\xb7\x84\xa3\xd6\xbd\xc3\x46\x58\x9a\x3e\x39\x3f\x9e"
+    },
+    {
+       "foo", "", -1, 
+       0,
+       ETYPE_ARCFOUR_HMAC_MD5, 16,
+       NULL,
+       "\xac\x8e\x65\x7f\x83\xdf\x82\xbe\xea\x5d\x43\xbd\xaf\x78\x00\xcc"
+    },
+    {
+       "test", "", -1, 
+       0,
+       ETYPE_ARCFOUR_HMAC_MD5, 16,
+       NULL,
+       "\x0c\xb6\x94\x88\x05\xf7\x97\xbf\x2a\x82\x80\x79\x73\xb8\x95\x37"
+    }
+};
+
+static int
+string_to_key_test(krb5_context context)
+{
+    krb5_data password, opaque;
+    krb5_error_code ret;
+    krb5_keyblock key;
+    krb5_salt salt;
+    int i, val = 0;
+    char iter[4];
+
+    for (i = 0; i < sizeof(keys)/sizeof(keys[0]); i++) {
+
+       password.data = keys[i].password;
+       password.length = strlen(password.data);
+
+       salt.salttype = KRB5_PW_SALT;
+       salt.saltvalue.data = keys[i].salt;
+       if (keys[i].saltlen == -1)
+           salt.saltvalue.length = strlen(salt.saltvalue.data);
+       else
+           salt.saltvalue.length = keys[i].saltlen;
+    
+       opaque.data = iter;
+       opaque.length = sizeof(iter);
+       _krb5_put_int(iter, keys[i].iterations, 4);
+       
+       if (keys[i].pbkdf2) {
+#ifdef HAVE_OPENSSL
+           char keyout[32];
+
+           if (keys[i].keylen > sizeof(keyout))
+               abort();
+
+           PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length,
+                                  salt.saltvalue.data, salt.saltvalue.length,
+                                  keys[i].iterations, 
+                                  keys[i].keylen, keyout);
+           
+           if (memcmp(keyout, keys[i].pbkdf2, keys[i].keylen) != 0) {
+               krb5_warnx(context, "%d: openssl key pbkdf2", i);
+               val = 1;
+               continue;
+           }
+#endif
+           
+           ret = _krb5_PKCS5_PBKDF2(context, CKSUMTYPE_SHA1, password, salt, 
+                                    keys[i].iterations - 1,
+                                    keys[i].enctype,
+                                    &key);
+           if (ret) {
+               krb5_warn(context, ret, "%d: krb5_PKCS5_PBKDF2", i);
+               val = 1;
+               continue;
+           }
+           
+           if (key.keyvalue.length != keys[i].keylen) {
+               krb5_warnx(context, "%d: size key pbkdf2", i);
+               val = 1;
+               continue;
+           }
+
+           if (memcmp(key.keyvalue.data, keys[i].pbkdf2, keys[i].keylen) != 0) {
+               krb5_warnx(context, "%d: key pbkdf2 pl %lu", 
+                          i, (unsigned long)password.length);
+               val = 1;
+               continue;
+           }
+
+           if (verbose) {
+               printf("PBKDF2:\n");
+               hex_dump_data(&key.keyvalue);
+           }
+           
+           krb5_free_keyblock_contents(context, &key);
+       }
+
+       ret = krb5_string_to_key_data_salt_opaque (context, keys[i].enctype,
+                                                  password, salt, opaque, 
+                                                  &key);
+       if (ret) {
+           krb5_warn(context, ret, "%d: string_to_key_data_salt_opaque", i);
+           val = 1;
+           continue;
+       }
+
+       if (key.keyvalue.length != keys[i].keylen) {
+           krb5_warnx(context, "%d: key wrong length (%lu/%lu)",
+                      i, (unsigned long)key.keyvalue.length, 
+                      (unsigned long)keys[i].keylen);
+           val = 1;
+           continue;
+       }
+
+       if (memcmp(key.keyvalue.data, keys[i].key, keys[i].keylen) != 0) {
+           krb5_warnx(context, "%d: key wrong", i);
+           val = 1;
+           continue;
+       }
+       
+       if (verbose) {
+           printf("key:\n");
+           hex_dump_data(&key.keyvalue);
+       }
+       krb5_free_keyblock_contents(context, &key);
+    }
+    return val;
+}
+
+struct enc_test {
+    size_t len;
+    char *input;
+    char *output;
+    char *nextiv;
+};
+
+struct enc_test encs1[] = {
+    {
+       17,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20",
+       "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
+       "\x97",
+       "\xc6\x35\x35\x68\xf2\xbf\x8c\xb4\xd8\xa5\x80\x36\x2d\xa7\xff\x7f"
+    },
+    {
+       31,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20",
+       "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
+       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5",
+       "\xfc\x00\x78\x3e\x0e\xfd\xb2\xc1\xd4\x45\xd4\xc8\xef\xf7\xed\x22"
+    },
+    {
+       32,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43",
+       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
+       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84",
+       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
+    },
+    {
+       47,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c",
+       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
+       "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
+       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5",
+       "\xb3\xff\xfd\x94\x0c\x16\xa1\x8c\x1b\x55\x49\xd2\xf8\x38\x02\x9e"
+    },
+    {
+       48,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20",
+       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
+       "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
+       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8",
+       "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8"
+    },
+    {
+       64,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
+       "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
+       "\x97\x68\x72\x68\xd6\xec\xcc\xc0\xc0\x7b\x25\xe2\x5e\xcf\xe5\x84"
+       "\x39\x31\x25\x23\xa7\x86\x62\xd5\xbe\x7f\xcb\xcc\x98\xeb\xf5\xa8"
+       "\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
+       "\x9d\xad\x8b\xbb\x96\xc4\xcd\xc0\x3b\xc1\x03\xe1\xa1\x94\xbb\xd8",
+       "\x48\x07\xef\xe8\x36\xee\x89\xa5\x26\x73\x0d\xbc\x2f\x7b\xc8\x40"
+    }
+};
+       
+
+struct enc_test encs2[] = {
+    {
+       17,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20",
+       "\x5c\x13\x26\x27\xc4\xcb\xca\x04\x14\x43\x8a\xb5\x97\x97\x7c\x10"
+       "\x16"
+    },
+    {
+       31,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20",
+       "\x16\xb3\xd8\xe5\xcd\x93\xe6\x2c\x28\x70\xa0\x36\x6e\x9a\xb9\x74"
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53"
+    },
+    {
+       32,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43",
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+    },
+    {
+       47,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\xe5\x56\xb4\x88\x41\xb9\xde\x27\xf0\x07\xa1\x6e\x89\x94\x47\xf1"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff"
+    },
+    {
+       48,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+    },
+    {
+       64,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
+       "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+       "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67"
+       "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30"
+    },
+    {
+       78,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
+       "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e"
+       "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+       "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30"
+       "\x73\xfb\x2c\x36\x76\xaf\xcf\x31\xff\xe3\x8a\x89\x0c\x7e\x99\x3f"
+       "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62"
+    },
+    {
+       83,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
+       "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e"
+       "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
+       "\x41\x41\x41",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+       "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30"
+       "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67"
+       "\x65\x39\x3a\xdb\x92\x05\x4d\x4f\x08\xa1\xfa\x59\xda\x56\x58\x0e"
+       "\x3b\xac\x12"
+    },
+    {
+       92,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
+       "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e"
+       "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
+       "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+       "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30"
+       "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67"
+       "\x0c\xff\xd7\x63\x50\xf8\x4e\xf9\xec\x56\x1c\x79\xc5\xc8\xfe\x50"
+       "\x3b\xac\x12\x6e\xd3\x2d\x02\xc4\xe5\x06\x43\x5f"
+    },
+    {
+       96,
+       "\x49\x20\x77\x6f\x75\x6c\x64\x20\x6c\x69\x6b\x65\x20\x74\x68\x65"
+       "\x20\x47\x65\x6e\x65\x72\x61\x6c\x20\x47\x61\x75\x27\x73\x20\x43"
+       "\x68\x69\x63\x6b\x65\x6e\x2c\x20\x70\x6c\x65\x61\x73\x65\x2c\x20"
+       "\x61\x6e\x64\x20\x77\x6f\x6e\x74\x6f\x6e\x20\x73\x6f\x75\x70\x2e"
+       "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
+       "\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41",
+       "\x16\xc1\xee\xdf\x39\xc8\x3f\xfb\xc5\xf6\x72\xe9\xc1\x6e\x53\x0c"
+       "\x69\xde\xce\x59\x83\x6a\x82\xe1\xcd\x21\x93\xd0\x9e\x2a\xff\xc8"
+       "\xfd\x68\xd1\x56\x32\x23\x7b\xfa\xb0\x09\x86\x3b\x17\x53\xfa\x30"
+       "\x70\x29\xf2\x6f\x7c\x79\xc1\x77\x91\xad\x94\xb0\x78\x62\x27\x67"
+       "\x08\x28\x49\xad\xfc\x2d\x8e\x86\xae\x69\xa5\xa8\xd9\x29\x9e\xe4"
+       "\x3b\xac\x12\x6e\xd3\x2d\x02\xc4\xe5\x06\x43\x5f\x4c\x41\xd1\xb8"
+    }
+};
+
+
+
+char *aes_key1 = 
+       "\x63\x68\x69\x63\x6b\x65\x6e\x20\x74\x65\x72\x69\x79\x61\x6b\x69";
+
+char *aes_key2 =
+       "\x63\x68\x69\x63\x6b\x65\x6e\x20\x74\x65\x72\x69\x79\x61\x6b\x69"
+       "\x2c\x20\x79\x75\x6d\x6d\x79\x20\x79\x75\x6d\x6d\x79\x21\x21\x21";
+
+
+static int
+samep(int testn, char *type, const char *p1, const char *p2, size_t len)
+{
+    size_t i;
+    int val = 1;
+
+    for (i = 0; i < len; i++) {
+       if (p1[i] != p2[i]) {
+           if (verbose)
+               printf("M");
+           val = 0;
+       } else {
+           if (verbose)
+               printf(".");
+       }
+    }
+    if (verbose)
+       printf("\n");
+    return val;
+}
+
+static int
+encryption_test(krb5_context context, char *key, size_t keylen,
+               struct enc_test *enc, int numenc)
+{
+    char iv[AES_BLOCK_SIZE];
+    int i, val, failed = 0;
+    AES_KEY ekey, dkey;
+    char *p;
+
+    AES_set_encrypt_key(key, keylen, &ekey);
+    AES_set_decrypt_key(key, keylen, &dkey);
+
+    for (i = 0; i < numenc; i++) {
+       val = 0;
+
+       if (verbose)
+           printf("test: %d\n", i);
+       memset(iv, 0, sizeof(iv));
+
+       p = malloc(enc[i].len + 1);
+       if (p == NULL)
+           krb5_errx(context, 1, "malloc");
+
+       p[enc[i].len] = '\0';
+
+       memcpy(p, enc[i].input, enc[i].len);
+
+       _krb5_aes_cts_encrypt(p, p, enc[i].len,
+                             &ekey, iv, AES_ENCRYPT);
+
+       if (p[enc[i].len] != '\0') {
+           krb5_warnx(context, "%d: encrypt modified off end", i);
+           val = 1;
+       }
+
+       if (!samep(i, "cipher", p, enc[i].output, enc[i].len)) {
+           krb5_warnx(context, "%d: cipher", i);
+           val = 1;
+       }
+
+       if (enc[i].nextiv && !samep(i, "iv", iv, enc[i].nextiv, 16)){ /*XXX*/ 
+           krb5_warnx(context, "%d: iv", i);
+           val = 1;
+       }
+
+       memset(iv, 0, sizeof(iv));
+
+       _krb5_aes_cts_encrypt(p, p, enc[i].len,
+                             &dkey, iv, AES_DECRYPT);
+
+       if (p[enc[i].len] != '\0') {
+           krb5_warnx(context, "%d: decrypt modified off end", i);
+           val = 1;
+       }
+
+       if (!samep(i, "clear", p, enc[i].input, enc[i].len))
+           val = 1;
+
+       if (enc[i].nextiv && !samep(i, "iv", iv, enc[i].nextiv, 16)){ /*XXX*/ 
+           krb5_warnx(context, "%d: iv", i);
+           val = 1;
+       }
+
+       free(p);
+
+       if (val) {
+           printf("test %d failed\n", i);
+           failed = 1;
+       }
+       val = 0;
+    }
+    return failed;
+}
+
+static int
+krb_enc(krb5_context context,
+       krb5_crypto crypto, 
+       unsigned usage,
+       krb5_data *cipher, 
+       krb5_data *clear)
+{
+    krb5_data decrypt;
+    krb5_error_code ret;
+
+    krb5_data_zero(&decrypt);
+
+    ret = krb5_decrypt(context,
+                      crypto,
+                      usage,
+                      cipher->data,
+                      cipher->length,
+                      &decrypt);
+
+    if (ret) {
+       krb5_warn(context, ret, "krb5_decrypt");
+       return ret;
+    }
+
+    if (decrypt.length != clear->length ||
+       memcmp(decrypt.data, clear->data, decrypt.length) != 0) {
+       krb5_warnx(context, "clear text not same");
+       return EINVAL;
+    }
+
+    krb5_data_free(&decrypt);
+
+    return 0;
+}
+
+static int
+krb_enc_mit(krb5_context context,
+           krb5_enctype enctype,
+           krb5_keyblock *key,
+           unsigned usage,
+           krb5_data *cipher, 
+           krb5_data *clear)
+{
+    krb5_error_code ret;
+    krb5_enc_data e;
+    krb5_data decrypt;
+    size_t len;
+
+    e.kvno = 0;
+    e.enctype = enctype;
+    e.ciphertext = *cipher;
+
+    ret = krb5_c_decrypt(context, *key, usage, NULL, &e, &decrypt);
+    if (ret)
+       return ret;
+
+    if (decrypt.length != clear->length ||
+       memcmp(decrypt.data, clear->data, decrypt.length) != 0) {
+       krb5_warnx(context, "clear text not same");
+       return EINVAL;
+    }
+
+    krb5_data_free(&decrypt);
+
+    ret = krb5_c_encrypt_length(context, enctype, clear->length, &len);
+    if (ret)
+       return ret;
+
+    if (len != cipher->length) {
+       krb5_warnx(context, "c_encrypt_length wrong %lu != %lu",
+                  (unsigned long)len, (unsigned long)cipher->length);
+       return EINVAL;
+    }
+
+    return 0;
+}
+
+
+struct {
+    krb5_enctype enctype;
+    unsigned usage;
+    size_t keylen;
+    void *key;
+    size_t elen;
+    void* edata;
+    size_t plen;
+    void *pdata;
+} krbencs[] =  {
+    { 
+       ETYPE_AES256_CTS_HMAC_SHA1_96,
+       7,
+       32,   
+       "\x47\x75\x69\x64\x65\x6c\x69\x6e\x65\x73\x20\x74\x6f\x20\x41\x75"
+       "\x74\x68\x6f\x72\x73\x20\x6f\x66\x20\x49\x6e\x74\x65\x72\x6e\x65",
+       44,
+       "\xcf\x79\x8f\x0d\x76\xf3\xe0\xbe\x8e\x66\x94\x70\xfa\xcc\x9e\x91"
+       "\xa9\xec\x1c\x5c\x21\xfb\x6e\xef\x1a\x7a\xc8\xc1\xcc\x5a\x95\x24"
+       "\x6f\x9f\xf4\xd5\xbe\x5d\x59\x97\x44\xd8\x47\xcd",
+       16,
+       "\x54\x68\x69\x73\x20\x69\x73\x20\x61\x20\x74\x65\x73\x74\x2e\x0a"
+    }
+};
+
+
+static int
+krb_enc_test(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    krb5_keyblock kb;
+    krb5_data cipher, plain;
+    int i, failed = 0;
+
+    for (i = 0; i < sizeof(krbencs)/sizeof(krbencs[0]); i++) {
+
+       ret = krb5_enctype_to_keytype(context, 
+                                     krbencs[i].enctype,
+                                     (krb5_keytype *)&kb.keytype);
+       if (ret)
+           return ret;
+
+       kb.keyvalue.length = krbencs[i].keylen;
+       kb.keyvalue.data = krbencs[i].key;
+
+       ret = krb5_crypto_init(context, &kb, krbencs[i].enctype, &crypto);
+
+       cipher.length = krbencs[i].elen;
+       cipher.data = krbencs[i].edata;
+       plain.length = krbencs[i].plen;
+       plain.data = krbencs[i].pdata;
+       
+       ret = krb_enc(context, crypto, krbencs[i].usage, &cipher, &plain);
+                      
+       if (ret) {
+           failed = 1;
+           printf("krb_enc failed with %d\n", ret);
+       }
+       krb5_crypto_destroy(context, crypto);
+
+       ret = krb_enc_mit(context, krbencs[i].enctype, &kb, 
+                         krbencs[i].usage, &cipher, &plain);
+       if (ret) {
+           failed = 1;
+           printf("krb_enc_mit failed with %d\n", ret);
+       }
+
+    }
+
+    return failed;
+}
+
+
+static int
+random_to_key(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_keyblock key;
+
+    ret = krb5_random_to_key(context,
+                            ETYPE_DES3_CBC_SHA1,
+                            "\x21\x39\x04\x58\x6A\xBD\x7F"
+                            "\x21\x39\x04\x58\x6A\xBD\x7F"
+                            "\x21\x39\x04\x58\x6A\xBD\x7F",
+                            21,
+                            &key);
+    if (ret){
+       krb5_warn(context, ret, "random_to_key");
+       return 1;
+    }
+    if (key.keyvalue.length != 24)
+       return 1;
+
+    if (memcmp(key.keyvalue.data,
+              "\x20\x38\x04\x58\x6b\xbc\x7f\xc7"
+              "\x20\x38\x04\x58\x6b\xbc\x7f\xc7"
+              "\x20\x38\x04\x58\x6b\xbc\x7f\xc7",
+              24) != 0)
+       return 1;
+
+    krb5_free_keyblock_contents(context, &key);
+
+    return 0;
+}
+
+
+int
+main(int argc, char **argv)
+{
+    krb5_error_code ret;
+    krb5_context context;
+    int val = 0;
+    
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    val |= string_to_key_test(context);
+
+    val |= encryption_test(context, aes_key1, 128,
+                          encs1, sizeof(encs1)/sizeof(encs1[0]));
+    val |= encryption_test(context, aes_key2, 256, 
+                          encs2, sizeof(encs2)/sizeof(encs2[0]));
+    val |= krb_enc_test(context);
+    val |= random_to_key(context);
+
+    if (verbose && val == 0)
+       printf("all ok\n");
+    if (val)
+       printf("tests failed\n");
+
+    krb5_free_context(context);
+
+    return val;
+}
diff --git a/src/kerberosV/src/lib/krb5/aname_to_localname.c b/src/kerberosV/src/lib/krb5/aname_to_localname.c
new file mode 100644 (file)
index 0000000..ac84327
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997 - 1999, 2002 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: aname_to_localname.c,v 1.8 2004/05/25 21:16:49 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_aname_to_localname (krb5_context context,
+                        krb5_const_principal aname,
+                        size_t lnsize,
+                        char *lname)
+{
+    krb5_error_code ret;
+    krb5_realm *lrealms, *r;
+    int valid;
+    size_t len;
+    const char *res;
+
+    ret = krb5_get_default_realms (context, &lrealms);
+    if (ret)
+       return ret;
+
+    valid = 0;
+    for (r = lrealms; *r != NULL; ++r) {
+       if (strcmp (*r, aname->realm) == 0) {
+           valid = 1;
+           break;
+       }
+    }
+    krb5_free_host_realm (context, lrealms);
+    if (valid == 0)
+       return KRB5_NO_LOCALNAME;
+
+    if (aname->name.name_string.len == 1)
+       res = aname->name.name_string.val[0];
+    else if (aname->name.name_string.len == 2
+            && strcmp (aname->name.name_string.val[1], "root") == 0) {
+       krb5_principal rootprinc;
+       krb5_boolean userok;
+
+       res = "root";
+
+       ret = krb5_copy_principal(context, aname, &rootprinc);
+       if (ret)
+           return ret;
+       
+       userok = krb5_kuserok(context, rootprinc, res);
+       krb5_free_principal(context, rootprinc);
+       if (!userok)
+           return KRB5_NO_LOCALNAME;
+
+    } else
+       return KRB5_NO_LOCALNAME;
+
+    len = strlen (res);
+    if (len >= lnsize)
+       return ERANGE;
+    strlcpy (lname, res, lnsize);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/appdefault.c b/src/kerberosV/src/lib/krb5/appdefault.c
new file mode 100644 (file)
index 0000000..f88853d
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2000 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: appdefault.c,v 1.10 2005/01/05 05:40:59 lukeh Exp $");
+
+extern char *__progname;
+
+void KRB5_LIB_FUNCTION
+krb5_appdefault_boolean(krb5_context context, const char *appname, 
+                       krb5_const_realm realm, const char *option,
+                       krb5_boolean def_val, krb5_boolean *ret_val)
+{
+    
+    if(appname == NULL)
+       appname = __progname;
+
+    def_val = krb5_config_get_bool_default(context, NULL, def_val, 
+                                          "libdefaults", option, NULL);
+    if(realm != NULL)
+       def_val = krb5_config_get_bool_default(context, NULL, def_val, 
+                                              "realms", realm, option, NULL);
+       
+    def_val = krb5_config_get_bool_default(context, NULL, def_val, 
+                                          "appdefaults", 
+                                          option, 
+                                          NULL);
+    if(realm != NULL)
+       def_val = krb5_config_get_bool_default(context, NULL, def_val,
+                                              "appdefaults", 
+                                              realm, 
+                                              option, 
+                                              NULL);
+    if(appname != NULL) {
+       def_val = krb5_config_get_bool_default(context, NULL, def_val, 
+                                              "appdefaults", 
+                                              appname, 
+                                              option, 
+                                              NULL);
+       if(realm != NULL)
+           def_val = krb5_config_get_bool_default(context, NULL, def_val,
+                                                  "appdefaults", 
+                                                  appname, 
+                                                  realm, 
+                                                  option, 
+                                                  NULL);
+    }
+    *ret_val = def_val;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_appdefault_string(krb5_context context, const char *appname, 
+                      krb5_const_realm realm, const char *option,
+                      const char *def_val, char **ret_val)
+{
+    if(appname == NULL)
+       appname = __progname;
+
+    def_val = krb5_config_get_string_default(context, NULL, def_val, 
+                                            "libdefaults", option, NULL);
+    if(realm != NULL)
+       def_val = krb5_config_get_string_default(context, NULL, def_val, 
+                                                "realms", realm, option, NULL);
+
+    def_val = krb5_config_get_string_default(context, NULL, def_val, 
+                                            "appdefaults", 
+                                            option, 
+                                            NULL);
+    if(realm != NULL)
+       def_val = krb5_config_get_string_default(context, NULL, def_val,
+                                                "appdefaults", 
+                                                realm, 
+                                                option, 
+                                                NULL);
+    if(appname != NULL) {
+       def_val = krb5_config_get_string_default(context, NULL, def_val, 
+                                                "appdefaults", 
+                                                appname, 
+                                                option, 
+                                                NULL);
+       if(realm != NULL)
+           def_val = krb5_config_get_string_default(context, NULL, def_val,
+                                                    "appdefaults", 
+                                                    appname, 
+                                                    realm, 
+                                                    option, 
+                                                    NULL);
+    }
+    if(def_val != NULL)
+       *ret_val = strdup(def_val);
+    else
+       *ret_val = NULL;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_appdefault_time(krb5_context context, const char *appname,
+                    krb5_const_realm realm, const char *option,
+                    time_t def_val, time_t *ret_val)
+{
+    krb5_deltat t;
+    char *val;
+
+    krb5_appdefault_string(context, appname, realm, option, NULL, &val);
+    if (val == NULL) {
+       *ret_val = def_val;
+       return;
+    }
+    if (krb5_string_to_deltat(val, &t))
+       *ret_val = def_val;
+    else
+       *ret_val = t;
+    free(val);
+}
diff --git a/src/kerberosV/src/lib/krb5/asn1_glue.c b/src/kerberosV/src/lib/krb5/asn1_glue.c
new file mode 100644 (file)
index 0000000..ab193bb
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: asn1_glue.c,v 1.9 2004/12/29 18:54:15 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_principal2principalname (PrincipalName *p,
+                              const krb5_principal from)
+{
+    return copy_PrincipalName(&from->name, p);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_principalname2krb5_principal (krb5_principal *principal,
+                                   const PrincipalName from,
+                                   const Realm realm)
+{
+    krb5_principal p = malloc(sizeof(*p));
+    copy_PrincipalName(&from, &p->name);
+    p->realm = strdup(realm);
+    *principal = p;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/auth_context.c b/src/kerberosV/src/lib/krb5/auth_context.c
new file mode 100644 (file)
index 0000000..d25f537
--- /dev/null
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: auth_context.c,v 1.62 2005/01/05 02:34:08 lukeh Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_init(krb5_context context,
+                  krb5_auth_context *auth_context)
+{
+    krb5_auth_context p;
+
+    ALLOC(p, 1);
+    if(!p) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memset(p, 0, sizeof(*p));
+    ALLOC(p->authenticator, 1);
+    if (!p->authenticator) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free(p);
+       return ENOMEM;
+    }
+    memset (p->authenticator, 0, sizeof(*p->authenticator));
+    p->flags = KRB5_AUTH_CONTEXT_DO_TIME;
+
+    p->local_address  = NULL;
+    p->remote_address = NULL;
+    p->local_port     = 0;
+    p->remote_port    = 0;
+    p->keytype        = KEYTYPE_NULL;
+    p->cksumtype      = CKSUMTYPE_NONE;
+    *auth_context     = p;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_free(krb5_context context,
+                  krb5_auth_context auth_context)
+{
+    if (auth_context != NULL) {
+       krb5_free_authenticator(context, &auth_context->authenticator);
+       if(auth_context->local_address){
+           free_HostAddress(auth_context->local_address);
+           free(auth_context->local_address);
+       }
+       if(auth_context->remote_address){
+           free_HostAddress(auth_context->remote_address);
+           free(auth_context->remote_address);
+       }
+       krb5_free_keyblock(context, auth_context->keyblock);
+       krb5_free_keyblock(context, auth_context->remote_subkey);
+       krb5_free_keyblock(context, auth_context->local_subkey);
+       free (auth_context);
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setflags(krb5_context context,
+                      krb5_auth_context auth_context,
+                      int32_t flags)
+{
+    auth_context->flags = flags;
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getflags(krb5_context context,
+                      krb5_auth_context auth_context,
+                      int32_t *flags)
+{
+    *flags = auth_context->flags;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_addflags(krb5_context context,
+                      krb5_auth_context auth_context,
+                      int32_t addflags,
+                      int32_t *flags)
+{
+    if (flags)
+       *flags = auth_context->flags;
+    auth_context->flags |= addflags;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_removeflags(krb5_context context,
+                         krb5_auth_context auth_context,
+                         int32_t removeflags,
+                         int32_t *flags)
+{
+    if (flags)
+       *flags = auth_context->flags;
+    auth_context->flags &= ~removeflags;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setaddrs(krb5_context context,
+                      krb5_auth_context auth_context,
+                      krb5_address *local_addr,
+                      krb5_address *remote_addr)
+{
+    if (local_addr) {
+       if (auth_context->local_address)
+           krb5_free_address (context, auth_context->local_address);
+       else
+           auth_context->local_address = malloc(sizeof(krb5_address));
+       krb5_copy_address(context, local_addr, auth_context->local_address);
+    }
+    if (remote_addr) {
+       if (auth_context->remote_address)
+           krb5_free_address (context, auth_context->remote_address);
+       else
+           auth_context->remote_address = malloc(sizeof(krb5_address));
+       krb5_copy_address(context, remote_addr, auth_context->remote_address);
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_genaddrs(krb5_context context, 
+                      krb5_auth_context auth_context, 
+                      int fd, int flags)
+{
+    krb5_error_code ret;
+    krb5_address local_k_address, remote_k_address;
+    krb5_address *lptr = NULL, *rptr = NULL;
+    struct sockaddr_storage ss_local, ss_remote;
+    struct sockaddr *local  = (struct sockaddr *)&ss_local;
+    struct sockaddr *remote = (struct sockaddr *)&ss_remote;
+    socklen_t len;
+
+    if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) {
+       if (auth_context->local_address == NULL) {
+           len = sizeof(ss_local);
+           if(getsockname(fd, local, &len) < 0) {
+               ret = errno;
+               krb5_set_error_string (context, "getsockname: %s",
+                                      strerror(ret));
+               goto out;
+           }
+           ret = krb5_sockaddr2address (context, local, &local_k_address);
+           if(ret) goto out;
+           if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) {
+               krb5_sockaddr2port (context, local, &auth_context->local_port);
+           } else
+               auth_context->local_port = 0;
+           lptr = &local_k_address;
+       }
+    }
+    if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) {
+       len = sizeof(ss_remote);
+       if(getpeername(fd, remote, &len) < 0) {
+           ret = errno;
+           krb5_set_error_string (context, "getpeername: %s", strerror(ret));
+           goto out;
+       }
+       ret = krb5_sockaddr2address (context, remote, &remote_k_address);
+       if(ret) goto out;
+       if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) {
+           krb5_sockaddr2port (context, remote, &auth_context->remote_port);
+       } else
+           auth_context->remote_port = 0;
+       rptr = &remote_k_address;
+    }
+    ret = krb5_auth_con_setaddrs (context,
+                                 auth_context,
+                                 lptr,
+                                 rptr);
+  out:
+    if (lptr)
+       krb5_free_address (context, lptr);
+    if (rptr)
+       krb5_free_address (context, rptr);
+    return ret;
+
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setaddrs_from_fd (krb5_context context,
+                               krb5_auth_context auth_context,
+                               void *p_fd)
+{
+    int fd = *(int*)p_fd;
+    int flags = 0;
+    if(auth_context->local_address == NULL)
+       flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR;
+    if(auth_context->remote_address == NULL)
+       flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR;
+    return krb5_auth_con_genaddrs(context, auth_context, fd, flags);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getaddrs(krb5_context context,
+                      krb5_auth_context auth_context,
+                      krb5_address **local_addr,
+                      krb5_address **remote_addr)
+{
+    if(*local_addr)
+       krb5_free_address (context, *local_addr);
+    *local_addr = malloc (sizeof(**local_addr));
+    if (*local_addr == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    krb5_copy_address(context,
+                     auth_context->local_address,
+                     *local_addr);
+
+    if(*remote_addr)
+       krb5_free_address (context, *remote_addr);
+    *remote_addr = malloc (sizeof(**remote_addr));
+    if (*remote_addr == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       krb5_free_address (context, *local_addr);
+       *local_addr = NULL;
+       return ENOMEM;
+    }
+    krb5_copy_address(context,
+                     auth_context->remote_address,
+                     *remote_addr);
+    return 0;
+}
+
+static krb5_error_code
+copy_key(krb5_context context,
+        krb5_keyblock *in,
+        krb5_keyblock **out)
+{
+    if(in)
+       return krb5_copy_keyblock(context, in, out);
+    *out = NULL; /* is this right? */
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getkey(krb5_context context,
+                    krb5_auth_context auth_context,
+                    krb5_keyblock **keyblock)
+{
+    return copy_key(context, auth_context->keyblock, keyblock);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getlocalsubkey(krb5_context context,
+                            krb5_auth_context auth_context,
+                            krb5_keyblock **keyblock)
+{
+    return copy_key(context, auth_context->local_subkey, keyblock);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getremotesubkey(krb5_context context,
+                             krb5_auth_context auth_context,
+                             krb5_keyblock **keyblock)
+{
+    return copy_key(context, auth_context->remote_subkey, keyblock);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setkey(krb5_context context,
+                    krb5_auth_context auth_context,
+                    krb5_keyblock *keyblock)
+{
+    if(auth_context->keyblock)
+       krb5_free_keyblock(context, auth_context->keyblock);
+    return copy_key(context, keyblock, &auth_context->keyblock);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setlocalsubkey(krb5_context context,
+                            krb5_auth_context auth_context,
+                            krb5_keyblock *keyblock)
+{
+    if(auth_context->local_subkey)
+       krb5_free_keyblock(context, auth_context->local_subkey);
+    return copy_key(context, keyblock, &auth_context->local_subkey);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_generatelocalsubkey(krb5_context context,
+                                 krb5_auth_context auth_context,
+                                 krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    krb5_keyblock *subkey;
+
+    ret = krb5_generate_subkey_extended (context, key,
+                                        auth_context->keytype,
+                                        &subkey);
+    if(ret)
+       return ret;
+    if(auth_context->local_subkey)
+       krb5_free_keyblock(context, auth_context->local_subkey);
+    auth_context->local_subkey = subkey;
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setremotesubkey(krb5_context context,
+                             krb5_auth_context auth_context,
+                             krb5_keyblock *keyblock)
+{
+    if(auth_context->remote_subkey)
+       krb5_free_keyblock(context, auth_context->remote_subkey);
+    return copy_key(context, keyblock, &auth_context->remote_subkey);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setcksumtype(krb5_context context,
+                          krb5_auth_context auth_context,
+                          krb5_cksumtype cksumtype)
+{
+    auth_context->cksumtype = cksumtype;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getcksumtype(krb5_context context,
+                          krb5_auth_context auth_context,
+                          krb5_cksumtype *cksumtype)
+{
+    *cksumtype = auth_context->cksumtype;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setkeytype (krb5_context context,
+                         krb5_auth_context auth_context,
+                         krb5_keytype keytype)
+{
+    auth_context->keytype = keytype;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getkeytype (krb5_context context,
+                         krb5_auth_context auth_context,
+                         krb5_keytype *keytype)
+{
+    *keytype = auth_context->keytype;
+    return 0;
+}
+
+#if 0
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setenctype(krb5_context context,
+                        krb5_auth_context auth_context,
+                        krb5_enctype etype)
+{
+    if(auth_context->keyblock)
+       krb5_free_keyblock(context, auth_context->keyblock);
+    ALLOC(auth_context->keyblock, 1);
+    if(auth_context->keyblock == NULL)
+       return ENOMEM;
+    auth_context->keyblock->keytype = etype;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getenctype(krb5_context context,
+                        krb5_auth_context auth_context,
+                        krb5_enctype *etype)
+{
+    krb5_abortx(context, "unimplemented krb5_auth_getenctype called");
+}
+#endif
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getlocalseqnumber(krb5_context context,
+                           krb5_auth_context auth_context,
+                           int32_t *seqnumber)
+{
+  *seqnumber = auth_context->local_seqnumber;
+  return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setlocalseqnumber (krb5_context context,
+                            krb5_auth_context auth_context,
+                            int32_t seqnumber)
+{
+  auth_context->local_seqnumber = seqnumber;
+  return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_getremoteseqnumber(krb5_context context,
+                            krb5_auth_context auth_context,
+                            int32_t *seqnumber)
+{
+  *seqnumber = auth_context->remote_seqnumber;
+  return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setremoteseqnumber (krb5_context context,
+                             krb5_auth_context auth_context,
+                             int32_t seqnumber)
+{
+  auth_context->remote_seqnumber = seqnumber;
+  return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getauthenticator(krb5_context context,
+                          krb5_auth_context auth_context,
+                          krb5_authenticator *authenticator)
+{
+    *authenticator = malloc(sizeof(**authenticator));
+    if (*authenticator == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    copy_Authenticator(auth_context->authenticator,
+                      *authenticator);
+    return 0;
+}
+
+
+void KRB5_LIB_FUNCTION
+krb5_free_authenticator(krb5_context context,
+                       krb5_authenticator *authenticator)
+{
+    free_Authenticator (*authenticator);
+    free (*authenticator);
+    *authenticator = NULL;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setuserkey(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_LIB_FUNCTION
+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_LIB_FUNCTION
+krb5_auth_con_setrcache(krb5_context context,
+                       krb5_auth_context auth_context,
+                       krb5_rcache rcache)
+{
+    auth_context->rcache = rcache;
+    return 0;
+}
+
+#if 0 /* not implemented */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_initivector(krb5_context context,
+                         krb5_auth_context auth_context)
+{
+    krb5_abortx(context, "unimplemented krb5_auth_con_initivector called");
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setivector(krb5_context context,
+                        krb5_auth_context auth_context,
+                        krb5_pointer ivector)
+{
+    krb5_abortx(context, "unimplemented krb5_auth_con_setivector called");
+}
+
+#endif /* not implemented */
diff --git a/src/kerberosV/src/lib/krb5/build_ap_req.c b/src/kerberosV/src/lib/krb5/build_ap_req.c
new file mode 100644 (file)
index 0000000..1cb90d7
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: build_ap_req.c,v 1.20 2004/05/25 21:18:17 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_ap_req (krb5_context context,
+                  krb5_enctype enctype,
+                  krb5_creds *cred,
+                  krb5_flags ap_options,
+                  krb5_data authenticator,
+                  krb5_data *retdata)
+{
+  krb5_error_code ret = 0;
+  AP_REQ ap;
+  Ticket t;
+  size_t len;
+  
+  ap.pvno = 5;
+  ap.msg_type = krb_ap_req;
+  memset(&ap.ap_options, 0, sizeof(ap.ap_options));
+  ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0;
+  ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0;
+  
+  ap.ticket.tkt_vno = 5;
+  copy_Realm(&cred->server->realm, &ap.ticket.realm);
+  copy_PrincipalName(&cred->server->name, &ap.ticket.sname);
+
+  decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
+  copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part);
+  free_Ticket(&t);
+
+  ap.authenticator.etype = enctype;
+  ap.authenticator.kvno  = NULL;
+  ap.authenticator.cipher = authenticator;
+
+  ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length,
+                    &ap, &len, ret);
+  if(ret == 0 && retdata->length != len)
+      krb5_abortx(context, "internal error in ASN.1 encoder");
+  free_AP_REQ(&ap);
+  return ret;
+
+}
diff --git a/src/kerberosV/src/lib/krb5/build_auth.c b/src/kerberosV/src/lib/krb5/build_auth.c
new file mode 100644 (file)
index 0000000..a5571c0
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: build_auth.c,v 1.42 2005/01/05 02:34:53 lukeh Exp $");
+
+static krb5_error_code
+make_etypelist(krb5_context context,
+              krb5_authdata **auth_data)
+{
+    EtypeList etypes;
+    krb5_error_code ret;
+    krb5_authdata ad;
+    u_char *buf;
+    size_t len;
+    size_t buf_size;
+     
+    ret = krb5_init_etype(context, &etypes.len, &etypes.val, NULL);
+    if (ret)
+       return ret;
+
+    ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret);
+    if (ret) {
+       free_EtypeList(&etypes);
+       return ret;
+    }
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    free_EtypeList(&etypes);
+
+    ALLOC_SEQ(&ad, 1);
+    if (ad.val == NULL) {
+       free(buf);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION;
+    ad.val[0].ad_data.length = len;
+    ad.val[0].ad_data.data = buf;
+
+    ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret);
+    if (ret) {
+       free_AuthorizationData(&ad);
+       return ret;
+    } 
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    free_AuthorizationData(&ad);
+
+    ALLOC(*auth_data, 1);
+    if (*auth_data == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ALLOC_SEQ(*auth_data, 1);
+    if ((*auth_data)->val == NULL) {
+       free(buf);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+    (*auth_data)->val[0].ad_data.length = len;
+    (*auth_data)->val[0].ad_data.data = buf;
+
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_authenticator (krb5_context context,
+                         krb5_auth_context auth_context,
+                         krb5_enctype enctype,
+                         krb5_creds *cred,
+                         Checksum *cksum,
+                         Authenticator **auth_result,
+                         krb5_data *result,
+                         krb5_key_usage usage)
+{
+    Authenticator *auth;
+    u_char *buf = NULL;
+    size_t buf_size;
+    size_t len;
+    krb5_error_code ret;
+    krb5_crypto crypto;
+
+    auth = calloc(1, sizeof(*auth));
+    if (auth == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    auth->authenticator_vno = 5;
+    copy_Realm(&cred->client->realm, &auth->crealm);
+    copy_PrincipalName(&cred->client->name, &auth->cname);
+
+    krb5_us_timeofday (context, &auth->ctime, &auth->cusec);
+    
+    ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey);
+    if(ret)
+       goto fail;
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+       if(auth_context->local_seqnumber == 0)
+           krb5_generate_seq_number (context,
+                                     &cred->session, 
+                                     &auth_context->local_seqnumber);
+       ALLOC(auth->seq_number, 1);
+       if(auth->seq_number == NULL) {
+           ret = ENOMEM;
+           goto fail;
+       }
+       *auth->seq_number = auth_context->local_seqnumber;
+    } else
+       auth->seq_number = NULL;
+    auth->authorization_data = NULL;
+    auth->cksum = cksum;
+
+    if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) {
+       /*
+        * This is not GSS-API specific, we only enable it for
+        * GSS for now
+        */
+       ret = make_etypelist(context, &auth->authorization_data);
+       if (ret)
+           goto fail;
+    }
+
+    /* XXX - Copy more to auth_context? */
+
+    auth_context->authenticator->ctime = auth->ctime;
+    auth_context->authenticator->cusec = auth->cusec;
+
+    ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret);
+    if (ret)
+       goto fail;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_crypto_init(context, &cred->session, enctype, &crypto);
+    if (ret)
+       goto fail;
+    ret = krb5_encrypt (context,
+                       crypto,
+                       usage /* KRB5_KU_AP_REQ_AUTH */,
+                       buf + buf_size - len, 
+                       len,
+                       result);
+    krb5_crypto_destroy(context, crypto);
+
+    if (ret)
+       goto fail;
+
+    free (buf);
+
+    if (auth_result)
+       *auth_result = auth;
+    else {
+       /* Don't free the `cksum', it's allocated by the caller */
+       auth->cksum = NULL;
+       free_Authenticator (auth);
+       free (auth);
+    }
+    return ret;
+  fail:
+    free_Authenticator (auth);
+    free (auth);
+    free (buf);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/cache.c b/src/kerberosV/src/lib/krb5/cache.c
new file mode 100644 (file)
index 0000000..8c056e9
--- /dev/null
@@ -0,0 +1,658 @@
+/*
+ * Copyright (c) 1997-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: cache.c,v 1.69.2.1 2005/06/15 11:24:47 lha Exp $");
+
+/*
+ * Add a new ccache type with operations `ops', overwriting any
+ * existing one if `override'.
+ * Return an error code or 0.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_register(krb5_context context, 
+                const krb5_cc_ops *ops, 
+                krb5_boolean override)
+{
+    int i;
+
+    for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
+       if(strcmp(context->cc_ops[i].prefix, ops->prefix) == 0) {
+           if(!override) {
+               krb5_set_error_string(context,
+                                     "ccache type %s already exists",
+                                     ops->prefix);
+               return KRB5_CC_TYPE_EXISTS;
+           }
+           break;
+       }
+    }
+    if(i == context->num_cc_ops) {
+       krb5_cc_ops *o = realloc(context->cc_ops,
+                                (context->num_cc_ops + 1) *
+                                sizeof(*context->cc_ops));
+       if(o == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return KRB5_CC_NOMEM;
+       }
+       context->num_cc_ops++;
+       context->cc_ops = o;
+       memset(context->cc_ops + i, 0, 
+              (context->num_cc_ops - i) * sizeof(*context->cc_ops));
+    }
+    memcpy(&context->cc_ops[i], ops, sizeof(context->cc_ops[i]));
+    return 0;
+}
+
+/*
+ * Allocate memory for a new ccache in `id' with operations `ops'
+ * and name `residual'.
+ * Return 0 or an error code.
+ */
+
+static krb5_error_code
+allocate_ccache (krb5_context context,
+                const krb5_cc_ops *ops,
+                const char *residual,
+                krb5_ccache *id)
+{
+    krb5_error_code ret;
+    krb5_ccache p;
+
+    p = malloc(sizeof(*p));
+    if(p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    p->ops = ops;
+    *id = p;
+    ret = p->ops->resolve(context, id, residual);
+    if(ret)
+       free(p);
+    return ret;
+}
+
+/*
+ * Find and allocate a ccache in `id' from the specification in `residual'.
+ * If the ccache name doesn't contain any colon, interpret it as a file name.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_resolve(krb5_context context,
+               const char *name,
+               krb5_ccache *id)
+{
+    int i;
+
+    for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
+       size_t prefix_len = strlen(context->cc_ops[i].prefix);
+
+       if(strncmp(context->cc_ops[i].prefix, name, prefix_len) == 0
+          && name[prefix_len] == ':') {
+           return allocate_ccache (context, &context->cc_ops[i],
+                                   name + prefix_len + 1,
+                                   id);
+       }
+    }
+    if (strchr (name, ':') == NULL)
+       return allocate_ccache (context, &krb5_fcc_ops, name, id);
+    else {
+       krb5_set_error_string(context, "unknown ccache type %s", name);
+       return KRB5_CC_UNKNOWN_TYPE;
+    }
+}
+
+/*
+ * Generate a new ccache of type `ops' in `id'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_gen_new(krb5_context context,
+               const krb5_cc_ops *ops,
+               krb5_ccache *id)
+{
+    krb5_ccache p;
+
+    p = malloc (sizeof(*p));
+    if (p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    p->ops = ops;
+    *id = p;
+    return p->ops->gen_new(context, id);
+}
+
+/*
+ * Generates a new unique ccache of `type` in `id'. If `type' is NULL,
+ * the library chooses the default credential cache type. The supplied
+ * `hint' (that can be NULL) is a string that the credential cache
+ * type can use to base the name of the credential on, this is to make
+ * its easier for the user to differentiate the credentials.
+ *
+ *  Returns 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_new_unique(krb5_context context, const char *type, 
+                  const char *hint, krb5_ccache *id)
+{
+    const krb5_cc_ops *ops;
+
+    if (type == NULL)
+       type = "FILE";
+
+    ops = krb5_cc_get_prefix_ops(context, type);
+    if (ops == NULL) {
+       krb5_set_error_string(context, "Credential cache type %s is unknown",
+                             type);
+       return KRB5_CC_UNKNOWN_TYPE;
+    }
+
+    return krb5_cc_gen_new(context, ops, id);
+}
+
+/*
+ * Return the name of the ccache `id'
+ */
+
+const char* KRB5_LIB_FUNCTION
+krb5_cc_get_name(krb5_context context,
+                krb5_ccache id)
+{
+    return id->ops->get_name(context, id);
+}
+
+/*
+ * Return the type of the ccache `id'.
+ */
+
+const char* KRB5_LIB_FUNCTION
+krb5_cc_get_type(krb5_context context,
+                krb5_ccache id)
+{
+    return id->ops->prefix;
+}
+
+/*
+ * Return krb5_cc_ops of a the ccache `id'.
+ */
+
+const krb5_cc_ops *
+krb5_cc_get_ops(krb5_context context, krb5_ccache id)
+{
+    return id->ops;
+}
+
+/*
+ * Expand variables in `str' into `res'
+ */
+
+krb5_error_code
+_krb5_expand_default_cc_name(krb5_context context, const char *str, char **res)
+{
+    size_t tlen, len = 0;
+    char *tmp, *tmp2, *append;
+
+    *res = NULL;
+
+    while (str && *str) {
+       tmp = strstr(str, "%{");
+       if (tmp && tmp != str) {
+           append = malloc((tmp - str) + 1);
+           if (append) {
+               memcpy(append, str, tmp - str);
+               append[tmp - str] = '\0';
+           }
+           str = tmp;
+       } else if (tmp) {
+           tmp2 = strchr(tmp, '}');
+           if (tmp2 == NULL) {
+               free(*res);
+               *res = NULL;
+               krb5_set_error_string(context, "variable missing }");
+               return KRB5_CONFIG_BADFORMAT;
+           }
+           if (strncasecmp(tmp, "%{uid}", 6) == 0)
+               asprintf(&append, "%u", (unsigned)getuid());
+           else if (strncasecmp(tmp, "%{null}", 7) == 0)
+               append = strdup("");
+           else {
+               free(*res);
+               *res = NULL;
+               krb5_set_error_string(context, 
+                                     "expand default cache unknown "
+                                     "variable \"%.*s\"",
+                                     (int)(tmp2 - tmp) - 2, tmp + 2);
+               return KRB5_CONFIG_BADFORMAT;
+           }
+           if (append == NULL) {
+               free(*res);
+               res = NULL;
+               krb5_set_error_string(context, "malloc - out of memory");
+               return ENOMEM;
+           }
+           str = tmp2 + 1;
+       } else {
+           append = (char *)str;
+           str = NULL;
+       }
+
+       tlen = strlen(append);
+       tmp = realloc(*res, len + tlen + 1);
+       if (tmp == NULL) {
+           free(*res);
+           *res = NULL;
+           krb5_set_error_string(context, "malloc - out of memory");
+           return ENOMEM;
+       }
+       *res = tmp;
+       memcpy(*res + len, append, tlen + 1);
+       len = len + tlen;
+       if (str)
+           free(append);
+    }    
+    return 0;
+}
+
+/*
+ * Set the default cc name for `context' to `name'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_set_default_name(krb5_context context, const char *name)
+{
+    krb5_error_code ret = 0;
+    char *p;
+
+    if (name == NULL) {
+       const char *e = NULL;
+
+       if(!issuid()) {
+           e = getenv("KRB5CCNAME");
+           if (e)
+               p = strdup(e);
+       }
+       if (e == NULL) {
+           e = krb5_config_get_string(context, NULL, "libdefaults",
+                                      "default_cc_name", NULL);
+           if (e) {
+               ret = _krb5_expand_default_cc_name(context, e, &p);
+               if (ret)
+                   return ret;
+           }
+       }
+       if (e == NULL)
+           asprintf(&p,"FILE:/tmp/krb5cc_%u", (unsigned)getuid());
+    } else
+       p = strdup(name);
+
+    if (p == NULL) {
+       krb5_set_error_string(context, "malloc - out of memory");
+       return ENOMEM;
+    }
+
+    if (context->default_cc_name)
+       free(context->default_cc_name);
+
+    context->default_cc_name = p;
+
+    return ret;
+}
+
+/*
+ * Return a pointer to a context static string containing the default
+ * ccache name.
+ */
+
+const char* KRB5_LIB_FUNCTION
+krb5_cc_default_name(krb5_context context)
+{
+    if (context->default_cc_name == NULL)
+       krb5_cc_set_default_name(context, NULL);
+
+    return context->default_cc_name;
+}
+
+/*
+ * Open the default ccache in `id'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_default(krb5_context context,
+               krb5_ccache *id)
+{
+    const char *p = krb5_cc_default_name(context);
+
+    if (p == NULL) {
+       krb5_set_error_string(context, "malloc - out of memory");
+       return ENOMEM;
+    }
+    return krb5_cc_resolve(context, p, id);
+}
+
+/*
+ * Create a new ccache in `id' for `primary_principal'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_initialize(krb5_context context,
+                  krb5_ccache id,
+                  krb5_principal primary_principal)
+{
+    return id->ops->init(context, id, primary_principal);
+}
+
+
+/*
+ * Remove the ccache `id'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_destroy(krb5_context context,
+               krb5_ccache id)
+{
+    krb5_error_code ret;
+
+    ret = id->ops->destroy(context, id);
+    krb5_cc_close (context, id);
+    return ret;
+}
+
+/*
+ * Stop using the ccache `id' and free the related resources.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_close(krb5_context context,
+             krb5_ccache id)
+{
+    krb5_error_code ret;
+    ret = id->ops->close(context, id);
+    free(id);
+    return ret;
+}
+
+/*
+ * Store `creds' in the ccache `id'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_store_cred(krb5_context context,
+                  krb5_ccache id,
+                  krb5_creds *creds)
+{
+    return id->ops->store(context, id, creds);
+}
+
+/*
+ * Retrieve the credential identified by `mcreds' (and `whichfields')
+ * from `id' in `creds'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_retrieve_cred(krb5_context context,
+                     krb5_ccache id,
+                     krb5_flags whichfields,
+                     const krb5_creds *mcreds,
+                     krb5_creds *creds)
+{
+    krb5_error_code ret;
+    krb5_cc_cursor cursor;
+
+    if (id->ops->retrieve != NULL) {
+       return id->ops->retrieve(context, id, whichfields,
+                                mcreds, creds);
+    }
+
+    krb5_cc_start_seq_get(context, id, &cursor);
+    while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){
+       if(krb5_compare_creds(context, whichfields, mcreds, creds)){
+           ret = 0;
+           break;
+       }
+       krb5_free_cred_contents (context, creds);
+    }
+    krb5_cc_end_seq_get(context, id, &cursor);
+    return ret;
+}
+
+/*
+ * Return the principal of `id' in `principal'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_principal(krb5_context context,
+                     krb5_ccache id,
+                     krb5_principal *principal)
+{
+    return id->ops->get_princ(context, id, principal);
+}
+
+/*
+ * Start iterating over `id', `cursor' is initialized to the
+ * beginning.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_start_seq_get (krb5_context context,
+                      const krb5_ccache id,
+                      krb5_cc_cursor *cursor)
+{
+    return id->ops->get_first(context, id, cursor);
+}
+
+/*
+ * Retrieve the next cred pointed to by (`id', `cursor') in `creds'
+ * and advance `cursor'.
+ * Return 0 or an error code.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_next_cred (krb5_context context,
+                  const krb5_ccache id,
+                  krb5_cc_cursor *cursor,
+                  krb5_creds *creds)
+{
+    return id->ops->get_next(context, id, cursor, creds);
+}
+
+/* like krb5_cc_next_cred, but allow for selective retrieval */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_next_cred_match(krb5_context context,
+                       const krb5_ccache id,
+                       krb5_cc_cursor * cursor,
+                       krb5_creds * creds,
+                       krb5_flags whichfields,
+                       const krb5_creds * mcreds)
+{
+    krb5_error_code ret;
+    while (1) {
+       ret = krb5_cc_next_cred(context, id, cursor, creds);
+       if (ret)
+           return ret;
+       if (mcreds == NULL || krb5_compare_creds(context, whichfields, mcreds, creds))
+           return 0;
+       krb5_free_cred_contents(context, creds);
+    }
+}
+
+/*
+ * Destroy the cursor `cursor'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_end_seq_get (krb5_context context,
+                    const krb5_ccache id,
+                    krb5_cc_cursor *cursor)
+{
+    return id->ops->end_get(context, id, cursor);
+}
+
+/*
+ * Remove the credential identified by `cred', `which' from `id'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_remove_cred(krb5_context context,
+                   krb5_ccache id,
+                   krb5_flags which,
+                   krb5_creds *cred)
+{
+    if(id->ops->remove_cred == NULL) {
+       krb5_set_error_string(context,
+                             "ccache %s does not support remove_cred",
+                             id->ops->prefix);
+       return EACCES; /* XXX */
+    }
+    return (*id->ops->remove_cred)(context, id, which, cred);
+}
+
+/*
+ * Set the flags of `id' to `flags'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_set_flags(krb5_context context,
+                 krb5_ccache id,
+                 krb5_flags flags)
+{
+    return id->ops->set_flags(context, id, flags);
+}
+                   
+/*
+ * Copy the contents of `from' to `to'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_copy_cache_match(krb5_context context,
+                        const krb5_ccache from,
+                        krb5_ccache to,
+                        krb5_flags whichfields,
+                        const krb5_creds * mcreds,
+                        unsigned int *matched)
+{
+    krb5_error_code ret;
+    krb5_cc_cursor cursor;
+    krb5_creds cred;
+    krb5_principal princ;
+
+    ret = krb5_cc_get_principal(context, from, &princ);
+    if (ret)
+       return ret;
+    ret = krb5_cc_initialize(context, to, princ);
+    if (ret) {
+       krb5_free_principal(context, princ);
+       return ret;
+    }
+    ret = krb5_cc_start_seq_get(context, from, &cursor);
+    if (ret) {
+       krb5_free_principal(context, princ);
+       return ret;
+    }
+    if (matched)
+       *matched = 0;
+    while (ret == 0 &&
+          krb5_cc_next_cred_match(context, from, &cursor, &cred,
+                                  whichfields, mcreds) == 0) {
+       if (matched)
+           (*matched)++;
+       ret = krb5_cc_store_cred(context, to, &cred);
+       krb5_free_cred_contents(context, &cred);
+    }
+    krb5_cc_end_seq_get(context, from, &cursor);
+    krb5_free_principal(context, princ);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_copy_cache(krb5_context context,
+                  const krb5_ccache from,
+                  krb5_ccache to)
+{
+    return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL);
+}
+
+/*
+ * Return the version of `id'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_version(krb5_context context,
+                   const krb5_ccache id)
+{
+    if(id->ops->get_version)
+       return id->ops->get_version(context, id);
+    else
+       return 0;
+}
+
+/*
+ * Clear `mcreds' so it can be used with krb5_cc_retrieve_cred
+ */
+
+void KRB5_LIB_FUNCTION
+krb5_cc_clear_mcred(krb5_creds *mcred)
+{
+    memset(mcred, 0, sizeof(*mcred));
+}
+
+/*
+ * Get the cc ops that is registered in `context' to handle the
+ * `prefix'. Returns NULL if ops not found.
+ */
+
+const krb5_cc_ops *
+krb5_cc_get_prefix_ops(krb5_context context, const char *prefix)
+{
+    int i;
+
+    for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) {
+       if(strcmp(context->cc_ops[i].prefix, prefix) == 0)
+           return &context->cc_ops[i];
+    }
+    return NULL;
+}
diff --git a/src/kerberosV/src/lib/krb5/changepw.c b/src/kerberosV/src/lib/krb5/changepw.c
new file mode 100644 (file)
index 0000000..c80bbb0
--- /dev/null
@@ -0,0 +1,816 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: changepw.c,v 1.53 2005/05/25 05:30:42 lha Exp $");
+
+static void
+str2data (krb5_data *d,
+         const char *fmt,
+         ...) __attribute__ ((format (printf, 2, 3)));
+
+static void
+str2data (krb5_data *d,
+         const char *fmt,
+         ...)
+{
+    va_list args;
+
+    va_start(args, fmt);
+    d->length = vasprintf ((char **)&d->data, fmt, args);
+    va_end(args);
+}
+
+/*
+ * Change password protocol defined by
+ * draft-ietf-cat-kerb-chg-password-02.txt
+ * 
+ * Share the response part of the protocol with MS set password
+ * (RFC3244)
+ */
+
+static krb5_error_code
+chgpw_send_request (krb5_context context,
+                   krb5_auth_context *auth_context,
+                   krb5_creds *creds,
+                   krb5_principal targprinc,
+                   int is_stream,
+                   int sock,
+                   char *passwd,
+                   const char *host)
+{
+    krb5_error_code ret;
+    krb5_data ap_req_data;
+    krb5_data krb_priv_data;
+    krb5_data passwd_data;
+    size_t len;
+    u_char header[6];
+    u_char *p;
+    struct iovec iov[3];
+    struct msghdr msghdr;
+
+    if (is_stream)
+       return KRB5_KPASSWD_MALFORMED;
+
+    if (targprinc &&
+       krb5_principal_compare(context, creds->client, targprinc) != TRUE)
+       return KRB5_KPASSWD_MALFORMED;
+
+    krb5_data_zero (&ap_req_data);
+
+    ret = krb5_mk_req_extended (context,
+                               auth_context,
+                               AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
+                               NULL, /* in_data */
+                               creds,
+                               &ap_req_data);
+    if (ret)
+       return ret;
+
+    passwd_data.data   = passwd;
+    passwd_data.length = strlen(passwd);
+
+    krb5_data_zero (&krb_priv_data);
+
+    ret = krb5_mk_priv (context,
+                       *auth_context,
+                       &passwd_data,
+                       &krb_priv_data,
+                       NULL);
+    if (ret)
+       goto out2;
+
+    len = 6 + ap_req_data.length + krb_priv_data.length;
+    p = header;
+    *p++ = (len >> 8) & 0xFF;
+    *p++ = (len >> 0) & 0xFF;
+    *p++ = 0;
+    *p++ = 1;
+    *p++ = (ap_req_data.length >> 8) & 0xFF;
+    *p++ = (ap_req_data.length >> 0) & 0xFF;
+
+    memset(&msghdr, 0, sizeof(msghdr));
+    msghdr.msg_name       = NULL;
+    msghdr.msg_namelen    = 0;
+    msghdr.msg_iov        = iov;
+    msghdr.msg_iovlen     = sizeof(iov)/sizeof(*iov);
+#if 0
+    msghdr.msg_control    = NULL;
+    msghdr.msg_controllen = 0;
+#endif
+
+    iov[0].iov_base    = (void*)header;
+    iov[0].iov_len     = 6;
+    iov[1].iov_base    = ap_req_data.data;
+    iov[1].iov_len     = ap_req_data.length;
+    iov[2].iov_base    = krb_priv_data.data;
+    iov[2].iov_len     = krb_priv_data.length;
+
+    if (sendmsg (sock, &msghdr, 0) < 0) {
+       ret = errno;
+       krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret));
+    }
+
+    krb5_data_free (&krb_priv_data);
+out2:
+    krb5_data_free (&ap_req_data);
+    return ret;
+}
+
+/*
+ * Set password protocol as defined by RFC3244 --
+ * Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols
+ */
+
+static krb5_error_code
+setpw_send_request (krb5_context context,
+                   krb5_auth_context *auth_context,
+                   krb5_creds *creds,
+                   krb5_principal targprinc,
+                   int is_stream,
+                   int sock,
+                   char *passwd,
+                   const char *host)
+{
+    krb5_error_code ret;
+    krb5_data ap_req_data;
+    krb5_data krb_priv_data;
+    krb5_data pwd_data;
+    ChangePasswdDataMS chpw;
+    size_t len;
+    u_char header[4 + 6];
+    u_char *p;
+    struct iovec iov[3];
+    struct msghdr msghdr;
+
+    krb5_data_zero (&ap_req_data);
+
+    ret = krb5_mk_req_extended (context,
+                               auth_context,
+                               AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY,
+                               NULL, /* in_data */
+                               creds,
+                               &ap_req_data);
+    if (ret)
+       return ret;
+
+    chpw.newpasswd.length = strlen(passwd);
+    chpw.newpasswd.data = passwd;
+    if (targprinc) {
+       chpw.targname = &targprinc->name;
+       chpw.targrealm = &targprinc->realm;
+    } else {
+       chpw.targname = NULL;
+       chpw.targrealm = NULL;
+    }
+       
+    ASN1_MALLOC_ENCODE(ChangePasswdDataMS, pwd_data.data, pwd_data.length,
+                      &chpw, &len, ret);
+    if (ret) {
+       krb5_data_free (&ap_req_data);
+       return ret;
+    }
+
+    if(pwd_data.length != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_mk_priv (context,
+                       *auth_context,
+                       &pwd_data,
+                       &krb_priv_data,
+                       NULL);
+    if (ret)
+       goto out2;
+
+    len = 6 + ap_req_data.length + krb_priv_data.length;
+    p = header;
+    if (is_stream) {
+       _krb5_put_int(p, len, 4);
+       p += 4;
+    }
+    *p++ = (len >> 8) & 0xFF;
+    *p++ = (len >> 0) & 0xFF;
+    *p++ = 0xff;
+    *p++ = 0x80;
+    *p++ = (ap_req_data.length >> 8) & 0xFF;
+    *p++ = (ap_req_data.length >> 0) & 0xFF;
+
+    memset(&msghdr, 0, sizeof(msghdr));
+    msghdr.msg_name       = NULL;
+    msghdr.msg_namelen    = 0;
+    msghdr.msg_iov        = iov;
+    msghdr.msg_iovlen     = sizeof(iov)/sizeof(*iov);
+#if 0
+    msghdr.msg_control    = NULL;
+    msghdr.msg_controllen = 0;
+#endif
+
+    iov[0].iov_base    = (void*)header;
+    if (is_stream)
+       iov[0].iov_len     = 10;
+    else
+       iov[0].iov_len     = 6;
+    iov[1].iov_base    = ap_req_data.data;
+    iov[1].iov_len     = ap_req_data.length;
+    iov[2].iov_base    = krb_priv_data.data;
+    iov[2].iov_len     = krb_priv_data.length;
+
+    if (sendmsg (sock, &msghdr, 0) < 0) {
+       ret = errno;
+       krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret));
+    }
+
+    krb5_data_free (&krb_priv_data);
+out2:
+    krb5_data_free (&ap_req_data);
+    krb5_data_free (&pwd_data);
+    return ret;
+}
+
+static krb5_error_code
+process_reply (krb5_context context,
+              krb5_auth_context auth_context,
+              int is_stream,
+              int sock,
+              int *result_code,
+              krb5_data *result_code_string,
+              krb5_data *result_string,
+              const char *host)
+{
+    krb5_error_code ret;
+    u_char reply[1024 * 3];
+    ssize_t len;
+    u_int16_t pkt_len, pkt_ver;
+    krb5_data ap_rep_data;
+    int save_errno;
+
+    len = 0;
+    if (is_stream) {
+       while (len < sizeof(reply)) {
+           unsigned long size;
+
+           ret = recvfrom (sock, reply + len, sizeof(reply) - len, 
+                           0, NULL, NULL);
+           if (ret < 0) {
+               save_errno = errno;
+               krb5_set_error_string(context, "recvfrom %s: %s",
+                                     host, strerror(save_errno));
+               return save_errno;
+           } else if (ret == 0) {
+               krb5_set_error_string(context, "recvfrom timeout %s", host);
+               return 1;
+           }
+           len += ret;
+           if (len < 4)
+               continue;
+           _krb5_get_int(reply, &size, 4);
+           if (size + 4 < len)
+               continue;
+           memmove(reply, reply + 4, size);            
+           len = size;
+           break;
+       }
+       if (len == sizeof(reply)) {
+           krb5_set_error_string(context, "message too large from %s",
+                                 host);
+           return ENOMEM;
+       }
+    } else {
+       ret = recvfrom (sock, reply, sizeof(reply), 0, NULL, NULL);
+       if (ret < 0) {
+           save_errno = errno;
+           krb5_set_error_string(context, "recvfrom %s: %s",
+                                 host, strerror(save_errno));
+           return save_errno;
+       }
+       len = ret;
+    }
+
+    if (len < 6) {
+       str2data (result_string, "server %s sent to too short message "
+                 "(%ld bytes)", host, (long)len);
+       *result_code = KRB5_KPASSWD_MALFORMED;
+       return 0;
+    }
+
+    pkt_len = (reply[0] << 8) | (reply[1]);
+    pkt_ver = (reply[2] << 8) | (reply[3]);
+
+    if ((pkt_len != len) || (reply[1] == 0x7e || reply[1] == 0x5e)) {
+       KRB_ERROR error;
+       size_t size;
+       u_char *p;
+
+       memset(&error, 0, sizeof(error));
+
+       ret = decode_KRB_ERROR(reply, len, &error, &size);
+       if (ret)
+           return ret;
+
+       if (error.e_data->length < 2) {
+           str2data(result_string, "server %s sent too short "
+                    "e_data to print anything usable", host);
+           free_KRB_ERROR(&error);
+           *result_code = KRB5_KPASSWD_MALFORMED;
+           return 0;
+       }
+
+       p = error.e_data->data;
+       *result_code = (p[0] << 8) | p[1];
+       if (error.e_data->length == 2)
+           str2data(result_string, "server only sent error code");
+       else 
+           krb5_data_copy (result_string,
+                           p + 2,
+                           error.e_data->length - 2);
+       free_KRB_ERROR(&error);
+       return 0;
+    }
+
+    if (pkt_len != len) {
+       str2data (result_string, "client: wrong len in reply");
+       *result_code = KRB5_KPASSWD_MALFORMED;
+       return 0;
+    }
+    if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW) {
+       str2data (result_string,
+                 "client: wrong version number (%d)", pkt_ver);
+       *result_code = KRB5_KPASSWD_MALFORMED;
+       return 0;
+    }
+
+    ap_rep_data.data = reply + 6;
+    ap_rep_data.length  = (reply[4] << 8) | (reply[5]);
+  
+    if (reply + len < (u_char *)ap_rep_data.data + ap_rep_data.length) {
+       str2data (result_string, "client: wrong AP len in reply");
+       *result_code = KRB5_KPASSWD_MALFORMED;
+       return 0;
+    }
+
+    if (ap_rep_data.length) {
+       krb5_ap_rep_enc_part *ap_rep;
+       krb5_data priv_data;
+       u_char *p;
+
+       priv_data.data   = (u_char*)ap_rep_data.data + ap_rep_data.length;
+       priv_data.length = len - ap_rep_data.length - 6;
+
+       ret = krb5_rd_rep (context,
+                          auth_context,
+                          &ap_rep_data,
+                          &ap_rep);
+       if (ret)
+           return ret;
+
+       krb5_free_ap_rep_enc_part (context, ap_rep);
+
+       ret = krb5_rd_priv (context,
+                           auth_context,
+                           &priv_data,
+                           result_code_string,
+                           NULL);
+       if (ret) {
+           krb5_data_free (result_code_string);
+           return ret;
+       }
+
+       if (result_code_string->length < 2) {
+           *result_code = KRB5_KPASSWD_MALFORMED;
+           str2data (result_string,
+                     "client: bad length in result");
+           return 0;
+       }
+
+        p = result_code_string->data;
+      
+        *result_code = (p[0] << 8) | p[1];
+        krb5_data_copy (result_string,
+                        (unsigned char*)result_code_string->data + 2,
+                        result_code_string->length - 2);
+        return 0;
+    } else {
+       KRB_ERROR error;
+       size_t size;
+       u_char *p;
+      
+       ret = decode_KRB_ERROR(reply + 6, len - 6, &error, &size);
+       if (ret) {
+           return ret;
+       }
+       if (error.e_data->length < 2) {
+           krb5_warnx (context, "too short e_data to print anything usable");
+           return 1;           /* XXX */
+       }
+
+       p = error.e_data->data;
+       *result_code = (p[0] << 8) | p[1];
+       krb5_data_copy (result_string,
+                       p + 2,
+                       error.e_data->length - 2);
+       return 0;
+    }
+}
+
+
+/*
+ * change the password using the credentials in `creds' (for the
+ * principal indicated in them) to `newpw', storing the result of
+ * the operation in `result_*' and an error code or 0.
+ */
+
+typedef krb5_error_code (*kpwd_send_request) (krb5_context,
+                                             krb5_auth_context *,
+                                             krb5_creds *,
+                                             krb5_principal,
+                                             int,
+                                             int,
+                                             char *,
+                                             const char *);
+typedef krb5_error_code (*kpwd_process_reply) (krb5_context,
+                                              krb5_auth_context,
+                                              int,
+                                              int,
+                                              int *,
+                                              krb5_data *,
+                                              krb5_data *,
+                                              const char *);
+
+static struct kpwd_proc {
+    const char *name;
+    int flags;
+#define SUPPORT_TCP    1
+#define SUPPORT_UDP    2
+    kpwd_send_request send_req;
+    kpwd_process_reply process_rep;
+} procs[] = {
+    {
+       "MS set password", 
+       SUPPORT_TCP|SUPPORT_UDP,
+       setpw_send_request, 
+       process_reply
+    },
+    {
+       "change password",
+       SUPPORT_UDP,
+       chgpw_send_request,
+       process_reply
+    },
+    { NULL }
+};
+
+static struct kpwd_proc *
+find_chpw_proto(const char *name)
+{
+    struct kpwd_proc *p;
+    for (p = procs; p->name != NULL; p++) {
+       if (strcmp(p->name, name) == 0)
+           return p;
+    }
+    return NULL;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+change_password_loop (krb5_context     context,
+                     krb5_creds        *creds,
+                     krb5_principal    targprinc,
+                     char              *newpw,
+                     int               *result_code,
+                     krb5_data         *result_code_string,
+                     krb5_data         *result_string,
+                     struct kpwd_proc  *proc)
+{
+    krb5_error_code ret;
+    krb5_auth_context auth_context = NULL;
+    krb5_krbhst_handle handle = NULL;
+    krb5_krbhst_info *hi;
+    int sock;
+    int i;
+    int done = 0;
+    krb5_realm realm = creds->client->realm;
+
+    ret = krb5_auth_con_init (context, &auth_context);
+    if (ret)
+       return ret;
+
+    krb5_auth_con_setflags (context, auth_context,
+                           KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+
+    ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle);
+    if (ret)
+       goto out;
+
+    while (!done && (ret = krb5_krbhst_next(context, handle, &hi)) == 0) {
+       struct addrinfo *ai, *a;
+       int is_stream;
+
+       switch (hi->proto) {
+       case KRB5_KRBHST_UDP:
+           if ((proc->flags & SUPPORT_UDP) == 0)
+               continue;
+           is_stream = 0;
+           break;
+       case KRB5_KRBHST_TCP:
+           if ((proc->flags & SUPPORT_TCP) == 0)
+               continue;
+           is_stream = 1;
+           break;
+       default:
+           continue;
+       }
+
+       ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
+       if (ret)
+           continue;
+
+       for (a = ai; !done && a != NULL; a = a->ai_next) {
+           int replied = 0;
+
+           sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+           if (sock < 0)
+               continue;
+
+           ret = connect(sock, a->ai_addr, a->ai_addrlen);
+           if (ret < 0) {
+               close (sock);
+               goto out;
+           }
+
+           ret = krb5_auth_con_genaddrs (context, auth_context, sock,
+                                         KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR);
+           if (ret) {
+               close (sock);
+               goto out;
+           }
+
+           for (i = 0; !done && i < 5; ++i) {
+               fd_set fdset;
+               struct timeval tv;
+
+               if (!replied) {
+                   replied = 0;
+                   
+                   ret = (*proc->send_req) (context,
+                                            &auth_context,
+                                            creds,
+                                            targprinc,
+                                            is_stream,
+                                            sock,
+                                            newpw,
+                                            hi->hostname);
+                   if (ret) {
+                       close(sock);
+                       goto out;
+                   }
+               }
+           
+               if (sock >= FD_SETSIZE) {
+                   krb5_set_error_string(context, "fd %d too large", sock);
+                   ret = ERANGE;
+                   close (sock);
+                   goto out;
+               }
+
+               FD_ZERO(&fdset);
+               FD_SET(sock, &fdset);
+               tv.tv_usec = 0;
+               tv.tv_sec  = 1 + (1 << i);
+
+               ret = select (sock + 1, &fdset, NULL, NULL, &tv);
+               if (ret < 0 && errno != EINTR) {
+                   close(sock);
+                   goto out;
+               }
+               if (ret == 1) {
+                   ret = (*proc->process_rep) (context,
+                                               auth_context,
+                                               is_stream,
+                                               sock,
+                                               result_code,
+                                               result_code_string,
+                                               result_string,
+                                               hi->hostname);
+                   if (ret == 0)
+                       done = 1;
+                   else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL)
+                       replied = 1;
+               } else {
+                   ret = KRB5_KDC_UNREACH;
+               }
+           }
+           close (sock);
+       }
+    }
+
+ out:
+    krb5_krbhst_free (context, handle);
+    krb5_auth_con_free (context, auth_context);
+    if (done)
+       return 0;
+    else {
+       if (ret == KRB5_KDC_UNREACH) {
+           krb5_set_error_string(context,
+                                 "unable to reach any changepw server "
+                                 " in realm %s", realm);
+           *result_code = KRB5_KPASSWD_HARDERROR;
+       }
+       return ret;
+    }
+}
+
+
+/*
+ * change the password using the credentials in `creds' (for the
+ * principal indicated in them) to `newpw', storing the result of
+ * the operation in `result_*' and an error code or 0.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_change_password (krb5_context     context,
+                     krb5_creds        *creds,
+                     char              *newpw,
+                     int               *result_code,
+                     krb5_data         *result_code_string,
+                     krb5_data         *result_string)
+{
+    struct kpwd_proc *p = find_chpw_proto("change password");
+
+    *result_code = KRB5_KPASSWD_MALFORMED;
+    result_code_string->data = result_string->data = NULL;
+    result_code_string->length = result_string->length = 0;
+
+    if (p == NULL)
+       return KRB5_KPASSWD_MALFORMED;
+
+    return change_password_loop(context, creds, NULL, newpw, 
+                               result_code, result_code_string, 
+                               result_string, p);
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_password(krb5_context context,
+                 krb5_creds *creds,
+                 char *newpw,
+                 krb5_principal targprinc,
+                 int *result_code,
+                 krb5_data *result_code_string,
+                 krb5_data *result_string)
+{
+    krb5_principal principal = NULL;
+    krb5_error_code ret = 0;
+    int i;
+
+    *result_code = KRB5_KPASSWD_MALFORMED;
+    result_code_string->data = result_string->data = NULL;
+    result_code_string->length = result_string->length = 0;
+
+    if (targprinc == NULL) {
+       ret = krb5_get_default_principal(context, &principal);
+       if (ret)
+           return ret;
+    } else
+       principal = targprinc;
+
+    for (i = 0; procs[i].name != NULL; i++) {
+       *result_code = 0;
+       ret = change_password_loop(context, creds, targprinc, newpw, 
+                                  result_code, result_code_string, 
+                                  result_string, 
+                                  &procs[i]);
+       if (ret == 0 && *result_code == 0)
+           break;
+    }
+
+    if (targprinc == NULL)
+       krb5_free_principal(context, principal);
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_password_using_ccache(krb5_context context,
+                              krb5_ccache ccache,
+                              char *newpw,
+                              krb5_principal targprinc,
+                              int *result_code,
+                              krb5_data *result_code_string,
+                              krb5_data *result_string)
+{
+    krb5_creds creds, *credsp;
+    krb5_error_code ret;
+    krb5_principal principal = NULL;
+
+    *result_code = KRB5_KPASSWD_MALFORMED;
+    result_code_string->data = result_string->data = NULL;
+    result_code_string->length = result_string->length = 0;
+
+    memset(&creds, 0, sizeof(creds));
+
+    if (targprinc == NULL) {
+       ret = krb5_cc_get_principal(context, ccache, &principal);
+       if (ret)
+           return ret;
+    } else
+       principal = targprinc;
+
+    ret = krb5_make_principal(context, &creds.server, 
+                             krb5_principal_get_realm(context, principal),
+                             "kadmin", "changepw", NULL);
+    if (ret)
+       goto out;
+
+    ret = krb5_cc_get_principal(context, ccache, &creds.client);
+    if (ret) {
+        krb5_free_principal(context, creds.server);
+       goto out;
+    }
+
+    ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
+    krb5_free_principal(context, creds.server);
+    krb5_free_principal(context, creds.client);
+    if (ret)
+       goto out;
+
+    ret = krb5_set_password(context,
+                           credsp,
+                           newpw,
+                           principal,
+                           result_code,
+                           result_code_string,
+                           result_string);
+
+    krb5_free_creds(context, credsp); 
+
+    return ret;
+ out:
+    if (targprinc == NULL)
+       krb5_free_principal(context, principal);
+    return ret;
+}
+
+/*
+ *
+ */
+
+const char* KRB5_LIB_FUNCTION
+krb5_passwd_result_to_string (krb5_context context,
+                             int result)
+{
+    static const char *strings[] = {
+       "Success",
+       "Malformed",
+       "Hard error",
+       "Auth error",
+       "Soft error" ,
+       "Access denied",
+       "Bad version",
+       "Initial flag needed"
+    };
+
+    if (result < 0 || result > KRB5_KPASSWD_INITIAL_FLAG_NEEDED)
+       return "unknown result code";
+    else
+       return strings[result];
+}
diff --git a/src/kerberosV/src/lib/krb5/codec.c b/src/kerberosV/src/lib/krb5/codec.c
new file mode 100644 (file)
index 0000000..ccb519c
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 1998 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: codec.c,v 1.9 2004/05/25 21:19:37 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncTicketPart (krb5_context context,
+                          const void *data,
+                          size_t length,
+                          EncTicketPart *t,
+                          size_t *len)
+{
+    return decode_EncTicketPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncTicketPart (krb5_context context,
+                          void *data,
+                          size_t length,
+                          EncTicketPart *t,
+                          size_t *len)
+{
+    return encode_EncTicketPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncASRepPart (krb5_context context,
+                         const void *data,
+                         size_t length,
+                         EncASRepPart *t,
+                         size_t *len)
+{
+    return decode_EncASRepPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncASRepPart (krb5_context context,
+                         void *data,
+                         size_t length,
+                         EncASRepPart *t,
+                         size_t *len)
+{
+    return encode_EncASRepPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncTGSRepPart (krb5_context context,
+                          const void *data,
+                          size_t length,
+                          EncTGSRepPart *t,
+                          size_t *len)
+{
+    return decode_EncTGSRepPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncTGSRepPart (krb5_context context,
+                          void *data,
+                          size_t length,
+                          EncTGSRepPart *t,
+                          size_t *len)
+{
+    return encode_EncTGSRepPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncAPRepPart (krb5_context context,
+                         const void *data,
+                         size_t length,
+                         EncAPRepPart *t,
+                         size_t *len)
+{
+    return decode_EncAPRepPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncAPRepPart (krb5_context context,
+                         void *data,
+                         size_t length,
+                         EncAPRepPart *t,
+                         size_t *len)
+{
+    return encode_EncAPRepPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_Authenticator (krb5_context context,
+                          const void *data,
+                          size_t length,
+                          Authenticator *t,
+                          size_t *len)
+{
+    return decode_Authenticator(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_Authenticator (krb5_context context,
+                          void *data,
+                          size_t length,
+                          Authenticator *t,
+                          size_t *len)
+{
+    return encode_Authenticator(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncKrbCredPart (krb5_context context,
+                           const void *data,
+                           size_t length,
+                           EncKrbCredPart *t,
+                           size_t *len)
+{
+    return decode_EncKrbCredPart(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncKrbCredPart (krb5_context context,
+                           void *data,
+                           size_t length,
+                           EncKrbCredPart *t,
+                           size_t *len)
+{
+    return encode_EncKrbCredPart (data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_ETYPE_INFO (krb5_context context,
+                       const void *data,
+                       size_t length,
+                       ETYPE_INFO *t,
+                       size_t *len)
+{
+    return decode_ETYPE_INFO(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_ETYPE_INFO (krb5_context context,
+                       void *data,
+                       size_t length,
+                       ETYPE_INFO *t,
+                       size_t *len)
+{
+    return encode_ETYPE_INFO (data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_ETYPE_INFO2 (krb5_context context,
+                       const void *data,
+                       size_t length,
+                       ETYPE_INFO2 *t,
+                       size_t *len)
+{
+    return decode_ETYPE_INFO2(data, length, t, len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_ETYPE_INFO2 (krb5_context context,
+                        void *data,
+                        size_t length,
+                        ETYPE_INFO2 *t,
+                        size_t *len)
+{
+    return encode_ETYPE_INFO2 (data, length, t, len);
+}
diff --git a/src/kerberosV/src/lib/krb5/config_file.c b/src/kerberosV/src/lib/krb5/config_file.c
new file mode 100644 (file)
index 0000000..3c2a252
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+RCSID("$KTH: config_file.c,v 1.52 2004/09/30 11:22:48 lha Exp $");
+
+#ifndef HAVE_NETINFO
+
+/* Gaah! I want a portable funopen */
+struct fileptr {
+    const char *s;
+    FILE *f;
+};
+
+static char *
+config_fgets(char *str, size_t len, struct fileptr *ptr)
+{
+    /* XXX this is not correct, in that they don't do the same if the
+       line is longer than len */
+    if(ptr->f != NULL)
+       return fgets(str, len, ptr->f);
+    else {
+       /* this is almost strsep_copy */
+       const char *p;
+       ssize_t l;
+       if(*ptr->s == '\0')
+           return NULL;
+       p = ptr->s + strcspn(ptr->s, "\n");
+       if(*p == '\n')
+           p++;
+       l = min(len, p - ptr->s);
+       if(len > 0) {
+           memcpy(str, ptr->s, l);
+           str[l] = '\0';
+       }
+       ptr->s = p;
+       return str;
+    }
+}
+
+static krb5_error_code parse_section(char *p, krb5_config_section **s,
+                                    krb5_config_section **res,
+                                    const char **error_message);
+static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p,
+                                    krb5_config_binding **b,
+                                    krb5_config_binding **parent,
+                                    const char **error_message);
+static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno,
+                                 krb5_config_binding **parent,
+                                 const char **error_message);
+
+static krb5_config_section *
+get_entry(krb5_config_section **parent, const char *name, int type)
+{
+    krb5_config_section **q;
+
+    for(q = parent; *q != NULL; q = &(*q)->next)
+       if(type == krb5_config_list && 
+          type == (*q)->type &&
+          strcmp(name, (*q)->name) == 0)
+           return *q;
+    *q = calloc(1, sizeof(**q));
+    if(*q == NULL)
+       return NULL;
+    (*q)->name = strdup(name);
+    (*q)->type = type;
+    if((*q)->name == NULL) {
+       free(*q);
+       *q = NULL;
+       return NULL;
+    }
+    return *q;
+}
+
+/*
+ * Parse a section:
+ *
+ * [section]
+ *     foo = bar
+ *     b = {
+ *             a
+ *         }
+ * ...
+ * 
+ * starting at the line in `p', storing the resulting structure in
+ * `s' and hooking it into `parent'.
+ * Store the error message in `error_message'.
+ */
+
+static krb5_error_code
+parse_section(char *p, krb5_config_section **s, krb5_config_section **parent,
+             const char **error_message)
+{
+    char *p1;
+    krb5_config_section *tmp;
+
+    p1 = strchr (p + 1, ']');
+    if (p1 == NULL) {
+       *error_message = "missing ]";
+       return KRB5_CONFIG_BADFORMAT;
+    }
+    *p1 = '\0';
+    tmp = get_entry(parent, p + 1, krb5_config_list);
+    if(tmp == NULL) {
+       *error_message = "out of memory";
+       return KRB5_CONFIG_BADFORMAT;
+    }
+    *s = tmp;
+    return 0;
+}
+
+/*
+ * Parse a brace-enclosed list from `f', hooking in the structure at
+ * `parent'.
+ * Store the error message in `error_message'.
+ */
+
+static krb5_error_code
+parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent,
+          const char **error_message)
+{
+    char buf[BUFSIZ];
+    krb5_error_code ret;
+    krb5_config_binding *b = NULL;
+    unsigned beg_lineno = *lineno;
+
+    while(config_fgets(buf, sizeof(buf), f) != NULL) {
+       char *p;
+
+       ++*lineno;
+       buf[strcspn(buf, "\r\n")] = '\0';
+       p = buf;
+       while(isspace((unsigned char)*p))
+           ++p;
+       if (*p == '#' || *p == ';' || *p == '\0')
+           continue;
+       while(isspace((unsigned char)*p))
+           ++p;
+       if (*p == '}')
+           return 0;
+       if (*p == '\0')
+           continue;
+       ret = parse_binding (f, lineno, p, &b, parent, error_message);
+       if (ret)
+           return ret;
+    }
+    *lineno = beg_lineno;
+    *error_message = "unclosed {";
+    return KRB5_CONFIG_BADFORMAT;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+parse_binding(struct fileptr *f, unsigned *lineno, char *p,
+             krb5_config_binding **b, krb5_config_binding **parent,
+             const char **error_message)
+{
+    krb5_config_binding *tmp;
+    char *p1, *p2;
+    krb5_error_code ret = 0;
+
+    p1 = p;
+    while (*p && *p != '=' && !isspace((unsigned char)*p))
+       ++p;
+    if (*p == '\0') {
+       *error_message = "missing =";
+       return KRB5_CONFIG_BADFORMAT;
+    }
+    p2 = p;
+    while (isspace((unsigned char)*p))
+       ++p;
+    if (*p != '=') {
+       *error_message = "missing =";
+       return KRB5_CONFIG_BADFORMAT;
+    }
+    ++p;
+    while(isspace((unsigned char)*p))
+       ++p;
+    *p2 = '\0';
+    if (*p == '{') {
+       tmp = get_entry(parent, p1, krb5_config_list);
+       if (tmp == NULL) {
+           *error_message = "out of memory";
+           return KRB5_CONFIG_BADFORMAT;
+       }
+       ret = parse_list (f, lineno, &tmp->u.list, error_message);
+    } else {
+       tmp = get_entry(parent, p1, krb5_config_string);
+       if (tmp == NULL) {
+           *error_message = "out of memory";
+           return KRB5_CONFIG_BADFORMAT;
+       }
+       p1 = p;
+       p = p1 + strlen(p1);
+       while(p > p1 && isspace((unsigned char)*(p-1)))
+           --p;
+       *p = '\0';
+       tmp->u.string = strdup(p1);
+    }
+    *b = tmp;
+    return ret;
+}
+
+/*
+ * Parse the config file `fname', generating the structures into `res'
+ * returning error messages in `error_message'
+ */
+
+static krb5_error_code
+krb5_config_parse_debug (struct fileptr *f,
+                        krb5_config_section **res,
+                        unsigned *lineno,
+                        const char **error_message)
+{
+    krb5_config_section *s = NULL;
+    krb5_config_binding *b = NULL;
+    char buf[BUFSIZ];
+    krb5_error_code ret;
+
+    while (config_fgets(buf, sizeof(buf), f) != NULL) {
+       char *p;
+
+       ++*lineno;
+       buf[strcspn(buf, "\r\n")] = '\0';
+       p = buf;
+       while(isspace((unsigned char)*p))
+           ++p;
+       if (*p == '#' || *p == ';')
+           continue;
+       if (*p == '[') {
+           ret = parse_section(p, &s, res, error_message);
+           if (ret) 
+               return ret;
+           b = NULL;
+       } else if (*p == '}') {
+           *error_message = "unmatched }";
+           return EINVAL;      /* XXX */
+       } else if(*p != '\0') {
+           if (s == NULL) {
+               *error_message = "binding before section";
+               return EINVAL;
+           }
+           ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message);
+           if (ret)
+               return ret;
+       }
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_string_multi(krb5_context context,
+                              const char *string,
+                              krb5_config_section **res)
+{
+    const char *str;
+    unsigned lineno = 0;
+    krb5_error_code ret;
+    struct fileptr f;
+    f.f = NULL;
+    f.s = string;
+
+    ret = krb5_config_parse_debug (&f, res, &lineno, &str);
+    if (ret) {
+       krb5_set_error_string (context, "%s:%u: %s", "<constant>", lineno, str);
+       return ret;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_file_multi (krb5_context context,
+                             const char *fname,
+                             krb5_config_section **res)
+{
+    const char *str;
+    unsigned lineno = 0;
+    krb5_error_code ret;
+    struct fileptr f;
+    f.f = fopen(fname, "r");
+    f.s = NULL;
+    if(f.f == NULL) {
+       ret = errno;
+       krb5_set_error_string (context, "open %s: %s", fname, strerror(ret));
+       return ret;
+    }
+
+    ret = krb5_config_parse_debug (&f, res, &lineno, &str);
+    fclose(f.f);
+    if (ret) {
+       krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str);
+       return ret;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_file (krb5_context context,
+                       const char *fname,
+                       krb5_config_section **res)
+{
+    *res = NULL;
+    return krb5_config_parse_file_multi(context, fname, res);
+}
+
+#endif /* !HAVE_NETINFO */
+
+static void
+free_binding (krb5_context context, krb5_config_binding *b)
+{
+    krb5_config_binding *next_b;
+
+    while (b) {
+       free (b->name);
+       if (b->type == krb5_config_string)
+           free (b->u.string);
+       else if (b->type == krb5_config_list)
+           free_binding (context, b->u.list);
+       else
+           krb5_abortx(context, "unknown binding type (%d) in free_binding", 
+                       b->type);
+       next_b = b->next;
+       free (b);
+       b = next_b;
+    }
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_file_free (krb5_context context, krb5_config_section *s)
+{
+    free_binding (context, s);
+    return 0;
+}
+
+const void *
+krb5_config_get_next (krb5_context context,
+                     const krb5_config_section *c,
+                     const krb5_config_binding **pointer,
+                     int type,
+                     ...)
+{
+    const char *ret;
+    va_list args;
+
+    va_start(args, type);
+    ret = krb5_config_vget_next (context, c, pointer, type, args);
+    va_end(args);
+    return ret;
+}
+
+static const void *
+vget_next(krb5_context context,
+         const krb5_config_binding *b,
+         const krb5_config_binding **pointer,
+         int type,
+         const char *name,
+         va_list args)
+{
+    const char *p = va_arg(args, const char *);
+    while(b != NULL) {
+       if(strcmp(b->name, name) == 0) {
+           if(b->type == type && p == NULL) {
+               *pointer = b;
+               return b->u.generic;
+           } else if(b->type == krb5_config_list && p != NULL) {
+               return vget_next(context, b->u.list, pointer, type, p, args);
+           }
+       }
+       b = b->next;
+    }
+    return NULL;
+}
+
+const void *
+krb5_config_vget_next (krb5_context context,
+                      const krb5_config_section *c,
+                      const krb5_config_binding **pointer,
+                      int type,
+                      va_list args)
+{
+    const krb5_config_binding *b;
+    const char *p;
+
+    if(c == NULL)
+       c = context->cf;
+
+    if (c == NULL)
+       return NULL;
+
+    if (*pointer == NULL) {
+       /* first time here, walk down the tree looking for the right
+           section */
+       p = va_arg(args, const char *);
+       if (p == NULL)
+           return NULL;
+       return vget_next(context, c, pointer, type, p, args);
+    }
+
+    /* we were called again, so just look for more entries with the
+       same name and type */
+    for (b = (*pointer)->next; b != NULL; b = b->next) {
+       if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) {
+           *pointer = b;
+           return b->u.generic;
+       }
+    }
+    return NULL;
+}
+
+const void *
+krb5_config_get (krb5_context context,
+                const krb5_config_section *c,
+                int type,
+                ...)
+{
+    const void *ret;
+    va_list args;
+
+    va_start(args, type);
+    ret = krb5_config_vget (context, c, type, args);
+    va_end(args);
+    return ret;
+}
+
+const void *
+krb5_config_vget (krb5_context context,
+                 const krb5_config_section *c,
+                 int type,
+                 va_list args)
+{
+    const krb5_config_binding *foo = NULL;
+
+    return krb5_config_vget_next (context, c, &foo, type, args);
+}
+
+const krb5_config_binding *
+krb5_config_get_list (krb5_context context,
+                     const krb5_config_section *c,
+                     ...)
+{
+    const krb5_config_binding *ret;
+    va_list args;
+
+    va_start(args, c);
+    ret = krb5_config_vget_list (context, c, args);
+    va_end(args);
+    return ret;
+}
+
+const krb5_config_binding *
+krb5_config_vget_list (krb5_context context,
+                      const krb5_config_section *c,
+                      va_list args)
+{
+    return krb5_config_vget (context, c, krb5_config_list, args);
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_get_string (krb5_context context,
+                       const krb5_config_section *c,
+                       ...)
+{
+    const char *ret;
+    va_list args;
+
+    va_start(args, c);
+    ret = krb5_config_vget_string (context, c, args);
+    va_end(args);
+    return ret;
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_vget_string (krb5_context context,
+                        const krb5_config_section *c,
+                        va_list args)
+{
+    return krb5_config_vget (context, c, krb5_config_string, args);
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_vget_string_default (krb5_context context,
+                                const krb5_config_section *c,
+                                const char *def_value,
+                                va_list args)
+{
+    const char *ret;
+
+    ret = krb5_config_vget_string (context, c, args);
+    if (ret == NULL)
+       ret = def_value;
+    return ret;
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_get_string_default (krb5_context context,
+                               const krb5_config_section *c,
+                               const char *def_value,
+                               ...)
+{
+    const char *ret;
+    va_list args;
+
+    va_start(args, def_value);
+    ret = krb5_config_vget_string_default (context, c, def_value, args);
+    va_end(args);
+    return ret;
+}
+
+char ** KRB5_LIB_FUNCTION
+krb5_config_vget_strings(krb5_context context,
+                        const krb5_config_section *c,
+                        va_list args)
+{
+    char **strings = NULL;
+    int nstr = 0;
+    const krb5_config_binding *b = NULL;
+    const char *p;
+
+    while((p = krb5_config_vget_next(context, c, &b, 
+                                    krb5_config_string, args))) {
+       char *tmp = strdup(p);
+       char *pos = NULL;
+       char *s;
+       if(tmp == NULL)
+           goto cleanup;
+       s = strtok_r(tmp, " \t", &pos);
+       while(s){
+           char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
+           if(tmp == NULL)
+               goto cleanup;
+           strings = tmp;
+           strings[nstr] = strdup(s);
+           nstr++;
+           if(strings[nstr-1] == NULL)
+               goto cleanup;
+           s = strtok_r(NULL, " \t", &pos);
+       }
+       free(tmp);
+    }
+    if(nstr){
+       char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings));
+       if(strings == NULL)
+           goto cleanup;
+       strings = tmp;
+       strings[nstr] = NULL;
+    }
+    return strings;
+cleanup:
+    while(nstr--)
+       free(strings[nstr]);
+    free(strings);
+    return NULL;
+
+}
+
+char**
+krb5_config_get_strings(krb5_context context,
+                       const krb5_config_section *c,
+                       ...)
+{
+    va_list ap;
+    char **ret;
+    va_start(ap, c);
+    ret = krb5_config_vget_strings(context, c, ap);
+    va_end(ap);
+    return ret;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_config_free_strings(char **strings)
+{
+    char **s = strings;
+    while(s && *s){
+       free(*s);
+       s++;
+    }
+    free(strings);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_vget_bool_default (krb5_context context,
+                              const krb5_config_section *c,
+                              krb5_boolean def_value,
+                              va_list args)
+{
+    const char *str;
+    str = krb5_config_vget_string (context, c, args);
+    if(str == NULL)
+       return def_value;
+    if(strcasecmp(str, "yes") == 0 ||
+       strcasecmp(str, "true") == 0 ||
+       atoi(str)) return TRUE;
+    return FALSE;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_vget_bool  (krb5_context context,
+                       const krb5_config_section *c,
+                       va_list args)
+{
+    return krb5_config_vget_bool_default (context, c, FALSE, args);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_get_bool_default (krb5_context context,
+                             const krb5_config_section *c,
+                             krb5_boolean def_value,
+                             ...)
+{
+    va_list ap;
+    krb5_boolean ret;
+    va_start(ap, def_value);
+    ret = krb5_config_vget_bool_default(context, c, def_value, ap);
+    va_end(ap);
+    return ret;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_get_bool (krb5_context context,
+                     const krb5_config_section *c,
+                     ...)
+{
+    va_list ap;
+    krb5_boolean ret;
+    va_start(ap, c);
+    ret = krb5_config_vget_bool (context, c, ap);
+    va_end(ap);
+    return ret;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_time_default (krb5_context context,
+                              const krb5_config_section *c,
+                              int def_value,
+                              va_list args)
+{
+    const char *str;
+    krb5_deltat t;
+
+    str = krb5_config_vget_string (context, c, args);
+    if(str == NULL)
+       return def_value;
+    if (krb5_string_to_deltat(str, &t))
+       return def_value;
+    return t;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_time  (krb5_context context,
+                       const krb5_config_section *c,
+                       va_list args)
+{
+    return krb5_config_vget_time_default (context, c, -1, args);
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_time_default (krb5_context context,
+                             const krb5_config_section *c,
+                             int def_value,
+                             ...)
+{
+    va_list ap;
+    int ret;
+    va_start(ap, def_value);
+    ret = krb5_config_vget_time_default(context, c, def_value, ap);
+    va_end(ap);
+    return ret;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_time (krb5_context context,
+                     const krb5_config_section *c,
+                     ...)
+{
+    va_list ap;
+    int ret;
+    va_start(ap, c);
+    ret = krb5_config_vget_time (context, c, ap);
+    va_end(ap);
+    return ret;
+}
+
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_int_default (krb5_context context,
+                             const krb5_config_section *c,
+                             int def_value,
+                             va_list args)
+{
+    const char *str;
+    str = krb5_config_vget_string (context, c, args);
+    if(str == NULL)
+       return def_value;
+    else { 
+       char *endptr; 
+       long l; 
+       l = strtol(str, &endptr, 0); 
+       if (endptr == str) 
+           return def_value; 
+       else 
+           return l;
+    }
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_int  (krb5_context context,
+                      const krb5_config_section *c,
+                      va_list args)
+{
+    return krb5_config_vget_int_default (context, c, -1, args);
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_int_default (krb5_context context,
+                            const krb5_config_section *c,
+                            int def_value,
+                            ...)
+{
+    va_list ap;
+    int ret;
+    va_start(ap, def_value);
+    ret = krb5_config_vget_int_default(context, c, def_value, ap);
+    va_end(ap);
+    return ret;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_int (krb5_context context,
+                    const krb5_config_section *c,
+                    ...)
+{
+    va_list ap;
+    int ret;
+    va_start(ap, c);
+    ret = krb5_config_vget_int (context, c, ap);
+    va_end(ap);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/config_file_netinfo.c b/src/kerberosV/src/lib/krb5/config_file_netinfo.c
new file mode 100644 (file)
index 0000000..45a400c
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+RCSID("$KTH: config_file_netinfo.c,v 1.4 2004/05/25 21:20:18 lha Exp $");
+
+/*
+ * Netinfo implementation from Luke Howard <lukeh@xedoc.com.au>
+ */
+
+#ifdef HAVE_NETINFO
+#include <netinfo/ni.h>
+static ni_status
+ni_proplist2binding(ni_proplist *pl, krb5_config_section **ret)
+{
+    int i, j;
+    krb5_config_section **next = NULL;
+
+    for (i = 0; i < pl->ni_proplist_len; i++) {
+       if (!strcmp(pl->nipl_val[i].nip_name, "name"))
+           continue;
+
+       for (j = 0; j < pl->nipl_val[i].nip_val.ni_namelist_len; j++) {
+           krb5_config_binding *b;
+
+           b = malloc(sizeof(*b));
+           if (b == NULL)
+               return NI_FAILED;
+       
+           b->next = NULL;
+           b->type = krb5_config_string;
+           b->name = ni_name_dup(pl->nipl_val[i].nip_name);
+           b->u.string = ni_name_dup(pl->nipl_val[i].nip_val.ninl_val[j]);
+
+           if (next == NULL) {
+               *ret = b;
+           } else {
+               *next = b;
+           }
+           next = &b->next;
+       }
+    }
+    return NI_OK;
+}
+
+static ni_status
+ni_idlist2binding(void *ni, ni_idlist *idlist, krb5_config_section **ret)
+{
+    int i;
+    ni_status nis;
+    krb5_config_section **next;
+
+    for (i = 0; i < idlist->ni_idlist_len; i++) {
+       ni_proplist pl;
+        ni_id nid;
+       ni_idlist children;
+       krb5_config_binding *b;
+       ni_index index;
+
+       nid.nii_instance = 0;
+       nid.nii_object = idlist->ni_idlist_val[i];
+
+       nis = ni_read(ni, &nid, &pl);
+
+       if (nis != NI_OK) {
+            return nis;
+       }
+       index = ni_proplist_match(pl, "name", NULL);
+       b = malloc(sizeof(*b));
+       if (b == NULL) return NI_FAILED;
+
+       if (i == 0) {
+           *ret = b;
+       } else {
+           *next = b;
+       }
+
+       b->type = krb5_config_list;
+       b->name = ni_name_dup(pl.nipl_val[index].nip_val.ninl_val[0]);
+       b->next = NULL;
+       b->u.list = NULL;
+
+       /* get the child directories */
+       nis = ni_children(ni, &nid, &children);
+       if (nis == NI_OK) {
+           nis = ni_idlist2binding(ni, &children, &b->u.list);
+           if (nis != NI_OK) {
+               return nis;
+           }
+       }
+
+       nis = ni_proplist2binding(&pl, b->u.list == NULL ? &b->u.list : &b->u.list->next);
+       ni_proplist_free(&pl);
+       if (nis != NI_OK) {
+           return nis;
+       }
+       next = &b->next;
+    }
+    ni_idlist_free(idlist);
+    return NI_OK;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_file (krb5_context context,
+                       const char *fname,
+                       krb5_config_section **res)
+{
+    void *ni = NULL, *lastni = NULL;
+    int i;
+    ni_status nis;
+    ni_id nid;
+    ni_idlist children;
+
+    krb5_config_section *s;
+    int ret;
+
+    s = NULL;
+
+    for (i = 0; i < 256; i++) {
+       if (i == 0) {
+           nis = ni_open(NULL, ".", &ni);
+       } else {
+           if (lastni != NULL) ni_free(lastni);
+           lastni = ni;
+           nis = ni_open(lastni, "..", &ni);
+       }
+       if (nis != NI_OK)
+           break;
+       nis = ni_pathsearch(ni, &nid, "/locations/kerberos");
+       if (nis == NI_OK) {
+           nis = ni_children(ni, &nid, &children);
+           if (nis != NI_OK)
+               break;
+           nis = ni_idlist2binding(ni, &children, &s);
+           break;
+       }
+    }
+
+    if (ni != NULL) ni_free(ni);
+    if (ni != lastni && lastni != NULL) ni_free(lastni);
+
+    ret = (nis == NI_OK) ? 0 : -1;
+    if (ret == 0) {
+       *res = s;
+    } else {
+       *res = NULL;
+    }
+    return ret;
+}
+#endif /* HAVE_NETINFO */
diff --git a/src/kerberosV/src/lib/krb5/constants.c b/src/kerberosV/src/lib/krb5/constants.c
new file mode 100644 (file)
index 0000000..4a89c38
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: constants.c,v 1.8 2004/09/23 07:57:37 joda Exp $");
+
+const char *krb5_config_file = 
+#ifdef __APPLE__
+"/Library/Preferences/edu.mit.Kerberos:"
+#endif
+SYSCONFDIR "/krb5.conf";
+const char *krb5_defkeyname = KEYTAB_DEFAULT;
diff --git a/src/kerberosV/src/lib/krb5/context.c b/src/kerberosV/src/lib/krb5/context.c
new file mode 100644 (file)
index 0000000..b442f19
--- /dev/null
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <com_err.h>
+
+RCSID("$KTH: context.c,v 1.102 2005/05/18 04:20:50 lha Exp $");
+
+#define INIT_FIELD(C, T, E, D, F)                                      \
+    (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D),        \
+                                               "libdefaults", F, NULL)
+
+/*
+ * Set the list of etypes `ret_etypes' from the configuration variable
+ * `name'
+ */
+
+static krb5_error_code
+set_etypes (krb5_context context,
+           const char *name,
+           krb5_enctype **ret_enctypes)
+{
+    char **etypes_str;
+    krb5_enctype *etypes = NULL;
+
+    etypes_str = krb5_config_get_strings(context, NULL, "libdefaults", 
+                                        name, NULL);
+    if(etypes_str){
+       int i, j, k;
+       for(i = 0; etypes_str[i]; i++);
+       etypes = malloc((i+1) * sizeof(*etypes));
+       if (etypes == NULL) {
+           krb5_config_free_strings (etypes_str);
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       for(j = 0, k = 0; j < i; j++) {
+           krb5_enctype e;
+           if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0)
+               continue;
+           if (krb5_enctype_valid(context, e) != 0)
+               continue;
+           etypes[k++] = e;
+       }
+       etypes[k] = ETYPE_NULL;
+       krb5_config_free_strings(etypes_str);
+    } 
+    *ret_enctypes = etypes;
+    return 0;
+}
+
+/*
+ * read variables from the configuration file and set in `context'
+ */
+
+static krb5_error_code
+init_context_from_config_file(krb5_context context)
+{
+    krb5_error_code ret;
+    const char * tmp;
+    krb5_enctype *tmptypes;
+
+    INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew");
+    INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout");
+    INIT_FIELD(context, int, max_retries, 3, "max_retries");
+
+    INIT_FIELD(context, string, http_proxy, NULL, "http_proxy");
+    
+    ret = set_etypes (context, "default_etypes", &tmptypes);
+    if(ret)
+       return ret;
+    free(context->etypes);
+    context->etypes = tmptypes;
+    
+    ret = set_etypes (context, "default_etypes_des", &tmptypes);
+    if(ret)
+       return ret;
+    free(context->etypes_des);
+    context->etypes_des = tmptypes;
+
+    /* default keytab name */
+    tmp = NULL;
+    if(!issuid())
+       tmp = getenv("KRB5_KTNAME");
+    if(tmp != NULL)
+       context->default_keytab = tmp;
+    else
+       INIT_FIELD(context, string, default_keytab, 
+                  KEYTAB_DEFAULT, "default_keytab_name");
+
+    INIT_FIELD(context, string, default_keytab_modify, 
+              NULL, "default_keytab_modify_name");
+
+    INIT_FIELD(context, string, time_fmt, 
+              "%Y-%m-%dT%H:%M:%S", "time_format");
+
+    INIT_FIELD(context, string, date_fmt, 
+              "%Y-%m-%d", "date_format");
+
+    INIT_FIELD(context, bool, log_utc, 
+              FALSE, "log_utc");
+
+
+    
+    /* init dns-proxy slime */
+    tmp = krb5_config_get_string(context, NULL, "libdefaults", 
+                                "dns_proxy", NULL);
+    if(tmp) 
+       roken_gethostby_setup(context->http_proxy, tmp);
+    krb5_free_host_realm (context, context->default_realms);
+    context->default_realms = NULL;
+
+    {
+       krb5_addresses addresses;
+       char **adr, **a;
+
+       krb5_set_extra_addresses(context, NULL);
+       adr = krb5_config_get_strings(context, NULL, 
+                                     "libdefaults", 
+                                     "extra_addresses", 
+                                     NULL);
+       memset(&addresses, 0, sizeof(addresses));
+       for(a = adr; a && *a; a++) {
+           ret = krb5_parse_address(context, *a, &addresses);
+           if (ret == 0) {
+               krb5_add_extra_addresses(context, &addresses);
+               krb5_free_addresses(context, &addresses);
+           }
+       }
+       krb5_config_free_strings(adr);
+
+       krb5_set_ignore_addresses(context, NULL);
+       adr = krb5_config_get_strings(context, NULL, 
+                                     "libdefaults", 
+                                     "ignore_addresses", 
+                                     NULL);
+       memset(&addresses, 0, sizeof(addresses));
+       for(a = adr; a && *a; a++) {
+           ret = krb5_parse_address(context, *a, &addresses);
+           if (ret == 0) {
+               krb5_add_ignore_addresses(context, &addresses);
+               krb5_free_addresses(context, &addresses);
+           }
+       }
+       krb5_config_free_strings(adr);
+    }
+    
+    INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces");
+    INIT_FIELD(context, int, fcache_vno, 0, "fcache_version");
+    /* prefer dns_lookup_kdc over srv_lookup. */
+    INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup");
+    INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc");
+    INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size");
+    context->default_cc_name = NULL;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_context(krb5_context *context)
+{
+    krb5_context p;
+    krb5_error_code ret;
+    char **files;
+
+    *context = NULL;
+
+    p = calloc(1, sizeof(*p));
+    if(!p)
+       return ENOMEM;
+
+    p->mutex = malloc(sizeof(HEIMDAL_MUTEX));
+    if (p->mutex == NULL) {
+       free(p);
+       return ENOMEM;
+    }
+    HEIMDAL_MUTEX_init(p->mutex);
+
+    ret = krb5_get_default_config_files(&files);
+    if(ret) 
+       goto out;
+    ret = krb5_set_config_files(p, files);
+    krb5_free_config_files(files);
+    if(ret) 
+       goto out;
+
+    /* init error tables */
+    krb5_init_ets(p);
+
+    p->cc_ops = NULL;
+    p->num_cc_ops = 0;
+    krb5_cc_register(p, &krb5_acc_ops, TRUE);
+    krb5_cc_register(p, &krb5_fcc_ops, TRUE);
+    krb5_cc_register(p, &krb5_mcc_ops, TRUE);
+#ifdef HAVE_KCM
+    krb5_cc_register(p, &krb5_kcm_ops, TRUE);
+#endif
+
+    p->num_kt_types = 0;
+    p->kt_types     = NULL;
+    krb5_kt_register (p, &krb5_fkt_ops);
+    krb5_kt_register (p, &krb5_wrfkt_ops);
+    krb5_kt_register (p, &krb5_javakt_ops);
+    krb5_kt_register (p, &krb5_mkt_ops);
+    krb5_kt_register (p, &krb5_akf_ops);
+    krb5_kt_register (p, &krb4_fkt_ops);
+    krb5_kt_register (p, &krb5_srvtab_fkt_ops);
+    krb5_kt_register (p, &krb5_any_ops);
+
+out:
+    if(ret) {
+       krb5_free_context(p);
+       p = NULL;
+    }
+    *context = p;
+    return ret;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_context(krb5_context context)
+{
+    if (context->default_cc_name)
+       free(context->default_cc_name);
+    free(context->etypes);
+    free(context->etypes_des);
+    krb5_free_host_realm (context, context->default_realms);
+    krb5_config_file_free (context, context->cf);
+    free_error_table (context->et_list);
+    free(context->cc_ops);
+    free(context->kt_types);
+    krb5_clear_error_string(context);
+    if(context->warn_dest != NULL)
+       krb5_closelog(context, context->warn_dest);
+    krb5_set_extra_addresses(context, NULL);
+    krb5_set_ignore_addresses(context, NULL);
+    if (context->mutex != NULL) {
+       HEIMDAL_MUTEX_destroy(context->mutex);
+       free(context->mutex);
+    }
+    memset(context, 0, sizeof(*context));
+    free(context);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_config_files(krb5_context context, char **filenames)
+{
+    krb5_error_code ret;
+    krb5_config_binding *tmp = NULL;
+    while(filenames != NULL && *filenames != NULL && **filenames != '\0') {
+       ret = krb5_config_parse_file_multi(context, *filenames, &tmp);
+       if(ret != 0 && ret != ENOENT && ret != EACCES) {
+           krb5_config_file_free(context, tmp);
+           return ret;
+       }
+       filenames++;
+    }
+#if 0
+    /* with this enabled and if there are no config files, Kerberos is
+       considererd disabled */
+    if(tmp == NULL)
+       return ENXIO;
+#endif
+    krb5_config_file_free(context, context->cf);
+    context->cf = tmp;
+    ret = init_context_from_config_file(context);
+    return ret;
+}
+
+static krb5_error_code
+add_file(char ***pfilenames, int *len, char *file)
+{
+    char **pp = *pfilenames;
+    int i;
+
+    for(i = 0; i < *len; i++) {
+       if(strcmp(pp[i], file) == 0) {
+           free(file);
+           return 0;
+       }
+    }
+
+    pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp));
+    if (pp == NULL) {
+       free(file);
+       return ENOMEM;
+    }
+
+    pp[*len] = file;
+    pp[*len + 1] = NULL;
+    *pfilenames = pp;
+    *len += 1;
+    return 0;
+}
+
+/*
+ *  `pq' isn't free, its up the the caller
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp)
+{
+    krb5_error_code ret;
+    const char *p, *q;
+    char **pp;
+    int len;
+    char *fn;
+
+    pp = NULL;
+
+    len = 0;
+    p = filelist;
+    while(1) {
+       ssize_t l;
+       q = p;
+       l = strsep_copy(&q, ":", NULL, 0);
+       if(l == -1)
+           break;
+       fn = malloc(l + 1);
+       if(fn == NULL) {
+           krb5_free_config_files(pp);
+           return ENOMEM;
+       }
+       l = strsep_copy(&p, ":", fn, l + 1);
+       ret = add_file(&pp, &len, fn);
+       if (ret) {
+           krb5_free_config_files(pp);
+           return ret;
+       }
+    }
+
+    if (pq != NULL) {
+       int i;
+
+       for (i = 0; pq[i] != NULL; i++) {
+           fn = strdup(pq[i]);
+           if (fn == NULL) {
+               krb5_free_config_files(pp);
+               return ENOMEM;
+           }
+           ret = add_file(&pp, &len, fn);
+           if (ret) {
+               krb5_free_config_files(pp);
+               return ret;
+           }
+       }
+    }
+
+    *ret_pp = pp;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_prepend_config_files_default(const char *filelist, char ***pfilenames)
+{
+    krb5_error_code ret;
+    char **defpp, **pp = NULL;
+    
+    ret = krb5_get_default_config_files(&defpp);
+    if (ret)
+       return ret;
+
+    ret = krb5_prepend_config_files(filelist, defpp, &pp);
+    krb5_free_config_files(defpp);
+    if (ret) {
+       return ret;
+    }  
+    *pfilenames = pp;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION 
+krb5_get_default_config_files(char ***pfilenames)
+{
+    const char *files = NULL;
+
+    if (pfilenames == NULL)
+        return EINVAL;
+    if(!issuid())
+       files = getenv("KRB5_CONFIG");
+    if (files == NULL)
+       files = krb5_config_file;
+
+    return krb5_prepend_config_files(files, NULL, pfilenames);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_config_files(char **filenames)
+{
+    char **p;
+    for(p = filenames; *p != NULL; p++)
+       free(*p);
+    free(filenames);
+}
+
+/*
+ * set `etype' to a malloced list of the default enctypes
+ */
+
+static krb5_error_code
+default_etypes(krb5_context context, krb5_enctype **etype)
+{
+    krb5_enctype p[] = {
+       ETYPE_AES256_CTS_HMAC_SHA1_96,
+       ETYPE_AES128_CTS_HMAC_SHA1_96,
+       ETYPE_DES3_CBC_SHA1,
+       ETYPE_DES3_CBC_MD5,
+       ETYPE_ARCFOUR_HMAC_MD5,
+       ETYPE_DES_CBC_MD5,
+       ETYPE_DES_CBC_MD4,
+       ETYPE_DES_CBC_CRC
+    };
+    krb5_enctype *e = NULL, *ep;
+    int i, n = 0;
+
+    for (i = 0; i < sizeof(p)/sizeof(p[0]); i++) {
+       if (krb5_enctype_valid(context, p[i]) != 0)
+           continue;
+       ep = realloc(e, (n + 2) * sizeof(*e));
+       if (ep == NULL) {
+           free(e);
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       e = ep;
+       e[n] = p[i];
+       e[n + 1] = ETYPE_NULL;
+       n++;
+    }
+    *etype = e;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_default_in_tkt_etypes(krb5_context context, 
+                              const krb5_enctype *etypes)
+{
+    krb5_enctype *p = NULL;
+    int i;
+
+    if(etypes) {
+       for (i = 0; etypes[i]; ++i) {
+           krb5_error_code ret;
+           ret = krb5_enctype_valid(context, etypes[i]);
+           if (ret)
+               return ret;
+       }
+       ++i;
+       ALLOC(p, i);
+       if(!p) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       memmove(p, etypes, i * sizeof(krb5_enctype));
+    }
+    if(context->etypes)
+       free(context->etypes);
+    context->etypes = p;
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_in_tkt_etypes(krb5_context context,
+                              krb5_enctype **etypes)
+{
+  krb5_enctype *p;
+  int i;
+  krb5_error_code ret;
+
+  if(context->etypes) {
+    for(i = 0; context->etypes[i]; i++);
+    ++i;
+    ALLOC(p, i);
+    if(!p) {
+      krb5_set_error_string (context, "malloc: out of memory");
+      return ENOMEM;
+    }
+    memmove(p, context->etypes, i * sizeof(krb5_enctype));
+  } else {
+    ret = default_etypes(context, &p);
+    if (ret)
+      return ret;
+  }
+  *etypes = p;
+  return 0;
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_get_err_text(krb5_context context, krb5_error_code code)
+{
+    const char *p = NULL;
+    if(context != NULL)
+       p = com_right(context->et_list, code);
+    if(p == NULL)
+       p = strerror(code);
+    if (p == NULL)
+       p = "Unknown error";
+    return p;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_init_ets(krb5_context context)
+{
+    if(context->et_list == NULL){
+       krb5_add_et_list(context, initialize_krb5_error_table_r);
+       krb5_add_et_list(context, initialize_asn1_error_table_r);
+       krb5_add_et_list(context, initialize_heim_error_table_r);
+       krb5_add_et_list(context, initialize_k524_error_table_r);
+    }
+}
+
+void KRB5_LIB_FUNCTION
+krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag)
+{
+    context->use_admin_kdc = flag;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_get_use_admin_kdc (krb5_context context)
+{
+    return context->use_admin_kdc;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses)
+{
+
+    if(context->extra_addresses)
+       return krb5_append_addresses(context, 
+                                    context->extra_addresses, addresses);
+    else
+       return krb5_set_extra_addresses(context, addresses);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses)
+{
+    if(context->extra_addresses)
+       krb5_free_addresses(context, context->extra_addresses);
+
+    if(addresses == NULL) {
+       if(context->extra_addresses != NULL) {
+           free(context->extra_addresses);
+           context->extra_addresses = NULL;
+       }
+       return 0;
+    }
+    if(context->extra_addresses == NULL) {
+       context->extra_addresses = malloc(sizeof(*context->extra_addresses));
+       if(context->extra_addresses == NULL) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+    }
+    return krb5_copy_addresses(context, addresses, context->extra_addresses);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses)
+{
+    if(context->extra_addresses == NULL) {
+       memset(addresses, 0, sizeof(*addresses));
+       return 0;
+    }
+    return krb5_copy_addresses(context,context->extra_addresses, addresses);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses)
+{
+
+    if(context->ignore_addresses)
+       return krb5_append_addresses(context, 
+                                    context->ignore_addresses, addresses);
+    else
+       return krb5_set_ignore_addresses(context, addresses);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses)
+{
+    if(context->ignore_addresses)
+       krb5_free_addresses(context, context->ignore_addresses);
+    if(addresses == NULL) {
+       if(context->ignore_addresses != NULL) {
+           free(context->ignore_addresses);
+           context->ignore_addresses = NULL;
+       }
+       return 0;
+    }
+    if(context->ignore_addresses == NULL) {
+       context->ignore_addresses = malloc(sizeof(*context->ignore_addresses));
+       if(context->ignore_addresses == NULL) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+    }
+    return krb5_copy_addresses(context, addresses, context->ignore_addresses);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses)
+{
+    if(context->ignore_addresses == NULL) {
+       memset(addresses, 0, sizeof(*addresses));
+       return 0;
+    }
+    return krb5_copy_addresses(context, context->ignore_addresses, addresses);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_fcache_version(krb5_context context, int version)
+{
+    context->fcache_vno = version;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_fcache_version(krb5_context context, int *version)
+{
+    *version = context->fcache_vno;
+    return 0;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_is_thread_safe(void)
+{
+#ifdef ENABLE_PTHREAD_SUPPORT
+    return TRUE;
+#else
+    return FALSE;
+#endif
+}
diff --git a/src/kerberosV/src/lib/krb5/convert_creds.c b/src/kerberosV/src/lib/krb5/convert_creds.c
new file mode 100644 (file)
index 0000000..0bf0899
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+RCSID("$KTH: convert_creds.c,v 1.32 2005/04/23 19:40:57 lha Exp $");
+
+#include "krb5-v4compat.h"
+
+static krb5_error_code
+check_ticket_flags(TicketFlags f)
+{
+    return 0; /* maybe add some more tests here? */
+}
+
+/* Convert the v5 credentials in `in_cred' to v4-dito in `v4creds'.
+ * This is done by sending them to the 524 function in the KDC.  If
+ * `in_cred' doesn't contain a DES session key, then a new one is
+ * gotten from the KDC and stored in the cred cache `ccache'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb524_convert_creds_kdc(krb5_context context, 
+                        krb5_creds *in_cred,
+                        struct credentials *v4creds)
+{
+    krb5_error_code ret;
+    krb5_data reply;
+    krb5_storage *sp;
+    int32_t tmp;
+    krb5_data ticket;
+    char realm[REALM_SZ];
+    krb5_creds *v5_creds = in_cred;
+
+    ret = check_ticket_flags(v5_creds->flags.b);
+    if(ret)
+       goto out2;
+
+    {
+       krb5_krbhst_handle handle;
+
+       ret = krb5_krbhst_init(context,
+                              krb5_principal_get_realm(context, 
+                                                       v5_creds->server),
+                              KRB5_KRBHST_KRB524,
+                              &handle);
+       if (ret)
+           goto out2;
+
+       ret = krb5_sendto (context,
+                          &v5_creds->ticket,
+                          handle,
+                          &reply);
+       krb5_krbhst_free(context, handle);
+       if (ret)
+           goto out2;
+    }
+    sp = krb5_storage_from_mem(reply.data, reply.length);
+    if(sp == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string (context, "malloc: out of memory");
+       goto out2;
+    }
+    krb5_ret_int32(sp, &tmp);
+    ret = tmp;
+    if(ret == 0) {
+       memset(v4creds, 0, sizeof(*v4creds));
+       ret = krb5_ret_int32(sp, &tmp);
+       if(ret)
+           goto out;
+       v4creds->kvno = tmp;
+       ret = krb5_ret_data(sp, &ticket);
+       if(ret)
+           goto out;
+       v4creds->ticket_st.length = ticket.length;
+       memcpy(v4creds->ticket_st.dat, ticket.data, ticket.length);
+       krb5_data_free(&ticket);
+       ret = krb5_524_conv_principal(context, 
+                                     v5_creds->server, 
+                                     v4creds->service, 
+                                     v4creds->instance, 
+                                     v4creds->realm);
+       if(ret)
+           goto out;
+       v4creds->issue_date = v5_creds->times.starttime;
+       v4creds->lifetime = _krb5_krb_time_to_life(v4creds->issue_date,
+                                                  v5_creds->times.endtime);
+       ret = krb5_524_conv_principal(context, v5_creds->client, 
+                                     v4creds->pname, 
+                                     v4creds->pinst, 
+                                     realm);
+       if(ret)
+           goto out;
+       memcpy(v4creds->session, v5_creds->session.keyvalue.data, 8);
+    } else {
+       krb5_set_error_string(context, "converting credentials: %s", 
+                             krb5_get_err_text(context, ret));
+    }
+out:
+    krb5_storage_free(sp);
+    krb5_data_free(&reply);
+out2:
+    if (v5_creds != in_cred)
+       krb5_free_creds (context, v5_creds);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb524_convert_creds_kdc_ccache(krb5_context context, 
+                               krb5_ccache ccache,
+                               krb5_creds *in_cred,
+                               struct credentials *v4creds)
+{
+    krb5_error_code ret;
+    krb5_creds *v5_creds = in_cred;
+    krb5_keytype keytype;
+
+    keytype = v5_creds->session.keytype;
+
+    if (keytype != ENCTYPE_DES_CBC_CRC) {
+       /* MIT krb524d doesn't like nothing but des-cbc-crc tickets,
+           so go get one */
+       krb5_creds template;
+
+       memset (&template, 0, sizeof(template));
+       template.session.keytype = ENCTYPE_DES_CBC_CRC;
+       ret = krb5_copy_principal (context, in_cred->client, &template.client);
+       if (ret) {
+           krb5_free_cred_contents (context, &template);
+           return ret;
+       }
+       ret = krb5_copy_principal (context, in_cred->server, &template.server);
+       if (ret) {
+           krb5_free_cred_contents (context, &template);
+           return ret;
+       }
+
+       ret = krb5_get_credentials (context, 0, ccache,
+                                   &template, &v5_creds);
+       krb5_free_cred_contents (context, &template);
+       if (ret)
+           return ret;
+    }
+
+    ret = krb524_convert_creds_kdc(context, v5_creds, v4creds);
+
+    if (v5_creds != in_cred)
+       krb5_free_creds (context, v5_creds);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/copy_host_realm.c b/src/kerberosV/src/lib/krb5/copy_host_realm.c
new file mode 100644 (file)
index 0000000..277e526
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: copy_host_realm.c,v 1.5 2004/05/25 21:21:17 lha Exp $");
+
+/*
+ * Copy the list of realms from `from' to `to'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_host_realm(krb5_context context,
+                    const krb5_realm *from,
+                    krb5_realm **to)
+{
+    int n, i;
+    const krb5_realm *p;
+
+    for (n = 0, p = from; *p != NULL; ++p)
+       ++n;
+    ++n;
+    *to = malloc (n * sizeof(**to));
+    if (*to == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    for (i = 0; i < n; ++i)
+       (*to)[i] = NULL;
+    for (i = 0, p = from; *p != NULL; ++p, ++i) {
+       (*to)[i] = strdup(*p);
+       if ((*to)[i] == NULL) {
+           krb5_free_host_realm (context, *to);
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/crc.c b/src/kerberosV/src/lib/krb5/crc.c
new file mode 100644 (file)
index 0000000..4e7b600
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1997 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: crc.c,v 1.9 2000/08/03 01:45:14 assar Exp $");
+
+static u_long table[256];
+
+#define CRC_GEN 0xEDB88320L
+
+void
+_krb5_crc_init_table(void)
+{
+    static int flag = 0;
+    unsigned long crc, poly;
+    int     i, j;
+    
+    if(flag) return;
+    poly = CRC_GEN;
+    for (i = 0; i < 256; i++) {
+       crc = i;
+       for (j = 8; j > 0; j--) {
+           if (crc & 1) {
+               crc = (crc >> 1) ^ poly;
+           } else {
+               crc >>= 1;
+           }
+       }
+       table[i] = crc;
+    }
+    flag = 1;
+}
+
+u_int32_t
+_krb5_crc_update (const char *p, size_t len, u_int32_t res)
+{
+    while (len--)
+       res = table[(res ^ *p++) & 0xFF] ^ (res >> 8);
+    return res & 0xFFFFFFFF;
+}
diff --git a/src/kerberosV/src/lib/krb5/creds.c b/src/kerberosV/src/lib/krb5/creds.c
new file mode 100644 (file)
index 0000000..b05e8e4
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: creds.c,v 1.20 2005/05/18 04:21:04 lha Exp $");
+
+/* keep this for compatibility with older code */
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_creds_contents (krb5_context context, krb5_creds *c)
+{
+    return krb5_free_cred_contents (context, c);
+}    
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_cred_contents (krb5_context context, krb5_creds *c)
+{
+    krb5_free_principal (context, c->client);
+    c->client = NULL;
+    krb5_free_principal (context, c->server);
+    c->server = NULL;
+    krb5_free_keyblock_contents (context, &c->session);
+    krb5_data_free (&c->ticket);
+    krb5_data_free (&c->second_ticket);
+    free_AuthorizationData (&c->authdata);
+    krb5_free_addresses (context, &c->addresses);
+    memset(c, 0, sizeof(*c));
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_creds_contents (krb5_context context,
+                         const krb5_creds *incred,
+                         krb5_creds *c)
+{
+    krb5_error_code ret;
+
+    memset(c, 0, sizeof(*c));
+    ret = krb5_copy_principal (context, incred->client, &c->client);
+    if (ret)
+       goto fail;
+    ret = krb5_copy_principal (context, incred->server, &c->server);
+    if (ret)
+       goto fail;
+    ret = krb5_copy_keyblock_contents (context, &incred->session, &c->session);
+    if (ret)
+       goto fail;
+    c->times = incred->times;
+    ret = krb5_data_copy (&c->ticket,
+                         incred->ticket.data,
+                         incred->ticket.length);
+    if (ret)
+       goto fail;
+    ret = krb5_data_copy (&c->second_ticket,
+                         incred->second_ticket.data,
+                         incred->second_ticket.length);
+    if (ret)
+       goto fail;
+    ret = copy_AuthorizationData(&incred->authdata, &c->authdata);
+    if (ret)
+       goto fail;
+    ret = krb5_copy_addresses (context,
+                              &incred->addresses,
+                              &c->addresses);
+    if (ret)
+       goto fail;
+    c->flags = incred->flags;
+    return 0;
+
+fail:
+    krb5_free_cred_contents (context, c);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_creds (krb5_context context,
+                const krb5_creds *incred,
+                krb5_creds **outcred)
+{
+    krb5_creds *c;
+
+    c = malloc (sizeof (*c));
+    if (c == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memset (c, 0, sizeof(*c));
+    *outcred = c;
+    return krb5_copy_creds_contents (context, incred, c);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_creds (krb5_context context, krb5_creds *c)
+{
+    krb5_free_cred_contents (context, c);
+    free (c);
+    return 0;
+}
+
+/* XXX these do not belong here */
+static krb5_boolean
+krb5_data_equal(const krb5_data *a, const krb5_data *b)
+{
+    if(a->length != b->length)
+       return FALSE;
+    return memcmp(a->data, b->data, a->length) == 0;
+}
+
+static krb5_boolean
+krb5_times_equal(const krb5_times *a, const krb5_times *b)
+{
+    return a->starttime == b->starttime &&
+       a->authtime == b->authtime &&
+       a->endtime == b->endtime &&
+       a->renew_till == b->renew_till;
+}
+
+/*
+ * Return TRUE if `mcreds' and `creds' are equal (`whichfields'
+ * determines what equal means).
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_compare_creds(krb5_context context, krb5_flags whichfields,
+                  const krb5_creds * mcreds, const krb5_creds * creds)
+{
+    krb5_boolean match = TRUE;
+    
+    if (match && mcreds->server) {
+       if (whichfields & (KRB5_TC_DONT_MATCH_REALM | KRB5_TC_MATCH_SRV_NAMEONLY)) 
+           match = krb5_principal_compare_any_realm (context, mcreds->server, 
+                                                     creds->server);
+       else
+           match = krb5_principal_compare (context, mcreds->server, 
+                                           creds->server);
+    }
+
+    if (match && mcreds->client) {
+       if(whichfields & KRB5_TC_DONT_MATCH_REALM)
+           match = krb5_principal_compare_any_realm (context, mcreds->client, 
+                                                     creds->client);
+       else
+           match = krb5_principal_compare (context, mcreds->client, 
+                                           creds->client);
+    }
+           
+    if (match && (whichfields & KRB5_TC_MATCH_KEYTYPE))
+       match = krb5_enctypes_compatible_keys(context,
+                                             mcreds->session.keytype,
+                                             creds->session.keytype);
+
+    if (match && (whichfields & KRB5_TC_MATCH_FLAGS_EXACT))
+       match = mcreds->flags.i == creds->flags.i;
+
+    if (match && (whichfields & KRB5_TC_MATCH_FLAGS))
+       match = (creds->flags.i & mcreds->flags.i) == mcreds->flags.i;
+
+    if (match && (whichfields & KRB5_TC_MATCH_TIMES_EXACT))
+       match = krb5_times_equal(&mcreds->times, &creds->times);
+    
+    if (match && (whichfields & KRB5_TC_MATCH_TIMES))
+       /* compare only expiration times */
+       match = (mcreds->times.renew_till <= creds->times.renew_till) &&
+           (mcreds->times.endtime <= creds->times.endtime);
+
+    if (match && (whichfields & KRB5_TC_MATCH_AUTHDATA)) {
+       unsigned int i;
+       if(mcreds->authdata.len != creds->authdata.len)
+           match = FALSE;
+       else
+           for(i = 0; match && i < mcreds->authdata.len; i++)
+               match = (mcreds->authdata.val[i].ad_type == 
+                        creds->authdata.val[i].ad_type) &&
+                   krb5_data_equal(&mcreds->authdata.val[i].ad_data,
+                                   &creds->authdata.val[i].ad_data);
+    }
+    if (match && (whichfields & KRB5_TC_MATCH_2ND_TKT))
+       match = krb5_data_equal(&mcreds->second_ticket, &creds->second_ticket);
+
+    if (match && (whichfields & KRB5_TC_MATCH_IS_SKEY))
+       match = ((mcreds->second_ticket.length == 0) == 
+                (creds->second_ticket.length == 0));
+
+    return match;
+}
diff --git a/src/kerberosV/src/lib/krb5/crypto.c b/src/kerberosV/src/lib/krb5/crypto.c
new file mode 100644 (file)
index 0000000..f827320
--- /dev/null
@@ -0,0 +1,4421 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+RCSID("$KTH: crypto.c,v 1.120.2.1 2005/08/11 07:56:11 lha Exp $");
+
+#undef CRYPTO_DEBUG
+#ifdef CRYPTO_DEBUG
+static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*);
+#endif
+
+
+struct key_data {
+    krb5_keyblock *key;
+    krb5_data *schedule;
+};
+
+struct key_usage {
+    unsigned usage;
+    struct key_data key;
+};
+
+struct krb5_crypto_data {
+    struct encryption_type *et;
+    struct key_data key;
+    int num_key_usage;
+    struct key_usage *key_usage;
+    void *params;
+};
+
+#define kcrypto_oid_enc(n) { sizeof(n)/sizeof(n[0]), n }
+
+#define CRYPTO_ETYPE(C) ((C)->et->type)
+
+/* bits for `flags' below */
+#define F_KEYED                 1      /* checksum is keyed */
+#define F_CPROOF        2      /* checksum is collision proof */
+#define F_DERIVED       4      /* uses derived keys */
+#define F_VARIANT       8      /* uses `variant' keys (6.4.3) */
+#define F_PSEUDO       16      /* not a real protocol type */
+#define F_SPECIAL      32      /* backwards */
+#define F_DISABLED     64      /* enctype/checksum disabled */
+#define F_PADCMS       128     /* padding done like in CMS */
+
+struct salt_type {
+    krb5_salttype type;
+    const char *name;
+    krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data, 
+                                    krb5_salt, krb5_data, krb5_keyblock*);
+};
+
+struct key_type {
+    krb5_keytype type; /* XXX */
+    const char *name;
+    size_t bits;
+    size_t size;
+    size_t minsize;
+    size_t schedule_size;
+#if 0
+    krb5_enctype best_etype;
+#endif
+    void (*random_key)(krb5_context, krb5_keyblock*);
+    void (*schedule)(krb5_context, struct key_data *, const void *);
+    struct salt_type *string_to_key;
+    void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t);
+    krb5_error_code (*get_params)(krb5_context, const krb5_data *,
+                                 void **, krb5_data *);
+    krb5_error_code (*set_params)(krb5_context, const void *,
+                                 const krb5_data *, krb5_data *);
+};
+
+struct checksum_type {
+    krb5_cksumtype type;
+    const char *name;
+    size_t blocksize;
+    size_t checksumsize;
+    unsigned flags;
+    void (*checksum)(krb5_context context,
+                    struct key_data *key,
+                    const void *buf, size_t len,
+                    unsigned usage,
+                    Checksum *csum);
+    krb5_error_code (*verify)(krb5_context context,
+                             struct key_data *key,
+                             const void *buf, size_t len,
+                             unsigned usage,
+                             Checksum *csum);
+};
+
+struct encryption_type {
+    krb5_enctype type;
+    const char *name;
+    heim_oid *oid;
+    size_t blocksize;
+    size_t padsize;
+    size_t confoundersize;
+    struct key_type *keytype;
+    struct checksum_type *checksum;
+    struct checksum_type *keyed_checksum;
+    unsigned flags;
+    krb5_error_code (*encrypt)(krb5_context context,
+                              struct key_data *key,
+                              void *data, size_t len,
+                              krb5_boolean encrypt,
+                              int usage,
+                              void *ivec);
+};
+
+#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA)
+#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55)
+#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99)
+
+static struct checksum_type *_find_checksum(krb5_cksumtype type);
+static struct encryption_type *_find_enctype(krb5_enctype type);
+static struct key_type *_find_keytype(krb5_keytype type);
+static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, 
+                                       unsigned, struct key_data**);
+static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage);
+static krb5_error_code derive_key(krb5_context context,
+                                 struct encryption_type *et,
+                                 struct key_data *key,
+                                 const void *constant,
+                                 size_t len);
+static krb5_error_code hmac(krb5_context context,
+                           struct checksum_type *cm, 
+                           const void *data, 
+                           size_t len, 
+                           unsigned usage,
+                           struct key_data *keyblock,
+                           Checksum *result);
+static void free_key_data(krb5_context context, struct key_data *key);
+static krb5_error_code usage2arcfour (krb5_context, unsigned *);
+static void xor (DES_cblock *, const unsigned char *);
+
+/************************************************************
+ *                                                          *
+ ************************************************************/
+
+static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER;
+
+
+static void
+krb5_DES_random_key(krb5_context context,
+              krb5_keyblock *key)
+{
+    DES_cblock *k = key->keyvalue.data;
+    do {
+       krb5_generate_random_block(k, sizeof(DES_cblock));
+       DES_set_odd_parity(k);
+    } while(DES_is_weak_key(k));
+}
+
+static void
+krb5_DES_schedule(krb5_context context,
+                 struct key_data *key,
+                 const void *params)
+{
+    DES_set_key(key->key->keyvalue.data, key->schedule->data);
+}
+
+static void
+DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key)
+{
+    DES_key_schedule schedule;
+    int i;
+    int reverse = 0;
+    unsigned char *p;
+
+    unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 
+                            0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf };
+    memset(key, 0, 8);
+    
+    p = (unsigned char*)key;
+    for (i = 0; i < length; i++) {
+       unsigned char tmp = data[i];
+       if (!reverse)
+           *p++ ^= (tmp << 1);
+       else
+           *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4];
+       if((i % 8) == 7)
+           reverse = !reverse;
+    }
+    DES_set_odd_parity(key);
+    if(DES_is_weak_key(key))
+       (*key)[7] ^= 0xF0;
+    DES_set_key(key, &schedule);
+    DES_cbc_cksum((void*)data, key, length, &schedule, key);
+    memset(&schedule, 0, sizeof(schedule));
+    DES_set_odd_parity(key);
+    if(DES_is_weak_key(key))
+       (*key)[7] ^= 0xF0;
+}
+
+static krb5_error_code
+krb5_DES_string_to_key(krb5_context context,
+                 krb5_enctype enctype,
+                 krb5_data password,
+                 krb5_salt salt,
+                 krb5_data opaque,
+                 krb5_keyblock *key)
+{
+    unsigned char *s;
+    size_t len;
+    DES_cblock tmp;
+
+    len = password.length + salt.saltvalue.length;
+    s = malloc(len);
+    if(len > 0 && s == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(s, password.data, password.length);
+    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
+    DES_string_to_key_int(s, len, &tmp);
+    key->keytype = enctype;
+    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
+    memset(&tmp, 0, sizeof(tmp));
+    memset(s, 0, len);
+    free(s);
+    return 0;
+}
+
+/* This defines the Andrew string_to_key function.  It accepts a password
+ * string as input and converts its via a one-way encryption algorithm to a DES
+ * encryption key.  It is compatible with the original Andrew authentication
+ * service password database.
+ */
+
+/*
+ * Short passwords, i.e 8 characters or less.
+ */
+static void
+krb5_DES_AFS3_CMU_string_to_key (krb5_data pw,
+                           krb5_data cell,
+                           DES_cblock *key)
+{
+    char  password[8+1];       /* crypt is limited to 8 chars anyway */
+    int   i;
+    
+    for(i = 0; i < 8; i++) {
+       char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^
+                ((i < cell.length) ?
+                 tolower(((unsigned char*)cell.data)[i]) : 0);
+       password[i] = c ? c : 'X';
+    }
+    password[8] = '\0';
+
+    memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock));
+
+    /* parity is inserted into the LSB so left shift each byte up one
+       bit. This allows ascii characters with a zero MSB to retain as
+       much significance as possible. */
+    for (i = 0; i < sizeof(DES_cblock); i++)
+       ((unsigned char*)key)[i] <<= 1;
+    DES_set_odd_parity (key);
+}
+
+/*
+ * Long passwords, i.e 9 characters or more.
+ */
+static void
+krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw,
+                                krb5_data cell,
+                                DES_cblock *key)
+{
+    DES_key_schedule schedule;
+    DES_cblock temp_key;
+    DES_cblock ivec;
+    char password[512];
+    size_t passlen;
+
+    memcpy(password, pw.data, min(pw.length, sizeof(password)));
+    if(pw.length < sizeof(password)) {
+       int len = min(cell.length, sizeof(password) - pw.length);
+       int i;
+
+       memcpy(password + pw.length, cell.data, len);
+       for (i = pw.length; i < pw.length + len; ++i)
+           password[i] = tolower((unsigned char)password[i]);
+    }
+    passlen = min(sizeof(password), pw.length + cell.length);
+    memcpy(&ivec, "kerberos", 8);
+    memcpy(&temp_key, "kerberos", 8);
+    DES_set_odd_parity (&temp_key);
+    DES_set_key (&temp_key, &schedule);
+    DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec);
+
+    memcpy(&temp_key, &ivec, 8);
+    DES_set_odd_parity (&temp_key);
+    DES_set_key (&temp_key, &schedule);
+    DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec);
+    memset(&schedule, 0, sizeof(schedule));
+    memset(&temp_key, 0, sizeof(temp_key));
+    memset(&ivec, 0, sizeof(ivec));
+    memset(password, 0, sizeof(password));
+
+    DES_set_odd_parity (key);
+}
+
+static krb5_error_code
+DES_AFS3_string_to_key(krb5_context context,
+                      krb5_enctype enctype,
+                      krb5_data password,
+                      krb5_salt salt,
+                      krb5_data opaque,
+                      krb5_keyblock *key)
+{
+    DES_cblock tmp;
+    if(password.length > 8)
+       krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp);
+    else
+       krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp);
+    key->keytype = enctype;
+    krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp));
+    memset(&key, 0, sizeof(key));
+    return 0;
+}
+
+static void
+krb5_DES_random_to_key(krb5_context context,
+                      krb5_keyblock *key,
+                      const void *data,
+                      size_t size)
+{
+    DES_cblock *k = key->keyvalue.data;
+    memcpy(k, data, key->keyvalue.length);
+    DES_set_odd_parity(k);
+    if(DES_is_weak_key(k))
+       xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+}
+
+/*
+ *
+ */
+
+static void
+DES3_random_key(krb5_context context,
+               krb5_keyblock *key)
+{
+    DES_cblock *k = key->keyvalue.data;
+    do {
+       krb5_generate_random_block(k, 3 * sizeof(DES_cblock));
+       DES_set_odd_parity(&k[0]);
+       DES_set_odd_parity(&k[1]);
+       DES_set_odd_parity(&k[2]);
+    } while(DES_is_weak_key(&k[0]) ||
+           DES_is_weak_key(&k[1]) ||
+           DES_is_weak_key(&k[2]));
+}
+
+static void
+DES3_schedule(krb5_context context,
+             struct key_data *key,
+             const void *params)
+{
+    DES_cblock *k = key->key->keyvalue.data;
+    DES_key_schedule *s = key->schedule->data;
+    DES_set_key(&k[0], &s[0]);
+    DES_set_key(&k[1], &s[1]);
+    DES_set_key(&k[2], &s[2]);
+}
+
+/*
+ * A = A xor B. A & B are 8 bytes.
+ */
+
+static void
+xor (DES_cblock *key, const unsigned char *b)
+{
+    unsigned char *a = (unsigned char*)key;
+    a[0] ^= b[0];
+    a[1] ^= b[1];
+    a[2] ^= b[2];
+    a[3] ^= b[3];
+    a[4] ^= b[4];
+    a[5] ^= b[5];
+    a[6] ^= b[6];
+    a[7] ^= b[7];
+}
+
+static krb5_error_code
+DES3_string_to_key(krb5_context context,
+                  krb5_enctype enctype,
+                  krb5_data password,
+                  krb5_salt salt,
+                  krb5_data opaque,
+                  krb5_keyblock *key)
+{
+    char *str;
+    size_t len;
+    unsigned char tmp[24];
+    DES_cblock keys[3];
+    
+    len = password.length + salt.saltvalue.length;
+    str = malloc(len);
+    if(len != 0 && str == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(str, password.data, password.length);
+    memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length);
+    {
+       DES_cblock ivec;
+       DES_key_schedule s[3];
+       int i;
+       
+       _krb5_n_fold(str, len, tmp, 24);
+       
+       for(i = 0; i < 3; i++){
+           memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
+           DES_set_odd_parity(keys + i);
+           if(DES_is_weak_key(keys + i))
+               xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+           DES_set_key(keys + i, &s[i]);
+       }
+       memset(&ivec, 0, sizeof(ivec));
+       DES_ede3_cbc_encrypt(tmp,
+                            tmp, sizeof(tmp), 
+                            &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT);
+       memset(s, 0, sizeof(s));
+       memset(&ivec, 0, sizeof(ivec));
+       for(i = 0; i < 3; i++){
+           memcpy(keys + i, tmp + i * 8, sizeof(keys[i]));
+           DES_set_odd_parity(keys + i);
+           if(DES_is_weak_key(keys + i))
+               xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+       }
+       memset(tmp, 0, sizeof(tmp));
+    }
+    key->keytype = enctype;
+    krb5_data_copy(&key->keyvalue, keys, sizeof(keys));
+    memset(keys, 0, sizeof(keys));
+    memset(str, 0, len);
+    free(str);
+    return 0;
+}
+
+static krb5_error_code
+DES3_string_to_key_derived(krb5_context context,
+                          krb5_enctype enctype,
+                          krb5_data password,
+                          krb5_salt salt,
+                          krb5_data opaque,
+                          krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    size_t len = password.length + salt.saltvalue.length;
+    char *s;
+
+    s = malloc(len);
+    if(len != 0 && s == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(s, password.data, password.length);
+    memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length);
+    ret = krb5_string_to_key_derived(context,
+                                    s,
+                                    len,
+                                    enctype,
+                                    key);
+    memset(s, 0, len);
+    free(s);
+    return ret;
+}
+
+static void
+DES3_random_to_key(krb5_context context,
+                  krb5_keyblock *key,
+                  const void *data,
+                  size_t size)
+{
+    unsigned char *x = key->keyvalue.data;
+    const u_char *q = data;
+    DES_cblock *k;
+    int i, j;
+
+    memset(x, 0, sizeof(x));
+    for (i = 0; i < 3; ++i) {
+       unsigned char foo;
+       for (j = 0; j < 7; ++j) {
+           unsigned char b = q[7 * i + j];
+
+           x[8 * i + j] = b;
+       }
+       foo = 0;
+       for (j = 6; j >= 0; --j) {
+           foo |= q[7 * i + j] & 1;
+           foo <<= 1;
+       }
+       x[8 * i + 7] = foo;
+    }
+    k = key->keyvalue.data;
+    for (i = 0; i < 3; i++) {
+       DES_set_odd_parity(&k[i]);
+       if(DES_is_weak_key(&k[i]))
+           xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0");
+    }    
+}
+
+/*
+ * ARCFOUR
+ */
+
+static void
+ARCFOUR_schedule(krb5_context context, 
+                struct key_data *kd,
+                const void *params)
+{
+    RC4_set_key (kd->schedule->data,
+                kd->key->keyvalue.length, kd->key->keyvalue.data);
+}
+
+static krb5_error_code
+ARCFOUR_string_to_key(krb5_context context,
+                 krb5_enctype enctype,
+                 krb5_data password,
+                 krb5_salt salt,
+                 krb5_data opaque,
+                 krb5_keyblock *key)
+{
+    char *s, *p;
+    size_t len;
+    int i;
+    MD4_CTX m;
+
+    len = 2 * password.length;
+    s = malloc (len);
+    if (len != 0 && s == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    for (p = s, i = 0; i < password.length; ++i) {
+       *p++ = ((char *)password.data)[i];
+       *p++ = 0;
+    }
+    MD4_Init (&m);
+    MD4_Update (&m, s, len);
+    key->keytype = enctype;
+    krb5_data_alloc (&key->keyvalue, 16);
+    MD4_Final (key->keyvalue.data, &m);
+    memset (s, 0, len);
+    free (s);
+    return 0;
+}
+
+/*
+ * AES
+ */
+
+/* iter is really 1 based, so iter == 0 will be 1 iteration */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_PKCS5_PBKDF2(krb5_context context, krb5_cksumtype cktype,
+                  krb5_data password, krb5_salt salt, u_int32_t iter,
+                  krb5_keytype type, krb5_keyblock *key)
+{
+    struct checksum_type *c = _find_checksum(cktype);
+    struct key_type *kt;
+    size_t datalen, leftofkey;
+    krb5_error_code ret;
+    u_int32_t keypart;
+    struct key_data ksign;
+    krb5_keyblock kb;
+    Checksum result;
+    char *data, *tmpcksum;
+    int i, j;
+    char *p;
+    
+    if (c == NULL) {
+       krb5_set_error_string(context, "checksum %d not supported", cktype);
+       return KRB5_PROG_KEYTYPE_NOSUPP;
+    }
+
+    kt = _find_keytype(type);
+    if (kt == NULL) {
+       krb5_set_error_string(context, "key type %d not supported", type);
+       return KRB5_PROG_KEYTYPE_NOSUPP;
+    }
+    
+    key->keytype = type;
+    ret = krb5_data_alloc (&key->keyvalue, kt->bits / 8);
+    if (ret) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ret;
+    }
+       
+    ret = krb5_data_alloc (&result.checksum, c->checksumsize);
+    if (ret) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       krb5_data_free (&key->keyvalue);
+       return ret;
+    }
+
+    tmpcksum = malloc(c->checksumsize);
+    if (tmpcksum == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       krb5_data_free (&key->keyvalue);
+       krb5_data_free (&result.checksum);
+       return ENOMEM;
+    }
+
+    datalen = salt.saltvalue.length + 4;
+    data = malloc(datalen);
+    if (data == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       free(tmpcksum);
+       krb5_data_free (&key->keyvalue);
+       krb5_data_free (&result.checksum);
+       return ENOMEM;
+    }
+
+    kb.keyvalue = password;
+    ksign.key = &kb;
+
+    memcpy(data, salt.saltvalue.data, salt.saltvalue.length);
+
+    keypart = 1;
+    leftofkey = key->keyvalue.length;
+    p = key->keyvalue.data;
+
+    while (leftofkey) {
+       int len;
+
+       if (leftofkey > c->checksumsize)
+           len = c->checksumsize;
+       else
+           len = leftofkey;
+
+       _krb5_put_int(data + datalen - 4, keypart, 4);
+
+       ret = hmac(context, c, data, datalen, 0, &ksign, &result);
+       if (ret)
+           krb5_abortx(context, "hmac failed");
+       memcpy(p, result.checksum.data, len);
+       memcpy(tmpcksum, result.checksum.data, result.checksum.length);
+       for (i = 0; i < iter; i++) {
+           ret = hmac(context, c, tmpcksum, result.checksum.length,
+                      0, &ksign, &result);
+           if (ret)
+               krb5_abortx(context, "hmac failed");
+           memcpy(tmpcksum, result.checksum.data, result.checksum.length);
+           for (j = 0; j < len; j++)
+               p[j] ^= tmpcksum[j];
+       }
+
+       p += len;
+       leftofkey -= len;
+       keypart++;
+    }
+
+    free(data);
+    free(tmpcksum);
+    krb5_data_free (&result.checksum);
+
+    return 0;
+}
+
+int _krb5_AES_string_to_default_iterator = 4096;
+
+static krb5_error_code
+AES_string_to_key(krb5_context context,
+                 krb5_enctype enctype,
+                 krb5_data password,
+                 krb5_salt salt,
+                 krb5_data opaque,
+                 krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    u_int32_t iter;
+    struct encryption_type *et;
+    struct key_data kd;
+
+    if (opaque.length == 0)
+       iter = _krb5_AES_string_to_default_iterator - 1;
+    else if (opaque.length == 4) {
+       unsigned long v;
+       _krb5_get_int(opaque.data, &v, 4);
+       iter = ((u_int32_t)v) - 1;
+    } else
+       return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */
+       
+
+    et = _find_enctype(enctype);
+    if (et == NULL)
+       return KRB5_PROG_KEYTYPE_NOSUPP;
+
+    ret = _krb5_PKCS5_PBKDF2(context, CKSUMTYPE_SHA1, password, salt, 
+                            iter, enctype, key);
+    if (ret)
+       return ret;
+
+    ret = krb5_copy_keyblock(context, key, &kd.key);
+    kd.schedule = NULL;
+
+    ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos"));
+    krb5_free_keyblock_contents(context, key);
+    if (ret == 0) {
+       ret = krb5_copy_keyblock_contents(context, kd.key, key);
+       free_key_data(context, &kd);
+    }
+
+    return ret;
+}
+
+struct krb5_aes_schedule {
+    AES_KEY ekey;
+    AES_KEY dkey;
+};
+
+static void
+AES_schedule(krb5_context context,
+            struct key_data *kd,
+            const void *params)
+{
+    struct krb5_aes_schedule *key = kd->schedule->data;
+    int bits = kd->key->keyvalue.length * 8;
+
+    memset(key, 0, sizeof(*key));
+    AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key->ekey);
+    AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey);
+}
+
+/*
+ * RC2
+ */
+
+struct _RC2_params {
+    int maximum_effective_key;
+};
+
+static krb5_error_code
+rc2_get_params(krb5_context context,
+              const krb5_data *data,
+              void **params,
+              krb5_data *ivec)
+{
+    RC2CBCParameter rc2params;
+    struct _RC2_params *p;
+    krb5_error_code ret;
+    size_t size;
+
+    ret = decode_RC2CBCParameter(data->data, data->length, &rc2params, &size);
+    if (ret) {
+       krb5_set_error_string(context, "Can't decode RC2 parameters");
+       return ret;
+    }
+    p = malloc(sizeof(*p));
+    if (p == NULL) {
+       free_RC2CBCParameter(&rc2params);
+       krb5_set_error_string(context, "malloc - out of memory");
+       return ENOMEM;
+    }
+    /* XXX  */
+    switch(rc2params.rc2ParameterVersion) {
+    case 160:
+       p->maximum_effective_key = 40;
+       break;
+    case 120:
+       p->maximum_effective_key = 64;
+       break;
+    case 58:
+       p->maximum_effective_key = 128;
+       break;
+       
+    }
+    if (ivec)
+       ret = copy_octet_string(&rc2params.iv, ivec);
+    free_RC2CBCParameter(&rc2params);
+    *params = p;
+
+    return ret;
+}
+
+static krb5_error_code
+rc2_set_params(krb5_context context,
+              const void *params,
+              const krb5_data *ivec,
+              krb5_data *data)
+{
+    RC2CBCParameter rc2params;
+    const struct _RC2_params *p = params;
+    int maximum_effective_key = 128;
+    krb5_error_code ret;
+    size_t size;
+
+    memset(&rc2params, 0, sizeof(rc2params));
+
+    if (p)
+       maximum_effective_key = p->maximum_effective_key;
+
+    /* XXX */
+    switch(maximum_effective_key) {
+    case 40:
+       rc2params.rc2ParameterVersion = 160;
+       break;
+    case 64:
+       rc2params.rc2ParameterVersion = 120;
+       break;
+    case 128:
+       rc2params.rc2ParameterVersion = 58;
+       break;
+    }
+    ret = copy_octet_string(ivec, &rc2params.iv);
+    if (ret)
+       return ret;
+
+    ASN1_MALLOC_ENCODE(RC2CBCParameter, data->data, data->length,
+                      &rc2params, &size, ret);
+    if (ret == 0 && size != data->length)
+       krb5_abortx(context, "Internal asn1 encoder failure");
+    free_RC2CBCParameter(&rc2params);
+
+    return ret;
+}
+
+static void
+rc2_schedule(krb5_context context,
+            struct key_data *kd,
+            const void *params)
+{
+    const struct _RC2_params *p = params;
+    int maximum_effective_key = 128;
+    if (p)
+       maximum_effective_key = p->maximum_effective_key;
+    RC2_set_key (kd->schedule->data,
+                kd->key->keyvalue.length,
+                kd->key->keyvalue.data,
+                maximum_effective_key);
+}
+
+
+/*
+ *
+ */
+
+static struct salt_type des_salt[] = {
+    {
+       KRB5_PW_SALT,
+       "pw-salt",
+       krb5_DES_string_to_key
+    },
+    {
+       KRB5_AFS3_SALT,
+       "afs3-salt",
+       DES_AFS3_string_to_key
+    },
+    { 0 }
+};
+
+static struct salt_type des3_salt[] = {
+    {
+       KRB5_PW_SALT,
+       "pw-salt",
+       DES3_string_to_key
+    },
+    { 0 }
+};
+
+static struct salt_type des3_salt_derived[] = {
+    {
+       KRB5_PW_SALT,
+       "pw-salt",
+       DES3_string_to_key_derived
+    },
+    { 0 }
+};
+
+static struct salt_type AES_salt[] = {
+    {
+       KRB5_PW_SALT,
+       "pw-salt",
+       AES_string_to_key
+    },
+    { 0 }
+};
+
+static struct salt_type arcfour_salt[] = {
+    {
+       KRB5_PW_SALT,
+       "pw-salt",
+       ARCFOUR_string_to_key
+    },
+    { 0 }
+};
+
+/*
+ *
+ */
+
+static struct key_type keytype_null = {
+    KEYTYPE_NULL,
+    "null",
+    0,
+    0,
+    0,
+    0,
+    NULL,
+    NULL,
+    NULL
+};
+
+static struct key_type keytype_des = {
+    KEYTYPE_DES,
+    "des",
+    56,
+    sizeof(DES_cblock),
+    sizeof(DES_cblock),
+    sizeof(DES_key_schedule),
+    krb5_DES_random_key,
+    krb5_DES_schedule,
+    des_salt,
+    krb5_DES_random_to_key
+};
+
+static struct key_type keytype_des3 = {
+    KEYTYPE_DES3,
+    "des3",
+    168,
+    3 * sizeof(DES_cblock), 
+    3 * sizeof(DES_cblock), 
+    3 * sizeof(DES_key_schedule), 
+    DES3_random_key,
+    DES3_schedule,
+    des3_salt,
+    DES3_random_to_key
+};
+
+static struct key_type keytype_des3_derived = {
+    KEYTYPE_DES3,
+    "des3",
+    168,
+    3 * sizeof(DES_cblock),
+    3 * sizeof(DES_cblock),
+    3 * sizeof(DES_key_schedule), 
+    DES3_random_key,
+    DES3_schedule,
+    des3_salt_derived,
+    DES3_random_to_key
+};
+
+static struct key_type keytype_aes128 = {
+    KEYTYPE_AES128,
+    "aes-128",
+    128,
+    16,
+    16,
+    sizeof(struct krb5_aes_schedule),
+    NULL,
+    AES_schedule,
+    AES_salt
+};
+
+static struct key_type keytype_aes192 = {
+    KEYTYPE_AES192,
+    "aes-192",
+    192,
+    24,
+    24,
+    sizeof(struct krb5_aes_schedule),
+    NULL,
+    AES_schedule,
+    AES_salt
+};
+
+static struct key_type keytype_aes256 = {
+    KEYTYPE_AES256,
+    "aes-256",
+    256,
+    32,
+    32,
+    sizeof(struct krb5_aes_schedule),
+    NULL,
+    AES_schedule,
+    AES_salt
+};
+
+static struct key_type keytype_arcfour = {
+    KEYTYPE_ARCFOUR,
+    "arcfour",
+    128,
+    16,
+    16,
+    sizeof(RC4_KEY),
+    NULL,
+    ARCFOUR_schedule,
+    arcfour_salt
+};
+
+static struct key_type keytype_rc2 = {
+    KEYTYPE_RC2,
+    "rc2",
+    128,
+    16,
+    1,
+    sizeof(RC2_KEY),
+    NULL,
+    rc2_schedule,
+    NULL, /* XXX salt */
+    NULL,
+    rc2_get_params,
+    rc2_set_params
+};
+
+static struct key_type *keytypes[] = {
+    &keytype_null,
+    &keytype_des,
+    &keytype_des3_derived,
+    &keytype_des3,
+    &keytype_aes128,
+    &keytype_aes192,
+    &keytype_aes256,
+    &keytype_rc2,
+    &keytype_arcfour
+};
+
+static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
+
+static struct key_type *
+_find_keytype(krb5_keytype type)
+{
+    int i;
+    for(i = 0; i < num_keytypes; i++)
+       if(keytypes[i]->type == type)
+           return keytypes[i];
+    return NULL;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_salttype_to_string (krb5_context context,
+                        krb5_enctype etype,
+                        krb5_salttype stype,
+                        char **string)
+{
+    struct encryption_type *e;
+    struct salt_type *st;
+
+    e = _find_enctype (etype);
+    if (e == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    for (st = e->keytype->string_to_key; st && st->type; st++) {
+       if (st->type == stype) {
+           *string = strdup (st->name);
+           if (*string == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           return 0;
+       }
+    }
+    krb5_set_error_string(context, "salttype %d not supported", stype);
+    return HEIM_ERR_SALTTYPE_NOSUPP;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_salttype (krb5_context context,
+                        krb5_enctype etype,
+                        const char *string,
+                        krb5_salttype *salttype)
+{
+    struct encryption_type *e;
+    struct salt_type *st;
+
+    e = _find_enctype (etype);
+    if (e == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    for (st = e->keytype->string_to_key; st && st->type; st++) {
+       if (strcasecmp (st->name, string) == 0) {
+           *salttype = st->type;
+           return 0;
+       }
+    }
+    krb5_set_error_string(context, "salttype %s not supported", string);
+    return HEIM_ERR_SALTTYPE_NOSUPP;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_pw_salt(krb5_context context,
+                krb5_const_principal principal,
+                krb5_salt *salt)
+{
+    size_t len;
+    int i;
+    krb5_error_code ret;
+    char *p;
+     
+    salt->salttype = KRB5_PW_SALT;
+    len = strlen(principal->realm);
+    for (i = 0; i < principal->name.name_string.len; ++i)
+       len += strlen(principal->name.name_string.val[i]);
+    ret = krb5_data_alloc (&salt->saltvalue, len);
+    if (ret)
+       return ret;
+    p = salt->saltvalue.data;
+    memcpy (p, principal->realm, strlen(principal->realm));
+    p += strlen(principal->realm);
+    for (i = 0; i < principal->name.name_string.len; ++i) {
+       memcpy (p,
+               principal->name.name_string.val[i],
+               strlen(principal->name.name_string.val[i]));
+       p += strlen(principal->name.name_string.val[i]);
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_salt(krb5_context context, 
+              krb5_salt salt)
+{
+    krb5_data_free(&salt.saltvalue);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_data (krb5_context context,
+                        krb5_enctype enctype,
+                        krb5_data password,
+                        krb5_principal principal,
+                        krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    krb5_salt salt;
+
+    ret = krb5_get_pw_salt(context, principal, &salt);
+    if(ret)
+       return ret;
+    ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key);
+    krb5_free_salt(context, salt);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key (krb5_context context,
+                   krb5_enctype enctype,
+                   const char *password,
+                   krb5_principal principal,
+                   krb5_keyblock *key)
+{
+    krb5_data pw;
+    pw.data = (void*)password;
+    pw.length = strlen(password);
+    return krb5_string_to_key_data(context, enctype, pw, principal, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_data_salt (krb5_context context,
+                             krb5_enctype enctype,
+                             krb5_data password,
+                             krb5_salt salt,
+                             krb5_keyblock *key)
+{
+    krb5_data opaque;
+    krb5_data_zero(&opaque);
+    return krb5_string_to_key_data_salt_opaque(context, enctype, password, 
+                                              salt, opaque, key);
+}
+
+/*
+ * Do a string -> key for encryption type `enctype' operation on
+ * `password' (with salt `salt' and the enctype specific data string
+ * `opaque'), returning the resulting key in `key'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_data_salt_opaque (krb5_context context,
+                                    krb5_enctype enctype,
+                                    krb5_data password,
+                                    krb5_salt salt,
+                                    krb5_data opaque,
+                                    krb5_keyblock *key)
+{
+    struct encryption_type *et =_find_enctype(enctype);
+    struct salt_type *st;
+    if(et == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             enctype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    for(st = et->keytype->string_to_key; st && st->type; st++) 
+       if(st->type == salt.salttype)
+           return (*st->string_to_key)(context, enctype, password, 
+                                       salt, opaque, key);
+    krb5_set_error_string(context, "salt type %d not supported",
+                         salt.salttype);
+    return HEIM_ERR_SALTTYPE_NOSUPP;
+}
+
+/*
+ * Do a string -> key for encryption type `enctype' operation on the
+ * string `password' (with salt `salt'), returning the resulting key
+ * in `key'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_salt (krb5_context context,
+                        krb5_enctype enctype,
+                        const char *password,
+                        krb5_salt salt,
+                        krb5_keyblock *key)
+{
+    krb5_data pw;
+    pw.data = (void*)password;
+    pw.length = strlen(password);
+    return krb5_string_to_key_data_salt(context, enctype, pw, salt, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_salt_opaque (krb5_context context,
+                               krb5_enctype enctype,
+                               const char *password,
+                               krb5_salt salt,
+                               krb5_data opaque,
+                               krb5_keyblock *key)
+{
+    krb5_data pw;
+    pw.data = (void*)password;
+    pw.length = strlen(password);
+    return krb5_string_to_key_data_salt_opaque(context, enctype, 
+                                              pw, salt, opaque, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_string(krb5_context context,
+                      krb5_keytype keytype,
+                      char **string)
+{
+    struct key_type *kt = _find_keytype(keytype);
+    if(kt == NULL) {
+       krb5_set_error_string(context, "key type %d not supported", keytype);
+       return KRB5_PROG_KEYTYPE_NOSUPP;
+    }
+    *string = strdup(kt->name);
+    if(*string == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_keytype(krb5_context context,
+                      const char *string,
+                      krb5_keytype *keytype)
+{
+    int i;
+    for(i = 0; i < num_keytypes; i++)
+       if(strcasecmp(keytypes[i]->name, string) == 0){
+           *keytype = keytypes[i]->type;
+           return 0;
+       }
+    krb5_set_error_string(context, "key type %s not supported", string);
+    return KRB5_PROG_KEYTYPE_NOSUPP;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_keysize(krb5_context context,
+                    krb5_enctype type,
+                    size_t *keysize)
+{
+    struct encryption_type *et = _find_enctype(type);
+    if(et == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             type);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    *keysize = et->keytype->size;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_random_keyblock(krb5_context context,
+                             krb5_enctype type,
+                             krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    struct encryption_type *et = _find_enctype(type);
+    if(et == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             type);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
+    if(ret) 
+       return ret;
+    key->keytype = type;
+    if(et->keytype->random_key)
+       (*et->keytype->random_key)(context, key);
+    else
+       krb5_generate_random_block(key->keyvalue.data, 
+                                  key->keyvalue.length);
+    return 0;
+}
+
+static krb5_error_code
+_key_schedule(krb5_context context,
+             struct key_data *key,
+             const void *params)
+{
+    krb5_error_code ret;
+    struct encryption_type *et = _find_enctype(key->key->keytype);
+    struct key_type *kt = et->keytype;
+
+    if(kt->schedule == NULL)
+       return 0;
+    if (key->schedule != NULL)
+       return 0;
+    ALLOC(key->schedule, 1);
+    if(key->schedule == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = krb5_data_alloc(key->schedule, kt->schedule_size);
+    if(ret) {
+       free(key->schedule);
+       key->schedule = NULL;
+       return ret;
+    }
+    (*kt->schedule)(context, key, params);
+    return 0;
+}
+
+/************************************************************
+ *                                                          *
+ ************************************************************/
+
+static void
+NONE_checksum(krb5_context context,
+             struct key_data *key,
+             const void *data,
+             size_t len,
+             unsigned usage,
+             Checksum *C)
+{
+}
+
+static void
+CRC32_checksum(krb5_context context,
+              struct key_data *key,
+              const void *data,
+              size_t len,
+              unsigned usage,
+              Checksum *C)
+{
+    u_int32_t crc;
+    unsigned char *r = C->checksum.data;
+    _krb5_crc_init_table ();
+    crc = _krb5_crc_update (data, len, 0);
+    r[0] = crc & 0xff;
+    r[1] = (crc >> 8)  & 0xff;
+    r[2] = (crc >> 16) & 0xff;
+    r[3] = (crc >> 24) & 0xff;
+}
+
+static void
+RSA_MD4_checksum(krb5_context context,
+                struct key_data *key,
+                const void *data,
+                size_t len,
+                unsigned usage,
+                Checksum *C)
+{
+    MD4_CTX m;
+
+    MD4_Init (&m);
+    MD4_Update (&m, data, len);
+    MD4_Final (C->checksum.data, &m);
+}
+
+static void
+RSA_MD4_DES_checksum(krb5_context context, 
+                    struct key_data *key,
+                    const void *data, 
+                    size_t len, 
+                    unsigned usage,
+                    Checksum *cksum)
+{
+    MD4_CTX md4;
+    DES_cblock ivec;
+    unsigned char *p = cksum->checksum.data;
+    
+    krb5_generate_random_block(p, 8);
+    MD4_Init (&md4);
+    MD4_Update (&md4, p, 8);
+    MD4_Update (&md4, data, len);
+    MD4_Final (p + 8, &md4);
+    memset (&ivec, 0, sizeof(ivec));
+    DES_cbc_encrypt(p, 
+                   p, 
+                   24, 
+                   key->schedule->data, 
+                   &ivec, 
+                   DES_ENCRYPT);
+}
+
+static krb5_error_code
+RSA_MD4_DES_verify(krb5_context context,
+                  struct key_data *key,
+                  const void *data,
+                  size_t len,
+                  unsigned usage,
+                  Checksum *C)
+{
+    MD4_CTX md4;
+    unsigned char tmp[24];
+    unsigned char res[16];
+    DES_cblock ivec;
+    krb5_error_code ret = 0;
+
+    memset(&ivec, 0, sizeof(ivec));
+    DES_cbc_encrypt(C->checksum.data,
+                   (void*)tmp, 
+                   C->checksum.length, 
+                   key->schedule->data,
+                   &ivec,
+                   DES_DECRYPT);
+    MD4_Init (&md4);
+    MD4_Update (&md4, tmp, 8); /* confounder */
+    MD4_Update (&md4, data, len);
+    MD4_Final (res, &md4);
+    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    }
+    memset(tmp, 0, sizeof(tmp));
+    memset(res, 0, sizeof(res));
+    return ret;
+}
+
+static void
+RSA_MD5_checksum(krb5_context context,
+                struct key_data *key,
+                const void *data,
+                size_t len,
+                unsigned usage,
+                Checksum *C)
+{
+    MD5_CTX m;
+
+    MD5_Init  (&m);
+    MD5_Update(&m, data, len);
+    MD5_Final (C->checksum.data, &m);
+}
+
+static void
+RSA_MD5_DES_checksum(krb5_context context,
+                    struct key_data *key,
+                    const void *data,
+                    size_t len,
+                    unsigned usage,
+                    Checksum *C)
+{
+    MD5_CTX md5;
+    DES_cblock ivec;
+    unsigned char *p = C->checksum.data;
+    
+    krb5_generate_random_block(p, 8);
+    MD5_Init (&md5);
+    MD5_Update (&md5, p, 8);
+    MD5_Update (&md5, data, len);
+    MD5_Final (p + 8, &md5);
+    memset (&ivec, 0, sizeof(ivec));
+    DES_cbc_encrypt(p, 
+                   p, 
+                   24, 
+                   key->schedule->data, 
+                   &ivec, 
+                   DES_ENCRYPT);
+}
+
+static krb5_error_code
+RSA_MD5_DES_verify(krb5_context context,
+                  struct key_data *key,
+                  const void *data,
+                  size_t len,
+                  unsigned usage,
+                  Checksum *C)
+{
+    MD5_CTX md5;
+    unsigned char tmp[24];
+    unsigned char res[16];
+    DES_cblock ivec;
+    DES_key_schedule *sched = key->schedule->data;
+    krb5_error_code ret = 0;
+
+    memset(&ivec, 0, sizeof(ivec));
+    DES_cbc_encrypt(C->checksum.data, 
+                   (void*)tmp, 
+                   C->checksum.length, 
+                   &sched[0],
+                   &ivec,
+                   DES_DECRYPT);
+    MD5_Init (&md5);
+    MD5_Update (&md5, tmp, 8); /* confounder */
+    MD5_Update (&md5, data, len);
+    MD5_Final (res, &md5);
+    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    }
+    memset(tmp, 0, sizeof(tmp));
+    memset(res, 0, sizeof(res));
+    return ret;
+}
+
+static void
+RSA_MD5_DES3_checksum(krb5_context context,
+                     struct key_data *key,
+                     const void *data,
+                     size_t len,
+                     unsigned usage,
+                     Checksum *C)
+{
+    MD5_CTX md5;
+    DES_cblock ivec;
+    unsigned char *p = C->checksum.data;
+    DES_key_schedule *sched = key->schedule->data;
+    
+    krb5_generate_random_block(p, 8);
+    MD5_Init (&md5);
+    MD5_Update (&md5, p, 8);
+    MD5_Update (&md5, data, len);
+    MD5_Final (p + 8, &md5);
+    memset (&ivec, 0, sizeof(ivec));
+    DES_ede3_cbc_encrypt(p, 
+                        p, 
+                        24, 
+                        &sched[0], &sched[1], &sched[2],
+                        &ivec, 
+                        DES_ENCRYPT);
+}
+
+static krb5_error_code
+RSA_MD5_DES3_verify(krb5_context context,
+                   struct key_data *key,
+                   const void *data,
+                   size_t len,
+                   unsigned usage,
+                   Checksum *C)
+{
+    MD5_CTX md5;
+    unsigned char tmp[24];
+    unsigned char res[16];
+    DES_cblock ivec;
+    DES_key_schedule *sched = key->schedule->data;
+    krb5_error_code ret = 0;
+
+    memset(&ivec, 0, sizeof(ivec));
+    DES_ede3_cbc_encrypt(C->checksum.data, 
+                        (void*)tmp, 
+                        C->checksum.length, 
+                        &sched[0], &sched[1], &sched[2],
+                        &ivec,
+                        DES_DECRYPT);
+    MD5_Init (&md5);
+    MD5_Update (&md5, tmp, 8); /* confounder */
+    MD5_Update (&md5, data, len);
+    MD5_Final (res, &md5);
+    if(memcmp(res, tmp + 8, sizeof(res)) != 0) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    }
+    memset(tmp, 0, sizeof(tmp));
+    memset(res, 0, sizeof(res));
+    return ret;
+}
+
+static void
+SHA1_checksum(krb5_context context,
+             struct key_data *key,
+             const void *data,
+             size_t len,
+             unsigned usage,
+             Checksum *C)
+{
+    SHA_CTX m;
+
+    SHA1_Init(&m);
+    SHA1_Update(&m, data, len);
+    SHA1_Final(C->checksum.data, &m);
+}
+
+/* HMAC according to RFC2104 */
+static krb5_error_code
+hmac(krb5_context context,
+     struct checksum_type *cm, 
+     const void *data, 
+     size_t len, 
+     unsigned usage,
+     struct key_data *keyblock,
+     Checksum *result)
+{
+    unsigned char *ipad, *opad;
+    unsigned char *key;
+    size_t key_len;
+    int i;
+    
+    ipad = malloc(cm->blocksize + len);
+    if (ipad == NULL)
+       return ENOMEM;
+    opad = malloc(cm->blocksize + cm->checksumsize);
+    if (opad == NULL) {
+       free(ipad);
+       return ENOMEM;
+    }
+    memset(ipad, 0x36, cm->blocksize);
+    memset(opad, 0x5c, cm->blocksize);
+
+    if(keyblock->key->keyvalue.length > cm->blocksize){
+       (*cm->checksum)(context, 
+                       keyblock, 
+                       keyblock->key->keyvalue.data, 
+                       keyblock->key->keyvalue.length, 
+                       usage,
+                       result);
+       key = result->checksum.data;
+       key_len = result->checksum.length;
+    } else {
+       key = keyblock->key->keyvalue.data;
+       key_len = keyblock->key->keyvalue.length;
+    }
+    for(i = 0; i < key_len; i++){
+       ipad[i] ^= key[i];
+       opad[i] ^= key[i];
+    }
+    memcpy(ipad + cm->blocksize, data, len);
+    (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len,
+                   usage, result);
+    memcpy(opad + cm->blocksize, result->checksum.data, 
+          result->checksum.length);
+    (*cm->checksum)(context, keyblock, opad, 
+                   cm->blocksize + cm->checksumsize, usage, result);
+    memset(ipad, 0, cm->blocksize + len);
+    free(ipad);
+    memset(opad, 0, cm->blocksize + cm->checksumsize);
+    free(opad);
+
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_hmac(krb5_context context,
+         krb5_cksumtype cktype,
+         const void *data,
+         size_t len,
+         unsigned usage, 
+         krb5_keyblock *key,
+         Checksum *result)
+{
+    struct checksum_type *c = _find_checksum(cktype);
+    struct key_data kd;
+    krb5_error_code ret;
+
+    if (c == NULL) {
+       krb5_set_error_string (context, "checksum type %d not supported",
+                              cktype);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+
+    kd.key = key;
+    kd.schedule = NULL;
+
+    ret = hmac(context, c, data, len, usage, &kd, result);
+
+    if (kd.schedule)
+       krb5_free_data(context, kd.schedule);
+
+    return ret;
+ }
+
+static void
+SP_HMAC_SHA1_checksum(krb5_context context,
+                     struct key_data *key, 
+                     const void *data, 
+                     size_t len, 
+                     unsigned usage,
+                     Checksum *result)
+{
+    struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1);
+    Checksum res;
+    char sha1_data[20];
+    krb5_error_code ret;
+
+    res.checksum.data = sha1_data;
+    res.checksum.length = sizeof(sha1_data);
+
+    ret = hmac(context, c, data, len, usage, key, &res);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+    memcpy(result->checksum.data, res.checksum.data, result->checksum.length);
+}
+
+/*
+ * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt
+ */
+
+static void
+HMAC_MD5_checksum(krb5_context context,
+                 struct key_data *key,
+                 const void *data,
+                 size_t len,
+                 unsigned usage,
+                 Checksum *result)
+{
+    MD5_CTX md5;
+    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
+    const char signature[] = "signaturekey";
+    Checksum ksign_c;
+    struct key_data ksign;
+    krb5_keyblock kb;
+    unsigned char t[4];
+    unsigned char tmp[16];
+    unsigned char ksign_c_data[16];
+    krb5_error_code ret;
+
+    ksign_c.checksum.length = sizeof(ksign_c_data);
+    ksign_c.checksum.data   = ksign_c_data;
+    ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+    ksign.key = &kb;
+    kb.keyvalue = ksign_c.checksum;
+    MD5_Init (&md5);
+    t[0] = (usage >>  0) & 0xFF;
+    t[1] = (usage >>  8) & 0xFF;
+    t[2] = (usage >> 16) & 0xFF;
+    t[3] = (usage >> 24) & 0xFF;
+    MD5_Update (&md5, t, 4);
+    MD5_Update (&md5, data, len);
+    MD5_Final (tmp, &md5);
+    ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+}
+
+/*
+ * same as previous but being used while encrypting.
+ */
+
+static void
+HMAC_MD5_checksum_enc(krb5_context context,
+                     struct key_data *key,
+                     const void *data,
+                     size_t len,
+                     unsigned usage,
+                     Checksum *result)
+{
+    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
+    Checksum ksign_c;
+    struct key_data ksign;
+    krb5_keyblock kb;
+    unsigned char t[4];
+    unsigned char ksign_c_data[16];
+    krb5_error_code ret;
+
+    t[0] = (usage >>  0) & 0xFF;
+    t[1] = (usage >>  8) & 0xFF;
+    t[2] = (usage >> 16) & 0xFF;
+    t[3] = (usage >> 24) & 0xFF;
+
+    ksign_c.checksum.length = sizeof(ksign_c_data);
+    ksign_c.checksum.data   = ksign_c_data;
+    ret = hmac(context, c, t, sizeof(t), 0, key, &ksign_c);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+    ksign.key = &kb;
+    kb.keyvalue = ksign_c.checksum;
+    ret = hmac(context, c, data, len, 0, &ksign, result);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+}
+
+static struct checksum_type checksum_none = {
+    CKSUMTYPE_NONE, 
+    "none", 
+    1, 
+    0, 
+    0,
+    NONE_checksum, 
+    NULL
+};
+static struct checksum_type checksum_crc32 = {
+    CKSUMTYPE_CRC32,
+    "crc32",
+    1,
+    4,
+    0,
+    CRC32_checksum,
+    NULL
+};
+static struct checksum_type checksum_rsa_md4 = {
+    CKSUMTYPE_RSA_MD4,
+    "rsa-md4",
+    64,
+    16,
+    F_CPROOF,
+    RSA_MD4_checksum,
+    NULL
+};
+static struct checksum_type checksum_rsa_md4_des = {
+    CKSUMTYPE_RSA_MD4_DES,
+    "rsa-md4-des",
+    64,
+    24,
+    F_KEYED | F_CPROOF | F_VARIANT,
+    RSA_MD4_DES_checksum,
+    RSA_MD4_DES_verify
+};
+#if 0
+static struct checksum_type checksum_des_mac = { 
+    CKSUMTYPE_DES_MAC,
+    "des-mac",
+    0,
+    0,
+    0,
+    DES_MAC_checksum
+};
+static struct checksum_type checksum_des_mac_k = {
+    CKSUMTYPE_DES_MAC_K,
+    "des-mac-k",
+    0,
+    0,
+    0,
+    DES_MAC_K_checksum
+};
+static struct checksum_type checksum_rsa_md4_des_k = {
+    CKSUMTYPE_RSA_MD4_DES_K, 
+    "rsa-md4-des-k", 
+    0, 
+    0, 
+    0, 
+    RSA_MD4_DES_K_checksum,
+    RSA_MD4_DES_K_verify
+};
+#endif
+static struct checksum_type checksum_rsa_md5 = {
+    CKSUMTYPE_RSA_MD5,
+    "rsa-md5",
+    64,
+    16,
+    F_CPROOF,
+    RSA_MD5_checksum,
+    NULL
+};
+static struct checksum_type checksum_rsa_md5_des = {
+    CKSUMTYPE_RSA_MD5_DES,
+    "rsa-md5-des",
+    64,
+    24,
+    F_KEYED | F_CPROOF | F_VARIANT,
+    RSA_MD5_DES_checksum,
+    RSA_MD5_DES_verify
+};
+static struct checksum_type checksum_rsa_md5_des3 = {
+    CKSUMTYPE_RSA_MD5_DES3,
+    "rsa-md5-des3",
+    64,
+    24,
+    F_KEYED | F_CPROOF | F_VARIANT,
+    RSA_MD5_DES3_checksum,
+    RSA_MD5_DES3_verify
+};
+static struct checksum_type checksum_sha1 = {
+    CKSUMTYPE_SHA1,
+    "sha1",
+    64,
+    20,
+    F_CPROOF,
+    SHA1_checksum,
+    NULL
+};
+static struct checksum_type checksum_hmac_sha1_des3 = {
+    CKSUMTYPE_HMAC_SHA1_DES3,
+    "hmac-sha1-des3",
+    64,
+    20,
+    F_KEYED | F_CPROOF | F_DERIVED,
+    SP_HMAC_SHA1_checksum,
+    NULL
+};
+
+static struct checksum_type checksum_hmac_sha1_aes128 = {
+    CKSUMTYPE_HMAC_SHA1_96_AES_128,
+    "hmac-sha1-96-aes128",
+    64,
+    12,
+    F_KEYED | F_CPROOF | F_DERIVED,
+    SP_HMAC_SHA1_checksum,
+    NULL
+};
+
+static struct checksum_type checksum_hmac_sha1_aes256 = {
+    CKSUMTYPE_HMAC_SHA1_96_AES_256,
+    "hmac-sha1-96-aes256",
+    64,
+    12,
+    F_KEYED | F_CPROOF | F_DERIVED,
+    SP_HMAC_SHA1_checksum,
+    NULL
+};
+
+static struct checksum_type checksum_hmac_md5 = {
+    CKSUMTYPE_HMAC_MD5,
+    "hmac-md5",
+    64,
+    16,
+    F_KEYED | F_CPROOF,
+    HMAC_MD5_checksum,
+    NULL
+};
+
+static struct checksum_type checksum_hmac_md5_enc = {
+    CKSUMTYPE_HMAC_MD5_ENC,
+    "hmac-md5-enc",
+    64,
+    16,
+    F_KEYED | F_CPROOF | F_PSEUDO,
+    HMAC_MD5_checksum_enc,
+    NULL
+};
+
+static struct checksum_type *checksum_types[] = {
+    &checksum_none,
+    &checksum_crc32,
+    &checksum_rsa_md4,
+    &checksum_rsa_md4_des,
+#if 0
+    &checksum_des_mac, 
+    &checksum_des_mac_k,
+    &checksum_rsa_md4_des_k,
+#endif
+    &checksum_rsa_md5,
+    &checksum_rsa_md5_des,
+    &checksum_rsa_md5_des3,
+    &checksum_sha1,
+    &checksum_hmac_sha1_des3,
+    &checksum_hmac_sha1_aes128,
+    &checksum_hmac_sha1_aes256,
+    &checksum_hmac_md5,
+    &checksum_hmac_md5_enc
+};
+
+static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]);
+
+static struct checksum_type *
+_find_checksum(krb5_cksumtype type)
+{
+    int i;
+    for(i = 0; i < num_checksums; i++)
+       if(checksum_types[i]->type == type)
+           return checksum_types[i];
+    return NULL;
+}
+
+static krb5_error_code
+get_checksum_key(krb5_context context, 
+                krb5_crypto crypto,
+                unsigned usage,  /* not krb5_key_usage */
+                struct checksum_type *ct, 
+                struct key_data **key)
+{
+    krb5_error_code ret = 0;
+
+    if(ct->flags & F_DERIVED)
+       ret = _get_derived_key(context, crypto, usage, key);
+    else if(ct->flags & F_VARIANT) {
+       int i;
+
+       *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */);
+       if(*key == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key);
+       if(ret) 
+           return ret;
+       for(i = 0; i < (*key)->key->keyvalue.length; i++)
+           ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0;
+    } else {
+       *key = &crypto->key; 
+    }
+    if(ret == 0)
+       ret = _key_schedule(context, *key, crypto->params);
+    return ret;
+}
+
+static krb5_error_code
+create_checksum (krb5_context context,
+                struct checksum_type *ct,
+                krb5_crypto crypto,
+                unsigned usage,
+                void *data,
+                size_t len,
+                Checksum *result)
+{
+    krb5_error_code ret;
+    struct key_data *dkey;
+    int keyed_checksum;
+    
+    if (ct->flags & F_DISABLED) {
+       krb5_clear_error_string (context);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    keyed_checksum = (ct->flags & F_KEYED) != 0;
+    if(keyed_checksum && crypto == NULL) {
+       krb5_clear_error_string (context);
+       return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
+    }
+    if(keyed_checksum) {
+       ret = get_checksum_key(context, crypto, usage, ct, &dkey);
+       if (ret)
+           return ret;
+    } else
+       dkey = NULL;
+    result->cksumtype = ct->type;
+    krb5_data_alloc(&result->checksum, ct->checksumsize);
+    (*ct->checksum)(context, dkey, data, len, usage, result);
+    return 0;
+}
+
+static int
+arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto)
+{
+    return (ct->type == CKSUMTYPE_HMAC_MD5) &&
+       (crypto->key.key->keytype == KEYTYPE_ARCFOUR);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_create_checksum(krb5_context context,
+                    krb5_crypto crypto,
+                    krb5_key_usage usage,
+                    int type,
+                    void *data,
+                    size_t len,
+                    Checksum *result)
+{
+    struct checksum_type *ct = NULL;
+    unsigned keyusage;
+
+    /* type 0 -> pick from crypto */
+    if (type) {
+       ct = _find_checksum(type);
+    } else if (crypto) {
+       ct = crypto->et->keyed_checksum;
+       if (ct == NULL)
+           ct = crypto->et->checksum;
+    }
+
+    if(ct == NULL) {
+       krb5_set_error_string (context, "checksum type %d not supported",
+                              type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+
+    if (arcfour_checksum_p(ct, crypto)) {
+       keyusage = usage;
+       usage2arcfour(context, &keyusage);
+    } else
+       keyusage = CHECKSUM_USAGE(usage);
+
+    return create_checksum(context, ct, crypto, keyusage,
+                          data, len, result);
+}
+
+static krb5_error_code
+verify_checksum(krb5_context context,
+               krb5_crypto crypto,
+               unsigned usage, /* not krb5_key_usage */
+               void *data,
+               size_t len,
+               Checksum *cksum)
+{
+    krb5_error_code ret;
+    struct key_data *dkey;
+    int keyed_checksum;
+    Checksum c;
+    struct checksum_type *ct;
+
+    ct = _find_checksum(cksum->cksumtype);
+    if (ct == NULL || (ct->flags & F_DISABLED)) {
+       krb5_set_error_string (context, "checksum type %d not supported",
+                              cksum->cksumtype);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    if(ct->checksumsize != cksum->checksum.length) {
+       krb5_clear_error_string (context);
+       return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
+    }
+    keyed_checksum = (ct->flags & F_KEYED) != 0;
+    if(keyed_checksum && crypto == NULL) {
+       krb5_clear_error_string (context);
+       return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
+    }
+    if(keyed_checksum)
+       ret = get_checksum_key(context, crypto, usage, ct, &dkey);
+    else
+       dkey = NULL;
+    if(ct->verify)
+       return (*ct->verify)(context, dkey, data, len, usage, cksum);
+
+    ret = krb5_data_alloc (&c.checksum, ct->checksumsize);
+    if (ret)
+       return ret;
+
+    (*ct->checksum)(context, dkey, data, len, usage, &c);
+
+    if(c.checksum.length != cksum->checksum.length || 
+       memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    } else {
+       ret = 0;
+    }
+    krb5_data_free (&c.checksum);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_checksum(krb5_context context,
+                    krb5_crypto crypto,
+                    krb5_key_usage usage, 
+                    void *data,
+                    size_t len,
+                    Checksum *cksum)
+{
+    struct checksum_type *ct;
+    unsigned keyusage;
+
+    ct = _find_checksum(cksum->cksumtype);
+    if(ct == NULL) {
+       krb5_set_error_string (context, "checksum type %d not supported",
+                              cksum->cksumtype);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+
+    if (arcfour_checksum_p(ct, crypto)) {
+       keyusage = usage;
+       usage2arcfour(context, &keyusage);
+    } else
+       keyusage = CHECKSUM_USAGE(usage);
+
+    return verify_checksum(context, crypto, keyusage,
+                          data, len, cksum);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_get_checksum_type(krb5_context context,
+                              krb5_crypto crypto,
+                             krb5_cksumtype *type)
+{
+    struct checksum_type *ct = NULL;
+    
+    if (crypto != NULL) {
+        ct = crypto->et->keyed_checksum;
+        if (ct == NULL)
+            ct = crypto->et->checksum;
+    }
+    
+    if (ct == NULL) {
+       krb5_set_error_string (context, "checksum type not found");
+        return KRB5_PROG_SUMTYPE_NOSUPP;
+    }    
+
+    *type = ct->type;
+    
+    return 0;      
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_checksumsize(krb5_context context,
+                 krb5_cksumtype type,
+                 size_t *size)
+{
+    struct checksum_type *ct = _find_checksum(type);
+    if(ct == NULL) {
+       krb5_set_error_string (context, "checksum type %d not supported",
+                              type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    *size = ct->checksumsize;
+    return 0;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_checksum_is_keyed(krb5_context context,
+                      krb5_cksumtype type)
+{
+    struct checksum_type *ct = _find_checksum(type);
+    if(ct == NULL) {
+       if (context)
+           krb5_set_error_string (context, "checksum type %d not supported",
+                                  type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    return ct->flags & F_KEYED;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_checksum_is_collision_proof(krb5_context context,
+                                krb5_cksumtype type)
+{
+    struct checksum_type *ct = _find_checksum(type);
+    if(ct == NULL) {
+       if (context)
+           krb5_set_error_string (context, "checksum type %d not supported",
+                                  type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    return ct->flags & F_CPROOF;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_checksum_disable(krb5_context context,
+                     krb5_cksumtype type)
+{
+    struct checksum_type *ct = _find_checksum(type);
+    if(ct == NULL) {
+       if (context)
+           krb5_set_error_string (context, "checksum type %d not supported",
+                                  type);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    ct->flags |= F_DISABLED;
+    return 0;
+}
+
+/************************************************************
+ *                                                          *
+ ************************************************************/
+
+static krb5_error_code
+NULL_encrypt(krb5_context context,
+            struct key_data *key, 
+            void *data, 
+            size_t len, 
+            krb5_boolean encrypt,
+            int usage,
+            void *ivec)
+{
+    return 0;
+}
+
+static krb5_error_code
+DES_CBC_encrypt_null_ivec(krb5_context context,
+                         struct key_data *key, 
+                         void *data, 
+                         size_t len, 
+                         krb5_boolean encrypt,
+                         int usage,
+                         void *ignore_ivec)
+{
+    DES_cblock ivec;
+    DES_key_schedule *s = key->schedule->data;
+    memset(&ivec, 0, sizeof(ivec));
+    DES_cbc_encrypt(data, data, len, s, &ivec, encrypt);
+    return 0;
+}
+
+static krb5_error_code
+DES_CBC_encrypt_key_ivec(krb5_context context,
+                        struct key_data *key, 
+                        void *data, 
+                        size_t len, 
+                        krb5_boolean encrypt,
+                        int usage,
+                        void *ignore_ivec)
+{
+    DES_cblock ivec;
+    DES_key_schedule *s = key->schedule->data;
+    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
+    DES_cbc_encrypt(data, data, len, s, &ivec, encrypt);
+    return 0;
+}
+
+static krb5_error_code
+DES3_CBC_encrypt(krb5_context context,
+                struct key_data *key, 
+                void *data, 
+                size_t len, 
+                krb5_boolean encrypt,
+                int usage,
+                void *ivec)
+{
+    DES_cblock local_ivec;
+    DES_key_schedule *s = key->schedule->data;
+    if(ivec == NULL) {
+       ivec = &local_ivec;
+       memset(local_ivec, 0, sizeof(local_ivec));
+    }
+    DES_ede3_cbc_encrypt(data, data, len, &s[0], &s[1], &s[2], ivec, encrypt);
+    return 0;
+}
+
+static krb5_error_code
+DES_CFB64_encrypt_null_ivec(krb5_context context,
+                           struct key_data *key, 
+                           void *data, 
+                           size_t len, 
+                           krb5_boolean encrypt,
+                           int usage,
+                           void *ignore_ivec)
+{
+    DES_cblock ivec;
+    int num = 0;
+    DES_key_schedule *s = key->schedule->data;
+    memset(&ivec, 0, sizeof(ivec));
+
+    DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encrypt);
+    return 0;
+}
+
+static krb5_error_code
+DES_PCBC_encrypt_key_ivec(krb5_context context,
+                         struct key_data *key, 
+                         void *data, 
+                         size_t len, 
+                         krb5_boolean encrypt,
+                         int usage,
+                         void *ignore_ivec)
+{
+    DES_cblock ivec;
+    DES_key_schedule *s = key->schedule->data;
+    memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec));
+
+    DES_pcbc_encrypt(data, data, len, s, &ivec, encrypt);
+    return 0;
+}
+
+/*
+ * AES draft-raeburn-krb-rijndael-krb-02
+ */
+
+void KRB5_LIB_FUNCTION
+_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out,
+                     size_t len, const void *aes_key,
+                     unsigned char *ivec, const int encrypt)
+{
+    unsigned char tmp[AES_BLOCK_SIZE];
+    const AES_KEY *key = aes_key; /* XXX remove this when we always have AES */
+    int i;
+
+    /*
+     * In the framework of kerberos, the length can never be shorter
+     * then at least one blocksize.
+     */
+
+    if (encrypt) {
+
+       while(len > AES_BLOCK_SIZE) {
+           for (i = 0; i < AES_BLOCK_SIZE; i++)
+               tmp[i] = in[i] ^ ivec[i];
+           AES_encrypt(tmp, out, key);
+           memcpy(ivec, out, AES_BLOCK_SIZE);
+           len -= AES_BLOCK_SIZE;
+           in += AES_BLOCK_SIZE;
+           out += AES_BLOCK_SIZE;
+       }
+
+       for (i = 0; i < len; i++)
+           tmp[i] = in[i] ^ ivec[i];
+       for (; i < AES_BLOCK_SIZE; i++)
+           tmp[i] = 0 ^ ivec[i];
+
+       AES_encrypt(tmp, out - AES_BLOCK_SIZE, key);
+
+       memcpy(out, ivec, len);
+       memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
+
+    } else {
+       unsigned char tmp2[AES_BLOCK_SIZE];
+       unsigned char tmp3[AES_BLOCK_SIZE];
+
+       while(len > AES_BLOCK_SIZE * 2) {
+           memcpy(tmp, in, AES_BLOCK_SIZE);
+           AES_decrypt(in, out, key);
+           for (i = 0; i < AES_BLOCK_SIZE; i++)
+               out[i] ^= ivec[i];
+           memcpy(ivec, tmp, AES_BLOCK_SIZE);
+           len -= AES_BLOCK_SIZE;
+           in += AES_BLOCK_SIZE;
+           out += AES_BLOCK_SIZE;
+       }
+
+       len -= AES_BLOCK_SIZE;
+
+       memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */
+       AES_decrypt(in, tmp2, key);
+
+       memcpy(tmp3, in + AES_BLOCK_SIZE, len);
+       memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */
+
+       for (i = 0; i < len; i++)
+           out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i];
+
+       AES_decrypt(tmp3, out, key);
+       for (i = 0; i < AES_BLOCK_SIZE; i++)
+           out[i] ^= ivec[i];
+       memcpy(ivec, tmp, AES_BLOCK_SIZE);
+    }
+}
+
+static krb5_error_code
+AES_CTS_encrypt(krb5_context context,
+               struct key_data *key,
+               void *data,
+               size_t len,
+               krb5_boolean encrypt,
+               int usage,
+               void *ivec)
+{
+    struct krb5_aes_schedule *aeskey = key->schedule->data;
+    char local_ivec[AES_BLOCK_SIZE];
+    AES_KEY *k;
+
+    if (encrypt)
+       k = &aeskey->ekey;
+    else
+       k = &aeskey->dkey;
+    
+    if (len < AES_BLOCK_SIZE)
+       krb5_abortx(context, "invalid use of AES_CTS_encrypt");
+    if (len == AES_BLOCK_SIZE) {
+       if (encrypt)
+           AES_encrypt(data, data, k);
+       else
+           AES_decrypt(data, data, k);
+    } else {
+       if(ivec == NULL) {
+           memset(local_ivec, 0, sizeof(local_ivec));
+           ivec = local_ivec;
+       }
+       _krb5_aes_cts_encrypt(data, data, len, k, ivec, encrypt);
+    }
+
+    return 0;
+}
+
+static krb5_error_code 
+AES_CBC_encrypt(krb5_context context,
+                struct key_data *key, 
+                void *data,
+                size_t len,  
+                krb5_boolean encrypt, 
+                int usage,
+                void *ivec)
+{
+    struct krb5_aes_schedule *aeskey = key->schedule->data;
+    char local_ivec[AES_BLOCK_SIZE];
+    AES_KEY *k;
+
+    if (encrypt)
+       k = &aeskey->ekey;
+    else
+       k = &aeskey->dkey;
+
+    if(ivec == NULL) {
+        ivec = &local_ivec;
+        memset(local_ivec, 0, sizeof(local_ivec));
+    }
+    AES_cbc_encrypt(data, data, len, k, ivec, encrypt);
+    return 0;
+}
+
+/*
+ * RC2
+ */
+
+static krb5_error_code 
+RC2_CBC_encrypt(krb5_context context,
+                struct key_data *key, 
+                void *data,
+                size_t len,  
+                krb5_boolean encrypt, 
+                int usage,
+                void *ivec)
+{
+    unsigned char local_ivec[8];
+    RC2_KEY *s = key->schedule->data; 
+    if(ivec == NULL) {
+        ivec = &local_ivec;
+        memset(local_ivec, 0, sizeof(local_ivec));
+    }
+    RC2_cbc_encrypt(data, data, len, s, ivec, encrypt);
+    return 0;
+}
+
+/*
+ * section 6 of draft-brezak-win2k-krb-rc4-hmac-03
+ *
+ * warning: not for small children
+ */
+
+static krb5_error_code
+ARCFOUR_subencrypt(krb5_context context,
+                  struct key_data *key,
+                  void *data,
+                  size_t len,
+                  unsigned usage,
+                  void *ivec)
+{
+    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
+    Checksum k1_c, k2_c, k3_c, cksum;
+    struct key_data ke;
+    krb5_keyblock kb;
+    unsigned char t[4];
+    RC4_KEY rc4_key;
+    unsigned char *cdata = data;
+    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
+    krb5_error_code ret;
+
+    t[0] = (usage >>  0) & 0xFF;
+    t[1] = (usage >>  8) & 0xFF;
+    t[2] = (usage >> 16) & 0xFF;
+    t[3] = (usage >> 24) & 0xFF;
+
+    k1_c.checksum.length = sizeof(k1_c_data);
+    k1_c.checksum.data   = k1_c_data;
+
+    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+
+    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
+
+    k2_c.checksum.length = sizeof(k2_c_data);
+    k2_c.checksum.data   = k2_c_data;
+
+    ke.key = &kb;
+    kb.keyvalue = k2_c.checksum;
+
+    cksum.checksum.length = 16;
+    cksum.checksum.data   = data;
+
+    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+
+    ke.key = &kb;
+    kb.keyvalue = k1_c.checksum;
+
+    k3_c.checksum.length = sizeof(k3_c_data);
+    k3_c.checksum.data   = k3_c_data;
+
+    ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+
+    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
+    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
+    memset (k1_c_data, 0, sizeof(k1_c_data));
+    memset (k2_c_data, 0, sizeof(k2_c_data));
+    memset (k3_c_data, 0, sizeof(k3_c_data));
+    return 0;
+}
+
+static krb5_error_code
+ARCFOUR_subdecrypt(krb5_context context,
+                  struct key_data *key,
+                  void *data,
+                  size_t len,
+                  unsigned usage,
+                  void *ivec)
+{
+    struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5);
+    Checksum k1_c, k2_c, k3_c, cksum;
+    struct key_data ke;
+    krb5_keyblock kb;
+    unsigned char t[4];
+    RC4_KEY rc4_key;
+    unsigned char *cdata = data;
+    unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16];
+    unsigned char cksum_data[16];
+    krb5_error_code ret;
+
+    t[0] = (usage >>  0) & 0xFF;
+    t[1] = (usage >>  8) & 0xFF;
+    t[2] = (usage >> 16) & 0xFF;
+    t[3] = (usage >> 24) & 0xFF;
+
+    k1_c.checksum.length = sizeof(k1_c_data);
+    k1_c.checksum.data   = k1_c_data;
+
+    ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+
+    memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data));
+
+    k2_c.checksum.length = sizeof(k2_c_data);
+    k2_c.checksum.data   = k2_c_data;
+
+    ke.key = &kb;
+    kb.keyvalue = k1_c.checksum;
+
+    k3_c.checksum.length = sizeof(k3_c_data);
+    k3_c.checksum.data   = k3_c_data;
+
+    ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+
+    RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data);
+    RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16);
+
+    ke.key = &kb;
+    kb.keyvalue = k2_c.checksum;
+
+    cksum.checksum.length = 16;
+    cksum.checksum.data   = cksum_data;
+
+    ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum);
+    if (ret)
+       krb5_abortx(context, "hmac failed");
+
+    memset (k1_c_data, 0, sizeof(k1_c_data));
+    memset (k2_c_data, 0, sizeof(k2_c_data));
+    memset (k3_c_data, 0, sizeof(k3_c_data));
+
+    if (memcmp (cksum.checksum.data, data, 16) != 0) {
+       krb5_clear_error_string (context);
+       return KRB5KRB_AP_ERR_BAD_INTEGRITY;
+    } else {
+       return 0;
+    }
+}
+
+/*
+ * convert the usage numbers used in
+ * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in
+ * draft-brezak-win2k-krb-rc4-hmac-04.txt
+ */
+
+static krb5_error_code
+usage2arcfour (krb5_context context, unsigned *usage)
+{
+    switch (*usage) {
+    case KRB5_KU_AS_REP_ENC_PART : /* 3 */
+    case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */
+       *usage = 8;
+       return 0;
+    case KRB5_KU_USAGE_SEAL :  /* 22 */
+       *usage = 13;
+       return 0;
+    case KRB5_KU_USAGE_SIGN : /* 23 */
+        *usage = 15;
+        return 0;
+    case KRB5_KU_USAGE_SEQ: /* 24 */
+       *usage = 0;
+       return 0;
+    default :
+       return 0;
+    }
+}
+
+static krb5_error_code
+ARCFOUR_encrypt(krb5_context context,
+               struct key_data *key,
+               void *data,
+               size_t len,
+               krb5_boolean encrypt,
+               int usage,
+               void *ivec)
+{
+    krb5_error_code ret;
+    unsigned keyusage = usage;
+
+    if((ret = usage2arcfour (context, &keyusage)) != 0)
+       return ret;
+
+    if (encrypt)
+       return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec);
+    else
+       return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec);
+}
+
+
+/*
+ * these should currently be in reverse preference order.
+ * (only relevant for !F_PSEUDO) */
+
+static struct encryption_type enctype_null = {
+    ETYPE_NULL,
+    "null",
+    NULL,
+    1,
+    1,
+    0,
+    &keytype_null,
+    &checksum_none,
+    NULL,
+    F_DISABLED,
+    NULL_encrypt,
+};
+static struct encryption_type enctype_des_cbc_crc = {
+    ETYPE_DES_CBC_CRC,
+    "des-cbc-crc",
+    NULL,
+    8,
+    8,
+    8,
+    &keytype_des,
+    &checksum_crc32,
+    NULL,
+    0,
+    DES_CBC_encrypt_key_ivec,
+};
+static struct encryption_type enctype_des_cbc_md4 = {
+    ETYPE_DES_CBC_MD4,
+    "des-cbc-md4",
+    NULL,
+    8,
+    8,
+    8,
+    &keytype_des,
+    &checksum_rsa_md4,
+    &checksum_rsa_md4_des,
+    0,
+    DES_CBC_encrypt_null_ivec,
+};
+static struct encryption_type enctype_des_cbc_md5 = {
+    ETYPE_DES_CBC_MD5,
+    "des-cbc-md5",
+    NULL,
+    8,
+    8,
+    8,
+    &keytype_des,
+    &checksum_rsa_md5,
+    &checksum_rsa_md5_des,
+    0,
+    DES_CBC_encrypt_null_ivec,
+};
+static struct encryption_type enctype_arcfour_hmac_md5 = {
+    ETYPE_ARCFOUR_HMAC_MD5,
+    "arcfour-hmac-md5",
+    NULL,
+    1,
+    1,
+    8,
+    &keytype_arcfour,
+    &checksum_hmac_md5,
+    NULL,
+    F_SPECIAL,
+    ARCFOUR_encrypt
+};
+static struct encryption_type enctype_des3_cbc_md5 = { 
+    ETYPE_DES3_CBC_MD5,
+    "des3-cbc-md5",
+    NULL,
+    8,
+    8,
+    8,
+    &keytype_des3,
+    &checksum_rsa_md5,
+    &checksum_rsa_md5_des3,
+    0,
+    DES3_CBC_encrypt,
+};
+static struct encryption_type enctype_des3_cbc_sha1 = {
+    ETYPE_DES3_CBC_SHA1,
+    "des3-cbc-sha1",
+    NULL,
+    8,
+    8,
+    8,
+    &keytype_des3_derived,
+    &checksum_sha1,
+    &checksum_hmac_sha1_des3,
+    F_DERIVED,
+    DES3_CBC_encrypt,
+};
+static struct encryption_type enctype_old_des3_cbc_sha1 = {
+    ETYPE_OLD_DES3_CBC_SHA1,
+    "old-des3-cbc-sha1",
+    NULL,
+    8,
+    8,
+    8,
+    &keytype_des3,
+    &checksum_sha1,
+    &checksum_hmac_sha1_des3,
+    0,
+    DES3_CBC_encrypt,
+};
+static struct encryption_type enctype_aes128_cts_hmac_sha1 = {
+    ETYPE_AES128_CTS_HMAC_SHA1_96,
+    "aes128-cts-hmac-sha1-96",
+    NULL,
+    16,
+    1,
+    16,
+    &keytype_aes128,
+    &checksum_sha1,
+    &checksum_hmac_sha1_aes128,
+    F_DERIVED,
+    AES_CTS_encrypt,
+};
+static struct encryption_type enctype_aes256_cts_hmac_sha1 = {
+    ETYPE_AES256_CTS_HMAC_SHA1_96,
+    "aes256-cts-hmac-sha1-96",
+    NULL,
+    16,
+    1,
+    16,
+    &keytype_aes256,
+    &checksum_sha1,
+    &checksum_hmac_sha1_aes256,
+    F_DERIVED,
+    AES_CTS_encrypt,
+};
+static unsigned aes_128_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 2 };
+static heim_oid aes_128_cbc_oid = kcrypto_oid_enc(aes_128_cbc_num);
+static struct encryption_type enctype_aes128_cbc_none = {
+    ETYPE_AES128_CBC_NONE,
+    "aes128-cbc-none",
+    &aes_128_cbc_oid,
+    16,
+    16,
+    16,
+    &keytype_aes128,
+    &checksum_none,
+    NULL,
+    F_PSEUDO|F_PADCMS,
+    AES_CBC_encrypt,
+};
+static unsigned aes_192_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 22 };
+static heim_oid aes_192_cbc_oid = kcrypto_oid_enc(aes_192_cbc_num);
+static struct encryption_type enctype_aes192_cbc_none = {
+    ETYPE_AES192_CBC_NONE,
+    "aes192-cbc-none",
+    &aes_192_cbc_oid,
+    16,
+    16,
+    16,
+    &keytype_aes192,
+    &checksum_none,
+    NULL,
+    F_PSEUDO|F_PADCMS,
+    AES_CBC_encrypt,
+};
+static unsigned aes_256_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 42 };
+static heim_oid aes_256_cbc_oid = kcrypto_oid_enc(aes_256_cbc_num);
+static struct encryption_type enctype_aes256_cbc_none = {
+    ETYPE_AES256_CBC_NONE,
+    "aes256-cbc-none",
+    &aes_256_cbc_oid,
+    16,
+    16,
+    16,
+    &keytype_aes256,
+    &checksum_none,
+    NULL,
+    F_PSEUDO|F_PADCMS,
+    AES_CBC_encrypt,
+};
+static struct encryption_type enctype_des_cbc_none = {
+    ETYPE_DES_CBC_NONE,
+    "des-cbc-none",
+    NULL,
+    8,
+    8,
+    0,
+    &keytype_des,
+    &checksum_none,
+    NULL,
+    F_PSEUDO,
+    DES_CBC_encrypt_null_ivec,
+};
+static struct encryption_type enctype_des_cfb64_none = {
+    ETYPE_DES_CFB64_NONE,
+    "des-cfb64-none",
+    NULL,
+    1,
+    1,
+    0,
+    &keytype_des,
+    &checksum_none,
+    NULL,
+    F_PSEUDO,
+    DES_CFB64_encrypt_null_ivec,
+};
+static struct encryption_type enctype_des_pcbc_none = {
+    ETYPE_DES_PCBC_NONE,
+    "des-pcbc-none",
+    NULL,
+    8,
+    8,
+    0,
+    &keytype_des,
+    &checksum_none,
+    NULL,
+    F_PSEUDO,
+    DES_PCBC_encrypt_key_ivec,
+};
+static unsigned des_ede3_cbc_num[] = { 1, 2, 840, 113549, 3, 7 };
+static heim_oid des_ede3_cbc_oid = kcrypto_oid_enc(des_ede3_cbc_num);
+static struct encryption_type enctype_des3_cbc_none_cms = {
+    ETYPE_DES3_CBC_NONE_CMS,
+    "des3-cbc-none-cms",
+    &des_ede3_cbc_oid,
+    8,
+    8,
+    0,
+    &keytype_des3_derived,
+    &checksum_none,
+    NULL,
+    F_PSEUDO|F_PADCMS,
+    DES3_CBC_encrypt,
+};
+static struct encryption_type enctype_des3_cbc_none = {
+    ETYPE_DES3_CBC_NONE,
+    "des3-cbc-none",
+    NULL,
+    8,
+    8,
+    0,
+    &keytype_des3_derived,
+    &checksum_none,
+    NULL,
+    F_PSEUDO,
+    DES3_CBC_encrypt,
+};
+static unsigned rc2CBC_num[] = { 1, 2, 840, 113549, 3, 2 };
+static heim_oid rc2CBC_oid = kcrypto_oid_enc(rc2CBC_num);
+static struct encryption_type enctype_rc2_cbc_none = {
+    ETYPE_RC2_CBC_NONE,
+    "rc2-cbc-none",
+    &rc2CBC_oid,
+    8,
+    8,
+    0,
+    &keytype_rc2,
+    &checksum_none,
+    NULL,
+    F_PSEUDO|F_PADCMS,
+    RC2_CBC_encrypt,
+};
+
+static struct encryption_type *etypes[] = {
+    &enctype_null,
+    &enctype_des_cbc_crc,
+    &enctype_des_cbc_md4,
+    &enctype_des_cbc_md5,
+    &enctype_arcfour_hmac_md5,
+    &enctype_des3_cbc_md5, 
+    &enctype_des3_cbc_sha1,
+    &enctype_old_des3_cbc_sha1,
+    &enctype_aes128_cts_hmac_sha1,
+    &enctype_aes256_cts_hmac_sha1,
+    &enctype_aes128_cbc_none,
+    &enctype_aes192_cbc_none,
+    &enctype_aes256_cbc_none,
+    &enctype_des_cbc_none,
+    &enctype_des_cfb64_none,
+    &enctype_des_pcbc_none,
+    &enctype_des3_cbc_none,
+    &enctype_des3_cbc_none_cms,
+    &enctype_rc2_cbc_none
+};
+
+static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]);
+
+
+static struct encryption_type *
+_find_enctype(krb5_enctype type)
+{
+    int i;
+    for(i = 0; i < num_etypes; i++)
+       if(etypes[i]->type == type)
+           return etypes[i];
+    return NULL;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_to_string(krb5_context context,
+                      krb5_enctype etype,
+                      char **string)
+{
+    struct encryption_type *e;
+    e = _find_enctype(etype);
+    if(e == NULL) {
+       krb5_set_error_string (context, "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    *string = strdup(e->name);
+    if(*string == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_enctype(krb5_context context,
+                      const char *string,
+                      krb5_enctype *etype)
+{
+    int i;
+    for(i = 0; i < num_etypes; i++)
+       if(strcasecmp(etypes[i]->name, string) == 0){
+           *etype = etypes[i]->type;
+           return 0;
+       }
+    krb5_set_error_string (context, "encryption type %s not supported",
+                          string);
+    return KRB5_PROG_ETYPE_NOSUPP;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_to_oid(krb5_context context,
+                   krb5_enctype etype,
+                   heim_oid *oid)
+{
+    struct encryption_type *et = _find_enctype(etype);
+    if(et == NULL) {
+       krb5_set_error_string (context, "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    if(et->oid == NULL) {
+       krb5_set_error_string (context, "%s have not oid", et->name);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    krb5_clear_error_string(context);
+    return copy_oid(et->oid, oid);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_oid_to_enctype(krb5_context context,
+                    const heim_oid *oid,
+                    krb5_enctype *etype)
+{
+    int i;
+    for(i = 0; i < num_etypes; i++) {
+       if(etypes[i]->oid && heim_oid_cmp(etypes[i]->oid, oid) == 0) {
+           *etype = etypes[i]->type;
+           return 0;
+       }
+    }
+    krb5_set_error_string(context, "enctype for oid not supported");
+    return KRB5_PROG_ETYPE_NOSUPP;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_to_keytype(krb5_context context,
+                       krb5_enctype etype,
+                       krb5_keytype *keytype)
+{
+    struct encryption_type *e = _find_enctype(etype);
+    if(e == NULL) {
+       krb5_set_error_string (context, "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    *keytype = e->keytype->type; /* XXX */
+    return 0;
+}
+
+#if 0
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_enctype(krb5_context context,
+                       krb5_keytype keytype,
+                       krb5_enctype *etype)
+{
+    struct key_type *kt = _find_keytype(keytype);
+    krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype);
+    if(kt == NULL)
+       return KRB5_PROG_KEYTYPE_NOSUPP;
+    *etype = kt->best_etype;
+    return 0;
+}
+#endif
+    
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_enctypes (krb5_context context,
+                         krb5_keytype keytype,
+                         unsigned *len,
+                         krb5_enctype **val)
+{
+    int i;
+    unsigned n = 0;
+    krb5_enctype *ret;
+
+    for (i = num_etypes - 1; i >= 0; --i) {
+       if (etypes[i]->keytype->type == keytype
+           && !(etypes[i]->flags & F_PSEUDO))
+           ++n;
+    }
+    ret = malloc(n * sizeof(*ret));
+    if (ret == NULL && n != 0) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    n = 0;
+    for (i = num_etypes - 1; i >= 0; --i) {
+       if (etypes[i]->keytype->type == keytype
+           && !(etypes[i]->flags & F_PSEUDO))
+           ret[n++] = etypes[i]->type;
+    }
+    *len = n;
+    *val = ret;
+    return 0;
+}
+
+/*
+ * First take the configured list of etypes for `keytype' if available,
+ * else, do `krb5_keytype_to_enctypes'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_enctypes_default (krb5_context context,
+                                 krb5_keytype keytype,
+                                 unsigned *len,
+                                 krb5_enctype **val)
+{
+    int i, n;
+    krb5_enctype *ret;
+
+    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
+       return krb5_keytype_to_enctypes (context, keytype, len, val);
+
+    for (n = 0; context->etypes_des[n]; ++n)
+       ;
+    ret = malloc (n * sizeof(*ret));
+    if (ret == NULL && n != 0) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    for (i = 0; i < n; ++i)
+       ret[i] = context->etypes_des[i];
+    *len = n;
+    *val = ret;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_valid(krb5_context context, 
+                krb5_enctype etype)
+{
+    struct encryption_type *e = _find_enctype(etype);
+    if(e == NULL) {
+       krb5_set_error_string (context, "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    if (e->flags & F_DISABLED) {
+       krb5_set_error_string (context, "encryption type %s is disabled",
+                              e->name);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cksumtype_valid(krb5_context context, 
+                    krb5_cksumtype ctype)
+{
+    struct checksum_type *c = _find_checksum(ctype);
+    if (c == NULL) {
+       krb5_set_error_string (context, "checksum type %d not supported",
+                              ctype);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    if (c->flags & F_DISABLED) {
+       krb5_set_error_string (context, "checksum type %s is disabled",
+                              c->name);
+       return KRB5_PROG_SUMTYPE_NOSUPP;
+    }
+    return 0;
+}
+
+
+/* if two enctypes have compatible keys */
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_enctypes_compatible_keys(krb5_context context,
+                             krb5_enctype etype1,
+                             krb5_enctype etype2)
+{
+    struct encryption_type *e1 = _find_enctype(etype1);
+    struct encryption_type *e2 = _find_enctype(etype2);
+    return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
+}
+
+static krb5_boolean
+derived_crypto(krb5_context context,
+              krb5_crypto crypto)
+{
+    return (crypto->et->flags & F_DERIVED) != 0;
+}
+
+static krb5_boolean
+special_crypto(krb5_context context,
+              krb5_crypto crypto)
+{
+    return (crypto->et->flags & F_SPECIAL) != 0;
+}
+
+#define CHECKSUMSIZE(C) ((C)->checksumsize)
+#define CHECKSUMTYPE(C) ((C)->type)
+
+static krb5_error_code
+encrypt_internal_derived(krb5_context context,
+                        krb5_crypto crypto,
+                        unsigned usage,
+                        void *data,
+                        size_t len,
+                        krb5_data *result,
+                        void *ivec)
+{
+    size_t sz, block_sz, checksum_sz, total_sz;
+    Checksum cksum;
+    unsigned char *p, *q;
+    krb5_error_code ret;
+    struct key_data *dkey;
+    const struct encryption_type *et = crypto->et;
+    
+    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
+
+    sz = et->confoundersize + len;
+    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
+    total_sz = block_sz + checksum_sz;
+    p = calloc(1, total_sz);
+    if(p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    
+    q = p;
+    krb5_generate_random_block(q, et->confoundersize); /* XXX */
+    q += et->confoundersize;
+    memcpy(q, data, len);
+    
+    ret = create_checksum(context, 
+                         et->keyed_checksum,
+                         crypto, 
+                         INTEGRITY_USAGE(usage),
+                         p, 
+                         block_sz,
+                         &cksum);
+    if(ret == 0 && cksum.checksum.length != checksum_sz) {
+       free_Checksum (&cksum);
+       krb5_clear_error_string (context);
+       ret = KRB5_CRYPTO_INTERNAL;
+    }
+    if(ret)
+       goto fail;
+    memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length);
+    free_Checksum (&cksum);
+    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
+    if(ret)
+       goto fail;
+    ret = _key_schedule(context, dkey, crypto->params);
+    if(ret)
+       goto fail;
+#ifdef CRYPTO_DEBUG
+    krb5_crypto_debug(context, 1, block_sz, dkey->key);
+#endif
+    ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
+    if (ret)
+       goto fail;
+    result->data = p;
+    result->length = total_sz;
+    return 0;
+ fail:
+    memset(p, 0, total_sz);
+    free(p);
+    return ret;
+}
+
+
+static krb5_error_code
+encrypt_internal(krb5_context context,
+                krb5_crypto crypto,
+                void *data,
+                size_t len,
+                krb5_data *result,
+                void *ivec)
+{
+    size_t sz, block_sz, checksum_sz, padsize = 0;
+    Checksum cksum;
+    unsigned char *p, *q;
+    krb5_error_code ret;
+    const struct encryption_type *et = crypto->et;
+    
+    checksum_sz = CHECKSUMSIZE(et->checksum);
+    
+    sz = et->confoundersize + checksum_sz + len;
+    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
+    if ((et->flags & F_PADCMS) && et->padsize != 1) {
+       padsize = et->padsize - (sz % et->padsize);
+       if (padsize == et->padsize)
+           block_sz += et->padsize;
+    }
+    p = calloc(1, block_sz);
+    if(p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    
+    q = p;
+    krb5_generate_random_block(q, et->confoundersize); /* XXX */
+    q += et->confoundersize;
+    memset(q, 0, checksum_sz);
+    q += checksum_sz;
+    memcpy(q, data, len);
+
+    ret = create_checksum(context, 
+                         et->checksum,
+                         crypto,
+                         0,
+                         p, 
+                         block_sz,
+                         &cksum);
+    if(ret == 0 && cksum.checksum.length != checksum_sz) {
+       krb5_clear_error_string (context);
+       free_Checksum(&cksum);
+       ret = KRB5_CRYPTO_INTERNAL;
+    }
+    if(ret)
+       goto fail;
+    memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length);
+    free_Checksum(&cksum);
+    ret = _key_schedule(context, &crypto->key, crypto->params);
+    if(ret)
+       goto fail;
+    if (et->flags & F_PADCMS) {
+       int i;
+       q = p + len + checksum_sz + et->confoundersize;
+       for (i = 0; i < padsize; i++)
+           q[i] = padsize;
+    }
+#ifdef CRYPTO_DEBUG
+    krb5_crypto_debug(context, 1, block_sz, crypto->key.key);
+#endif
+    ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec);
+    if (ret) {
+       memset(p, 0, block_sz);
+       free(p);
+       return ret;
+    }
+    result->data = p;
+    result->length = block_sz;
+    return 0;
+ fail:
+    memset(p, 0, block_sz);
+    free(p);
+    return ret;
+}
+
+static krb5_error_code
+encrypt_internal_special(krb5_context context,
+                        krb5_crypto crypto,
+                        int usage,
+                        void *data,
+                        size_t len,
+                        krb5_data *result,
+                        void *ivec)
+{
+    struct encryption_type *et = crypto->et;
+    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
+    size_t sz = len + cksum_sz + et->confoundersize;
+    char *tmp, *p;
+    krb5_error_code ret;
+
+    tmp = malloc (sz);
+    if (tmp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    p = tmp;
+    memset (p, 0, cksum_sz);
+    p += cksum_sz;
+    krb5_generate_random_block(p, et->confoundersize);
+    p += et->confoundersize;
+    memcpy (p, data, len);
+    ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec);
+    if (ret) {
+       memset(tmp, 0, sz);
+       free(tmp);
+       return ret;
+    }
+    result->data   = tmp;
+    result->length = sz;
+    return 0;
+}
+
+static krb5_error_code
+decrypt_internal_derived(krb5_context context,
+                        krb5_crypto crypto,
+                        unsigned usage,
+                        void *data,
+                        size_t len,
+                        krb5_data *result,
+                        void *ivec)
+{
+    size_t checksum_sz;
+    Checksum cksum;
+    unsigned char *p;
+    krb5_error_code ret;
+    struct key_data *dkey;
+    struct encryption_type *et = crypto->et;
+    unsigned long l;
+    
+    checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
+    if (len < checksum_sz) {
+       krb5_clear_error_string (context);
+       return EINVAL;          /* XXX - better error code? */
+    }
+
+    if (((len - checksum_sz) % et->padsize) != 0) {
+       krb5_clear_error_string(context);
+       return KRB5_BAD_MSIZE;
+    }
+
+    if (len < checksum_sz + et->confoundersize) {
+       krb5_set_error_string(context, "Encrypted data shorter then "
+                                 "checksum + confunder");
+       return KRB5_BAD_MSIZE;
+    }
+
+    p = malloc(len);
+    if(len != 0 && p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(p, data, len);
+
+    len -= checksum_sz;
+
+    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+    ret = _key_schedule(context, dkey, crypto->params);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+#ifdef CRYPTO_DEBUG
+    krb5_crypto_debug(context, 0, len, dkey->key);
+#endif
+    ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec);
+    if (ret) {
+       free(p);
+       return ret;
+    }
+
+    cksum.checksum.data   = p + len;
+    cksum.checksum.length = checksum_sz;
+    cksum.cksumtype       = CHECKSUMTYPE(et->keyed_checksum);
+
+    ret = verify_checksum(context,
+                         crypto,
+                         INTEGRITY_USAGE(usage),
+                         p,
+                         len,
+                         &cksum);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+    l = len - et->confoundersize;
+    memmove(p, p + et->confoundersize, l);
+    result->data = realloc(p, l);
+    if(result->data == NULL) {
+       free(p);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    result->length = l;
+    return 0;
+}
+
+static krb5_error_code
+decrypt_internal(krb5_context context,
+                krb5_crypto crypto,
+                void *data,
+                size_t len,
+                krb5_data *result,
+                void *ivec)
+{
+    krb5_error_code ret;
+    unsigned char *p;
+    Checksum cksum;
+    size_t checksum_sz, l;
+    struct encryption_type *et = crypto->et;
+    
+    if ((len % et->padsize) != 0) {
+       krb5_clear_error_string(context);
+       return KRB5_BAD_MSIZE;
+    }
+
+    checksum_sz = CHECKSUMSIZE(et->checksum);
+
+    if (len < checksum_sz + et->confoundersize) {
+       krb5_set_error_string(context, "Encrypted data shorter then "
+                                 "checksum + confunder");
+       return KRB5_BAD_MSIZE;
+    }
+
+    p = malloc(len);
+    if(len != 0 && p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(p, data, len);
+    
+    ret = _key_schedule(context, &crypto->key, crypto->params);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+#ifdef CRYPTO_DEBUG
+    krb5_crypto_debug(context, 0, len, crypto->key.key);
+#endif
+    ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec);
+    if (ret) {
+       free(p);
+       return ret;
+    }
+    ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+    memset(p + et->confoundersize, 0, checksum_sz);
+    cksum.cksumtype = CHECKSUMTYPE(et->checksum);
+    ret = verify_checksum(context, NULL, 0, p, len, &cksum);
+    free_Checksum(&cksum);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+    l = len - et->confoundersize - checksum_sz;
+    memmove(p, p + et->confoundersize + checksum_sz, l);
+    result->data = realloc(p, l);
+    if(result->data == NULL) {
+       free(p);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    result->length = l;
+    return 0;
+}
+
+static krb5_error_code
+decrypt_internal_special(krb5_context context,
+                        krb5_crypto crypto,
+                        int usage,
+                        void *data,
+                        size_t len,
+                        krb5_data *result,
+                        void *ivec)
+{
+    struct encryption_type *et = crypto->et;
+    size_t cksum_sz = CHECKSUMSIZE(et->checksum);
+    size_t sz = len - cksum_sz - et->confoundersize;
+    unsigned char *p;
+    krb5_error_code ret;
+
+    if ((len % et->padsize) != 0) {
+       krb5_clear_error_string(context);
+       return KRB5_BAD_MSIZE;
+    }
+
+    if (len < cksum_sz + et->confoundersize) {
+       krb5_set_error_string(context, "Encrypted data shorter then "
+                                 "checksum + confunder");
+       return KRB5_BAD_MSIZE;
+    }
+
+    p = malloc (len);
+    if (p == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(p, data, len);
+    
+    ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec);
+    if (ret) {
+       free(p);
+       return ret;
+    }
+
+    memmove (p, p + cksum_sz + et->confoundersize, sz);
+    result->data = realloc(p, sz);
+    if(result->data == NULL) {
+       free(p);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    result->length = sz;
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encrypt_ivec(krb5_context context,
+                 krb5_crypto crypto,
+                 unsigned usage,
+                 void *data,
+                 size_t len,
+                 krb5_data *result,
+                 void *ivec)
+{
+    if(derived_crypto(context, crypto))
+       return encrypt_internal_derived(context, crypto, usage, 
+                                       data, len, result, ivec);
+    else if (special_crypto(context, crypto))
+       return encrypt_internal_special (context, crypto, usage,
+                                        data, len, result, ivec);
+    else
+       return encrypt_internal(context, crypto, data, len, result, ivec);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encrypt(krb5_context context,
+            krb5_crypto crypto,
+            unsigned usage,
+            void *data,
+            size_t len,
+            krb5_data *result)
+{
+    return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encrypt_EncryptedData(krb5_context context,
+                          krb5_crypto crypto,
+                          unsigned usage,
+                          void *data,
+                          size_t len,
+                          int kvno,
+                          EncryptedData *result)
+{
+    result->etype = CRYPTO_ETYPE(crypto);
+    if(kvno){
+       ALLOC(result->kvno, 1);
+       *result->kvno = kvno;
+    }else
+       result->kvno = NULL;
+    return krb5_encrypt(context, crypto, usage, data, len, &result->cipher);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt_ivec(krb5_context context,
+                 krb5_crypto crypto,
+                 unsigned usage,
+                 void *data,
+                 size_t len,
+                 krb5_data *result,
+                 void *ivec)
+{
+    if(derived_crypto(context, crypto))
+       return decrypt_internal_derived(context, crypto, usage, 
+                                       data, len, result, ivec);
+    else if (special_crypto (context, crypto))
+       return decrypt_internal_special(context, crypto, usage,
+                                       data, len, result, ivec);
+    else
+       return decrypt_internal(context, crypto, data, len, result, ivec);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt(krb5_context context,
+            krb5_crypto crypto,
+            unsigned usage,
+            void *data,
+            size_t len,
+            krb5_data *result)
+{
+    return krb5_decrypt_ivec (context, crypto, usage, data, len, result,
+                             NULL);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt_EncryptedData(krb5_context context,
+                          krb5_crypto crypto,
+                          unsigned usage,
+                          const EncryptedData *e,
+                          krb5_data *result)
+{
+    return krb5_decrypt(context, crypto, usage, 
+                       e->cipher.data, e->cipher.length, result);
+}
+
+/************************************************************
+ *                                                          *
+ ************************************************************/
+
+#ifdef HAVE_OPENSSL
+#include <openssl/rand.h>
+
+/* From openssl/crypto/rand/rand_lcl.h */
+#define ENTROPY_NEEDED 20
+static int
+seed_something(void)
+{
+    char buf[1024], seedfile[256];
+
+    /* If there is a seed file, load it. But such a file cannot be trusted,
+       so use 0 for the entropy estimate */
+    if (RAND_file_name(seedfile, sizeof(seedfile))) {
+       int fd;
+       fd = open(seedfile, O_RDONLY);
+       if (fd >= 0) {
+           ssize_t ret;
+           ret = read(fd, buf, sizeof(buf));
+           if (ret > 0)
+               RAND_add(buf, ret, 0.0);
+           close(fd);
+       } else
+           seedfile[0] = '\0';
+    } else
+       seedfile[0] = '\0';
+
+    /* Calling RAND_status() will try to use /dev/urandom if it exists so
+       we do not have to deal with it. */
+    if (RAND_status() != 1) {
+       krb5_context context;
+       const char *p;
+
+       /* Try using egd */
+       if (!krb5_init_context(&context)) {
+           p = krb5_config_get_string(context, NULL, "libdefaults",
+               "egd_socket", NULL);
+           if (p != NULL)
+               RAND_egd_bytes(p, ENTROPY_NEEDED);
+           krb5_free_context(context);
+       }
+    }
+    
+    if (RAND_status() == 1)    {
+       /* Update the seed file */
+       if (seedfile[0])
+           RAND_write_file(seedfile);
+
+       return 0;
+    } else
+       return -1;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_generate_random_block(void *buf, size_t len)
+{
+    static int rng_initialized = 0;
+    
+    HEIMDAL_MUTEX_lock(&crypto_mutex);
+    if (!rng_initialized) {
+       if (seed_something())
+           krb5_abortx(NULL, "Fatal: could not seed the random number generator");
+       
+       rng_initialized = 1;
+    }
+    HEIMDAL_MUTEX_unlock(&crypto_mutex);
+    RAND_bytes(buf, len);
+}
+
+#else
+
+void KRB5_LIB_FUNCTION
+krb5_generate_random_block(void *buf, size_t len)
+{
+    DES_cblock key, out;
+    static DES_cblock counter;
+    static DES_key_schedule schedule;
+    int i;
+    static int initialized = 0;
+
+    HEIMDAL_MUTEX_lock(&crypto_mutex);
+    if(!initialized) {
+       DES_new_random_key(&key);
+       DES_set_key(&key, &schedule);
+       memset(&key, 0, sizeof(key));
+       DES_new_random_key(&counter);
+       initialized = 1;
+    }
+    HEIMDAL_MUTEX_unlock(&crypto_mutex);
+    while(len > 0) {
+       DES_ecb_encrypt(&counter, &out, &schedule, DES_ENCRYPT);
+       for(i = 7; i >=0; i--)
+           if(counter[i]++)
+               break;
+       memcpy(buf, out, min(len, sizeof(out)));
+       len -= min(len, sizeof(out));
+       buf = (char*)buf + sizeof(out);
+    }
+}
+#endif
+
+static void
+DES3_postproc(krb5_context context,
+             unsigned char *k, size_t len, struct key_data *key)
+{
+    DES3_random_to_key(context, key->key, k, len);
+
+    if (key->schedule) {
+       krb5_free_data(context, key->schedule);
+       key->schedule = NULL;
+    }
+}
+
+static krb5_error_code
+derive_key(krb5_context context,
+          struct encryption_type *et,
+          struct key_data *key,
+          const void *constant,
+          size_t len)
+{
+    unsigned char *k;
+    unsigned int nblocks = 0, i;
+    krb5_error_code ret = 0;
+    
+    struct key_type *kt = et->keytype;
+    /* since RC2 is only the weird crypto alg with parameter and this
+     * function not defined with work with RC2, this is ok */
+    ret = _key_schedule(context, key, NULL);
+    if(ret)
+       return ret;
+    if(et->blocksize * 8 < kt->bits || 
+       len != et->blocksize) {
+       nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
+       k = malloc(nblocks * et->blocksize);
+       if(k == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       _krb5_n_fold(constant, len, k, et->blocksize);
+       for(i = 0; i < nblocks; i++) {
+           if(i > 0)
+               memcpy(k + i * et->blocksize, 
+                      k + (i - 1) * et->blocksize,
+                      et->blocksize);
+           (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize,
+                          1, 0, NULL);
+       }
+    } else {
+       /* this case is probably broken, but won't be run anyway */
+       void *c = malloc(len);
+       size_t res_len = (kt->bits + 7) / 8;
+
+       if(len != 0 && c == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       memcpy(c, constant, len);
+       (*et->encrypt)(context, key, c, len, 1, 0, NULL);
+       k = malloc(res_len);
+       if(res_len != 0 && k == NULL) {
+           free(c);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       _krb5_n_fold(c, len, k, res_len);
+       free(c);
+    }
+    
+    /* XXX keytype dependent post-processing */
+    switch(kt->type) {
+    case KEYTYPE_DES3:
+       DES3_postproc(context, k, nblocks * et->blocksize, key);
+       break;
+    case KEYTYPE_AES128:
+    case KEYTYPE_AES256:
+       memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length);
+       break;
+    default:
+       krb5_set_error_string(context,
+                             "derive_key() called with unknown keytype (%u)", 
+                             kt->type);
+       ret = KRB5_CRYPTO_INTERNAL;
+       break;
+    }
+    if (key->schedule) {
+       krb5_free_data(context, key->schedule);
+       key->schedule = NULL;
+    }
+    memset(k, 0, nblocks * et->blocksize);
+    free(k);
+    return ret;
+}
+
+static struct key_data *
+_new_derived_key(krb5_crypto crypto, unsigned usage)
+{
+    struct key_usage *d = crypto->key_usage;
+    d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d));
+    if(d == NULL)
+       return NULL;
+    crypto->key_usage = d;
+    d += crypto->num_key_usage++;
+    memset(d, 0, sizeof(*d));
+    d->usage = usage;
+    return &d->key;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_derive_key(krb5_context context,
+               const krb5_keyblock *key,
+               krb5_enctype etype,
+               const void *constant,
+               size_t constant_len,
+               krb5_keyblock **derived_key)
+{
+    krb5_error_code ret;
+    struct encryption_type *et;
+    struct key_data d;
+
+    et = _find_enctype (etype);
+    if (et == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+
+    ret = krb5_copy_keyblock(context, key, derived_key);
+    if (ret)
+       return ret;
+
+    d.key = *derived_key;
+    d.schedule = NULL;
+    ret = derive_key(context, et, &d, constant, constant_len);
+    if (ret)
+       return ret;
+    ret = krb5_copy_keyblock(context, d.key, derived_key);
+    return ret;
+}
+
+static krb5_error_code
+_get_derived_key(krb5_context context, 
+                krb5_crypto crypto, 
+                unsigned usage, 
+                struct key_data **key)
+{
+    int i;
+    struct key_data *d;
+    unsigned char constant[5];
+
+    for(i = 0; i < crypto->num_key_usage; i++)
+       if(crypto->key_usage[i].usage == usage) {
+           *key = &crypto->key_usage[i].key;
+           return 0;
+       }
+    d = _new_derived_key(crypto, usage);
+    if(d == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    krb5_copy_keyblock(context, crypto->key.key, &d->key);
+    _krb5_put_int(constant, usage, 5);
+    derive_key(context, crypto->et, d, constant, sizeof(constant));
+    *key = d;
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_init(krb5_context context,
+                const krb5_keyblock *key,
+                krb5_enctype etype,
+                krb5_crypto *crypto)
+{
+    krb5_error_code ret;
+    ALLOC(*crypto, 1);
+    if(*crypto == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    if(etype == ETYPE_NULL)
+       etype = key->keytype;
+    (*crypto)->et = _find_enctype(etype);
+    if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) {
+       free(*crypto);
+       *crypto = NULL;
+       krb5_set_error_string (context, "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    if((*crypto)->et->keytype->minsize > key->keyvalue.length) {
+       free(*crypto);
+       *crypto = NULL;
+       krb5_set_error_string (context, "encryption key has bad length");
+       return KRB5_BAD_KEYSIZE;
+    }
+    ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key);
+    if(ret) {
+       free(*crypto);
+       *crypto = NULL;
+       return ret;
+    }
+    (*crypto)->key.schedule = NULL;
+    (*crypto)->num_key_usage = 0;
+    (*crypto)->key_usage = NULL;
+    (*crypto)->params = NULL;
+    return 0;
+}
+
+static void
+free_key_data(krb5_context context, struct key_data *key)
+{
+    krb5_free_keyblock(context, key->key);
+    if(key->schedule) {
+       memset(key->schedule->data, 0, key->schedule->length);
+       krb5_free_data(context, key->schedule);
+    }
+}
+
+static void
+free_key_usage(krb5_context context, struct key_usage *ku)
+{
+    free_key_data(context, &ku->key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_destroy(krb5_context context,
+                   krb5_crypto crypto)
+{
+    int i;
+    
+    for(i = 0; i < crypto->num_key_usage; i++)
+       free_key_usage(context, &crypto->key_usage[i]);
+    free(crypto->key_usage);
+    free_key_data(context, &crypto->key);
+    free(crypto->params);
+    free (crypto);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_get_params(krb5_context context,
+                      const krb5_crypto crypto,
+                      const krb5_data *params,
+                      krb5_data *ivec)
+{
+    krb5_error_code (*gp)(krb5_context, const krb5_data *,void **,krb5_data *);
+    krb5_error_code ret;
+
+    gp = crypto->et->keytype->get_params;
+    if (gp) {
+       if (crypto->params) {
+           krb5_set_error_string(context,
+                                 "krb5_crypto_get_params called "
+                                 "more than once");
+           return KRB5_PROG_ETYPE_NOSUPP;
+       }
+       ret = (*gp)(context, params, &crypto->params, ivec);
+    } else {
+       size_t size;
+       if (ivec == NULL)
+           return 0;
+       ret = decode_CBCParameter(params->data, params->length, ivec, &size);
+    }
+    if (ret)
+       return ret;
+    if (ivec->length < crypto->et->blocksize) {
+       krb5_data_free(ivec);
+       krb5_set_error_string(context, "%s IV of wrong size", 
+                             crypto->et->name);
+       return ASN1_PARSE_ERROR;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_set_params(krb5_context context,
+                      const krb5_crypto crypto,
+                      const krb5_data *ivec,
+                      krb5_data *params)
+{
+    krb5_error_code (*sp)(krb5_context, const void *,
+                         const krb5_data *, krb5_data *);
+    krb5_error_code ret;
+
+    sp = crypto->et->keytype->set_params;
+    if (sp == NULL) {
+       size_t size;
+       if (ivec == NULL)
+           return 0;
+       ASN1_MALLOC_ENCODE(CBCParameter, params->data, params->length,
+                          ivec, &size, ret);
+       if (ret)
+           return ret;
+       if (size != params->length)
+           krb5_abortx(context, "Internal asn1 encoder failure");
+       return 0;
+    }
+    if (crypto->params) {
+       krb5_set_error_string(context,
+                             "krb5_crypto_set_params called "
+                             "more than once");
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    return (*sp)(context, crypto->params, ivec, params);
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getblocksize(krb5_context context,
+                        krb5_crypto crypto,
+                        size_t *blocksize)
+{
+    *blocksize = crypto->et->blocksize;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getenctype(krb5_context context,
+                      krb5_crypto crypto,
+                      krb5_enctype *enctype)
+{
+    *enctype = crypto->et->type;
+     return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getpadsize(krb5_context context,
+                       krb5_crypto crypto,
+                       size_t *padsize)      
+{
+    *padsize = crypto->et->padsize;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getconfoundersize(krb5_context context,
+                              krb5_crypto crypto,
+                              size_t *confoundersize)
+{
+    *confoundersize = crypto->et->confoundersize;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_disable(krb5_context context,
+                    krb5_enctype enctype)
+{
+    struct encryption_type *et = _find_enctype(enctype);
+    if(et == NULL) {
+       if (context)
+           krb5_set_error_string (context, "encryption type %d not supported",
+                                  enctype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    et->flags |= F_DISABLED;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_derived(krb5_context context,
+                          const void *str,
+                          size_t len,
+                          krb5_enctype etype,
+                          krb5_keyblock *key)
+{
+    struct encryption_type *et = _find_enctype(etype);
+    krb5_error_code ret;
+    struct key_data kd;
+    size_t keylen;
+    u_char *tmp;
+
+    if(et == NULL) {
+       krb5_set_error_string (context, "encryption type %d not supported",
+                              etype);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    keylen = et->keytype->bits / 8;
+
+    ALLOC(kd.key, 1);
+    if(kd.key == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size);
+    if(ret) {
+       free(kd.key);
+       return ret;
+    }
+    kd.key->keytype = etype;
+    tmp = malloc (keylen);
+    if(tmp == NULL) {
+       krb5_free_keyblock(context, kd.key);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    _krb5_n_fold(str, len, tmp, keylen);
+    kd.schedule = NULL;
+    DES3_postproc (context, tmp, keylen, &kd); /* XXX */
+    memset(tmp, 0, keylen);
+    free(tmp);
+    ret = derive_key(context, 
+                    et,
+                    &kd,
+                    "kerberos", /* XXX well known constant */
+                    strlen("kerberos"));
+    ret = krb5_copy_keyblock_contents(context, kd.key, key);
+    free_key_data(context, &kd);
+    return ret;
+}
+
+static size_t
+wrapped_length (krb5_context context,
+               krb5_crypto  crypto,
+               size_t       data_len)
+{
+    struct encryption_type *et = crypto->et;
+    size_t padsize = et->padsize;
+    size_t checksumsize = CHECKSUMSIZE(et->checksum);
+    size_t res;
+
+    res =  et->confoundersize + checksumsize + data_len;
+    res =  (res + padsize - 1) / padsize * padsize;
+    return res;
+}
+
+static size_t
+wrapped_length_dervied (krb5_context context,
+                       krb5_crypto  crypto,
+                       size_t       data_len)
+{
+    struct encryption_type *et = crypto->et;
+    size_t padsize = et->padsize;
+    size_t res;
+
+    res =  et->confoundersize + data_len;
+    res =  (res + padsize - 1) / padsize * padsize;
+    if (et->keyed_checksum)
+       res += et->keyed_checksum->checksumsize;
+    else
+       res += et->checksum->checksumsize;
+    return res;
+}
+
+/*
+ * Return the size of an encrypted packet of length `data_len'
+ */
+
+size_t
+krb5_get_wrapped_length (krb5_context context,
+                        krb5_crypto  crypto,
+                        size_t       data_len)
+{
+    if (derived_crypto (context, crypto))
+       return wrapped_length_dervied (context, crypto, data_len);
+    else
+       return wrapped_length (context, crypto, data_len);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_random_to_key(krb5_context context,
+                  krb5_enctype type,
+                  const void *data,
+                  size_t size,
+                  krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    struct encryption_type *et = _find_enctype(type);
+    if(et == NULL) {
+       krb5_set_error_string(context, "encryption type %d not supported",
+                             type);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    if ((et->keytype->bits + 7) / 8 > size) {
+       krb5_set_error_string(context, "encryption key %s needs %d bytes "
+                             "of random to make an encryption key out of it",
+                             et->name, (int)et->keytype->size);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    ret = krb5_data_alloc(&key->keyvalue, et->keytype->size);
+    if(ret) 
+       return ret;
+    key->keytype = type;
+    if (et->keytype->random_to_key)
+       (*et->keytype->random_to_key)(context, key, data, size);
+    else
+       memcpy(key->keyvalue.data, data, et->keytype->size);
+
+    return 0;
+}
+
+#ifdef CRYPTO_DEBUG
+
+static krb5_error_code
+krb5_get_keyid(krb5_context context,
+              krb5_keyblock *key,
+              u_int32_t *keyid)
+{
+    MD5_CTX md5;
+    unsigned char tmp[16];
+
+    MD5_Init (&md5);
+    MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length);
+    MD5_Final (tmp, &md5);
+    *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15];
+    return 0;
+}
+
+static void
+krb5_crypto_debug(krb5_context context,
+                 int encrypt,
+                 size_t len,
+                 krb5_keyblock *key)
+{
+    u_int32_t keyid;
+    char *kt;
+    krb5_get_keyid(context, key, &keyid);
+    krb5_enctype_to_string(context, key->keytype, &kt);
+    krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", 
+              encrypt ? "encrypting" : "decrypting",
+              (unsigned long)len,
+              keyid,
+              kt);
+    free(kt);
+}
+
+#endif /* CRYPTO_DEBUG */
+
+#if 0
+int
+main()
+{
+#if 0
+    int i;
+    krb5_context context;
+    krb5_crypto crypto;
+    struct key_data *d;
+    krb5_keyblock key;
+    char constant[4];
+    unsigned usage = ENCRYPTION_USAGE(3);
+    krb5_error_code ret;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
+    key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8"
+       "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e"
+       "\xc8\xdf\xab\x26\x86\x64\x15\x25";
+    key.keyvalue.length = 24;
+
+    krb5_crypto_init(context, &key, 0, &crypto);
+
+    d = _new_derived_key(crypto, usage);
+    if(d == NULL)
+       return ENOMEM;
+    krb5_copy_keyblock(context, crypto->key.key, &d->key);
+    _krb5_put_int(constant, usage, 4);
+    derive_key(context, crypto->et, d, constant, sizeof(constant));
+    return 0;
+#else
+    int i;
+    krb5_context context;
+    krb5_crypto crypto;
+    struct key_data *d;
+    krb5_keyblock key;
+    krb5_error_code ret;
+    Checksum res;
+
+    char *data = "what do ya want for nothing?";
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    key.keytype = ETYPE_NEW_DES3_CBC_SHA1;
+    key.keyvalue.data = "Jefe";
+    /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+       "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */
+    key.keyvalue.length = 4;
+
+    d = calloc(1, sizeof(*d));
+
+    d->key = &key;
+    res.checksum.length = 20;
+    res.checksum.data = malloc(res.checksum.length);
+    SP_HMAC_SHA1_checksum(context, d, data, 28, &res);
+
+    return 0;
+#endif
+}
+#endif
diff --git a/src/kerberosV/src/lib/krb5/data.c b/src/kerberosV/src/lib/krb5/data.c
new file mode 100644 (file)
index 0000000..fd49b5a
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: data.c,v 1.19 2004/05/25 21:22:23 lha Exp $");
+
+void KRB5_LIB_FUNCTION
+krb5_data_zero(krb5_data *p)
+{
+    p->length = 0;
+    p->data   = NULL;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_data_free(krb5_data *p)
+{
+    if(p->data != NULL)
+       free(p->data);
+    krb5_data_zero(p);
+}
+
+void KRB5_LIB_FUNCTION 
+krb5_free_data_contents(krb5_context context, krb5_data *data)
+{
+    krb5_data_free(data);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_data(krb5_context context,
+              krb5_data *p)
+{
+    krb5_data_free(p);
+    free(p);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_data_alloc(krb5_data *p, int len)
+{
+    p->data = malloc(len);
+    if(len && p->data == NULL)
+       return ENOMEM;
+    p->length = len;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_data_realloc(krb5_data *p, int len)
+{
+    void *tmp;
+    tmp = realloc(p->data, len);
+    if(len && !tmp)
+       return ENOMEM;
+    p->data = tmp;
+    p->length = len;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_data_copy(krb5_data *p, const void *data, size_t len)
+{
+    if (len) {
+       if(krb5_data_alloc(p, len))
+           return ENOMEM;
+       memmove(p->data, data, len);
+    } else
+       p->data = NULL;
+    p->length = len;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_data(krb5_context context, 
+              const krb5_data *indata, 
+              krb5_data **outdata)
+{
+    krb5_error_code ret;
+    ALLOC(*outdata, 1);
+    if(*outdata == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = copy_octet_string(indata, *outdata);
+    if(ret) {
+       krb5_clear_error_string (context);
+       free(*outdata);
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/derived-key-test.c b/src/kerberosV/src/lib/krb5/derived-key-test.c
new file mode 100644 (file)
index 0000000..2038da2
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2001 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: derived-key-test.c,v 1.3 2005/04/30 15:18:27 lha Exp $");
+
+enum { MAXSIZE = 24 };
+
+static struct testcase {
+    krb5_enctype enctype;
+    unsigned char constant[MAXSIZE];
+    size_t constant_len;
+    unsigned char key[MAXSIZE];
+    unsigned char res[MAXSIZE];
+} tests[] = {
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5,
+    {0xdc, 0xe0, 0x6b, 0x1f, 0x64, 0xc8, 0x57, 0xa1, 0x1c, 0x3d, 0xb5, 0x7c, 0x51, 0x89, 0x9b, 0x2c, 0xc1, 0x79, 0x10, 0x08, 0xce, 0x97, 0x3b, 0x92},
+    {0x92, 0x51, 0x79, 0xd0, 0x45, 0x91, 0xa7, 0x9b, 0x5d, 0x31, 0x92, 0xc4, 0xa7, 0xe9, 0xc2, 0x89, 0xb0, 0x49, 0xc7, 0x1f, 0x6e, 0xe6, 0x04, 0xcd}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5,
+     {0x5e, 0x13, 0xd3, 0x1c, 0x70, 0xef, 0x76, 0x57, 0x46, 0x57, 0x85, 0x31, 0xcb, 0x51, 0xc1, 0x5b, 0xf1, 0x1c, 0xa8, 0x2c, 0x97, 0xce, 0xe9, 0xf2},
+     {0x9e, 0x58, 0xe5, 0xa1, 0x46, 0xd9, 0x94, 0x2a, 0x10, 0x1c, 0x46, 0x98, 0x45, 0xd6, 0x7a, 0x20, 0xe3, 0xc4, 0x25, 0x9e, 0xd9, 0x13, 0xf2, 0x07}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5,
+     {0x98, 0xe6, 0xfd, 0x8a, 0x04, 0xa4, 0xb6, 0x85, 0x9b, 0x75, 0xa1, 0x76, 0x54, 0x0b, 0x97, 0x52, 0xba, 0xd3, 0xec, 0xd6, 0x10, 0xa2, 0x52, 0xbc},
+     {0x13, 0xfe, 0xf8, 0x0d, 0x76, 0x3e, 0x94, 0xec, 0x6d, 0x13, 0xfd, 0x2c, 0xa1, 0xd0, 0x85, 0x07, 0x02, 0x49, 0xda, 0xd3, 0x98, 0x08, 0xea, 0xbf}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5,
+     {0x62, 0x2a, 0xec, 0x25, 0xa2, 0xfe, 0x2c, 0xad, 0x70, 0x94, 0x68, 0x0b, 0x7c, 0x64, 0x94, 0x02, 0x80, 0x08, 0x4c, 0x1a, 0x7c, 0xec, 0x92, 0xb5},
+     {0xf8, 0xdf, 0xbf, 0x04, 0xb0, 0x97, 0xe6, 0xd9, 0xdc, 0x07, 0x02, 0x68, 0x6b, 0xcb, 0x34, 0x89, 0xd9, 0x1f, 0xd9, 0xa4, 0x51, 0x6b, 0x70, 0x3e}},
+    {ETYPE_DES3_CBC_SHA1, {0x6b, 0x65, 0x72, 0x62, 0x65, 0x72, 0x6f, 0x73}, 8,
+     {0xd3, 0xf8, 0x29, 0x8c, 0xcb, 0x16, 0x64, 0x38, 0xdc, 0xb9, 0xb9, 0x3e, 0xe5, 0xa7, 0x62, 0x92, 0x86, 0xa4, 0x91, 0xf8, 0x38, 0xf8, 0x02, 0xfb},
+     {0x23, 0x70, 0xda, 0x57, 0x5d, 0x2a, 0x3d, 0xa8, 0x64, 0xce, 0xbf, 0xdc, 0x52, 0x04, 0xd5, 0x6d, 0xf7, 0x79, 0xa7, 0xdf, 0x43, 0xd9, 0xda, 0x43}},
+    {ETYPE_DES3_CBC_SHA1, {0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x65}, 7,
+     {0xb5, 0x5e, 0x98, 0x34, 0x67, 0xe5, 0x51, 0xb3, 0xe5, 0xd0, 0xe5, 0xb6, 0xc8, 0x0d, 0x45, 0x76, 0x94, 0x23, 0xa8, 0x73, 0xdc, 0x62, 0xb3, 0x0e},
+     {0x01, 0x26, 0x38, 0x8a, 0xad, 0xc8, 0x1a, 0x1f, 0x2a, 0x62, 0xbc, 0x45, 0xf8, 0xd5, 0xc1, 0x91, 0x51, 0xba, 0xcd, 0xd5, 0xcb, 0x79, 0x8a, 0x3e}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5,
+     {0xc1, 0x08, 0x16, 0x49, 0xad, 0xa7, 0x43, 0x62, 0xe6, 0xa1, 0x45, 0x9d, 0x01, 0xdf, 0xd3, 0x0d, 0x67, 0xc2, 0x23, 0x4c, 0x94, 0x07, 0x04, 0xda},
+     {0x34, 0x80, 0x57, 0xec, 0x98, 0xfd, 0xc4, 0x80, 0x16, 0x16, 0x1c, 0x2a, 0x4c, 0x7a, 0x94, 0x3e, 0x92, 0xae, 0x49, 0x2c, 0x98, 0x91, 0x75, 0xf7}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5,
+     {0x5d, 0x15, 0x4a, 0xf2, 0x38, 0xf4, 0x67, 0x13, 0x15, 0x57, 0x19, 0xd5, 0x5e, 0x2f, 0x1f, 0x79, 0x0d, 0xd6, 0x61, 0xf2, 0x79, 0xa7, 0x91, 0x7c},
+     {0xa8, 0x80, 0x8a, 0xc2, 0x67, 0xda, 0xda, 0x3d, 0xcb, 0xe9, 0xa7, 0xc8, 0x46, 0x26, 0xfb, 0xc7, 0x61, 0xc2, 0x94, 0xb0, 0x13, 0x15, 0xe5, 0xc1}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0x55}, 5,
+     {0x79, 0x85, 0x62, 0xe0, 0x49, 0x85, 0x2f, 0x57, 0xdc, 0x8c, 0x34, 0x3b, 0xa1, 0x7f, 0x2c, 0xa1, 0xd9, 0x73, 0x94, 0xef, 0xc8, 0xad, 0xc4, 0x43},
+     {0xc8, 0x13, 0xf8, 0x8a, 0x3b, 0xe3, 0xb3, 0x34, 0xf7, 0x54, 0x25, 0xce, 0x91, 0x75, 0xfb, 0xe3, 0xc8, 0x49, 0x3b, 0x89, 0xc8, 0x70, 0x3b, 0x49}},
+    {ETYPE_DES3_CBC_SHA1, {0x00, 0x00, 0x00, 0x01, 0xaa}, 5,
+     {0x26, 0xdc, 0xe3, 0x34, 0xb5, 0x45, 0x29, 0x2f, 0x2f, 0xea, 0xb9, 0xa8, 0x70, 0x1a, 0x89, 0xa4, 0xb9, 0x9e, 0xb9, 0x94, 0x2c, 0xec, 0xd0, 0x16},
+     {0xf4, 0x8f, 0xfd, 0x6e, 0x83, 0xf8, 0x3e, 0x73, 0x54, 0xe6, 0x94, 0xfd, 0x25, 0x2c, 0xf8, 0x3b, 0xfe, 0x58, 0xf7, 0xd5, 0xba, 0x37, 0xec, 0x5d}},
+    {0}
+};
+
+int KRB5_LIB_FUNCTION
+main(int argc, char **argv)
+{
+    struct testcase *t;
+    krb5_context context;
+    krb5_error_code ret;
+    int val = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    for (t = tests; t->enctype != 0; ++t) {
+       krb5_keyblock key;
+       krb5_keyblock *dkey;
+
+       key.keytype = KEYTYPE_DES3;
+       key.keyvalue.length = MAXSIZE;
+       key.keyvalue.data   = t->key;
+
+       ret = krb5_derive_key(context, &key, t->enctype, t->constant,
+                             t->constant_len, &dkey);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_derive_key");
+       if (memcmp (dkey->keyvalue.data, t->res, dkey->keyvalue.length) != 0) {
+           const unsigned char *p = dkey->keyvalue.data;
+           int i;
+
+           printf ("derive_key failed\n");
+           printf ("should be: ");
+           for (i = 0; i < dkey->keyvalue.length; ++i)
+               printf ("%02x", t->res[i]);
+           printf ("\nresult was: ");
+           for (i = 0; i < dkey->keyvalue.length; ++i)
+               printf ("%02x", p[i]);
+           printf ("\n");
+           val = 1;
+       }
+    }
+    return val;
+}
diff --git a/src/kerberosV/src/lib/krb5/dump_config.c b/src/kerberosV/src/lib/krb5/dump_config.c
new file mode 100644 (file)
index 0000000..4ebc8ff
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#include "krb5_locl.h"
+
+RCSID("$KTH: dump_config.c,v 1.3 2004/05/25 21:23:14 lha Exp $");
+
+/* print contents of krb5.conf */
+
+static void
+print_tree(struct krb5_config_binding *b, int level)
+{
+    if (b == NULL)
+       return;
+
+    printf("%*s%s%s%s", level * 4, "", 
+          (level == 0) ? "[" : "", b->name, (level == 0) ? "]" : "");
+    if(b->type == krb5_config_list) {
+       if(level > 0)
+           printf(" = {");
+       printf("\n");
+       print_tree(b->u.list, level + 1);
+       if(level > 0)
+           printf("%*s}\n", level * 4, "");
+    } else if(b->type == krb5_config_string) {
+       printf(" = %s\n", b->u.string);
+    }
+    if(b->next)
+       print_tree(b->next, level);
+}
+
+int KRB5_LIB_FUNCTION
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret = krb5_init_context(&context);
+    if(ret == 0) {
+       print_tree(context->cf, 0);
+       return 0;
+    }
+    return 1;
+}
diff --git a/src/kerberosV/src/lib/krb5/eai_to_heim_errno.c b/src/kerberosV/src/lib/krb5/eai_to_heim_errno.c
new file mode 100644 (file)
index 0000000..561d0b9
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2000 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: eai_to_heim_errno.c,v 1.5 2004/05/25 21:23:35 lha Exp $");
+
+/*
+ * convert the getaddrinfo error code in `eai_errno' into a
+ * krb5_error_code. `system_error' should have the value of the errno
+ * after the failed call.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_eai_to_heim_errno(int eai_errno, int system_error)
+{
+    switch(eai_errno) {
+    case EAI_NOERROR:
+       return 0;
+#ifdef EAI_ADDRFAMILY
+    case EAI_ADDRFAMILY:
+       return HEIM_EAI_ADDRFAMILY;
+#endif
+    case EAI_AGAIN:
+       return HEIM_EAI_AGAIN;
+    case EAI_BADFLAGS:
+       return HEIM_EAI_BADFLAGS;
+    case EAI_FAIL:
+       return HEIM_EAI_FAIL;
+    case EAI_FAMILY:
+       return HEIM_EAI_FAMILY;
+    case EAI_MEMORY:
+       return HEIM_EAI_MEMORY;
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+    case EAI_NODATA:
+       return HEIM_EAI_NODATA;
+#endif
+    case EAI_NONAME:
+       return HEIM_EAI_NONAME;
+    case EAI_SERVICE:
+       return HEIM_EAI_SERVICE;
+    case EAI_SOCKTYPE:
+       return HEIM_EAI_SOCKTYPE;
+    case EAI_SYSTEM:
+       return system_error;
+    default:
+       return HEIM_EAI_UNKNOWN; /* XXX */
+    }
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_h_errno_to_heim_errno(int eai_errno)
+{
+    switch(eai_errno) {
+    case 0:
+       return 0;
+    case HOST_NOT_FOUND:
+       return HEIM_EAI_NONAME;
+    case TRY_AGAIN:
+       return HEIM_EAI_AGAIN;
+    case NO_RECOVERY:
+       return HEIM_EAI_FAIL;
+    case NO_DATA:
+       return HEIM_EAI_NONAME;
+    default:
+       return HEIM_EAI_UNKNOWN; /* XXX */
+    }
+}
diff --git a/src/kerberosV/src/lib/krb5/error_string.c b/src/kerberosV/src/lib/krb5/error_string.c
new file mode 100644 (file)
index 0000000..9c6bf5d
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: error_string.c,v 1.3 2004/05/25 21:23:55 lha Exp $");
+
+#undef __attribute__
+#define __attribute__(X)
+
+void KRB5_LIB_FUNCTION
+krb5_free_error_string(krb5_context context, char *str)
+{
+    HEIMDAL_MUTEX_lock(context->mutex);
+    if (str != context->error_buf)
+       free(str);
+    HEIMDAL_MUTEX_unlock(context->mutex);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_clear_error_string(krb5_context context)
+{
+    HEIMDAL_MUTEX_lock(context->mutex);
+    if (context->error_string != NULL
+       && context->error_string != context->error_buf)
+       free(context->error_string);
+    context->error_string = NULL;
+    HEIMDAL_MUTEX_unlock(context->mutex);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_error_string(krb5_context context, const char *fmt, ...)
+    __attribute__((format (printf, 2, 3)))
+{
+    krb5_error_code ret;
+    va_list ap;
+
+    va_start(ap, fmt);
+    ret = krb5_vset_error_string (context, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vset_error_string(krb5_context context, const char *fmt, va_list args)
+    __attribute__ ((format (printf, 2, 0)))
+{
+    krb5_clear_error_string(context);
+    HEIMDAL_MUTEX_lock(context->mutex);
+    vasprintf(&context->error_string, fmt, args);
+    if(context->error_string == NULL) {
+       vsnprintf (context->error_buf, sizeof(context->error_buf), fmt, args);
+       context->error_string = context->error_buf;
+    }
+    HEIMDAL_MUTEX_unlock(context->mutex);
+    return 0;
+}
+
+char * KRB5_LIB_FUNCTION
+krb5_get_error_string(krb5_context context)
+{
+    char *ret;
+
+    HEIMDAL_MUTEX_lock(context->mutex);
+    ret = context->error_string;
+    context->error_string = NULL;
+    HEIMDAL_MUTEX_unlock(context->mutex);
+    return ret;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_have_error_string(krb5_context context)
+{
+    char *str;
+    HEIMDAL_MUTEX_lock(context->mutex);
+    str = context->error_string;
+    HEIMDAL_MUTEX_unlock(context->mutex);
+    return str != NULL;
+}
diff --git a/src/kerberosV/src/lib/krb5/expand_hostname.c b/src/kerberosV/src/lib/krb5/expand_hostname.c
new file mode 100644 (file)
index 0000000..8eec998
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: expand_hostname.c,v 1.12 2004/05/25 21:24:14 lha Exp $");
+
+static krb5_error_code
+copy_hostname(krb5_context context,
+             const char *orig_hostname,
+             char **new_hostname)
+{
+    *new_hostname = strdup (orig_hostname);
+    if (*new_hostname == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    strlwr (*new_hostname);
+    return 0;
+}
+
+/*
+ * Try to make `orig_hostname' into a more canonical one in the newly
+ * allocated space returned in `new_hostname'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_expand_hostname (krb5_context context,
+                     const char *orig_hostname,
+                     char **new_hostname)
+{
+    struct addrinfo *ai, *a, hints;
+    int error;
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+
+    error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
+    if (error)
+       return copy_hostname (context, orig_hostname, new_hostname);
+    for (a = ai; a != NULL; a = a->ai_next) {
+       if (a->ai_canonname != NULL) {
+           *new_hostname = strdup (a->ai_canonname);
+           freeaddrinfo (ai);
+           if (*new_hostname == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               return ENOMEM;
+           } else {
+               return 0;
+           }
+       }
+    }
+    freeaddrinfo (ai);
+    return copy_hostname (context, orig_hostname, new_hostname);
+}
+
+/*
+ * handle the case of the hostname being unresolvable and thus identical
+ */
+
+static krb5_error_code
+vanilla_hostname (krb5_context context,
+                 const char *orig_hostname,
+                 char **new_hostname,
+                 char ***realms)
+{
+    krb5_error_code ret;
+
+    ret = copy_hostname (context, orig_hostname, new_hostname);
+    if (ret)
+       return ret;
+    strlwr (*new_hostname);
+
+    ret = krb5_get_host_realm (context, *new_hostname, realms);
+    if (ret) {
+       free (*new_hostname);
+       return ret;
+    }
+    return 0;
+}
+
+/*
+ * expand `hostname' to a name we believe to be a hostname in newly
+ * allocated space in `host' and return realms in `realms'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_expand_hostname_realms (krb5_context context,
+                            const char *orig_hostname,
+                            char **new_hostname,
+                            char ***realms)
+{
+    struct addrinfo *ai, *a, hints;
+    int error;
+    krb5_error_code ret = 0;
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_flags = AI_CANONNAME;
+
+    error = getaddrinfo (orig_hostname, NULL, &hints, &ai);
+    if (error)
+       return vanilla_hostname (context, orig_hostname, new_hostname,
+                                realms);
+
+    for (a = ai; a != NULL; a = a->ai_next) {
+       if (a->ai_canonname != NULL) {
+           ret = copy_hostname (context, a->ai_canonname, new_hostname);
+           if (ret) {
+               freeaddrinfo (ai);
+               return ret;
+           }
+           strlwr (*new_hostname);
+           ret = krb5_get_host_realm (context, *new_hostname, realms);
+           if (ret == 0) {
+               freeaddrinfo (ai);
+               return 0;
+           }
+           free (*new_hostname);
+       }
+    }
+    freeaddrinfo(ai);
+    return vanilla_hostname (context, orig_hostname, new_hostname, realms);
+}
diff --git a/src/kerberosV/src/lib/krb5/fcache.c b/src/kerberosV/src/lib/krb5/fcache.c
new file mode 100644 (file)
index 0000000..8d1a2db
--- /dev/null
@@ -0,0 +1,718 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: fcache.c,v 1.48 2005/05/31 22:06:15 lha Exp $");
+
+typedef struct krb5_fcache{
+    char *filename;
+    int version;
+}krb5_fcache;
+
+struct fcc_cursor {
+    int fd;
+    krb5_storage *sp;
+};
+
+#define KRB5_FCC_FVNO_1 1
+#define KRB5_FCC_FVNO_2 2
+#define KRB5_FCC_FVNO_3 3
+#define KRB5_FCC_FVNO_4 4
+
+#define FCC_TAG_DELTATIME 1
+
+#define FCACHE(X) ((krb5_fcache*)(X)->data.data)
+
+#define FILENAME(X) (FCACHE(X)->filename)
+
+#define FCC_CURSOR(C) ((struct fcc_cursor*)(C))
+
+static const char*
+fcc_get_name(krb5_context context,
+            krb5_ccache id)
+{
+    return FILENAME(id);
+}
+
+int
+_krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive,
+           const char *filename)
+{
+    int ret;
+#ifdef HAVE_FCNTL
+    struct flock l;
+
+    l.l_start = 0;
+    l.l_len = 0;
+    l.l_type = exclusive ? F_WRLCK : F_RDLCK;
+    l.l_whence = SEEK_SET;
+    ret = fcntl(fd, F_SETLKW, &l);
+#else
+    ret = flock(fd, exclusive ? LOCK_EX : LOCK_SH);
+#endif
+    if(ret < 0)
+       ret = errno;
+    if(ret == EACCES) /* fcntl can return EACCES instead of EAGAIN */
+       ret = EAGAIN;
+
+    switch (ret) {
+    case 0:
+       break;
+    case EINVAL: /* filesystem doesn't support locking, let the user have it */
+       ret = 0; 
+       break;
+    case EAGAIN:
+       krb5_set_error_string(context, "timed out locking cache file %s", 
+                             filename);
+       break;
+    default:
+       krb5_set_error_string(context, "error locking cache file %s: %s",
+                             filename, strerror(ret));
+       break;
+    }
+    return ret;
+}
+
+int
+_krb5_xunlock(krb5_context context, int fd)
+{
+    int ret;
+#ifdef HAVE_FCNTL_LOCK
+    struct flock l;
+    l.l_start = 0;
+    l.l_len = 0;
+    l.l_type = F_UNLCK;
+    l.l_whence = SEEK_SET;
+    ret = fcntl(fd, F_SETLKW, &l);
+#else
+    ret = flock(fd, LOCK_UN);
+#endif
+    if (ret < 0)
+       ret = errno;
+    switch (ret) {
+    case 0:
+       break;
+    case EINVAL: /* filesystem doesn't support locking, let the user have it */
+       ret = 0; 
+       break;
+    default:
+       krb5_set_error_string(context, 
+                             "Failed to unlock file: %s", strerror(ret));
+       break;
+    }
+    return ret;
+}
+
+static krb5_error_code
+fcc_lock(krb5_context context, krb5_ccache id,
+        int fd, krb5_boolean exclusive)
+{
+    return _krb5_xlock(context, fd, exclusive, fcc_get_name(context, id));
+}
+
+static krb5_error_code
+fcc_unlock(krb5_context context, int fd)
+{
+    return _krb5_xunlock(context, fd);
+}
+
+static krb5_error_code
+fcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
+{
+    krb5_fcache *f;
+    f = malloc(sizeof(*f));
+    if(f == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    f->filename = strdup(res);
+    if(f->filename == NULL){
+       free(f);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    f->version = 0;
+    (*id)->data.data = f;
+    (*id)->data.length = sizeof(*f);
+    return 0;
+}
+
+/*
+ * Try to scrub the contents of `filename' safely.
+ */
+
+static int
+scrub_file (int fd)
+{
+    off_t pos;
+    char buf[128];
+
+    pos = lseek(fd, 0, SEEK_END);
+    if (pos < 0)
+        return errno;
+    if (lseek(fd, 0, SEEK_SET) < 0)
+        return errno;
+    memset(buf, 0, sizeof(buf));
+    while(pos > 0) {
+        ssize_t tmp = write(fd, buf, min(sizeof(buf), pos));
+
+       if (tmp < 0)
+           return errno;
+       pos -= tmp;
+    }
+    fsync (fd);
+    return 0;
+}
+
+/*
+ * Erase `filename' if it exists, trying to remove the contents if
+ * it's `safe'.  We always try to remove the file, it it exists.  It's
+ * only overwritten if it's a regular file (not a symlink and not a
+ * hardlink)
+ */
+
+static krb5_error_code
+erase_file(const char *filename)
+{
+    int fd;
+    struct stat sb1, sb2;
+    int ret;
+
+    ret = lstat (filename, &sb1);
+    if (ret < 0)
+       return errno;
+
+    fd = open(filename, O_RDWR | O_BINARY);
+    if(fd < 0) {
+       if(errno == ENOENT)
+           return 0;
+       else
+           return errno;
+    }
+    if (unlink(filename) < 0) {
+        close (fd);
+        return errno;
+    }
+    ret = fstat (fd, &sb2);
+    if (ret < 0) {
+       close (fd);
+       return errno;
+    }
+
+    /* check if someone was playing with symlinks */
+
+    if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) {
+       close (fd);
+       return EPERM;
+    }
+
+    /* there are still hard links to this file */
+
+    if (sb2.st_nlink != 0) {
+        close (fd);
+        return 0;
+    }
+
+    ret = scrub_file (fd);
+    close (fd);
+    return ret;
+}
+
+static krb5_error_code
+fcc_gen_new(krb5_context context, krb5_ccache *id)
+{
+    krb5_fcache *f;
+    int fd;
+    char *file;
+
+    f = malloc(sizeof(*f));
+    if(f == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    asprintf (&file, "%sXXXXXXXXXX", KRB5_DEFAULT_CCFILE_ROOT);
+    if(file == NULL) {
+       free(f);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    fd = mkstemp(file);
+    if(fd < 0) {
+       free(f);
+       free(file);
+       krb5_set_error_string(context, "mkstemp %s", file);
+       return errno;
+    }
+    close(fd);
+    f->filename = file;
+    f->version = 0;
+    (*id)->data.data = f;
+    (*id)->data.length = sizeof(*f);
+    return 0;
+}
+
+static void
+storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
+{
+    int flags = 0;
+    switch(vno) {
+    case KRB5_FCC_FVNO_1:
+       flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
+       flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
+       flags |= KRB5_STORAGE_HOST_BYTEORDER;
+       break;
+    case KRB5_FCC_FVNO_2:
+       flags |= KRB5_STORAGE_HOST_BYTEORDER;
+       break;
+    case KRB5_FCC_FVNO_3:
+       flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE;
+       break;
+    case KRB5_FCC_FVNO_4:
+       break;
+    default:
+       krb5_abortx(context, 
+                   "storage_set_flags called with bad vno (%x)", vno);
+    }
+    krb5_storage_set_flags(sp, flags);
+}
+
+static krb5_error_code
+fcc_open(krb5_context context,
+        krb5_ccache id,
+        int *fd_ret,
+        int flags,
+        mode_t mode)
+{
+    krb5_boolean exclusive = ((flags | O_WRONLY) == flags ||
+                             (flags | O_RDWR) == flags);
+    krb5_error_code ret;
+    const char *filename = FILENAME(id);
+    int fd;
+    fd = open(filename, flags, mode);
+    if(fd < 0) {
+       ret = errno;
+       krb5_set_error_string(context, "open(%s): %s", filename,
+                             strerror(ret));
+       return ret;
+    }
+       
+    if((ret = fcc_lock(context, id, fd, exclusive)) != 0) {
+       close(fd);
+       return ret;
+    }
+    *fd_ret = fd;
+    return 0;
+}
+
+static krb5_error_code
+fcc_initialize(krb5_context context,
+              krb5_ccache id,
+              krb5_principal primary_principal)
+{
+    krb5_fcache *f = FCACHE(id);
+    int ret = 0;
+    int fd;
+    char *filename = f->filename;
+
+    unlink (filename);
+  
+    ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+    if(ret)
+       return ret;
+    {
+       krb5_storage *sp;    
+       sp = krb5_storage_from_fd(fd);
+       krb5_storage_set_eof_code(sp, KRB5_CC_END);
+       if(context->fcache_vno != 0)
+           f->version = context->fcache_vno;
+       else
+           f->version = KRB5_FCC_FVNO_4;
+       ret |= krb5_store_int8(sp, 5);
+       ret |= krb5_store_int8(sp, f->version);
+       storage_set_flags(context, sp, f->version);
+       if(f->version == KRB5_FCC_FVNO_4 && ret == 0) {
+           /* V4 stuff */
+           if (context->kdc_sec_offset) {
+               ret |= krb5_store_int16 (sp, 12); /* length */
+               ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */
+               ret |= krb5_store_int16 (sp, 8); /* length of data */
+               ret |= krb5_store_int32 (sp, context->kdc_sec_offset);
+               ret |= krb5_store_int32 (sp, context->kdc_usec_offset);
+           } else {
+               ret |= krb5_store_int16 (sp, 0);
+           }
+       }
+       ret |= krb5_store_principal(sp, primary_principal);
+       
+       krb5_storage_free(sp);
+    }
+    fcc_unlock(context, fd);
+    if (close(fd) < 0)
+       if (ret == 0) {
+           ret = errno;
+           krb5_set_error_string (context, "close %s: %s", 
+                                  FILENAME(id), strerror(ret));
+       }
+    return ret;
+}
+
+static krb5_error_code
+fcc_close(krb5_context context,
+         krb5_ccache id)
+{
+    free (FILENAME(id));
+    krb5_data_free(&id->data);
+    return 0;
+}
+
+static krb5_error_code
+fcc_destroy(krb5_context context,
+           krb5_ccache id)
+{
+    erase_file(FILENAME(id));
+    return 0;
+}
+
+static krb5_error_code
+fcc_store_cred(krb5_context context,
+              krb5_ccache id,
+              krb5_creds *creds)
+{
+    int ret;
+    int fd;
+
+    ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY, 0);
+    if(ret)
+       return ret;
+    {
+       krb5_storage *sp;
+       sp = krb5_storage_from_fd(fd);
+       krb5_storage_set_eof_code(sp, KRB5_CC_END);
+       storage_set_flags(context, sp, FCACHE(id)->version);
+       if (!krb5_config_get_bool_default(context, NULL, TRUE,
+                                         "libdefaults",
+                                         "fcc-mit-ticketflags",
+                                         NULL))
+           krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER);
+       ret = krb5_store_creds(sp, creds);
+       krb5_storage_free(sp);
+    }
+    fcc_unlock(context, fd);
+    if (close(fd) < 0)
+       if (ret == 0) {
+           ret = errno;
+           krb5_set_error_string (context, "close %s: %s", 
+                                  FILENAME(id), strerror(ret));
+       }
+    return ret;
+}
+
+static krb5_error_code
+init_fcc (krb5_context context,
+         krb5_ccache id,
+         krb5_storage **ret_sp,
+         int *ret_fd)
+{
+    int fd;
+    int8_t pvno, tag;
+    krb5_storage *sp;
+    krb5_error_code ret;
+
+    ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY, 0);
+    if(ret)
+       return ret;
+    
+    sp = krb5_storage_from_fd(fd);
+    if(sp == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+    krb5_storage_set_eof_code(sp, KRB5_CC_END);
+    ret = krb5_ret_int8(sp, &pvno);
+    if(ret != 0) {
+       if(ret == KRB5_CC_END)
+           ret = ENOENT; /* empty file */
+       krb5_clear_error_string(context);
+       goto out;
+    }
+    if(pvno != 5) {
+       krb5_set_error_string(context, "Bad version number in credential "
+                             "cache file: %s", FILENAME(id));
+       ret = KRB5_CCACHE_BADVNO;
+       goto out;
+    }
+    ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */
+    if(ret != 0) {
+       krb5_clear_error_string(context);
+       ret = KRB5_CC_FORMAT;
+       goto out;
+    }
+    FCACHE(id)->version = tag;
+    storage_set_flags(context, sp, FCACHE(id)->version);
+    switch (tag) {
+    case KRB5_FCC_FVNO_4: {
+       int16_t length;
+
+       ret = krb5_ret_int16 (sp, &length);
+       if(ret) {
+           ret = KRB5_CC_FORMAT;
+           krb5_clear_error_string(context);
+           goto out;
+       }
+       while(length > 0) {
+           int16_t tag, data_len;
+           int i;
+           int8_t dummy;
+
+           ret = krb5_ret_int16 (sp, &tag);
+           if(ret) {
+               krb5_clear_error_string(context);
+               ret = KRB5_CC_FORMAT;
+               goto out;
+           }
+           ret = krb5_ret_int16 (sp, &data_len);
+           if(ret) {
+               krb5_clear_error_string(context);
+               ret = KRB5_CC_FORMAT;
+               goto out;
+           }
+           switch (tag) {
+           case FCC_TAG_DELTATIME :
+               ret = krb5_ret_int32 (sp, &context->kdc_sec_offset);
+               if(ret) {
+                   krb5_clear_error_string(context);
+                   ret = KRB5_CC_FORMAT;
+                   goto out;
+               }
+               ret = krb5_ret_int32 (sp, &context->kdc_usec_offset);
+               if(ret) {
+                   krb5_clear_error_string(context);
+                   ret = KRB5_CC_FORMAT;
+                   goto out;
+               }
+               break;
+           default :
+               for (i = 0; i < data_len; ++i) {
+                   ret = krb5_ret_int8 (sp, &dummy);
+                   if(ret) {
+                       krb5_clear_error_string(context);
+                       ret = KRB5_CC_FORMAT;
+                       goto out;
+                   }
+               }
+               break;
+           }
+           length -= 4 + data_len;
+       }
+       break;
+    }
+    case KRB5_FCC_FVNO_3:
+    case KRB5_FCC_FVNO_2:
+    case KRB5_FCC_FVNO_1:
+       break;
+    default :
+       ret = KRB5_CCACHE_BADVNO;
+       krb5_set_error_string(context, "Unknown version number (%d) in "
+                             "credential cache file: %s",
+                             (int)tag, FILENAME(id));
+       goto out;
+    }
+    *ret_sp = sp;
+    *ret_fd = fd;
+    
+    return 0;
+  out:
+    if(sp != NULL)
+       krb5_storage_free(sp);
+    fcc_unlock(context, fd);
+    close(fd);
+    return ret;
+}
+
+static krb5_error_code
+fcc_get_principal(krb5_context context,
+                 krb5_ccache id,
+                 krb5_principal *principal)
+{
+    krb5_error_code ret;
+    int fd;
+    krb5_storage *sp;
+
+    ret = init_fcc (context, id, &sp, &fd);
+    if (ret)
+       return ret;
+    ret = krb5_ret_principal(sp, principal);
+    if (ret)
+       krb5_clear_error_string(context);
+    krb5_storage_free(sp);
+    fcc_unlock(context, fd);
+    close(fd);
+    return ret;
+}
+
+static krb5_error_code
+fcc_end_get (krb5_context context,
+            krb5_ccache id,
+            krb5_cc_cursor *cursor);
+
+static krb5_error_code
+fcc_get_first (krb5_context context,
+              krb5_ccache id,
+              krb5_cc_cursor *cursor)
+{
+    krb5_error_code ret;
+    krb5_principal principal;
+
+    *cursor = malloc(sizeof(struct fcc_cursor));
+    if (*cursor == NULL) {
+        krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memset(*cursor, 0, sizeof(struct fcc_cursor));
+
+    ret = init_fcc (context, id, &FCC_CURSOR(*cursor)->sp, 
+                   &FCC_CURSOR(*cursor)->fd);
+    if (ret) {
+       free(*cursor);
+       *cursor = NULL;
+       return ret;
+    }
+    ret = krb5_ret_principal (FCC_CURSOR(*cursor)->sp, &principal);
+    if(ret) {
+       krb5_clear_error_string(context);
+       fcc_end_get(context, id, cursor);
+       return ret;
+    }
+    krb5_free_principal (context, principal);
+    fcc_unlock(context, FCC_CURSOR(*cursor)->fd);
+    return 0;
+}
+
+static krb5_error_code
+fcc_get_next (krb5_context context,
+             krb5_ccache id,
+             krb5_cc_cursor *cursor,
+             krb5_creds *creds)
+{
+    krb5_error_code ret;
+    if((ret = fcc_lock(context, id, FCC_CURSOR(*cursor)->fd, FALSE)) != 0)
+       return ret;
+
+    ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds);
+    if (ret)
+       krb5_clear_error_string(context);
+
+    fcc_unlock(context, FCC_CURSOR(*cursor)->fd);
+    return ret;
+}
+
+static krb5_error_code
+fcc_end_get (krb5_context context,
+            krb5_ccache id,
+            krb5_cc_cursor *cursor)
+{
+    krb5_storage_free(FCC_CURSOR(*cursor)->sp);
+    close (FCC_CURSOR(*cursor)->fd);
+    free(*cursor);
+    *cursor = NULL;
+    return 0;
+}
+
+static krb5_error_code
+fcc_remove_cred(krb5_context context,
+                krb5_ccache id,
+                krb5_flags which,
+                krb5_creds *cred)
+{
+    krb5_error_code ret;
+    krb5_ccache copy;
+
+    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &copy);
+    if (ret)
+       return ret;
+
+    ret = krb5_cc_copy_cache(context, id, copy);
+    if (ret) {
+       krb5_cc_destroy(context, copy);
+       return ret;
+    }
+
+    ret = krb5_cc_remove_cred(context, copy, which, cred);
+    if (ret) {
+       krb5_cc_destroy(context, copy);
+       return ret;
+    }
+
+    fcc_destroy(context, id);
+
+    ret = krb5_cc_copy_cache(context, copy, id);
+    krb5_cc_destroy(context, copy);
+
+    return ret;
+}
+
+static krb5_error_code
+fcc_set_flags(krb5_context context,
+             krb5_ccache id,
+             krb5_flags flags)
+{
+    return 0; /* XXX */
+}
+
+static krb5_error_code
+fcc_get_version(krb5_context context,
+               krb5_ccache id)
+{
+    return FCACHE(id)->version;
+}
+                   
+const krb5_cc_ops krb5_fcc_ops = {
+    "FILE",
+    fcc_get_name,
+    fcc_resolve,
+    fcc_gen_new,
+    fcc_initialize,
+    fcc_destroy,
+    fcc_close,
+    fcc_store_cred,
+    NULL, /* fcc_retrieve */
+    fcc_get_principal,
+    fcc_get_first,
+    fcc_get_next,
+    fcc_end_get,
+    fcc_remove_cred,
+    fcc_set_flags,
+    fcc_get_version
+};
diff --git a/src/kerberosV/src/lib/krb5/free.c b/src/kerberosV/src/lib/krb5/free.c
new file mode 100644 (file)
index 0000000..7340d00
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1997 - 1999, 2004 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: free.c,v 1.8 2005/05/18 10:06:16 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep)
+{
+    free_KDC_REP(&rep->kdc_rep);
+    free_EncTGSRepPart(&rep->enc_part);
+    free_KRB_ERROR(&rep->error);
+    memset(rep, 0, sizeof(*rep));
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_xfree (void *ptr)
+{
+    free (ptr);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/free_host_realm.c b/src/kerberosV/src/lib/krb5/free_host_realm.c
new file mode 100644 (file)
index 0000000..cc974e2
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: free_host_realm.c,v 1.5 2004/05/25 21:25:02 lha Exp $");
+
+/*
+ * Free all memory allocated by `realmlist'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_host_realm(krb5_context context,
+                    krb5_realm *realmlist)
+{
+    krb5_realm *p;
+
+    if(realmlist == NULL)
+       return 0;
+    for (p = realmlist; *p; ++p)
+       free (*p);
+    free (realmlist);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/generate_seq_number.c b/src/kerberosV/src/lib/krb5/generate_seq_number.c
new file mode 100644 (file)
index 0000000..1de3535
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: generate_seq_number.c,v 1.9 2004/05/25 21:25:22 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_seq_number(krb5_context context,
+                        const krb5_keyblock *key,
+                        u_int32_t *seqno)
+{
+    krb5_error_code ret;
+    krb5_keyblock *subkey;
+    u_int32_t q;
+    u_char *p;
+    int i;
+
+    ret = krb5_generate_subkey (context, key, &subkey);
+    if (ret)
+       return ret;
+
+    q = 0;
+    for (p = (u_char *)subkey->keyvalue.data, i = 0;
+        i < subkey->keyvalue.length;
+        ++i, ++p)
+       q = (q << 8) | *p;
+    q &= 0xffffffff;
+    *seqno = q;
+    krb5_free_keyblock (context, subkey);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/generate_subkey.c b/src/kerberosV/src/lib/krb5/generate_subkey.c
new file mode 100644 (file)
index 0000000..e57453d
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: generate_subkey.c,v 1.11 2005/01/05 02:39:21 lukeh Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_subkey(krb5_context context,
+                    const krb5_keyblock *key,
+                    krb5_keyblock **subkey)
+{
+    return krb5_generate_subkey_extended(context, key, key->keytype, subkey);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_subkey_extended(krb5_context context,
+                             const krb5_keyblock *key,
+                             krb5_enctype etype,
+                             krb5_keyblock **subkey)
+{
+    krb5_error_code ret;
+
+    ALLOC(*subkey, 1);
+    if (*subkey == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    if (etype == ETYPE_NULL)
+       etype = key->keytype; /* use session key etype */
+
+    /* XXX should we use the session key as input to the RF? */
+    ret = krb5_generate_random_keyblock(context, etype, *subkey);
+    if (ret != 0) {
+       free(*subkey);
+       *subkey = NULL;
+    }
+
+    return ret;
+}
+
diff --git a/src/kerberosV/src/lib/krb5/get_addrs.c b/src/kerberosV/src/lib/krb5/get_addrs.c
new file mode 100644 (file)
index 0000000..c27530f
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_addrs.c,v 1.46 2004/05/25 21:26:05 lha Exp $");
+
+#ifdef __osf__
+/* hate */
+struct rtentry;
+struct mbuf;
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+#include <ifaddrs.h>
+
+static krb5_error_code
+gethostname_fallback (krb5_context context, krb5_addresses *res)
+{
+    krb5_error_code ret;
+    char hostname[MAXHOSTNAMELEN];
+    struct hostent *hostent;
+
+    if (gethostname (hostname, sizeof(hostname))) {
+       ret = errno;
+       krb5_set_error_string (context, "gethostname: %s", strerror(ret));
+       return ret;
+    }
+    hostent = roken_gethostbyname (hostname);
+    if (hostent == NULL) {
+       ret = errno;
+       krb5_set_error_string (context, "gethostbyname %s: %s",
+                              hostname, strerror(ret));
+       return ret;
+    }
+    res->len = 1;
+    res->val = malloc (sizeof(*res->val));
+    if (res->val == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    res->val[0].addr_type = hostent->h_addrtype;
+    res->val[0].address.data = NULL;
+    res->val[0].address.length = 0;
+    ret = krb5_data_copy (&res->val[0].address,
+                         hostent->h_addr,
+                         hostent->h_length);
+    if (ret) {
+       free (res->val);
+       return ret;
+    }
+    return 0;
+}
+
+enum {
+    LOOP            = 1,       /* do include loopback interfaces */
+    LOOP_IF_NONE    = 2,       /* include loopback if no other if's */
+    EXTRA_ADDRESSES = 4,       /* include extra addresses */
+    SCAN_INTERFACES = 8                /* scan interfaces for addresses */
+};
+
+/*
+ * Try to figure out the addresses of all configured interfaces with a
+ * lot of magic ioctls.
+ */
+
+static krb5_error_code
+find_all_addresses (krb5_context context, krb5_addresses *res, int flags)
+{
+    struct sockaddr sa_zero;
+    struct ifaddrs *ifa0, *ifa;
+    krb5_error_code ret = ENXIO; 
+    int num, idx;
+    krb5_addresses ignore_addresses;
+
+    res->val = NULL;
+
+    if (getifaddrs(&ifa0) == -1) {
+       ret = errno;
+       krb5_set_error_string(context, "getifaddrs: %s", strerror(ret));
+       return (ret);
+    }
+
+    memset(&sa_zero, 0, sizeof(sa_zero));
+
+    /* First, count all the ifaddrs. */
+    for (ifa = ifa0, num = 0; ifa != NULL; ifa = ifa->ifa_next, num++)
+       /* nothing */;
+
+    if (num == 0) {
+       freeifaddrs(ifa0);
+       krb5_set_error_string(context, "no addresses found");
+       return (ENXIO);
+    }
+
+    if (flags & EXTRA_ADDRESSES) {
+       /* we'll remove the addresses we don't care about */
+       ret = krb5_get_ignore_addresses(context, &ignore_addresses);
+       if(ret)
+           return ret;
+    }
+
+    /* Allocate storage for them. */
+    res->val = calloc(num, sizeof(*res->val));
+    if (res->val == NULL) {
+       krb5_free_addresses(context, &ignore_addresses);
+       freeifaddrs(ifa0);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return (ENOMEM);
+    }
+
+    /* Now traverse the list. */
+    for (ifa = ifa0, idx = 0; ifa != NULL; ifa = ifa->ifa_next) {
+       if ((ifa->ifa_flags & IFF_UP) == 0)
+           continue;
+       if (ifa->ifa_addr == NULL)
+           continue;
+       if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0)
+           continue;
+       if (krb5_sockaddr_uninteresting(ifa->ifa_addr))
+           continue;
+       if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) {
+           /* We'll deal with the LOOP_IF_NONE case later. */
+           if ((flags & LOOP) == 0)
+               continue;
+       }
+
+       ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]);
+       if (ret) {
+           /*
+            * The most likely error here is going to be "Program
+            * lacks support for address type".  This is no big
+            * deal -- just continue, and we'll listen on the
+            * addresses who's type we *do* support.
+            */
+           continue;
+       }
+       /* possibly skip this address? */
+       if((flags & EXTRA_ADDRESSES) && 
+          krb5_address_search(context, &res->val[idx], &ignore_addresses)) {
+           krb5_free_address(context, &res->val[idx]);
+           flags &= ~LOOP_IF_NONE; /* we actually found an address,
+                                       so don't add any loop-back
+                                       addresses */
+           continue;
+       }
+
+       idx++;
+    }
+
+    /*
+     * If no addresses were found, and LOOP_IF_NONE is set, then find
+     * the loopback addresses and add them to our list.
+     */
+    if ((flags & LOOP_IF_NONE) != 0 && idx == 0) {
+       for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) {
+           if ((ifa->ifa_flags & IFF_UP) == 0)
+               continue;
+           if (ifa->ifa_addr == NULL)
+               continue;
+           if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0)
+               continue;
+           if (krb5_sockaddr_uninteresting(ifa->ifa_addr))
+               continue;
+
+           if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) {
+               ret = krb5_sockaddr2address(context,
+                                           ifa->ifa_addr, &res->val[idx]);
+               if (ret) {
+                   /*
+                    * See comment above.
+                    */
+                   continue;
+               }
+               if((flags & EXTRA_ADDRESSES) && 
+                  krb5_address_search(context, &res->val[idx], 
+                                      &ignore_addresses)) {
+                   krb5_free_address(context, &res->val[idx]);
+                   continue;
+               }
+               idx++;
+           }
+       }
+    }
+
+    if (flags & EXTRA_ADDRESSES)
+       krb5_free_addresses(context, &ignore_addresses);
+    freeifaddrs(ifa0);
+    if (ret)
+       free(res->val);
+    else
+       res->len = idx;        /* Now a count. */
+    return (ret);
+}
+
+static krb5_error_code
+get_addrs_int (krb5_context context, krb5_addresses *res, int flags)
+{
+    krb5_error_code ret = -1;
+
+    if (flags & SCAN_INTERFACES) {
+       ret = find_all_addresses (context, res, flags);
+       if(ret || res->len == 0)
+           ret = gethostname_fallback (context, res);
+    } else {
+       res->len = 0;
+       res->val = NULL;
+       ret = 0;
+    }
+
+    if(ret == 0 && (flags & EXTRA_ADDRESSES)) {
+       krb5_addresses a;
+       /* append user specified addresses */
+       ret = krb5_get_extra_addresses(context, &a);
+       if(ret) {
+           krb5_free_addresses(context, res);
+           return ret;
+       }
+       ret = krb5_append_addresses(context, res, &a);
+       if(ret) {
+           krb5_free_addresses(context, res);
+           return ret;
+       }
+       krb5_free_addresses(context, &a);
+    }
+    if(res->len == 0) {
+       free(res->val);
+       res->val = NULL;
+    }
+    return ret;
+}
+
+/*
+ * Try to get all addresses, but return the one corresponding to
+ * `hostname' if we fail.
+ *
+ * Only include loopback address if there are no other.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_all_client_addrs (krb5_context context, krb5_addresses *res)
+{
+    int flags = LOOP_IF_NONE | EXTRA_ADDRESSES;
+
+    if (context->scan_interfaces)
+       flags |= SCAN_INTERFACES;
+
+    return get_addrs_int (context, res, flags);
+}
+
+/*
+ * Try to get all local addresses that a server should listen to.
+ * If that fails, we return the address corresponding to `hostname'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_all_server_addrs (krb5_context context, krb5_addresses *res)
+{
+    return get_addrs_int (context, res, LOOP | SCAN_INTERFACES);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_cred.c b/src/kerberosV/src/lib/krb5/get_cred.c
new file mode 100644 (file)
index 0000000..7aa5275
--- /dev/null
@@ -0,0 +1,905 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: get_cred.c,v 1.106.2.1 2005/07/13 20:52:43 lha Exp $");
+
+/*
+ * Take the `body' and encode it into `padata' using the credentials
+ * in `creds'.
+ */
+
+static krb5_error_code
+make_pa_tgs_req(krb5_context context, 
+               krb5_auth_context ac,
+               KDC_REQ_BODY *body,
+               PA_DATA *padata,
+               krb5_creds *creds,
+               krb5_key_usage usage)
+{
+    u_char *buf;
+    size_t buf_size;
+    size_t len;
+    krb5_data in_data;
+    krb5_error_code ret;
+
+    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
+    if (ret)
+       goto out;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    in_data.length = len;
+    in_data.data   = buf;
+    ret = _krb5_mk_req_internal(context, &ac, 0, &in_data, creds,
+                               &padata->padata_value,
+                               KRB5_KU_TGS_REQ_AUTH_CKSUM,
+                               usage
+                               /* KRB5_KU_TGS_REQ_AUTH */);
+ out:
+    free (buf);
+    if(ret)
+       return ret;
+    padata->padata_type = KRB5_PADATA_TGS_REQ;
+    return 0;
+}
+
+/*
+ * Set the `enc-authorization-data' in `req_body' based on `authdata'
+ */
+
+static krb5_error_code
+set_auth_data (krb5_context context,
+              KDC_REQ_BODY *req_body,
+              krb5_authdata *authdata,
+              krb5_keyblock *key)
+{
+    if(authdata->len) {
+       size_t len, buf_size;
+       unsigned char *buf;
+       krb5_crypto crypto;
+       krb5_error_code ret;
+
+       ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata,
+                          &len, ret);
+       if (ret)
+           return ret;
+       if (buf_size != len)
+           krb5_abortx(context, "internal error in ASN.1 encoder");
+
+       ALLOC(req_body->enc_authorization_data, 1);
+       if (req_body->enc_authorization_data == NULL) {
+           free (buf);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       ret = krb5_crypto_init(context, key, 0, &crypto);
+       if (ret) {
+           free (buf);
+           free (req_body->enc_authorization_data);
+           req_body->enc_authorization_data = NULL;
+           return ret;
+       }
+       krb5_encrypt_EncryptedData(context, 
+                                  crypto,
+                                  KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, 
+                                  /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */
+                                  buf,
+                                  len,
+                                  0,
+                                  req_body->enc_authorization_data);
+       free (buf);
+       krb5_crypto_destroy(context, crypto);
+    } else {
+       req_body->enc_authorization_data = NULL;
+    }
+    return 0;
+}    
+
+/*
+ * Create a tgs-req in `t' with `addresses', `flags', `second_ticket'
+ * (if not-NULL), `in_creds', `krbtgt', and returning the generated
+ * subkey in `subkey'.
+ */
+
+static krb5_error_code
+init_tgs_req (krb5_context context,
+             krb5_ccache ccache,
+             krb5_addresses *addresses,
+             krb5_kdc_flags flags,
+             Ticket *second_ticket,
+             krb5_creds *in_creds,
+             krb5_creds *krbtgt,
+             unsigned nonce,
+             krb5_keyblock **subkey,
+             TGS_REQ *t,
+             krb5_key_usage usage)
+{
+    krb5_error_code ret = 0;
+
+    memset(t, 0, sizeof(*t));
+    t->pvno = 5;
+    t->msg_type = krb_tgs_req;
+    if (in_creds->session.keytype) {
+       ALLOC_SEQ(&t->req_body.etype, 1);
+       if(t->req_body.etype.val == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       t->req_body.etype.val[0] = in_creds->session.keytype;
+    } else {
+       ret = krb5_init_etype(context, 
+                             &t->req_body.etype.len, 
+                             &t->req_body.etype.val, 
+                             NULL);
+    }
+    if (ret)
+       goto fail;
+    t->req_body.addresses = addresses;
+    t->req_body.kdc_options = flags.b;
+    ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm);
+    if (ret)
+       goto fail;
+    ALLOC(t->req_body.sname, 1);
+    if (t->req_body.sname == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+
+    /* some versions of some code might require that the client be
+       present in TGS-REQs, but this is clearly against the spec */
+
+    ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname);
+    if (ret)
+       goto fail;
+
+    /* req_body.till should be NULL if there is no endtime specified,
+       but old MIT code (like DCE secd) doesn't like that */
+    ALLOC(t->req_body.till, 1);
+    if(t->req_body.till == NULL){
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+    *t->req_body.till = in_creds->times.endtime;
+    
+    t->req_body.nonce = nonce;
+    if(second_ticket){
+       ALLOC(t->req_body.additional_tickets, 1);
+       if (t->req_body.additional_tickets == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       ALLOC_SEQ(t->req_body.additional_tickets, 1);
+       if (t->req_body.additional_tickets->val == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); 
+       if (ret)
+           goto fail;
+    }
+    ALLOC(t->padata, 1);
+    if (t->padata == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+    ALLOC_SEQ(t->padata, 1);
+    if (t->padata->val == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+
+    {
+       krb5_auth_context ac;
+       krb5_keyblock *key = NULL;
+
+       ret = krb5_auth_con_init(context, &ac);
+       if(ret)
+           goto fail;
+
+       if (krb5_config_get_bool_default(context, NULL, FALSE,
+                                        "realms",
+                                        krbtgt->server->realm,
+                                        "tgs_require_subkey",
+                                        NULL))
+       {
+           ret = krb5_generate_subkey (context, &krbtgt->session, &key);
+           if (ret) {
+               krb5_auth_con_free (context, ac);
+               goto fail;
+           }
+
+           ret = krb5_auth_con_setlocalsubkey(context, ac, key);
+           if (ret) {
+               if (key)
+                   krb5_free_keyblock (context, key);
+               krb5_auth_con_free (context, ac);
+               goto fail;
+           }
+       }
+
+       ret = set_auth_data (context, &t->req_body, &in_creds->authdata,
+                            key ? key : &krbtgt->session);
+       if (ret) {
+           if (key)
+               krb5_free_keyblock (context, key);
+           krb5_auth_con_free (context, ac);
+           goto fail;
+       }
+
+       ret = make_pa_tgs_req(context,
+                             ac,
+                             &t->req_body, 
+                             t->padata->val,
+                             krbtgt,
+                             usage);
+       if(ret) {
+           if (key)
+               krb5_free_keyblock (context, key);
+           krb5_auth_con_free(context, ac);
+           goto fail;
+       }
+       *subkey = key;
+       
+       krb5_auth_con_free(context, ac);
+    }
+fail:
+    if (ret) {
+       t->req_body.addresses = NULL;
+       free_TGS_REQ (t);
+    }
+    return ret;
+}
+
+krb5_error_code
+_krb5_get_krbtgt(krb5_context context,
+                krb5_ccache  id,
+                krb5_realm realm,
+                krb5_creds **cred)
+{
+    krb5_error_code ret;
+    krb5_creds tmp_cred;
+
+    memset(&tmp_cred, 0, sizeof(tmp_cred));
+
+    ret = krb5_cc_get_principal(context, id, &tmp_cred.client);
+    if (ret)
+       return ret;
+
+    ret = krb5_make_principal(context, 
+                             &tmp_cred.server,
+                             realm,
+                             KRB5_TGS_NAME,
+                             realm,
+                             NULL);
+    if(ret) {
+       krb5_free_principal(context, tmp_cred.client);
+       return ret;
+    }
+    ret = krb5_get_credentials(context,
+                              KRB5_GC_CACHED,
+                              id,
+                              &tmp_cred,
+                              cred);
+    krb5_free_principal(context, tmp_cred.client);
+    krb5_free_principal(context, tmp_cred.server);
+    if(ret)
+       return ret;
+    return 0;
+}
+
+/* DCE compatible decrypt proc */
+static krb5_error_code
+decrypt_tkt_with_subkey (krb5_context context,
+                        krb5_keyblock *key,
+                        krb5_key_usage usage,
+                        krb5_const_pointer subkey,
+                        krb5_kdc_rep *dec_rep)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    size_t size;
+    krb5_crypto crypto;
+    
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       return ret;
+    ret = krb5_decrypt_EncryptedData (context,
+                                     crypto,
+                                     usage,
+                                     &dec_rep->kdc_rep.enc_part,
+                                     &data);
+    krb5_crypto_destroy(context, crypto);
+    if(ret && subkey){
+       /* DCE compat -- try to decrypt with subkey */
+       ret = krb5_crypto_init(context, (krb5_keyblock*)subkey, 0, &crypto);
+       if (ret)
+           return ret;
+       ret = krb5_decrypt_EncryptedData (context,
+                                         crypto,
+                                         KRB5_KU_TGS_REP_ENC_PART_SUB_KEY,
+                                         &dec_rep->kdc_rep.enc_part,
+                                         &data);
+       krb5_crypto_destroy(context, crypto);
+    }
+    if (ret)
+       return ret;
+    
+    ret = krb5_decode_EncASRepPart(context,
+                                  data.data,
+                                  data.length,
+                                  &dec_rep->enc_part, 
+                                  &size);
+    if (ret)
+       ret = krb5_decode_EncTGSRepPart(context,
+                                       data.data,
+                                       data.length,
+                                       &dec_rep->enc_part, 
+                                       &size);
+    krb5_data_free (&data);
+    return ret;
+}
+
+static krb5_error_code
+get_cred_kdc_usage(krb5_context context, 
+                  krb5_ccache id, 
+                  krb5_kdc_flags flags,
+                  krb5_addresses *addresses, 
+                  krb5_creds *in_creds, 
+                  krb5_creds *krbtgt,
+                  krb5_creds *out_creds,
+                  krb5_key_usage usage)
+{
+    TGS_REQ req;
+    krb5_data enc;
+    krb5_data resp;
+    krb5_kdc_rep rep;
+    KRB_ERROR error;
+    krb5_error_code ret;
+    unsigned nonce;
+    krb5_keyblock *subkey = NULL;
+    size_t len;
+    Ticket second_ticket;
+    int send_to_kdc_flags = 0;
+    
+    krb5_data_zero(&resp);
+    krb5_data_zero(&enc);
+
+    krb5_generate_random_block(&nonce, sizeof(nonce));
+    nonce &= 0xffffffff;
+    
+    if(flags.b.enc_tkt_in_skey){
+       ret = decode_Ticket(in_creds->second_ticket.data, 
+                           in_creds->second_ticket.length, 
+                           &second_ticket, &len);
+       if(ret)
+           return ret;
+    }
+
+    ret = init_tgs_req (context,
+                       id,
+                       addresses,
+                       flags,
+                       flags.b.enc_tkt_in_skey ? &second_ticket : NULL,
+                       in_creds,
+                       krbtgt,
+                       nonce,
+                       &subkey, 
+                       &req,
+                       usage);
+    if(flags.b.enc_tkt_in_skey)
+       free_Ticket(&second_ticket);
+    if (ret)
+       goto out;
+
+    ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret);
+    if (ret) 
+       goto out;
+    if(enc.length != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    /* don't free addresses */
+    req.req_body.addresses = NULL;
+    free_TGS_REQ(&req);
+
+    /*
+     * Send and receive
+     */
+again:
+    ret = krb5_sendto_kdc_flags (context, &enc, 
+                                &krbtgt->server->name.name_string.val[1],
+                                &resp,
+                                send_to_kdc_flags);
+    if(ret)
+       goto out;
+
+    memset(&rep, 0, sizeof(rep));
+    if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){
+       ret = krb5_copy_principal(context, 
+                                 in_creds->client, 
+                                 &out_creds->client);
+       if(ret)
+           goto out;
+       ret = krb5_copy_principal(context, 
+                                 in_creds->server, 
+                                 &out_creds->server);
+       if(ret)
+           goto out;
+       /* this should go someplace else */
+       out_creds->times.endtime = in_creds->times.endtime;
+
+       ret = _krb5_extract_ticket(context,
+                                  &rep,
+                                  out_creds,
+                                  &krbtgt->session,
+                                  NULL,
+                                  KRB5_KU_TGS_REP_ENC_PART_SESSION,
+                                  &krbtgt->addresses,
+                                  nonce,
+                                  TRUE,
+                                  flags.b.request_anonymous,
+                                  decrypt_tkt_with_subkey,
+                                  subkey);
+       krb5_free_kdc_rep(context, &rep);
+    } else if(krb5_rd_error(context, &resp, &error) == 0) {
+       ret = krb5_error_from_rd_error(context, &error, in_creds);
+       krb5_free_error_contents(context, &error);
+
+       if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) {
+           send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
+           krb5_data_free(&resp);
+           goto again;
+       }
+    } else if(resp.data && ((char*)resp.data)[0] == 4) {
+       ret = KRB5KRB_AP_ERR_V4_REPLY;
+       krb5_clear_error_string(context);
+    } else {
+       ret = KRB5KRB_AP_ERR_MSG_TYPE;
+       krb5_clear_error_string(context);
+    }
+
+out:
+    krb5_data_free(&resp);
+    krb5_data_free(&enc);
+    if(subkey){
+       krb5_free_keyblock_contents(context, subkey);
+       free(subkey);
+    }
+    return ret;
+    
+}
+
+static krb5_error_code
+get_cred_kdc(krb5_context context, 
+            krb5_ccache id, 
+            krb5_kdc_flags flags,
+            krb5_addresses *addresses, 
+            krb5_creds *in_creds, 
+            krb5_creds *krbtgt,
+            krb5_creds *out_creds)
+{
+    krb5_error_code ret;
+
+    ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds,
+                            krbtgt, out_creds, KRB5_KU_TGS_REQ_AUTH);
+    if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) {
+       krb5_clear_error_string (context);
+       ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds,
+                                krbtgt, out_creds, KRB5_KU_AP_REQ_AUTH);
+    }
+    return ret;
+}
+
+/* same as above, just get local addresses first */
+
+static krb5_error_code
+get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, 
+               krb5_creds *in_creds, krb5_creds *krbtgt, 
+               krb5_creds *out_creds)
+{
+    krb5_error_code ret;
+    krb5_addresses addresses, *addrs = &addresses;
+    
+    krb5_get_all_client_addrs(context, &addresses);
+    /* XXX this sucks. */
+    if(addresses.len == 0)
+       addrs = NULL;
+    ret = get_cred_kdc(context, id, flags, addrs, 
+                      in_creds, krbtgt, out_creds);
+    krb5_free_addresses(context, &addresses);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_kdc_cred(krb5_context context,
+                 krb5_ccache id,
+                 krb5_kdc_flags flags,
+                 krb5_addresses *addresses,
+                 Ticket  *second_ticket,
+                 krb5_creds *in_creds,
+                 krb5_creds **out_creds
+                 )
+{
+    krb5_error_code ret;
+    krb5_creds *krbtgt;
+
+    *out_creds = calloc(1, sizeof(**out_creds));
+    if(*out_creds == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = _krb5_get_krbtgt (context,
+                           id,
+                           in_creds->server->realm,
+                           &krbtgt);
+    if(ret) {
+       free(*out_creds);
+       return ret;
+    }
+    ret = get_cred_kdc(context, id, flags, addresses, 
+                      in_creds, krbtgt, *out_creds);
+    krb5_free_creds (context, krbtgt);
+    if(ret)
+       free(*out_creds);
+    return ret;
+}
+
+
+static krb5_error_code
+find_cred(krb5_context context,
+         krb5_ccache id,
+         krb5_principal server,
+         krb5_creds **tgts,
+         krb5_creds *out_creds)
+{
+    krb5_error_code ret;
+    krb5_creds mcreds;
+
+    krb5_cc_clear_mcred(&mcreds);
+    mcreds.server = server;
+    ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_DONT_MATCH_REALM, 
+                               &mcreds, out_creds);
+    if(ret == 0)
+       return 0;
+    while(tgts && *tgts){
+       if(krb5_compare_creds(context, KRB5_TC_DONT_MATCH_REALM, 
+                             &mcreds, *tgts)){
+           ret = krb5_copy_creds_contents(context, *tgts, out_creds);
+           return ret;
+       }
+       tgts++;
+    }
+    krb5_clear_error_string(context);
+    return KRB5_CC_NOTFOUND;
+}
+
+static krb5_error_code
+add_cred(krb5_context context, krb5_creds ***tgts, krb5_creds *tkt)
+{
+    int i;
+    krb5_error_code ret;
+    krb5_creds **tmp = *tgts;
+
+    for(i = 0; tmp && tmp[i]; i++); /* XXX */
+    tmp = realloc(tmp, (i+2)*sizeof(*tmp));
+    if(tmp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    *tgts = tmp;
+    ret = krb5_copy_creds(context, tkt, &tmp[i]);
+    tmp[i+1] = NULL;
+    return ret;
+}
+
+/*
+get_cred(server)
+       creds = cc_get_cred(server)
+       if(creds) return creds
+       tgt = cc_get_cred(krbtgt/server_realm@any_realm)
+       if(tgt)
+               return get_cred_tgt(server, tgt)
+       if(client_realm == server_realm)
+               return NULL
+       tgt = get_cred(krbtgt/server_realm@client_realm)
+       while(tgt_inst != server_realm)
+               tgt = get_cred(krbtgt/server_realm@tgt_inst)
+       return get_cred_tgt(server, tgt)
+       */
+
+static krb5_error_code
+get_cred_from_kdc_flags(krb5_context context,
+                       krb5_kdc_flags flags,
+                       krb5_ccache ccache,
+                       krb5_creds *in_creds,
+                       krb5_creds **out_creds,
+                       krb5_creds ***ret_tgts)
+{
+    krb5_error_code ret;
+    krb5_creds *tgt, tmp_creds;
+    krb5_const_realm client_realm, server_realm, try_realm;
+
+    *out_creds = NULL;
+
+    client_realm = krb5_principal_get_realm(context, in_creds->client);
+    server_realm = krb5_principal_get_realm(context, in_creds->server);
+    memset(&tmp_creds, 0, sizeof(tmp_creds));
+    ret = krb5_copy_principal(context, in_creds->client, &tmp_creds.client);
+    if(ret)
+       return ret;
+
+    try_realm = krb5_config_get_string(context, NULL, "capaths", 
+                                      client_realm, server_realm, NULL);
+    
+#if 1
+    /* XXX remove in future release */
+    if(try_realm == NULL)
+       try_realm = krb5_config_get_string(context, NULL, "libdefaults", 
+                                          "capath", server_realm, NULL);
+#endif
+
+    if (try_realm == NULL)
+       try_realm = client_realm;
+
+    ret = krb5_make_principal(context,
+                             &tmp_creds.server,
+                             try_realm,
+                             KRB5_TGS_NAME,
+                             server_realm, 
+                             NULL);
+    if(ret){
+       krb5_free_principal(context, tmp_creds.client);
+       return ret;
+    }
+    {
+       krb5_creds tgts;
+       /* XXX try krb5_cc_retrieve_cred first? */
+       ret = find_cred(context, ccache, tmp_creds.server, 
+                       *ret_tgts, &tgts);
+       if(ret == 0){
+           *out_creds = calloc(1, sizeof(**out_creds));
+           if(*out_creds == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               ret = ENOMEM;
+           } else {
+               krb5_boolean noaddr;
+
+               krb5_appdefault_boolean(context, NULL, tgts.server->realm,
+                                       "no-addresses", FALSE, &noaddr);
+
+               if (noaddr)
+                   ret = get_cred_kdc(context, ccache, flags, NULL,
+                                      in_creds, &tgts, *out_creds);
+               else
+                   ret = get_cred_kdc_la(context, ccache, flags, 
+                                         in_creds, &tgts, *out_creds);
+               if (ret) {
+                   free (*out_creds);
+                   *out_creds = NULL;
+               }
+           }
+           krb5_free_cred_contents(context, &tgts);
+           krb5_free_principal(context, tmp_creds.server);
+           krb5_free_principal(context, tmp_creds.client);
+           return ret;
+       }
+    }
+    if(krb5_realm_compare(context, in_creds->client, in_creds->server)) {
+       krb5_clear_error_string (context);
+       return KRB5_CC_NOTFOUND;
+    }
+    /* XXX this can loop forever */
+    while(1){
+       heim_general_string tgt_inst;
+
+       ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, 
+                                     &tgt, ret_tgts);
+       if(ret) {
+           krb5_free_principal(context, tmp_creds.server);
+           krb5_free_principal(context, tmp_creds.client);
+           return ret;
+       }
+       ret = add_cred(context, ret_tgts, tgt);
+       if(ret) {
+           krb5_free_principal(context, tmp_creds.server);
+           krb5_free_principal(context, tmp_creds.client);
+           return ret;
+       }
+       tgt_inst = tgt->server->name.name_string.val[1];
+       if(strcmp(tgt_inst, server_realm) == 0)
+           break;
+       krb5_free_principal(context, tmp_creds.server);
+       ret = krb5_make_principal(context, &tmp_creds.server, 
+                                 tgt_inst, KRB5_TGS_NAME, server_realm, NULL);
+       if(ret) {
+           krb5_free_principal(context, tmp_creds.server);
+           krb5_free_principal(context, tmp_creds.client);
+           return ret;
+       }
+       ret = krb5_free_creds(context, tgt);
+       if(ret) {
+           krb5_free_principal(context, tmp_creds.server);
+           krb5_free_principal(context, tmp_creds.client);
+           return ret;
+       }
+    }
+       
+    krb5_free_principal(context, tmp_creds.server);
+    krb5_free_principal(context, tmp_creds.client);
+    *out_creds = calloc(1, sizeof(**out_creds));
+    if(*out_creds == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+    } else {
+       krb5_boolean noaddr;
+
+       krb5_appdefault_boolean(context, NULL, tgt->server->realm,
+                               "no-addresses", FALSE, &noaddr);
+       if (noaddr)
+           ret = get_cred_kdc (context, ccache, flags, NULL,
+                               in_creds, tgt, *out_creds);
+       else
+           ret = get_cred_kdc_la(context, ccache, flags, 
+                                 in_creds, tgt, *out_creds);
+       if (ret) {
+           free (*out_creds);
+           *out_creds = NULL;
+       }
+    }
+    krb5_free_creds(context, tgt);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_cred_from_kdc_opt(krb5_context context,
+                          krb5_ccache ccache,
+                          krb5_creds *in_creds,
+                          krb5_creds **out_creds,
+                          krb5_creds ***ret_tgts,
+                          krb5_flags flags)
+{
+    krb5_kdc_flags f;
+    f.i = flags;
+    return get_cred_from_kdc_flags(context, f, ccache, 
+                                  in_creds, out_creds, ret_tgts);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_cred_from_kdc(krb5_context context,
+                      krb5_ccache ccache,
+                      krb5_creds *in_creds,
+                      krb5_creds **out_creds,
+                      krb5_creds ***ret_tgts)
+{
+    return krb5_get_cred_from_kdc_opt(context, ccache, 
+                                     in_creds, out_creds, ret_tgts, 0);
+}
+     
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_credentials_with_flags(krb5_context context,
+                               krb5_flags options,
+                               krb5_kdc_flags flags,
+                               krb5_ccache ccache,
+                               krb5_creds *in_creds,
+                               krb5_creds **out_creds)
+{
+    krb5_error_code ret;
+    krb5_creds **tgts;
+    krb5_creds *res_creds;
+    int i;
+    
+    *out_creds = NULL;
+    res_creds = calloc(1, sizeof(*res_creds));
+    if (res_creds == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    if (in_creds->session.keytype)
+       options |= KRB5_TC_MATCH_KEYTYPE;
+
+    /* 
+     * If we got a credential, check if credential is expired before
+     * returning it.
+     */
+    ret = krb5_cc_retrieve_cred(context,
+                                ccache,
+                                in_creds->session.keytype ?
+                                KRB5_TC_MATCH_KEYTYPE : 0,
+                                in_creds, res_creds);
+    /* 
+     * If we got a credential, check if credential is expired before
+     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
+     */
+    if (ret == 0) {
+       krb5_timestamp timeret;
+
+       /* If expired ok, don't bother checking */
+        if(options & KRB5_GC_EXPIRED_OK) {
+            *out_creds = res_creds;
+            return 0;
+        }
+           
+       krb5_timeofday(context, &timeret);
+       if(res_creds->times.endtime > timeret) {
+           *out_creds = res_creds;
+           return 0;
+       }
+       if(options & KRB5_GC_CACHED)
+           krb5_cc_remove_cred(context, ccache, 0, res_creds);
+
+    } else if(ret != KRB5_CC_END) {
+        free(res_creds);
+        return ret;
+    }
+    free(res_creds);
+    if(options & KRB5_GC_CACHED) {
+        krb5_clear_error_string (context);        
+        return KRB5_CC_NOTFOUND;
+    }
+    if(options & KRB5_GC_USER_USER)
+       flags.b.enc_tkt_in_skey = 1;
+    tgts = NULL;
+    ret = get_cred_from_kdc_flags(context, flags, ccache, 
+                                 in_creds, out_creds, &tgts);
+    for(i = 0; tgts && tgts[i]; i++) {
+       krb5_cc_store_cred(context, ccache, tgts[i]);
+       krb5_free_creds(context, tgts[i]);
+    }
+    free(tgts);
+    if(ret == 0 && flags.b.enc_tkt_in_skey == 0)
+       krb5_cc_store_cred(context, ccache, *out_creds);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_credentials(krb5_context context,
+                    krb5_flags options,
+                    krb5_ccache ccache,
+                    krb5_creds *in_creds,
+                    krb5_creds **out_creds)
+{
+    krb5_kdc_flags flags;
+    flags.i = 0;
+    return krb5_get_credentials_with_flags(context, options, flags,
+                                          ccache, in_creds, out_creds);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_default_principal.c b/src/kerberosV/src/lib/krb5/get_default_principal.c
new file mode 100644 (file)
index 0000000..e1d7bef
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_default_principal.c,v 1.10 2005/04/20 20:53:29 lha Exp $");
+
+/*
+ * Try to find out what's a reasonable default principal.
+ */
+
+static const char*
+get_env_user(void)
+{
+    const char *user = getenv("USER");
+    if(user == NULL)
+       user = getenv("LOGNAME");
+    if(user == NULL)
+       user = getenv("USERNAME");
+    return user;
+}
+
+/*
+ * Will only use operating-system dependant operation to get the
+ * default principal, for use of functions that in ccache layer to
+ * avoid recursive calls.
+ */
+
+krb5_error_code
+_krb5_get_default_principal_local (krb5_context context, 
+                                  krb5_principal *princ)
+{
+    krb5_error_code ret;
+    const char *user;
+    uid_t uid;
+
+    *princ = NULL;
+
+    uid = getuid();    
+    if(uid == 0) {
+       user = getlogin();
+       if(user == NULL)
+           user = get_env_user();
+       if(user != NULL && strcmp(user, "root") != 0)
+           ret = krb5_make_principal(context, princ, NULL, user, "root", NULL);
+       else
+           ret = krb5_make_principal(context, princ, NULL, "root", NULL);
+    } else {
+       struct passwd *pw = getpwuid(uid);      
+       if(pw != NULL)
+           user = pw->pw_name;
+       else {
+           user = get_env_user();
+           if(user == NULL)
+               user = getlogin();
+       }
+       if(user == NULL) {
+           krb5_set_error_string(context,
+                                 "unable to figure out current principal");
+           return ENOTTY; /* XXX */
+       }
+       ret = krb5_make_principal(context, princ, NULL, user, NULL);
+    }
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_principal (krb5_context context,
+                           krb5_principal *princ)
+{
+    krb5_error_code ret;
+    krb5_ccache id;
+
+    *princ = NULL;
+
+    ret = krb5_cc_default (context, &id);
+    if (ret == 0) {
+       ret = krb5_cc_get_principal (context, id, princ);
+       krb5_cc_close (context, id);
+       if (ret == 0)
+           return 0;
+    }
+
+    return _krb5_get_default_principal_local(context, princ);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_default_realm.c b/src/kerberosV/src/lib/krb5/get_default_realm.c
new file mode 100644 (file)
index 0000000..153fa84
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1997 - 2001, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_default_realm.c,v 1.13 2004/05/25 21:27:17 lha Exp $");
+
+/*
+ * Return a NULL-terminated list of default realms in `realms'.
+ * Free this memory with krb5_free_host_realm.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_realms (krb5_context context,
+                        krb5_realm **realms)
+{
+    if (context->default_realms == NULL) {
+       krb5_error_code ret = krb5_set_default_realm (context, NULL);
+       if (ret)
+           return KRB5_CONFIG_NODEFREALM;
+    }
+
+    return krb5_copy_host_realm (context,
+                                context->default_realms,
+                                realms);
+}
+
+/*
+ * Return the first default realm.  For compatibility.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_realm(krb5_context context,
+                      krb5_realm *realm)
+{
+    krb5_error_code ret;
+    char *res;
+
+    if (context->default_realms == NULL
+       || context->default_realms[0] == NULL) {
+       krb5_clear_error_string(context);
+       ret = krb5_set_default_realm (context, NULL);
+       if (ret)
+           return ret;
+    }
+
+    res = strdup (context->default_realms[0]);
+    if (res == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    *realm = res;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/get_for_creds.c b/src/kerberosV/src/lib/krb5/get_for_creds.c
new file mode 100644 (file)
index 0000000..dc6c75c
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: get_for_creds.c,v 1.44 2005/05/17 08:12:29 lha Exp $");
+
+static krb5_error_code
+add_addrs(krb5_context context,
+         krb5_addresses *addr,
+         struct addrinfo *ai)
+{
+    krb5_error_code ret;
+    unsigned n, i;
+    void *tmp;
+    struct addrinfo *a;
+
+    n = 0;
+    for (a = ai; a != NULL; a = a->ai_next)
+       ++n;
+
+    tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val));
+    if (tmp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto fail;
+    }
+    addr->val = tmp;
+    for (i = addr->len; i < (addr->len + n); ++i) {
+       addr->val[i].addr_type = 0;
+       krb5_data_zero(&addr->val[i].address);
+    }
+    i = addr->len;
+    for (a = ai; a != NULL; a = a->ai_next) {
+       krb5_address ad;
+
+       ret = krb5_sockaddr2address (context, a->ai_addr, &ad);
+       if (ret == 0) {
+           if (krb5_address_search(context, &ad, addr))
+               krb5_free_address(context, &ad);
+           else
+               addr->val[i++] = ad;
+       }
+       else if (ret == KRB5_PROG_ATYPE_NOSUPP)
+           krb5_clear_error_string (context);
+       else
+           goto fail;
+       addr->len = i;
+    }
+    return 0;
+fail:
+    krb5_free_addresses (context, addr);
+    return ret;
+}
+
+/*
+ * Forward credentials for `client' to host `hostname`,
+ * making them forwardable if `forwardable', and returning the
+ * blob of data to sent in `out_data'.
+ * If hostname == NULL, pick it from `server'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_fwd_tgt_creds (krb5_context       context,
+                   krb5_auth_context   auth_context,
+                   const char          *hostname,
+                   krb5_principal      client,
+                   krb5_principal      server,
+                   krb5_ccache         ccache,
+                   int                 forwardable,
+                   krb5_data           *out_data)
+{
+    krb5_flags flags = 0;
+    krb5_creds creds;
+    krb5_error_code ret;
+    krb5_const_realm client_realm;
+
+    flags |= KDC_OPT_FORWARDED;
+
+    if (forwardable)
+       flags |= KDC_OPT_FORWARDABLE;
+
+    if (hostname == NULL &&
+       krb5_principal_get_type(context, server) == KRB5_NT_SRV_HST) {
+       const char *inst = krb5_principal_get_comp_string(context, server, 0);
+       const char *host = krb5_principal_get_comp_string(context, server, 1);
+
+       if (inst != NULL &&
+           strcmp(inst, "host") == 0 &&
+           host != NULL && 
+           krb5_principal_get_comp_string(context, server, 2) == NULL)
+           hostname = host;
+    }
+
+    client_realm = krb5_principal_get_realm(context, client);
+    
+    memset (&creds, 0, sizeof(creds));
+    creds.client = client;
+
+    ret = krb5_build_principal(context,
+                              &creds.server,
+                              strlen(client_realm),
+                              client_realm,
+                              KRB5_TGS_NAME,
+                              client_realm,
+                              NULL);
+    if (ret)
+       return ret;
+
+    ret = krb5_get_forwarded_creds (context,
+                                   auth_context,
+                                   ccache,
+                                   flags,
+                                   hostname,
+                                   &creds,
+                                   out_data);
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_forwarded_creds (krb5_context     context,
+                         krb5_auth_context auth_context,
+                         krb5_ccache       ccache,
+                         krb5_flags        flags,
+                         const char        *hostname,
+                         krb5_creds        *in_creds,
+                         krb5_data         *out_data)
+{
+    krb5_error_code ret;
+    krb5_creds *out_creds;
+    krb5_addresses addrs, *paddrs;
+    KRB_CRED cred;
+    KrbCredInfo *krb_cred_info;
+    EncKrbCredPart enc_krb_cred_part;
+    size_t len;
+    unsigned char *buf;
+    size_t buf_size;
+    krb5_kdc_flags kdc_flags;
+    krb5_crypto crypto;
+    struct addrinfo *ai;
+    int save_errno;
+    krb5_creds *ticket;
+    char *realm;
+
+    if (in_creds->client && in_creds->client->realm)
+       realm = in_creds->client->realm;
+    else
+       realm = in_creds->server->realm;
+
+    addrs.len = 0;
+    addrs.val = NULL;
+    paddrs = &addrs;
+
+    /*
+     * If tickets are address-less, forward address-less tickets.
+     */
+
+    ret = _krb5_get_krbtgt (context,
+                           ccache,
+                           realm,
+                           &ticket);
+    if(ret == 0) {
+       if (ticket->addresses.len == 0)
+           paddrs = NULL;
+       krb5_free_creds (context, ticket);
+    }
+    
+    if (paddrs != NULL) {
+
+       ret = getaddrinfo (hostname, NULL, NULL, &ai);
+       if (ret) {
+           save_errno = errno;
+           krb5_set_error_string(context, "resolving %s: %s",
+                                 hostname, gai_strerror(ret));
+           return krb5_eai_to_heim_errno(ret, save_errno);
+       }
+       
+       ret = add_addrs (context, &addrs, ai);
+       freeaddrinfo (ai);
+       if (ret)
+           return ret;
+    }
+    
+    kdc_flags.b = int2KDCOptions(flags);
+
+    ret = krb5_get_kdc_cred (context,
+                            ccache,
+                            kdc_flags,
+                            paddrs,
+                            NULL,
+                            in_creds,
+                            &out_creds);
+    krb5_free_addresses (context, &addrs);
+    if (ret) {
+       return ret;
+    }
+
+    memset (&cred, 0, sizeof(cred));
+    cred.pvno = 5;
+    cred.msg_type = krb_cred;
+    ALLOC_SEQ(&cred.tickets, 1);
+    if (cred.tickets.val == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto out2;
+    }
+    ret = decode_Ticket(out_creds->ticket.data,
+                       out_creds->ticket.length,
+                       cred.tickets.val, &len);
+    if (ret)
+       goto out3;
+
+    memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
+    ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1);
+    if (enc_krb_cred_part.ticket_info.val == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto out4;
+    }
+    
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+       krb5_timestamp sec;
+       int32_t usec;
+       
+       krb5_us_timeofday (context, &sec, &usec);
+       
+       ALLOC(enc_krb_cred_part.timestamp, 1);
+       if (enc_krb_cred_part.timestamp == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto out4;
+       }
+       *enc_krb_cred_part.timestamp = sec;
+       ALLOC(enc_krb_cred_part.usec, 1);
+       if (enc_krb_cred_part.usec == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto out4;
+       }
+       *enc_krb_cred_part.usec      = usec;
+    } else {
+       enc_krb_cred_part.timestamp = NULL;
+       enc_krb_cred_part.usec = NULL;
+    }
+
+    if (auth_context->local_address && auth_context->local_port) {
+       krb5_boolean noaddr;
+       krb5_const_realm realm;
+
+       realm = krb5_principal_get_realm(context, out_creds->server);
+       krb5_appdefault_boolean(context, NULL, realm, "no-addresses", paddrs == NULL,
+                               &noaddr);
+       if (!noaddr) {
+           ret = krb5_make_addrport (context,
+                                     &enc_krb_cred_part.s_address,
+                                     auth_context->local_address,
+                                     auth_context->local_port);
+           if (ret)
+               goto out4;
+       }
+    }
+
+    if (auth_context->remote_address) {
+       if (auth_context->remote_port) {
+           krb5_boolean noaddr;
+           krb5_const_realm realm;
+
+           realm = krb5_principal_get_realm(context, out_creds->server);
+           /* Is this correct, and should we use the paddrs == NULL
+               trick here as well? Having an address-less ticket may
+               indicate that we don't know our own global address, but
+               it does not necessary mean that we don't know the
+               server's. */
+           krb5_appdefault_boolean(context, NULL, realm, "no-addresses",
+                                   FALSE, &noaddr);
+           if (!noaddr) {
+               ret = krb5_make_addrport (context,
+                                         &enc_krb_cred_part.r_address,
+                                         auth_context->remote_address,
+                                         auth_context->remote_port);
+               if (ret)
+                   goto out4;
+           }
+       } else {
+           ALLOC(enc_krb_cred_part.r_address, 1);
+           if (enc_krb_cred_part.r_address == NULL) {
+               ret = ENOMEM;
+               krb5_set_error_string(context, "malloc: out of memory");
+               goto out4;
+           }
+
+           ret = krb5_copy_address (context, auth_context->remote_address,
+                                    enc_krb_cred_part.r_address);
+           if (ret)
+               goto out4;
+       }
+    }
+
+    /* fill ticket_info.val[0] */
+
+    enc_krb_cred_part.ticket_info.len = 1;
+
+    krb_cred_info = enc_krb_cred_part.ticket_info.val;
+
+    copy_EncryptionKey (&out_creds->session, &krb_cred_info->key);
+    ALLOC(krb_cred_info->prealm, 1);
+    copy_Realm (&out_creds->client->realm, krb_cred_info->prealm);
+    ALLOC(krb_cred_info->pname, 1);
+    copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname);
+    ALLOC(krb_cred_info->flags, 1);
+    *krb_cred_info->flags          = out_creds->flags.b;
+    ALLOC(krb_cred_info->authtime, 1);
+    *krb_cred_info->authtime       = out_creds->times.authtime;
+    ALLOC(krb_cred_info->starttime, 1);
+    *krb_cred_info->starttime      = out_creds->times.starttime;
+    ALLOC(krb_cred_info->endtime, 1);
+    *krb_cred_info->endtime        = out_creds->times.endtime;
+    ALLOC(krb_cred_info->renew_till, 1);
+    *krb_cred_info->renew_till = out_creds->times.renew_till;
+    ALLOC(krb_cred_info->srealm, 1);
+    copy_Realm (&out_creds->server->realm, krb_cred_info->srealm);
+    ALLOC(krb_cred_info->sname, 1);
+    copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname);
+    ALLOC(krb_cred_info->caddr, 1);
+    copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr);
+
+    krb5_free_creds (context, out_creds);
+
+    /* encode EncKrbCredPart */
+
+    ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, 
+                      &enc_krb_cred_part, &len, ret);
+    free_EncKrbCredPart (&enc_krb_cred_part);
+    if (ret) {
+       free_KRB_CRED(&cred);
+       return ret;
+    }
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) {
+       cred.enc_part.etype = ENCTYPE_NULL;
+       cred.enc_part.kvno = NULL;
+       cred.enc_part.cipher.data = buf;
+       cred.enc_part.cipher.length = buf_size;
+    } else {
+       krb5_keyblock *key;
+
+       if (auth_context->local_subkey)
+           key = auth_context->local_subkey;
+       else if (auth_context->remote_subkey)
+           key = auth_context->remote_subkey;
+       else
+           key = auth_context->keyblock;
+       
+       ret = krb5_crypto_init(context, key, 0, &crypto);
+       if (ret) {
+           free(buf);
+           free_KRB_CRED(&cred);
+           return ret;
+       }
+       ret = krb5_encrypt_EncryptedData (context,
+                                         crypto,
+                                         KRB5_KU_KRB_CRED,
+                                         buf,
+                                         len,
+                                         0,
+                                         &cred.enc_part);
+       free(buf);
+       krb5_crypto_destroy(context, crypto);
+       if (ret) {
+           free_KRB_CRED(&cred);
+           return ret;
+       }
+    }
+
+    ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret);
+    free_KRB_CRED (&cred);
+    if (ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    out_data->length = len;
+    out_data->data   = buf;
+    return 0;
+ out4:
+    free_EncKrbCredPart(&enc_krb_cred_part);
+ out3:
+    free_KRB_CRED(&cred);
+ out2:
+    krb5_free_creds (context, out_creds);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/get_host_realm.c b/src/kerberosV/src/lib/krb5/get_host_realm.c
new file mode 100644 (file)
index 0000000..61c1d4a
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <resolve.h>
+
+RCSID("$KTH: get_host_realm.c,v 1.34 2005/04/19 18:52:51 lha Exp $");
+
+/* To automagically find the correct realm of a host (without
+ * [domain_realm] in krb5.conf) add a text record for your domain with
+ * the name of your realm, like this:
+ *
+ * _kerberos   IN      TXT     "FOO.SE"
+ *
+ * The search is recursive, so you can add entries for specific
+ * hosts. To find the realm of host a.b.c, it first tries
+ * _kerberos.a.b.c, then _kerberos.b.c and so on.
+ *
+ * This method is described in draft-ietf-cat-krb-dns-locate-03.txt.
+ *
+ */
+
+static int
+copy_txt_to_realms (struct resource_record *head,
+                   krb5_realm **realms)
+{
+    struct resource_record *rr;
+    int n, i;
+
+    for(n = 0, rr = head; rr; rr = rr->next)
+       if (rr->type == T_TXT)
+           ++n;
+
+    if (n == 0)
+       return -1;
+
+    *realms = malloc ((n + 1) * sizeof(krb5_realm));
+    if (*realms == NULL)
+       return -1;
+
+    for (i = 0; i < n + 1; ++i)
+       (*realms)[i] = NULL;
+
+    for (i = 0, rr = head; rr; rr = rr->next) {
+       if (rr->type == T_TXT) {
+           char *tmp;
+
+           tmp = strdup(rr->u.txt);
+           if (tmp == NULL) {
+               for (i = 0; i < n; ++i)
+                   free ((*realms)[i]);
+               free (*realms);
+               return -1;
+           }
+           (*realms)[i] = tmp;
+           ++i;
+       }
+    }
+    return 0;
+}
+
+static int
+dns_find_realm(krb5_context context,
+              const char *domain,
+              krb5_realm **realms)
+{
+    static char *default_labels[] = { "_kerberos", NULL };
+    char dom[MAXHOSTNAMELEN];
+    struct dns_reply *r;
+    char **labels;
+    int i, ret;
+    
+    labels = krb5_config_get_strings(context, NULL, "libdefaults",
+       "dns_lookup_realm_labels", NULL);
+    if(labels == NULL)
+       labels = default_labels;
+    if(*domain == '.')
+       domain++;
+    for (i = 0; labels[i] != NULL; i++) {
+       ret = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain);
+       if(ret < 0 || ret >= sizeof(dom))
+           return -1;
+       r = dns_lookup(dom, "TXT");
+       if(r != NULL) {
+           ret = copy_txt_to_realms (r->head, realms);
+           dns_free_data(r);
+           if(ret == 0)
+               return 0;
+       }
+    }
+    return -1;
+}
+
+/*
+ * Try to figure out what realms host in `domain' belong to from the
+ * configuration file.
+ */
+
+static int
+config_find_realm(krb5_context context, 
+                 const char *domain, 
+                 krb5_realm **realms)
+{
+    char **tmp = krb5_config_get_strings (context, NULL,
+                                         "domain_realm",
+                                         domain,
+                                         NULL);
+
+    if (tmp == NULL)
+       return -1;
+    *realms = tmp;
+    return 0;
+}
+
+/*
+ * This function assumes that `host' is a FQDN (and doesn't handle the
+ * special case of host == NULL either).
+ * Try to find mapping in the config file or DNS and it that fails,
+ * fall back to guessing
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_get_host_realm_int (krb5_context context,
+                         const char *host,
+                         krb5_boolean use_dns,
+                         krb5_realm **realms)
+{
+    const char *p, *q;
+    krb5_boolean dns_locate_enable;
+
+    dns_locate_enable = krb5_config_get_bool_default(context, NULL, TRUE,
+       "libdefaults", "dns_lookup_realm", NULL);
+    for (p = host; p != NULL; p = strchr (p + 1, '.')) {
+       if(config_find_realm(context, p, realms) == 0) {
+           if(strcasecmp(*realms[0], "dns_locate") == 0) {
+               if(use_dns)
+                   for (q = host; q != NULL; q = strchr(q + 1, '.'))
+                       if(dns_find_realm(context, q, realms) == 0)
+                           return 0;
+               continue; 
+           } else 
+               return 0;
+       }
+       else if(use_dns && dns_locate_enable) {
+           if(dns_find_realm(context, p, realms) == 0)
+               return 0;
+       }
+    }
+    p = strchr(host, '.');
+    if(p != NULL) {
+       p++;
+       *realms = malloc(2 * sizeof(krb5_realm));
+       if (*realms == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+
+       (*realms)[0] = strdup(p);
+       if((*realms)[0] == NULL) {
+           free(*realms);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       strupr((*realms)[0]);
+       (*realms)[1] = NULL;
+       return 0;
+    }
+    krb5_set_error_string(context, "unable to find realm of host %s", host);
+    return KRB5_ERR_HOST_REALM_UNKNOWN;
+}
+
+/*
+ * Return the realm(s) of `host' as a NULL-terminated list in `realms'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_host_realm(krb5_context context,
+                   const char *host,
+                   krb5_realm **realms)
+{
+    char hostname[MAXHOSTNAMELEN];
+
+    if (host == NULL) {
+       if (gethostname (hostname, sizeof(hostname)))
+           return errno;
+       host = hostname;
+    }
+
+    return _krb5_get_host_realm_int (context, host, 1, realms);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_in_tkt.c b/src/kerberosV/src/lib/krb5/get_in_tkt.c
new file mode 100644 (file)
index 0000000..8794616
--- /dev/null
@@ -0,0 +1,823 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_in_tkt.c,v 1.115 2004/12/29 18:55:14 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_etype (krb5_context context,
+                unsigned *len,
+                krb5_enctype **val,
+                const krb5_enctype *etypes)
+{
+    int i;
+    krb5_error_code ret;
+    krb5_enctype *tmp = NULL;
+
+    ret = 0;
+    if (etypes == NULL) {
+       ret = krb5_get_default_in_tkt_etypes(context,
+                                            &tmp);
+       if (ret)
+           return ret;
+       etypes = tmp;
+    }
+
+    for (i = 0; etypes[i]; ++i)
+       ;
+    *len = i;
+    *val = malloc(i * sizeof(**val));
+    if (i != 0 && *val == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto cleanup;
+    }
+    memmove (*val,
+            etypes,
+            i * sizeof(*tmp));
+cleanup:
+    if (tmp != NULL)
+       free (tmp);
+    return ret;
+}
+
+
+static krb5_error_code
+decrypt_tkt (krb5_context context,
+            krb5_keyblock *key,
+            krb5_key_usage usage,
+            krb5_const_pointer decrypt_arg,
+            krb5_kdc_rep *dec_rep)
+{
+    krb5_error_code ret;
+    krb5_data data;
+    size_t size;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       return ret;
+
+    ret = krb5_decrypt_EncryptedData (context,
+                                     crypto,
+                                     usage,
+                                     &dec_rep->kdc_rep.enc_part,
+                                     &data);
+    krb5_crypto_destroy(context, crypto);
+
+    if (ret)
+       return ret;
+
+    ret = krb5_decode_EncASRepPart(context,
+                                  data.data,
+                                  data.length,
+                                  &dec_rep->enc_part, 
+                                  &size);
+    if (ret)
+       ret = krb5_decode_EncTGSRepPart(context,
+                                       data.data,
+                                       data.length,
+                                       &dec_rep->enc_part, 
+                                       &size);
+    krb5_data_free (&data);
+    if (ret)
+       return ret;
+    return 0;
+}
+
+int
+_krb5_extract_ticket(krb5_context context, 
+                    krb5_kdc_rep *rep, 
+                    krb5_creds *creds,         
+                    krb5_keyblock *key,
+                    krb5_const_pointer keyseed,
+                    krb5_key_usage key_usage,
+                    krb5_addresses *addrs,
+                    unsigned nonce,
+                    krb5_boolean allow_server_mismatch,
+                    krb5_boolean ignore_cname,
+                    krb5_decrypt_proc decrypt_proc,
+                    krb5_const_pointer decryptarg)
+{
+    krb5_error_code ret;
+    krb5_principal tmp_principal;
+    int tmp;
+    size_t len;
+    time_t tmp_time;
+    krb5_timestamp sec_now;
+
+    ret = _krb5_principalname2krb5_principal (&tmp_principal,
+                                             rep->kdc_rep.cname,
+                                             rep->kdc_rep.crealm);
+    if (ret)
+       goto out;
+
+    /* compare client */
+
+    if (!ignore_cname) {
+       tmp = krb5_principal_compare (context, tmp_principal, creds->client);
+       if (!tmp) {
+           krb5_free_principal (context, tmp_principal);
+           krb5_clear_error_string (context);
+           ret = KRB5KRB_AP_ERR_MODIFIED;
+           goto out;
+       }
+    }
+
+    krb5_free_principal (context, creds->client);
+    creds->client = tmp_principal;
+
+    /* extract ticket */
+    ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, 
+                      &rep->kdc_rep.ticket, &len, ret);
+    if(ret)
+       goto out;
+    if (creds->ticket.length != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    creds->second_ticket.length = 0;
+    creds->second_ticket.data   = NULL;
+
+    /* compare server */
+
+    ret = _krb5_principalname2krb5_principal (&tmp_principal,
+                                             rep->kdc_rep.ticket.sname,
+                                             rep->kdc_rep.ticket.realm);
+    if (ret)
+       goto out;
+    if(allow_server_mismatch){
+       krb5_free_principal(context, creds->server);
+       creds->server = tmp_principal;
+       tmp_principal = NULL;
+    }else{
+       tmp = krb5_principal_compare (context, tmp_principal, creds->server);
+       krb5_free_principal (context, tmp_principal);
+       if (!tmp) {
+           ret = KRB5KRB_AP_ERR_MODIFIED;
+           krb5_clear_error_string (context);
+           goto out;
+       }
+    }
+    
+    /* decrypt */
+
+    if (decrypt_proc == NULL)
+       decrypt_proc = decrypt_tkt;
+    
+    ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
+    if (ret)
+       goto out;
+
+#if 0
+    /* XXX should this decode be here, or in the decrypt_proc? */
+    ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1);
+    if(ret)
+       goto out;
+#endif
+
+    /* compare nonces */
+
+    if (nonce != rep->enc_part.nonce) {
+       ret = KRB5KRB_AP_ERR_MODIFIED;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto out;
+    }
+
+    /* set kdc-offset */
+
+    krb5_timeofday (context, &sec_now);
+    if (rep->enc_part.flags.initial
+       && context->kdc_sec_offset == 0
+       && krb5_config_get_bool (context, NULL,
+                                "libdefaults",
+                                "kdc_timesync",
+                                NULL)) {
+       context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
+       krb5_timeofday (context, &sec_now);
+    }
+
+    /* check all times */
+
+    if (rep->enc_part.starttime) {
+       tmp_time = *rep->enc_part.starttime;
+    } else
+       tmp_time = rep->enc_part.authtime;
+
+    if (creds->times.starttime == 0
+       && abs(tmp_time - sec_now) > context->max_skew) {
+       ret = KRB5KRB_AP_ERR_SKEW;
+       krb5_set_error_string (context,
+                              "time skew (%d) larger than max (%d)",
+                              abs(tmp_time - sec_now),
+                              (int)context->max_skew);
+       goto out;
+    }
+
+    if (creds->times.starttime != 0
+       && tmp_time != creds->times.starttime) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_MODIFIED;
+       goto out;
+    }
+
+    creds->times.starttime = tmp_time;
+
+    if (rep->enc_part.renew_till) {
+       tmp_time = *rep->enc_part.renew_till;
+    } else
+       tmp_time = 0;
+
+    if (creds->times.renew_till != 0
+       && tmp_time > creds->times.renew_till) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_MODIFIED;
+       goto out;
+    }
+
+    creds->times.renew_till = tmp_time;
+
+    creds->times.authtime = rep->enc_part.authtime;
+
+    if (creds->times.endtime != 0
+       && rep->enc_part.endtime > creds->times.endtime) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_MODIFIED;
+       goto out;
+    }
+
+    creds->times.endtime  = rep->enc_part.endtime;
+
+    if(rep->enc_part.caddr)
+       krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
+    else if(addrs)
+       krb5_copy_addresses (context, addrs, &creds->addresses);
+    else {
+       creds->addresses.len = 0;
+       creds->addresses.val = NULL;
+    }
+    creds->flags.b = rep->enc_part.flags;
+         
+    creds->authdata.len = 0;
+    creds->authdata.val = NULL;
+    creds->session.keyvalue.length = 0;
+    creds->session.keyvalue.data   = NULL;
+    creds->session.keytype = rep->enc_part.key.keytype;
+    ret = krb5_data_copy (&creds->session.keyvalue,
+                         rep->enc_part.key.keyvalue.data,
+                         rep->enc_part.key.keyvalue.length);
+
+out:
+    memset (rep->enc_part.key.keyvalue.data, 0,
+           rep->enc_part.key.keyvalue.length);
+    return ret;
+}
+
+
+static krb5_error_code
+make_pa_enc_timestamp(krb5_context context, PA_DATA *pa, 
+                     krb5_enctype etype, krb5_keyblock *key)
+{
+    PA_ENC_TS_ENC p;
+    unsigned char *buf;
+    size_t buf_size;
+    size_t len;
+    EncryptedData encdata;
+    krb5_error_code ret;
+    int32_t usec;
+    int usec2;
+    krb5_crypto crypto;
+    
+    krb5_us_timeofday (context, &p.patimestamp, &usec);
+    usec2         = usec;
+    p.pausec      = &usec2;
+
+    ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
+    if (ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret) {
+       free(buf);
+       return ret;
+    }
+    ret = krb5_encrypt_EncryptedData(context, 
+                                    crypto,
+                                    KRB5_KU_PA_ENC_TIMESTAMP,
+                                    buf,
+                                    len,
+                                    0,
+                                    &encdata);
+    free(buf);
+    krb5_crypto_destroy(context, crypto);
+    if (ret)
+       return ret;
+                   
+    ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
+    free_EncryptedData(&encdata);
+    if (ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
+    pa->padata_value.length = len;
+    pa->padata_value.data = buf;
+    return 0;
+}
+
+static krb5_error_code
+add_padata(krb5_context context,
+          METHOD_DATA *md, 
+          krb5_principal client,
+          krb5_key_proc key_proc,
+          krb5_const_pointer keyseed,
+          krb5_enctype *enctypes,
+          unsigned netypes,
+          krb5_salt *salt)
+{
+    krb5_error_code ret;
+    PA_DATA *pa2;
+    krb5_salt salt2;
+    krb5_enctype *ep;
+    int i;
+    
+    if(salt == NULL) {
+       /* default to standard salt */
+       ret = krb5_get_pw_salt (context, client, &salt2);
+       salt = &salt2;
+    }
+    if (!enctypes) {
+       enctypes = context->etypes;
+       netypes = 0;
+       for (ep = enctypes; *ep != ETYPE_NULL; ep++)
+           netypes++;
+    }
+    pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val));
+    if (pa2 == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    md->val = pa2;
+
+    for (i = 0; i < netypes; ++i) {
+       krb5_keyblock *key;
+
+       ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key);
+       if (ret)
+           continue;
+       ret = make_pa_enc_timestamp (context, &md->val[md->len],
+                                    enctypes[i], key);
+       krb5_free_keyblock (context, key);
+       if (ret)
+           return ret;
+       ++md->len;
+    }
+    if(salt == &salt2)
+       krb5_free_salt(context, salt2);
+    return 0;
+}
+
+static krb5_error_code
+init_as_req (krb5_context context,
+            krb5_kdc_flags opts,
+            krb5_creds *creds,
+            const krb5_addresses *addrs,
+            const krb5_enctype *etypes,
+            const krb5_preauthtype *ptypes,
+            const krb5_preauthdata *preauth,
+            krb5_key_proc key_proc,
+            krb5_const_pointer keyseed,
+            unsigned nonce,
+            AS_REQ *a)
+{
+    krb5_error_code ret;
+    krb5_salt salt;
+
+    memset(a, 0, sizeof(*a));
+
+    a->pvno = 5;
+    a->msg_type = krb_as_req;
+    a->req_body.kdc_options = opts.b;
+    a->req_body.cname = malloc(sizeof(*a->req_body.cname));
+    if (a->req_body.cname == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+    a->req_body.sname = malloc(sizeof(*a->req_body.sname));
+    if (a->req_body.sname == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+    ret = _krb5_principal2principalname (a->req_body.cname, creds->client);
+    if (ret)
+       goto fail;
+    ret = _krb5_principal2principalname (a->req_body.sname, creds->server);
+    if (ret)
+       goto fail;
+    ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
+    if (ret)
+       goto fail;
+
+    if(creds->times.starttime) {
+       a->req_body.from = malloc(sizeof(*a->req_body.from));
+       if (a->req_body.from == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       *a->req_body.from = creds->times.starttime;
+    }
+    if(creds->times.endtime){
+       ALLOC(a->req_body.till, 1);
+       *a->req_body.till = creds->times.endtime;
+    }
+    if(creds->times.renew_till){
+       a->req_body.rtime = malloc(sizeof(*a->req_body.rtime));
+       if (a->req_body.rtime == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       *a->req_body.rtime = creds->times.renew_till;
+    }
+    a->req_body.nonce = nonce;
+    ret = krb5_init_etype (context,
+                          &a->req_body.etype.len,
+                          &a->req_body.etype.val,
+                          etypes);
+    if (ret)
+       goto fail;
+
+    /*
+     * This means no addresses
+     */
+
+    if (addrs && addrs->len == 0) {
+       a->req_body.addresses = NULL;
+    } else {
+       a->req_body.addresses = malloc(sizeof(*a->req_body.addresses));
+       if (a->req_body.addresses == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+
+       if (addrs)
+           ret = krb5_copy_addresses(context, addrs, a->req_body.addresses);
+       else {
+           ret = krb5_get_all_client_addrs (context, a->req_body.addresses);
+           if(ret == 0 && a->req_body.addresses->len == 0) {
+               free(a->req_body.addresses);
+               a->req_body.addresses = NULL;
+           }
+       }
+       if (ret)
+           return ret;
+    }
+
+    a->req_body.enc_authorization_data = NULL;
+    a->req_body.additional_tickets = NULL;
+
+    if(preauth != NULL) {
+       int i;
+       ALLOC(a->padata, 1);
+       if(a->padata == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       a->padata->val = NULL;
+       a->padata->len = 0;
+       for(i = 0; i < preauth->len; i++) {
+           if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){
+               int j;
+
+               for(j = 0; j < preauth->val[i].info.len; j++) {
+                   krb5_salt *sp = &salt;
+                   if(preauth->val[i].info.val[j].salttype)
+                       salt.salttype = *preauth->val[i].info.val[j].salttype;
+                   else
+                       salt.salttype = KRB5_PW_SALT;
+                   if(preauth->val[i].info.val[j].salt)
+                       salt.saltvalue = *preauth->val[i].info.val[j].salt;
+                   else
+                       if(salt.salttype == KRB5_PW_SALT)
+                           sp = NULL;
+                       else
+                           krb5_data_zero(&salt.saltvalue);
+                   ret = add_padata(context, a->padata, creds->client, 
+                                    key_proc, keyseed, 
+                                    &preauth->val[i].info.val[j].etype, 1,
+                                    sp);
+                   if (ret == 0)
+                       break;
+               }
+           }
+       }
+    } else 
+    /* not sure this is the way to use `ptypes' */
+    if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE)
+       a->padata = NULL;
+    else if (*ptypes ==  KRB5_PADATA_ENC_TIMESTAMP) {
+       ALLOC(a->padata, 1);
+       if (a->padata == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       a->padata->len = 0;
+       a->padata->val = NULL;
+
+       /* make a v5 salted pa-data */
+       add_padata(context, a->padata, creds->client, 
+                  key_proc, keyseed, a->req_body.etype.val,
+                  a->req_body.etype.len, NULL);
+       
+       /* make a v4 salted pa-data */
+       salt.salttype = KRB5_PW_SALT;
+       krb5_data_zero(&salt.saltvalue);
+       add_padata(context, a->padata, creds->client, 
+                  key_proc, keyseed, a->req_body.etype.val,
+                  a->req_body.etype.len, &salt);
+    } else {
+       krb5_set_error_string (context, "pre-auth type %d not supported",
+                              *ptypes);
+       ret = KRB5_PREAUTH_BAD_TYPE;
+       goto fail;
+    }
+    return 0;
+fail:
+    free_AS_REQ(a);
+    return ret;
+}
+
+static int
+set_ptypes(krb5_context context,
+          KRB_ERROR *error, 
+          const krb5_preauthtype **ptypes,
+          krb5_preauthdata **preauth)
+{
+    static krb5_preauthdata preauth2;
+    static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE };
+
+    if(error->e_data) {
+       METHOD_DATA md;
+       int i;
+       decode_METHOD_DATA(error->e_data->data, 
+                          error->e_data->length, 
+                          &md, 
+                          NULL);
+       for(i = 0; i < md.len; i++){
+           switch(md.val[i].padata_type){
+           case KRB5_PADATA_ENC_TIMESTAMP:
+               *ptypes = ptypes2;
+               break;
+           case KRB5_PADATA_ETYPE_INFO:
+               *preauth = &preauth2;
+               ALLOC_SEQ(*preauth, 1);
+               (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP;
+               krb5_decode_ETYPE_INFO(context,
+                                      md.val[i].padata_value.data, 
+                                      md.val[i].padata_value.length,
+                                      &(*preauth)->val[0].info,
+                                      NULL);
+               break;
+           default:
+               break;
+           }
+       }
+       free_METHOD_DATA(&md);
+    } else {
+       *ptypes = ptypes2;
+    }
+    return(1);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_cred(krb5_context context,
+                krb5_flags options,
+                const krb5_addresses *addrs,
+                const krb5_enctype *etypes,
+                const krb5_preauthtype *ptypes,
+                const krb5_preauthdata *preauth,
+                krb5_key_proc key_proc,
+                krb5_const_pointer keyseed,
+                krb5_decrypt_proc decrypt_proc,
+                krb5_const_pointer decryptarg,
+                krb5_creds *creds,
+                krb5_kdc_rep *ret_as_reply)
+{
+    krb5_error_code ret;
+    AS_REQ a;
+    krb5_kdc_rep rep;
+    krb5_data req, resp;
+    size_t len;
+    krb5_salt salt;
+    krb5_keyblock *key;
+    size_t size;
+    krb5_kdc_flags opts;
+    PA_DATA *pa;
+    krb5_enctype etype;
+    krb5_preauthdata *my_preauth = NULL;
+    unsigned nonce;
+    int done;
+
+    opts.i = options;
+
+    krb5_generate_random_block (&nonce, sizeof(nonce));
+    nonce &= 0xffffffff;
+
+    do {
+       done = 1;
+       ret = init_as_req (context,
+                          opts,
+                          creds,
+                          addrs,
+                          etypes,
+                          ptypes,
+                          preauth,
+                          key_proc,
+                          keyseed,
+                          nonce,
+                          &a);
+       if (my_preauth) {
+           free_ETYPE_INFO(&my_preauth->val[0].info);
+           free (my_preauth->val);
+           my_preauth = NULL;
+       }
+       if (ret)
+           return ret;
+
+       ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret);
+       free_AS_REQ(&a);
+       if (ret)
+           return ret;
+       if(len != req.length)
+           krb5_abortx(context, "internal error in ASN.1 encoder");
+
+       ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp);
+       krb5_data_free(&req);
+       if (ret)
+           return ret;
+
+       memset (&rep, 0, sizeof(rep));
+       ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
+       if(ret) {
+           /* let's try to parse it as a KRB-ERROR */
+           KRB_ERROR error;
+           int ret2;
+
+           ret2 = krb5_rd_error(context, &resp, &error);
+           if(ret2 && resp.data && ((char*)resp.data)[0] == 4)
+               ret = KRB5KRB_AP_ERR_V4_REPLY;
+           krb5_data_free(&resp);
+           if (ret2 == 0) {
+               ret = krb5_error_from_rd_error(context, &error, creds);
+               /* if no preauth was set and KDC requires it, give it
+                   one more try */
+               if (!ptypes && !preauth
+                   && ret == KRB5KDC_ERR_PREAUTH_REQUIRED
+#if 0
+                       || ret == KRB5KDC_ERR_BADOPTION
+#endif
+                   && set_ptypes(context, &error, &ptypes, &my_preauth)) {
+                   done = 0;
+                   preauth = my_preauth;
+                   krb5_free_error_contents(context, &error);
+                   krb5_clear_error_string(context);
+                   continue;
+               }
+               if(ret_as_reply)
+                   ret_as_reply->error = error;
+               else
+                   free_KRB_ERROR (&error);
+               return ret;
+           }
+           return ret;
+       }
+       krb5_data_free(&resp);
+    } while(!done);
+    
+    pa = NULL;
+    etype = rep.kdc_rep.enc_part.etype;
+    if(rep.kdc_rep.padata){
+       int index = 0;
+       pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len, 
+                             KRB5_PADATA_PW_SALT, &index);
+       if(pa == NULL) {
+           index = 0;
+           pa = krb5_find_padata(rep.kdc_rep.padata->val, 
+                                 rep.kdc_rep.padata->len, 
+                                 KRB5_PADATA_AFS3_SALT, &index);
+       }
+    }
+    if(pa) {
+       salt.salttype = pa->padata_type;
+       salt.saltvalue = pa->padata_value;
+       
+       ret = (*key_proc)(context, etype, salt, keyseed, &key);
+    } else {
+       /* make a v5 salted pa-data */
+       ret = krb5_get_pw_salt (context, creds->client, &salt);
+       
+       if (ret)
+           goto out;
+       ret = (*key_proc)(context, etype, salt, keyseed, &key);
+       krb5_free_salt(context, salt);
+    }
+    if (ret)
+       goto out;
+       
+    ret = _krb5_extract_ticket(context, 
+                              &rep, 
+                              creds, 
+                              key, 
+                              keyseed, 
+                              KRB5_KU_AS_REP_ENC_PART,
+                              NULL, 
+                              nonce, 
+                              FALSE, 
+                              opts.b.request_anonymous,
+                              decrypt_proc, 
+                              decryptarg);
+    memset (key->keyvalue.data, 0, key->keyvalue.length);
+    krb5_free_keyblock_contents (context, key);
+    free (key);
+
+out:
+    if (ret == 0 && ret_as_reply)
+       *ret_as_reply = rep;
+    else
+       krb5_free_kdc_rep (context, &rep);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt(krb5_context context,
+               krb5_flags options,
+               const krb5_addresses *addrs,
+               const krb5_enctype *etypes,
+               const krb5_preauthtype *ptypes,
+               krb5_key_proc key_proc,
+               krb5_const_pointer keyseed,
+               krb5_decrypt_proc decrypt_proc,
+               krb5_const_pointer decryptarg,
+               krb5_creds *creds,
+               krb5_ccache ccache,
+               krb5_kdc_rep *ret_as_reply)
+{
+    krb5_error_code ret;
+    krb5_kdc_flags opts;
+    opts.i = 0;
+    opts.b = int2KDCOptions(options);
+    
+    ret = krb5_get_in_cred (context,
+                           opts.i,
+                           addrs,
+                           etypes,
+                           ptypes,
+                           NULL,
+                           key_proc,
+                           keyseed,
+                           decrypt_proc,
+                           decryptarg,
+                           creds,
+                           ret_as_reply);
+    if(ret) 
+       return ret;
+    if (ccache)
+       ret = krb5_cc_store_cred (context, ccache, creds);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/get_in_tkt_pw.c b/src/kerberosV/src/lib/krb5/get_in_tkt_pw.c
new file mode 100644 (file)
index 0000000..60a76b6
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_in_tkt_pw.c,v 1.18 2004/05/25 21:28:51 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_password_key_proc (krb5_context context,
+                       krb5_enctype type,
+                       krb5_salt salt,
+                       krb5_const_pointer keyseed,
+                       krb5_keyblock **key)
+{
+    krb5_error_code ret;
+    const char *password = (const char *)keyseed;
+    char buf[BUFSIZ];
+     
+    *key = malloc (sizeof (**key));
+    if (*key == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    if (password == NULL) {
+       if(UI_UTIL_read_pw_string (buf, sizeof(buf), "Password: ", 0)) {
+           free (*key);
+           krb5_clear_error_string(context);
+           return KRB5_LIBOS_PWDINTR;
+       }
+       password = buf;
+    }
+    ret = krb5_string_to_key_salt (context, type, password, salt, *key);
+    memset (buf, 0, sizeof(buf));
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt_with_password (krb5_context context,
+                              krb5_flags options,
+                              krb5_addresses *addrs,
+                              const krb5_enctype *etypes,
+                              const krb5_preauthtype *pre_auth_types,
+                              const char *password,
+                              krb5_ccache ccache,
+                              krb5_creds *creds,
+                              krb5_kdc_rep *ret_as_reply)
+{
+     return krb5_get_in_tkt (context,
+                            options,
+                            addrs,
+                            etypes,
+                            pre_auth_types,
+                            krb5_password_key_proc,
+                            password,
+                            NULL,
+                            NULL,
+                            creds,
+                            ccache,
+                            ret_as_reply);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_in_tkt_with_keytab.c b/src/kerberosV/src/lib/krb5/get_in_tkt_with_keytab.c
new file mode 100644 (file)
index 0000000..fda6622
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_in_tkt_with_keytab.c,v 1.8 2004/05/25 21:29:17 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytab_key_proc (krb5_context context,
+                     krb5_enctype enctype,
+                     krb5_salt salt,
+                     krb5_const_pointer keyseed,
+                     krb5_keyblock **key)
+{
+    krb5_keytab_key_proc_args *args  = (krb5_keytab_key_proc_args *)keyseed;
+    krb5_keytab keytab = args->keytab;
+    krb5_principal principal  = args->principal;
+    krb5_error_code ret;
+    krb5_keytab real_keytab;
+    krb5_keytab_entry entry;
+
+    if(keytab == NULL)
+       krb5_kt_default(context, &real_keytab);
+    else
+       real_keytab = keytab;
+
+    ret = krb5_kt_get_entry (context, real_keytab, principal,
+                            0, enctype, &entry);
+
+    if (keytab == NULL)
+       krb5_kt_close (context, real_keytab);
+
+    if (ret)
+       return ret;
+
+    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
+    krb5_kt_free_entry(context, &entry);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt_with_keytab (krb5_context context,
+                            krb5_flags options,
+                            krb5_addresses *addrs,
+                            const krb5_enctype *etypes,
+                            const krb5_preauthtype *pre_auth_types,
+                            krb5_keytab keytab,
+                            krb5_ccache ccache,
+                            krb5_creds *creds,
+                            krb5_kdc_rep *ret_as_reply)
+{
+    krb5_keytab_key_proc_args a;
+
+    a.principal = creds->client;
+    a.keytab    = keytab;
+
+    return krb5_get_in_tkt (context,
+                           options,
+                           addrs,
+                           etypes,
+                           pre_auth_types,
+                           krb5_keytab_key_proc,
+                           &a,
+                           NULL,
+                           NULL,
+                           creds,
+                           ccache,
+                           ret_as_reply);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_in_tkt_with_skey.c b/src/kerberosV/src/lib/krb5/get_in_tkt_with_skey.c
new file mode 100644 (file)
index 0000000..16cf04d
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: get_in_tkt_with_skey.c,v 1.4 2004/05/25 21:29:38 lha Exp $");
+
+static krb5_error_code
+krb5_skey_key_proc (krb5_context context,
+                   krb5_enctype type,
+                   krb5_salt salt,
+                   krb5_const_pointer keyseed,
+                   krb5_keyblock **key)
+{
+    return krb5_copy_keyblock (context, keyseed, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt_with_skey (krb5_context context,
+                          krb5_flags options,
+                          krb5_addresses *addrs,
+                          const krb5_enctype *etypes,
+                          const krb5_preauthtype *pre_auth_types,
+                          const krb5_keyblock *key,
+                          krb5_ccache ccache,
+                          krb5_creds *creds,
+                          krb5_kdc_rep *ret_as_reply)
+{
+    if(key == NULL)
+       return krb5_get_in_tkt_with_keytab (context,
+                                           options,
+                                           addrs,
+                                           etypes,
+                                           pre_auth_types,
+                                           NULL,
+                                           ccache,
+                                           creds,
+                                           ret_as_reply);
+    else
+       return krb5_get_in_tkt (context,
+                               options,
+                               addrs,
+                               etypes,
+                               pre_auth_types,
+                               krb5_skey_key_proc,
+                               key,
+                               NULL,
+                               NULL,
+                               creds,
+                               ccache,
+                               ret_as_reply);
+}
diff --git a/src/kerberosV/src/lib/krb5/get_port.c b/src/kerberosV/src/lib/krb5/get_port.c
new file mode 100644 (file)
index 0000000..0a49a02
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: get_port.c,v 1.9 2004/05/25 21:29:59 lha Exp $");
+
+int KRB5_LIB_FUNCTION
+krb5_getportbyname (krb5_context context,
+                   const char *service,
+                   const char *proto,
+                   int default_port)
+{
+    struct servent *sp;
+
+    if ((sp = roken_getservbyname (service, proto)) == NULL) {
+#if 0
+       krb5_warnx(context, "%s/%s unknown service, using default port %d", 
+                  service, proto, default_port);
+#endif
+       return htons(default_port);
+    } else
+       return sp->s_port;
+}
diff --git a/src/kerberosV/src/lib/krb5/heim_err.et b/src/kerberosV/src/lib/krb5/heim_err.et
new file mode 100644 (file)
index 0000000..6b11406
--- /dev/null
@@ -0,0 +1,44 @@
+#
+# Error messages for the krb5 library
+#
+# This might look like a com_err file, but is not
+#
+id "$KTH: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $"
+
+error_table heim
+
+prefix HEIM_ERR
+
+error_code LOG_PARSE,          "Error parsing log destination"
+error_code V4_PRINC_NO_CONV,   "Failed to convert v4 principal"
+error_code SALTTYPE_NOSUPP,    "Salt type is not supported by enctype"
+error_code NOHOST,             "Host not found"
+error_code OPNOTSUPP,          "Operation not supported"
+error_code EOF,                        "End of file"
+error_code BAD_MKEY,           "Failed to get the master key"
+error_code SERVICE_NOMATCH,    "Unacceptable service used"
+
+index 64
+prefix HEIM_PKINIT
+error_code NO_CERTIFICATE,     "Certificate missing"
+error_code NO_PRIVATE_KEY,     "Private key missing"
+error_code NO_VALID_CA,                "No valid certificate authority"
+error_code CERTIFICATE_INVALID,        "Certificate invalid"
+error_code PRIVATE_KEY_INVALID,        "Private key invalid"
+
+index 128
+prefix HEIM_EAI
+#error_code NOERROR,           "no error"
+error_code UNKNOWN,            "unknown error from getaddrinfo"
+error_code ADDRFAMILY,         "address family for nodename not supported"
+error_code AGAIN,              "temporary failure in name resolution"
+error_code BADFLAGS,           "invalid value for ai_flags"
+error_code FAIL,               "non-recoverable failure in name resolution"
+error_code FAMILY,             "ai_family not supported"
+error_code MEMORY,             "memory allocation failure"
+error_code NODATA,             "no address associated with nodename"
+error_code NONAME,             "nodename nor servname provided, or not known"
+error_code SERVICE,            "servname not supported for ai_socktype"
+error_code SOCKTYPE,           "ai_socktype not supported"
+error_code SYSTEM,             "system error returned in errno"
+end
diff --git a/src/kerberosV/src/lib/krb5/heim_threads.h b/src/kerberosV/src/lib/krb5/heim_threads.h
new file mode 100644 (file)
index 0000000..4e05d9e
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: heim_threads.h,v 1.11 2004/12/18 16:03:38 lha Exp $ */
+
+/*
+ * Provide wrapper macros for thread synchronization primitives so we
+ * can use native thread functions for those operating system that
+ * supports it.
+ *
+ * This is so libkrb5.so (or more importantly, libgssapi.so) can have
+ * thread support while the program that that dlopen(3)s the library
+ * don't need to be linked to libpthread.
+ */
+
+#ifndef HEIM_THREADS_H
+#define HEIM_THREADS_H 1
+
+/* assume headers already included */
+
+#if defined(__NetBSD__) && __NetBSD_Version__ >= 106120000 && __NetBSD_Version__< 299001200 && defined(ENABLE_PTHREAD_SUPPORT)
+
+/* 
+ * NetBSD have a thread lib that we can use that part of libc that
+ * works regardless if application are linked to pthreads or not.
+ * NetBSD newer then 2.99.11 just use pthread.h, and the same thing
+ * will happen.
+ */
+#include <threadlib.h>
+
+#define HEIMDAL_MUTEX mutex_t
+#define HEIMDAL_MUTEX_INITIALIZER MUTEX_INITIALIZER
+#define HEIMDAL_MUTEX_init(m) mutex_init(m, NULL)
+#define HEIMDAL_MUTEX_lock(m) mutex_lock(m)
+#define HEIMDAL_MUTEX_unlock(m) mutex_unlock(m)
+#define HEIMDAL_MUTEX_destroy(m) mutex_destroy(m)
+
+#define HEIMDAL_RWLOCK rwlock_t
+#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER
+#define        HEIMDAL_RWLOCK_init(l) rwlock_init(l, NULL)     
+#define        HEIMDAL_RWLOCK_rdlock(l) rwlock_rdlock(l)       
+#define        HEIMDAL_RWLOCK_wrlock(l) rwlock_wrlock(l)       
+#define        HEIMDAL_RWLOCK_tryrdlock(l) rwlock_tryrdlock(l) 
+#define        HEIMDAL_RWLOCK_trywrlock(l) rwlock_trywrlock(l) 
+#define        HEIMDAL_RWLOCK_unlock(l) rwlock_unlock(l)       
+#define        HEIMDAL_RWLOCK_destroy(l) rwlock_destroy(l)     
+
+#define HEIMDAL_thread_key thread_key_t
+#define HEIMDAL_key_create(k,d,r) do { r = thr_keycreate(k,d); } while(0)
+#define HEIMDAL_setspecific(k,s,r) do { r = thr_setspecific(k,s); } while(0)
+#define HEIMDAL_getspecific(k) thr_getspecific(k)
+#define HEIMDAL_key_delete(k) thr_keydelete(k)
+
+#elif defined(ENABLE_PTHREAD_SUPPORT) && (!defined(__NetBSD__) || __NetBSD_Version__ >= 299001200)
+
+#include <pthread.h>
+
+#define HEIMDAL_MUTEX pthread_mutex_t
+#define HEIMDAL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define HEIMDAL_MUTEX_init(m) pthread_mutex_init(m, NULL)
+#define HEIMDAL_MUTEX_lock(m) pthread_mutex_lock(m)
+#define HEIMDAL_MUTEX_unlock(m) pthread_mutex_unlock(m)
+#define HEIMDAL_MUTEX_destroy(m) pthread_mutex_destroy(m)
+
+#define HEIMDAL_RWLOCK rwlock_t
+#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER
+#define        HEIMDAL_RWLOCK_init(l) pthread_rwlock_init(l, NULL)     
+#define        HEIMDAL_RWLOCK_rdlock(l) pthread_rwlock_rdlock(l)       
+#define        HEIMDAL_RWLOCK_wrlock(l) pthread_rwlock_wrlock(l)       
+#define        HEIMDAL_RWLOCK_tryrdlock(l) pthread_rwlock_tryrdlock(l) 
+#define        HEIMDAL_RWLOCK_trywrlock(l) pthread_rwlock_trywrlock(l) 
+#define        HEIMDAL_RWLOCK_unlock(l) pthread_rwlock_unlock(l)       
+#define        HEIMDAL_RWLOCK_destroy(l) pthread_rwlock_destroy(l)     
+
+#define HEIMDAL_thread_key pthread_key_t
+#define HEIMDAL_key_create(k,d,r) do { r = pthread_key_create(k,d); } while(0)
+#define HEIMDAL_setspecific(k,s,r) do { r = pthread_setspecific(k,s); } while(0)
+#define HEIMDAL_getspecific(k) pthread_getspecific(k)
+#define HEIMDAL_key_delete(k) pthread_key_delete(k)
+
+#elif defined(HEIMDAL_DEBUG_THREADS)
+
+/* no threads support, just do consistency checks */
+#include <stdlib.h>
+
+#define HEIMDAL_MUTEX int
+#define HEIMDAL_MUTEX_INITIALIZER 0
+#define HEIMDAL_MUTEX_init(m)  do { (*(m)) = 0; } while(0)
+#define HEIMDAL_MUTEX_lock(m)  do { if ((*(m))++ != 0) abort(); } while(0)
+#define HEIMDAL_MUTEX_unlock(m) do { if ((*(m))-- != 1) abort(); } while(0)
+#define HEIMDAL_MUTEX_destroy(m) do {if ((*(m)) != 0) abort(); } while(0)
+
+#define HEIMDAL_RWLOCK rwlock_t int
+#define HEIMDAL_RWLOCK_INITIALIZER 0
+#define        HEIMDAL_RWLOCK_init(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_rdlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_wrlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_trywrlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_unlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_destroy(l) do { } while(0)
+
+#define HEIMDAL_internal_thread_key 1
+
+#else /* no thread support, no debug case */
+
+#define HEIMDAL_MUTEX int
+#define HEIMDAL_MUTEX_INITIALIZER 0
+#define HEIMDAL_MUTEX_init(m)  do { (void)(m); } while(0)
+#define HEIMDAL_MUTEX_lock(m)  do { (void)(m); } while(0)
+#define HEIMDAL_MUTEX_unlock(m) do { (void)(m); } while(0)
+#define HEIMDAL_MUTEX_destroy(m) do { (void)(m); } while(0)
+
+#define HEIMDAL_RWLOCK rwlock_t int
+#define HEIMDAL_RWLOCK_INITIALIZER 0
+#define        HEIMDAL_RWLOCK_init(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_rdlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_wrlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_trywrlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_unlock(l) do { } while(0)
+#define        HEIMDAL_RWLOCK_destroy(l) do { } while(0)
+
+#define HEIMDAL_internal_thread_key 1
+
+#endif /* no thread support */
+
+#ifdef HEIMDAL_internal_thread_key
+
+typedef struct heim_thread_key {
+    void *value;
+    void (*destructor)(void *);
+} heim_thread_key;
+
+#define HEIMDAL_thread_key heim_thread_key
+#define HEIMDAL_key_create(k,d,r) \
+       do { (k)->value = NULL; (k)->destructor = (d); r = 0; } while(0)
+#define HEIMDAL_setspecific(k,s,r) do { (k).value = s ; r = 0; } while(0)
+#define HEIMDAL_getspecific(k) ((k).value)
+#define HEIMDAL_key_delete(k) do { (*(k).destructor)((k).value); } while(0)
+
+#undef HEIMDAL_internal_thread_key
+#endif /* HEIMDAL_internal_thread_key */
+
+#endif /* HEIM_THREADS_H */
diff --git a/src/kerberosV/src/lib/krb5/init_creds.c b/src/kerberosV/src/lib/krb5/init_creds.c
new file mode 100644 (file)
index 0000000..0038c90
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: init_creds.c,v 1.20.4.2 2005/10/13 03:11:06 lha Exp $");
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
+{
+    memset (opt, 0, sizeof(*opt));
+    opt->flags = 0;
+    opt->opt_private = NULL;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_alloc(krb5_context context, 
+                             krb5_get_init_creds_opt **opt)
+{
+    krb5_get_init_creds_opt *o;
+    
+    *opt = NULL;
+    o = calloc(1, sizeof(*o));
+    if (o == NULL) {
+       krb5_set_error_string(context, "out of memory");
+       return ENOMEM;
+    }
+    krb5_get_init_creds_opt_init(o);
+    o->opt_private = calloc(1, sizeof(*o->opt_private));
+    if (o->opt_private == NULL) {
+       krb5_set_error_string(context, "out of memory");
+       free(o);
+       return ENOMEM;
+    }
+    o->opt_private->refcount = 1;
+    *opt = o;
+    return 0;
+}
+
+krb5_error_code
+_krb5_get_init_creds_opt_copy(krb5_context context, 
+                             const krb5_get_init_creds_opt *in,
+                             krb5_get_init_creds_opt **out)
+{
+    krb5_get_init_creds_opt *opt;
+
+    *out = NULL;
+    opt = malloc(sizeof(*opt));
+    if (opt == NULL) {
+       krb5_set_error_string(context, "out of memory");
+       return ENOMEM;
+    }
+    if (in)
+       *opt = *in;
+    if(opt->opt_private == NULL) {
+       opt->opt_private = calloc(1, sizeof(*opt->opt_private));
+       if (opt->opt_private == NULL) {
+           krb5_set_error_string(context, "out of memory");
+           free(opt);
+           return ENOMEM;
+       }
+       opt->opt_private->refcount = 1;
+    } else
+       opt->opt_private->refcount++;
+    *out = opt;
+    return 0;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
+{
+    if (opt->opt_private == NULL)
+       return;
+    if (opt->opt_private->refcount < 1) /* abort ? */
+       return;
+    if (--opt->opt_private->refcount == 0) {
+       _krb5_get_init_creds_opt_free_pkinit(opt);
+       free(opt->opt_private);
+    }
+    memset(opt, 0, sizeof(*opt));
+    free(opt);
+}
+
+static int
+get_config_time (krb5_context context,
+                const char *realm,
+                const char *name,
+                int def)
+{
+    int ret;
+
+    ret = krb5_config_get_time (context, NULL,
+                               "realms",
+                               realm,
+                               name,
+                               NULL);
+    if (ret >= 0)
+       return ret;
+    ret = krb5_config_get_time (context, NULL,
+                               "libdefaults",
+                               name,
+                               NULL);
+    if (ret >= 0)
+       return ret;
+    return def;
+}
+
+static krb5_boolean
+get_config_bool (krb5_context context,
+                const char *realm,
+                const char *name)
+{
+    return krb5_config_get_bool (context,
+                                NULL,
+                                "realms",
+                                realm,
+                                name,
+                                NULL)
+       || krb5_config_get_bool (context,
+                                NULL,
+                                "libdefaults",
+                                name,
+                                NULL);
+}
+
+/*
+ * set all the values in `opt' to the appropriate values for
+ * application `appname' (default to __progname if NULL), and realm
+ * `realm'.  First looks in [appdefaults] but falls back to
+ * [realms] or [libdefaults] for some of the values.
+ */
+
+static krb5_addresses no_addrs = {0, NULL};
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_default_flags(krb5_context context,
+                                         const char *appname,
+                                         krb5_const_realm realm,
+                                         krb5_get_init_creds_opt *opt)
+{
+    krb5_boolean b;
+    time_t t;
+
+    b = get_config_bool (context, realm, "forwardable");
+    krb5_appdefault_boolean(context, appname, (krb5_realm)realm, "forwardable", b, &b);
+    krb5_get_init_creds_opt_set_forwardable(opt, b);
+
+    b = get_config_bool (context, realm, "proxiable");
+    krb5_appdefault_boolean(context, appname, (krb5_realm)realm, "proxiable", b, &b);
+    krb5_get_init_creds_opt_set_proxiable (opt, b);
+
+    krb5_appdefault_time(context, appname, (krb5_realm)realm, "ticket_lifetime", 0, &t);
+    if (t == 0)
+       t = get_config_time (context, realm, "ticket_lifetime", 0);
+    if(t != 0)
+       krb5_get_init_creds_opt_set_tkt_life(opt, t);
+
+    krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t);
+    if (t == 0)
+       t = get_config_time (context, realm, "renew_lifetime", 0);
+    if(t != 0)
+       krb5_get_init_creds_opt_set_renew_life(opt, t);
+
+    krb5_appdefault_boolean(context, appname, (krb5_realm)realm, "no-addresses", FALSE, &b);
+    if (b)
+       krb5_get_init_creds_opt_set_address_list (opt, &no_addrs);
+
+#if 0
+    krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b);
+    krb5_get_init_creds_opt_set_anonymous (opt, b);
+
+    krb5_get_init_creds_opt_set_etype_list(opt, enctype,
+                                          etype_str.num_strings);
+
+    krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt,
+                                    krb5_data *salt);
+
+    krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
+                                            krb5_preauthtype *preauth_list,
+                                            int preauth_list_length);
+#endif
+}
+
+
+void KRB5_LIB_FUNCTION
+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_LIB_FUNCTION
+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_LIB_FUNCTION
+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_LIB_FUNCTION
+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_LIB_FUNCTION
+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_LIB_FUNCTION
+krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt,
+                                        krb5_addresses *addresses)
+{
+    opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
+    opt->address_list = addresses;
+}
+
+void KRB5_LIB_FUNCTION
+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_length = preauth_list_length;
+    opt->preauth_list = preauth_list;
+}
+
+void KRB5_LIB_FUNCTION
+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_LIB_FUNCTION
+krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt,
+                                     int anonymous)
+{
+    opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS;
+    opt->anonymous = anonymous;
+}
+
+static krb5_error_code
+require_ext_opt(krb5_context context,
+               krb5_get_init_creds_opt *opt,
+               const char *type)
+{
+    if (opt->opt_private == NULL) {
+       krb5_set_error_string(context, "%s on non extendable opt", type);
+       return EINVAL;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_pa_password(krb5_context context,
+                                       krb5_get_init_creds_opt *opt,
+                                       const char *password,
+                                       krb5_s2k_proc key_proc)
+{
+    krb5_error_code ret;
+    ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password");
+    if (ret)
+       return ret;
+    opt->opt_private->password = password;
+    opt->opt_private->key_proc = key_proc;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_pac_request(krb5_context context,
+                                       krb5_get_init_creds_opt *opt,
+                                       krb5_boolean req_pac)
+{
+    krb5_error_code ret;
+    ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req");
+    if (ret)
+       return ret;
+    opt->opt_private->req_pac = req_pac ?
+       KRB5_PA_PAC_REQ_TRUE :
+       KRB5_PA_PAC_REQ_FALSE;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/init_creds_pw.c b/src/kerberosV/src/lib/krb5/init_creds_pw.c
new file mode 100644 (file)
index 0000000..5ed4b1f
--- /dev/null
@@ -0,0 +1,1555 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: init_creds_pw.c,v 1.85.2.1 2005/10/12 12:51:48 lha Exp $");
+
+typedef struct krb5_get_init_creds_ctx {
+    krb5_kdc_flags flags;
+    krb5_creds cred;
+    krb5_addresses *addrs;
+    krb5_enctype *etypes;
+    krb5_preauthtype *pre_auth_types;
+    const char *in_tkt_service;
+    unsigned nonce;
+    unsigned pk_nonce;
+
+    AS_REQ as_req;
+    int pa_counter;
+
+    const char *password;
+    krb5_s2k_proc key_proc;
+
+    krb5_get_init_creds_req_pac req_pac;
+
+    krb5_pk_init_ctx pk_init_ctx;
+} krb5_get_init_creds_ctx;
+
+static krb5_error_code
+default_s2k_func(krb5_context context, krb5_enctype type, 
+                krb5_const_pointer keyseed,
+                krb5_salt salt, krb5_data *s2kparms,
+                krb5_keyblock **key)
+{
+    krb5_error_code ret;
+    krb5_data password;
+    krb5_data opaque;
+
+    password.data = (void *)keyseed;
+    password.length = strlen(keyseed);
+    if (s2kparms)
+       opaque = *s2kparms;
+    else
+       krb5_data_zero(&opaque);
+       
+    *key = malloc(sizeof(**key));
+    if (*key == NULL)
+       return ENOMEM;
+    ret = krb5_string_to_key_data_salt_opaque(context, type, password,
+                                             salt, opaque, *key);
+    if (ret)
+       free(*key);
+    return ret;
+}
+
+static void
+free_init_creds_ctx(krb5_context context, krb5_get_init_creds_ctx *ctx)
+{
+    if (ctx->etypes)
+       free(ctx->etypes);
+    if (ctx->pre_auth_types)
+       free (ctx->pre_auth_types);
+    free_AS_REQ(&ctx->as_req);
+    memset(&ctx->as_req, 0, sizeof(ctx->as_req));
+}
+
+static int
+get_config_time (krb5_context context,
+                const char *realm,
+                const char *name,
+                int def)
+{
+    int ret;
+
+    ret = krb5_config_get_time (context, NULL,
+                               "realms",
+                               realm,
+                               name,
+                               NULL);
+    if (ret >= 0)
+       return ret;
+    ret = krb5_config_get_time (context, NULL,
+                               "libdefaults",
+                               name,
+                               NULL);
+    if (ret >= 0)
+       return ret;
+    return def;
+}
+
+static krb5_error_code
+init_cred (krb5_context context,
+          krb5_creds *cred,
+          krb5_principal client,
+          krb5_deltat start_time,
+          const char *in_tkt_service,
+          krb5_get_init_creds_opt *options)
+{
+    krb5_error_code ret;
+    krb5_const_realm client_realm;
+    int tmp;
+    krb5_timestamp now;
+
+    krb5_timeofday (context, &now);
+
+    memset (cred, 0, sizeof(*cred));
+    
+    if (client)
+       krb5_copy_principal(context, client, &cred->client);
+    else {
+       ret = krb5_get_default_principal (context,
+                                         &cred->client);
+       if (ret)
+           goto out;
+    }
+
+    client_realm = krb5_principal_get_realm (context, cred->client);
+
+    if (start_time)
+       cred->times.starttime  = now + start_time;
+
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE)
+       tmp = options->tkt_life;
+    else
+       tmp = 10 * 60 * 60;
+    cred->times.endtime = now + tmp;
+
+    if ((options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE) &&
+       options->renew_life > 0) {
+       cred->times.renew_till = now + options->renew_life;
+    }
+
+    if (in_tkt_service) {
+       krb5_realm server_realm;
+
+       ret = krb5_parse_name (context, in_tkt_service, &cred->server);
+       if (ret)
+           goto out;
+       server_realm = strdup (client_realm);
+       free (*krb5_princ_realm(context, cred->server));
+       krb5_princ_set_realm (context, cred->server, &server_realm);
+    } else {
+       ret = krb5_make_principal(context, &cred->server, 
+                                 client_realm, KRB5_TGS_NAME, client_realm,
+                                 NULL);
+       if (ret)
+           goto out;
+    }
+    return 0;
+
+out:
+    krb5_free_cred_contents (context, cred);
+    return ret;
+}
+
+/*
+ * Print a message (str) to the user about the expiration in `lr'
+ */
+
+static void
+report_expiration (krb5_context context,
+                  krb5_prompter_fct prompter,
+                  krb5_data *data,
+                  const char *str,
+                  time_t time)
+{
+    char *p;
+           
+    asprintf (&p, "%s%s", str, ctime(&time));
+    (*prompter) (context, data, NULL, p, 0, NULL);
+    free (p);
+}
+
+/*
+ * Parse the last_req data and show it to the user if it's interesting
+ */
+
+static void
+print_expire (krb5_context context,
+             krb5_const_realm realm,
+             krb5_kdc_rep *rep,
+             krb5_prompter_fct prompter,
+             krb5_data *data)
+{
+    int i;
+    LastReq *lr = &rep->enc_part.last_req;
+    krb5_timestamp sec;
+    time_t t;
+    krb5_boolean reported = FALSE;
+
+    krb5_timeofday (context, &sec);
+
+    t = sec + get_config_time (context,
+                              realm,
+                              "warn_pwexpire",
+                              7 * 24 * 60 * 60);
+
+    for (i = 0; i < lr->len; ++i) {
+       if (lr->val[i].lr_value <= t) {
+           switch (abs(lr->val[i].lr_type)) {
+           case LR_PW_EXPTIME :
+               report_expiration(context, prompter, data,
+                                 "Your password will expire at ",
+                                 lr->val[i].lr_value);
+               reported = TRUE;
+               break;
+           case LR_ACCT_EXPTIME :
+               report_expiration(context, prompter, data,
+                                 "Your account will expire at ",
+                                 lr->val[i].lr_value);
+               reported = TRUE;
+               break;
+           }
+       }
+    }
+
+    if (!reported
+       && rep->enc_part.key_expiration
+       && *rep->enc_part.key_expiration <= t) {
+       report_expiration(context, prompter, data,
+                         "Your password/account will expire at ",
+                         *rep->enc_part.key_expiration);
+    }
+}
+
+static krb5_error_code
+get_init_creds_common(krb5_context context,
+                     krb5_creds *creds,
+                     krb5_principal client,
+                     krb5_deltat start_time,
+                     const char *in_tkt_service,
+                     krb5_get_init_creds_opt *options,
+                     krb5_get_init_creds_ctx *ctx)
+{
+    krb5_get_init_creds_opt default_opt;
+    krb5_error_code ret;
+    krb5_enctype *etypes;
+    krb5_preauthtype *pre_auth_types;
+
+    memset(ctx, 0, sizeof(*ctx));
+
+    if (options == NULL) {
+       krb5_get_init_creds_opt_init (&default_opt);
+       options = &default_opt;
+    }
+
+    if (options->opt_private) {
+       ctx->password = options->opt_private->password;
+       ctx->key_proc = options->opt_private->key_proc;
+       ctx->req_pac = options->opt_private->req_pac;
+       ctx->pk_init_ctx = options->opt_private->pk_init_ctx;
+    } else
+       ctx->req_pac = KRB5_PA_PAC_DONT_CARE;
+
+    if (ctx->key_proc == NULL)
+       ctx->key_proc = default_s2k_func;
+
+    ctx->pre_auth_types = NULL;
+    ctx->flags.i = 0;
+    ctx->addrs = NULL;
+    ctx->etypes = NULL;
+    ctx->pre_auth_types = NULL;
+    ctx->in_tkt_service = in_tkt_service;
+
+    ret = init_cred (context, &ctx->cred, client, start_time,
+                    in_tkt_service, options);
+    if (ret)
+       return ret;
+
+    ctx->flags.i = 0;
+
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
+       ctx->flags.b.forwardable = options->forwardable;
+
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE)
+       ctx->flags.b.proxiable = options->proxiable;
+
+    if (start_time)
+       ctx->flags.b.postdated = 1;
+    if (ctx->cred.times.renew_till)
+       ctx->flags.b.renewable = 1;
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST)
+       ctx->addrs = options->address_list;
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) {
+       etypes = malloc((options->etype_list_length + 1)
+                       * sizeof(krb5_enctype));
+       if (etypes == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       memcpy (etypes, options->etype_list,
+               options->etype_list_length * sizeof(krb5_enctype));
+       etypes[options->etype_list_length] = ETYPE_NULL;
+       ctx->etypes = etypes;
+    }
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) {
+       pre_auth_types = malloc((options->preauth_list_length + 1)
+                               * sizeof(krb5_preauthtype));
+       if (pre_auth_types == NULL) {
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       memcpy (pre_auth_types, options->preauth_list,
+               options->preauth_list_length * sizeof(krb5_preauthtype));
+       pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE;
+       ctx->pre_auth_types = pre_auth_types;
+    }
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)
+       ;                       /* XXX */
+    if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
+       ctx->flags.b.request_anonymous = options->anonymous;
+    return 0;
+}
+
+static krb5_error_code
+change_password (krb5_context context,
+                krb5_principal client,
+                const char *password,
+                char *newpw,
+                size_t newpw_sz,
+                krb5_prompter_fct prompter,
+                void *data,
+                krb5_get_init_creds_opt *old_options)
+{
+    krb5_prompt prompts[2];
+    krb5_error_code ret;
+    krb5_creds cpw_cred;
+    char buf1[BUFSIZ], buf2[BUFSIZ];
+    krb5_data password_data[2];
+    int result_code;
+    krb5_data result_code_string;
+    krb5_data result_string;
+    char *p;
+    krb5_get_init_creds_opt options;
+
+    memset (&cpw_cred, 0, sizeof(cpw_cred));
+
+    krb5_get_init_creds_opt_init (&options);
+    krb5_get_init_creds_opt_set_tkt_life (&options, 60);
+    krb5_get_init_creds_opt_set_forwardable (&options, FALSE);
+    krb5_get_init_creds_opt_set_proxiable (&options, FALSE);
+    if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)
+       krb5_get_init_creds_opt_set_preauth_list (&options,
+                                                 old_options->preauth_list,
+                                                 old_options->preauth_list_length);                                          
+
+    krb5_data_zero (&result_code_string);
+    krb5_data_zero (&result_string);
+
+    ret = krb5_get_init_creds_password (context,
+                                       &cpw_cred,
+                                       client,
+                                       password,
+                                       prompter,
+                                       data,
+                                       0,
+                                       "kadmin/changepw",
+                                       &options);
+    if (ret)
+       goto out;
+
+    for(;;) {
+       password_data[0].data   = buf1;
+       password_data[0].length = sizeof(buf1);
+
+       prompts[0].hidden = 1;
+       prompts[0].prompt = "New password: ";
+       prompts[0].reply  = &password_data[0];
+       prompts[0].type   = KRB5_PROMPT_TYPE_NEW_PASSWORD;
+
+       password_data[1].data   = buf2;
+       password_data[1].length = sizeof(buf2);
+
+       prompts[1].hidden = 1;
+       prompts[1].prompt = "Repeat new password: ";
+       prompts[1].reply  = &password_data[1];
+       prompts[1].type   = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;
+
+       ret = (*prompter) (context, data, NULL, "Changing password",
+                          2, prompts);
+       if (ret) {
+           memset (buf1, 0, sizeof(buf1));
+           memset (buf2, 0, sizeof(buf2));
+           goto out;
+       }
+
+       if (strcmp (buf1, buf2) == 0)
+           break;
+       memset (buf1, 0, sizeof(buf1));
+       memset (buf2, 0, sizeof(buf2));
+    }
+    
+    ret = krb5_change_password (context,
+                               &cpw_cred,
+                               buf1,
+                               &result_code,
+                               &result_code_string,
+                               &result_string);
+    if (ret)
+       goto out;
+    asprintf (&p, "%s: %.*s\n",
+             result_code ? "Error" : "Success",
+             (int)result_string.length,
+             result_string.length > 0 ? (char*)result_string.data : "");
+
+    ret = (*prompter) (context, data, NULL, p, 0, NULL);
+    free (p);
+    if (result_code == 0) {
+       strlcpy (newpw, buf1, newpw_sz);
+       ret = 0;
+    } else {
+       krb5_set_error_string (context, "failed changing password");
+       ret = ENOTTY;
+    }
+
+out:
+    memset (buf1, 0, sizeof(buf1));
+    memset (buf2, 0, sizeof(buf2));
+    krb5_data_free (&result_string);
+    krb5_data_free (&result_code_string);
+    krb5_free_cred_contents (context, &cpw_cred);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keyblock_key_proc (krb5_context context,
+                       krb5_keytype type,
+                       krb5_data *salt,
+                       krb5_const_pointer keyseed,
+                       krb5_keyblock **key)
+{
+    return krb5_copy_keyblock (context, keyseed, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_keytab(krb5_context context,
+                          krb5_creds *creds,
+                          krb5_principal client,
+                          krb5_keytab keytab,
+                          krb5_deltat start_time,
+                          const char *in_tkt_service,
+                          krb5_get_init_creds_opt *options)
+{
+    krb5_get_init_creds_ctx ctx;
+    krb5_error_code ret;
+    krb5_keytab_key_proc_args *a;
+    
+    ret = get_init_creds_common(context, creds, client, start_time,
+                               in_tkt_service, options, &ctx);
+    if (ret)
+       goto out;
+
+    a = malloc (sizeof(*a));
+    if (a == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    a->principal = ctx.cred.client;
+    a->keytab    = keytab;
+
+    ret = krb5_get_in_cred (context,
+                           ctx.flags.i,
+                           ctx.addrs,
+                           ctx.etypes,
+                           ctx.pre_auth_types,
+                           NULL,
+                           krb5_keytab_key_proc,
+                           a,
+                           NULL,
+                           NULL,
+                           &ctx.cred,
+                           NULL);
+    free (a);
+
+    if (ret == 0 && creds)
+       *creds = ctx.cred;
+    else
+       krb5_free_cred_contents (context, &ctx.cred);
+
+ out:
+    free_init_creds_ctx(context, &ctx);
+    return ret;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+init_creds_init_as_req (krb5_context context,
+                       krb5_kdc_flags opts,
+                       const krb5_creds *creds,
+                       const krb5_addresses *addrs,
+                       const krb5_enctype *etypes,
+                       AS_REQ *a)
+{
+    krb5_error_code ret;
+
+    memset(a, 0, sizeof(*a));
+
+    a->pvno = 5;
+    a->msg_type = krb_as_req;
+    a->req_body.kdc_options = opts.b;
+    a->req_body.cname = malloc(sizeof(*a->req_body.cname));
+    if (a->req_body.cname == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+    a->req_body.sname = malloc(sizeof(*a->req_body.sname));
+    if (a->req_body.sname == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto fail;
+    }
+    if (creds->client) {
+       ret = _krb5_principal2principalname (a->req_body.cname, creds->client);
+       if (ret)
+           goto fail;
+       ret = copy_Realm(&creds->client->realm, &a->req_body.realm);
+       if (ret)
+           goto fail;
+    } else {
+       krb5_realm realm;
+
+       a->req_body.cname = NULL;
+       ret = krb5_get_default_realm(context, &realm);
+       if (ret)
+           goto fail;
+       ret = copy_Realm(&realm, &a->req_body.realm);
+       free(realm);
+    }
+    ret = _krb5_principal2principalname (a->req_body.sname, creds->server);
+    if (ret)
+       goto fail;
+
+    if(creds->times.starttime) {
+       a->req_body.from = malloc(sizeof(*a->req_body.from));
+       if (a->req_body.from == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       *a->req_body.from = creds->times.starttime;
+    }
+    if(creds->times.endtime){
+       ALLOC(a->req_body.till, 1);
+       *a->req_body.till = creds->times.endtime;
+    }
+    if(creds->times.renew_till){
+       a->req_body.rtime = malloc(sizeof(*a->req_body.rtime));
+       if (a->req_body.rtime == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+       *a->req_body.rtime = creds->times.renew_till;
+    }
+    a->req_body.nonce = 0;
+    ret = krb5_init_etype (context,
+                          &a->req_body.etype.len,
+                          &a->req_body.etype.val,
+                          etypes);
+    if (ret)
+       goto fail;
+
+    /*
+     * This means no addresses
+     */
+
+    if (addrs && addrs->len == 0) {
+       a->req_body.addresses = NULL;
+    } else {
+       a->req_body.addresses = malloc(sizeof(*a->req_body.addresses));
+       if (a->req_body.addresses == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "malloc: out of memory");
+           goto fail;
+       }
+
+       if (addrs)
+           ret = krb5_copy_addresses(context, addrs, a->req_body.addresses);
+       else {
+           ret = krb5_get_all_client_addrs (context, a->req_body.addresses);
+           if(ret == 0 && a->req_body.addresses->len == 0) {
+               free(a->req_body.addresses);
+               a->req_body.addresses = NULL;
+           }
+       }
+       if (ret)
+           goto fail;
+    }
+
+    a->req_body.enc_authorization_data = NULL;
+    a->req_body.additional_tickets = NULL;
+
+    a->padata = NULL;
+
+    return 0;
+ fail:
+    free_AS_REQ(a);
+    memset(a, 0, sizeof(*a));
+    return ret;
+}
+
+struct pa_info_data {
+    krb5_enctype etype;
+    krb5_salt salt;
+    krb5_data *s2kparams;
+};
+
+static void
+free_paid(krb5_context context, struct pa_info_data *ppaid)
+{
+    krb5_free_salt(context, ppaid->salt);
+    if (ppaid->s2kparams)
+       krb5_data_free(ppaid->s2kparams);
+}
+
+
+static krb5_error_code
+set_paid(struct pa_info_data *paid, krb5_context context,
+        krb5_enctype etype,
+        krb5_salttype salttype, void *salt_string, size_t salt_len,
+        krb5_data *s2kparams)
+{
+    paid->etype = etype;
+    paid->salt.salttype = salttype;
+    paid->salt.saltvalue.data = malloc(salt_len + 1);
+    if (paid->salt.saltvalue.data == NULL) {
+       krb5_clear_error_string(context);
+       return ENOMEM;
+    }
+    memcpy(paid->salt.saltvalue.data, salt_string, salt_len);
+    ((char *)paid->salt.saltvalue.data)[salt_len] = '\0';
+    paid->salt.saltvalue.length = salt_len;
+    if (s2kparams) {
+       krb5_error_code ret;
+
+       ret = krb5_copy_data(context, s2kparams, &paid->s2kparams);
+       if (ret) {
+           krb5_clear_error_string(context);
+           krb5_free_salt(context, paid->salt);
+           return ret;
+       }
+    } else
+       paid->s2kparams = NULL;
+
+    return 0;
+}
+
+static struct pa_info_data *
+pa_etype_info2(krb5_context context,
+              const krb5_principal client, 
+              const AS_REQ *asreq,
+              struct pa_info_data *paid, 
+              heim_octet_string *data)
+{
+    krb5_error_code ret;
+    ETYPE_INFO2 e;
+    size_t sz;
+    int i, j;
+
+    memset(&e, 0, sizeof(e));
+    ret = decode_ETYPE_INFO2(data->data, data->length, &e, &sz);
+    if (ret)
+       goto out;
+    if (e.len == 0)
+       goto out;
+    for (j = 0; j < asreq->req_body.etype.len; j++) {
+       for (i = 0; i < e.len; i++) {
+           if (asreq->req_body.etype.val[j] == e.val[i].etype) {
+               krb5_salt salt;
+               if (e.val[i].salt == NULL)
+                   ret = krb5_get_pw_salt(context, client, &salt);
+               else {
+                   salt.saltvalue.data = *e.val[i].salt;
+                   salt.saltvalue.length = strlen(*e.val[i].salt);
+                   ret = 0;
+               }
+               if (ret == 0)
+                   ret = set_paid(paid, context, e.val[i].etype,
+                                  KRB5_PW_SALT,
+                                  salt.saltvalue.data, 
+                                  salt.saltvalue.length,
+                                  e.val[i].s2kparams);
+               if (e.val[i].salt == NULL)
+                   krb5_free_salt(context, salt);
+               if (ret == 0) {
+                       free_ETYPE_INFO2(&e);
+                       return paid;
+               }
+           }
+       }
+    }
+ out:
+    free_ETYPE_INFO2(&e);
+    return NULL;
+}
+
+static struct pa_info_data *
+pa_etype_info(krb5_context context,
+             const krb5_principal client, 
+             const AS_REQ *asreq,
+             struct pa_info_data *paid,
+             heim_octet_string *data)
+{
+    krb5_error_code ret;
+    ETYPE_INFO e;
+    size_t sz;
+    int i, j;
+
+    memset(&e, 0, sizeof(e));
+    ret = decode_ETYPE_INFO(data->data, data->length, &e, &sz);
+    if (ret)
+       goto out;
+    if (e.len == 0)
+       goto out;
+    for (j = 0; j < asreq->req_body.etype.len; j++) {
+       for (i = 0; i < e.len; i++) {
+           if (asreq->req_body.etype.val[j] == e.val[i].etype) {
+               krb5_salt salt;
+               salt.salttype = KRB5_PW_SALT;
+               if (e.val[i].salt == NULL)
+                   ret = krb5_get_pw_salt(context, client, &salt);
+               else {
+                   salt.saltvalue = *e.val[i].salt;
+                   ret = 0;
+               }
+               if (e.val[i].salttype)
+                   salt.salttype = *e.val[i].salttype;
+               if (ret == 0) {
+                   ret = set_paid(paid, context, e.val[i].etype,
+                                  salt.salttype,
+                                  salt.saltvalue.data, 
+                                  salt.saltvalue.length,
+                                  NULL);
+                   if (e.val[i].salt == NULL)
+                       krb5_free_salt(context, salt);
+               }
+               if (ret == 0) {
+                   free_ETYPE_INFO(&e);
+                   return paid;
+               }
+           }
+       }
+    }
+ out:
+    free_ETYPE_INFO(&e);
+    return NULL;
+}
+
+static struct pa_info_data *
+pa_pw_or_afs3_salt(krb5_context context,
+                  const krb5_principal client, 
+                  const AS_REQ *asreq,
+                  struct pa_info_data *paid,
+                  heim_octet_string *data)
+{
+    krb5_error_code ret;
+    if (paid->etype == ENCTYPE_NULL)
+       return NULL;
+    ret = set_paid(paid, context, 
+                  paid->etype,
+                  paid->salt.salttype,
+                  data->data, 
+                  data->length,
+                  NULL);
+    if (ret)
+       return NULL;
+    return paid;
+}
+
+
+struct pa_info {
+    krb5_preauthtype type;
+    struct pa_info_data *(*salt_info)(krb5_context,
+                                     const krb5_principal, 
+                                     const AS_REQ *,
+                                     struct pa_info_data *, 
+                                     heim_octet_string *);
+};
+
+static struct pa_info pa_prefs[] = {
+    { KRB5_PADATA_ETYPE_INFO2, pa_etype_info2 },
+    { KRB5_PADATA_ETYPE_INFO, pa_etype_info },
+    { KRB5_PADATA_PW_SALT, pa_pw_or_afs3_salt },
+    { KRB5_PADATA_AFS3_SALT, pa_pw_or_afs3_salt }
+};
+    
+static PA_DATA *
+find_pa_data(const METHOD_DATA *md, int type)
+{
+    int i;
+    for (i = 0; i < md->len; i++)
+       if (md->val[i].padata_type == type)
+           return &md->val[i];
+    return NULL;
+}
+
+static struct pa_info_data *
+process_pa_info(krb5_context context, 
+               const krb5_principal client, 
+               const AS_REQ *asreq,
+               struct pa_info_data *paid,
+               METHOD_DATA *md)
+{
+    struct pa_info_data *p = NULL;
+    int i;
+
+    for (i = 0; p == NULL && i < sizeof(pa_prefs)/sizeof(pa_prefs[0]); i++) {
+       PA_DATA *pa = find_pa_data(md, pa_prefs[i].type);
+       if (pa == NULL)
+           continue;
+       paid->salt.salttype = pa_prefs[i].type;
+       p = (*pa_prefs[i].salt_info)(context, client, asreq,
+                                    paid, &pa->padata_value);
+    }
+    return p;
+}
+
+static krb5_error_code
+make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md, 
+                     krb5_enctype etype, krb5_keyblock *key)
+{
+    PA_ENC_TS_ENC p;
+    unsigned char *buf;
+    size_t buf_size;
+    size_t len;
+    EncryptedData encdata;
+    krb5_error_code ret;
+    int32_t usec;
+    int usec2;
+    krb5_crypto crypto;
+    
+    krb5_us_timeofday (context, &p.patimestamp, &usec);
+    usec2         = usec;
+    p.pausec      = &usec2;
+
+    ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret);
+    if (ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret) {
+       free(buf);
+       return ret;
+    }
+    ret = krb5_encrypt_EncryptedData(context, 
+                                    crypto,
+                                    KRB5_KU_PA_ENC_TIMESTAMP,
+                                    buf,
+                                    len,
+                                    0,
+                                    &encdata);
+    free(buf);
+    krb5_crypto_destroy(context, crypto);
+    if (ret)
+       return ret;
+                   
+    ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
+    free_EncryptedData(&encdata);
+    if (ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_padata_add(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len);
+    if (ret)
+       free(buf);
+    return ret;
+}
+
+static krb5_error_code
+add_enc_ts_padata(krb5_context context,
+                 METHOD_DATA *md, 
+                 krb5_principal client,
+                 krb5_s2k_proc key_proc,
+                 krb5_const_pointer keyseed,
+                 krb5_enctype *enctypes,
+                 unsigned netypes,
+                 krb5_salt *salt,
+                 krb5_data *s2kparams)
+{
+    krb5_error_code ret;
+    krb5_salt salt2;
+    krb5_enctype *ep;
+    int i;
+    
+    if(salt == NULL) {
+       /* default to standard salt */
+       ret = krb5_get_pw_salt (context, client, &salt2);
+       salt = &salt2;
+    }
+    if (!enctypes) {
+       enctypes = context->etypes;
+       netypes = 0;
+       for (ep = enctypes; *ep != ETYPE_NULL; ep++)
+           netypes++;
+    }
+
+    for (i = 0; i < netypes; ++i) {
+       krb5_keyblock *key;
+
+       ret = (*key_proc)(context, enctypes[i], keyseed,
+                         *salt, s2kparams, &key);
+       if (ret)
+           continue;
+       ret = make_pa_enc_timestamp (context, md, enctypes[i], key);
+       krb5_free_keyblock (context, key);
+       if (ret)
+           return ret;
+    }
+    if(salt == &salt2)
+       krb5_free_salt(context, salt2);
+    return 0;
+}
+
+static krb5_error_code
+pa_data_to_md_ts_enc(krb5_context context,
+                    const AS_REQ *a,
+                    const krb5_principal client,
+                    krb5_get_init_creds_ctx *ctx,
+                    struct pa_info_data *ppaid,
+                    METHOD_DATA *md)
+{
+    if (ctx->key_proc == NULL || ctx->password == NULL)
+       return 0;
+
+    if (ppaid) {
+       add_enc_ts_padata(context, md, client, 
+                         ctx->key_proc, ctx->password,
+                         &ppaid->etype, 1,
+                         &ppaid->salt, ppaid->s2kparams);
+    } else {
+       krb5_salt salt;
+       
+       /* make a v5 salted pa-data */
+       add_enc_ts_padata(context, md, client, 
+                         ctx->key_proc, ctx->password,
+                         a->req_body.etype.val, a->req_body.etype.len, 
+                         NULL, NULL);
+       
+       /* make a v4 salted pa-data */
+       salt.salttype = KRB5_PW_SALT;
+       krb5_data_zero(&salt.saltvalue);
+       add_enc_ts_padata(context, md, client, 
+                         ctx->key_proc, ctx->password, 
+                         a->req_body.etype.val, a->req_body.etype.len, 
+                         &salt, NULL);
+    }
+    return 0;
+}
+
+static krb5_error_code
+pa_data_to_key_plain(krb5_context context,
+                    const krb5_principal client,
+                    krb5_get_init_creds_ctx *ctx,
+                    krb5_salt salt,
+                    krb5_data *s2kparams,
+                    krb5_enctype etype,
+                    krb5_keyblock **key)
+{
+    krb5_error_code ret;
+
+    ret = (*ctx->key_proc)(context, etype, ctx->password,
+                          salt, s2kparams, key);
+    return ret;
+}
+
+
+static krb5_error_code
+pa_data_to_md_pkinit(krb5_context context,
+                    const AS_REQ *a,
+                    const krb5_principal client,
+                    krb5_get_init_creds_ctx *ctx,
+                    METHOD_DATA *md)
+{
+    if (ctx->pk_init_ctx == NULL)
+       return 0;
+#ifdef PKINIT
+    return _krb5_pk_mk_padata(context,
+                             ctx->pk_init_ctx,
+                             &a->req_body,
+                             ctx->pk_nonce,
+                             md);
+#else
+    krb5_set_error_string(context, "no support for PKINIT compiled in");
+    return EINVAL;
+#endif
+}
+
+static krb5_error_code
+pa_data_add_pac_request(krb5_context context,
+                       krb5_get_init_creds_ctx *ctx,
+                       METHOD_DATA *md)
+{
+    size_t len, length;
+    krb5_error_code ret;
+    PA_PAC_REQUEST req;
+    void *buf;
+    
+    switch (ctx->req_pac) {
+    case KRB5_PA_PAC_DONT_CARE:
+       return 0; /* don't bother */
+    case KRB5_PA_PAC_REQ_TRUE:
+       req.include_pac = 1;
+       break;
+    case KRB5_PA_PAC_REQ_FALSE:
+       req.include_pac = 0;
+    }  
+
+    ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length, 
+                      &req, &len, ret);
+    if (ret)
+       return ret;
+    if(len != length)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len);
+    if (ret)
+       free(buf);
+
+    return 0;
+}
+
+/*
+ * Assumes caller always will free `out_md', even on error.
+ */
+
+static krb5_error_code
+process_pa_data_to_md(krb5_context context,
+                     const krb5_creds *creds,
+                     const AS_REQ *a,
+                     krb5_get_init_creds_ctx *ctx,
+                     METHOD_DATA *in_md,
+                     METHOD_DATA **out_md,
+                     krb5_prompter_fct prompter,
+                     void *prompter_data)
+{
+    krb5_error_code ret;
+
+    ALLOC(*out_md, 1);
+    if (*out_md == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    (*out_md)->len = 0;
+    (*out_md)->val = NULL;
+    
+    if (in_md->len != 0) {
+       struct pa_info_data paid, *ppaid;
+
+       memset(&paid, 0, sizeof(paid));
+
+       paid.etype = ENCTYPE_NULL;
+       ppaid = process_pa_info(context, creds->client, a, &paid, in_md);
+
+       pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
+       if (ppaid)
+           free_paid(context, ppaid);
+    }
+
+    pa_data_add_pac_request(context, ctx, *out_md);
+    ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md);
+    if (ret)
+       return ret;
+
+    if ((*out_md)->len == 0) {
+       free(*out_md);
+       *out_md = NULL;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+process_pa_data_to_key(krb5_context context,
+                      krb5_get_init_creds_ctx *ctx,
+                      krb5_creds *creds,
+                      AS_REQ *a,
+                      krb5_kdc_rep *rep,
+                      krb5_keyblock **key)
+{
+    struct pa_info_data paid, *ppaid = NULL;
+    krb5_error_code ret;
+    krb5_enctype etype;
+    PA_DATA *pa;
+    int index;
+
+    memset(&paid, 0, sizeof(paid));
+
+    etype = rep->kdc_rep.enc_part.etype;
+
+    if (rep->kdc_rep.padata) {
+       paid.etype = etype;
+       ppaid = process_pa_info(context, creds->client, a, &paid, 
+                               rep->kdc_rep.padata);
+    }
+    if (ppaid == NULL) {
+       ret = krb5_get_pw_salt (context, creds->client, &paid.salt);
+       if (ret)
+           return ret;
+       paid.etype = etype;
+       paid.s2kparams = NULL;
+    }
+
+    pa = NULL;
+    if (rep->kdc_rep.padata) {
+       index = 0;
+       pa = krb5_find_padata(rep->kdc_rep.padata->val, 
+                             rep->kdc_rep.padata->len,
+                             KRB5_PADATA_PK_AS_REP,
+                             &index);
+       if (pa == NULL) {
+           index = 0;
+           pa = krb5_find_padata(rep->kdc_rep.padata->val, 
+                                 rep->kdc_rep.padata->len,
+                                 KRB5_PADATA_PK_AS_REP_19,
+                                 &index);
+       }
+    }
+    if (pa && ctx->pk_init_ctx) {
+#ifdef PKINIT
+       ret = _krb5_pk_rd_pa_reply(context,
+                                  ctx->pk_init_ctx,
+                                  etype,
+                                  ctx->pk_nonce,
+                                  pa,
+                                  key);
+#else
+       krb5_set_error_string(context, "no support for PKINIT compiled in");
+       ret = EINVAL;
+#endif
+    } else if (ctx->password)
+       ret = pa_data_to_key_plain(context, creds->client, ctx, 
+                                  paid.salt, paid.s2kparams, etype, key);
+    else {
+       krb5_set_error_string(context, "No usable pa data type");
+       ret = EINVAL;
+    }
+
+    free_paid(context, &paid);
+    return ret;
+}
+
+static krb5_error_code
+init_cred_loop(krb5_context context,
+              const krb5_get_init_creds_opt *init_cred_opts,
+              const krb5_prompter_fct prompter,
+              void *prompter_data,
+              krb5_get_init_creds_ctx *ctx,
+              krb5_creds *creds,
+              krb5_kdc_rep *ret_as_reply)
+{
+    krb5_error_code ret;
+    krb5_kdc_rep rep;
+    METHOD_DATA md;
+    krb5_data resp;
+    size_t len;
+    size_t size;
+    int send_to_kdc_flags = 0;
+
+    memset(&md, 0, sizeof(md));
+    memset(&rep, 0, sizeof(rep));
+
+    if (ret_as_reply)
+       memset(ret_as_reply, 0, sizeof(*ret_as_reply));
+
+    ret = init_creds_init_as_req(context, ctx->flags, creds,
+                                ctx->addrs, ctx->etypes, &ctx->as_req);
+    if (ret)
+       return ret;
+
+    /* Set a new nonce. */
+    krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
+    ctx->nonce &= 0xffffffff;
+    /* XXX these just needs to be the same when using Windows PK-INIT */
+    ctx->pk_nonce = ctx->nonce;
+
+    /*
+     * Increase counter when we want other pre-auth types then
+     * KRB5_PA_ENC_TIMESTAMP.
+     */
+#define MAX_PA_COUNTER 3 
+
+    ctx->pa_counter = 0;
+    while (ctx->pa_counter < MAX_PA_COUNTER) {
+       krb5_data req;
+
+       ctx->pa_counter++;
+
+       if (ctx->as_req.padata) {
+           free_METHOD_DATA(ctx->as_req.padata);
+           free(ctx->as_req.padata);
+           ctx->as_req.padata = NULL;
+       }
+
+       /* Set a new nonce. */
+       ctx->as_req.req_body.nonce = ctx->nonce;
+
+       /* fill_in_md_data */
+       ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx,
+                                   &md, &ctx->as_req.padata,
+                                   prompter, prompter_data);
+       if (ret)
+           goto out;
+       ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, 
+                          &ctx->as_req, &len, ret);
+       if (ret)
+           goto out;
+       if(len != req.length)
+           krb5_abortx(context, "internal error in ASN.1 encoder");
+
+       ret = krb5_sendto_kdc_flags (context, &req, 
+                                    &creds->client->realm, &resp,
+                                    send_to_kdc_flags);
+       krb5_data_free(&req);
+       if (ret)
+           goto out;
+
+       memset (&rep, 0, sizeof(rep));
+       ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
+       if (ret == 0) {
+           krb5_data_free(&resp);
+           krb5_clear_error_string(context);
+           break;
+       } else {
+           /* let's try to parse it as a KRB-ERROR */
+           KRB_ERROR error;
+
+           ret = krb5_rd_error(context, &resp, &error);
+           if(ret && resp.data && ((char*)resp.data)[0] == 4)
+               ret = KRB5KRB_AP_ERR_V4_REPLY;
+           krb5_data_free(&resp);
+           if (ret)
+               goto out;
+
+           ret = krb5_error_from_rd_error(context, &error, creds);
+
+           /*
+            * If no preauth was set and KDC requires it, give it one
+            * more try.
+            */
+
+           if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) {
+               free_METHOD_DATA(&md);
+               memset(&md, 0, sizeof(md));
+
+               if (error.e_data) {
+                   ret = decode_METHOD_DATA(error.e_data->data, 
+                                            error.e_data->length, 
+                                            &md, 
+                                            NULL);
+                   if (ret)
+                       krb5_set_error_string(context,
+                                             "failed to decode METHOD DATA");
+               } else {
+                   /* XXX guess what the server want here add add md */
+               }
+               krb5_free_error_contents(context, &error);
+               if (ret)
+                   goto out;
+           } else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
+               if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) {
+                   if (ret_as_reply)
+                       rep.error = error;
+                   else
+                       krb5_free_error_contents(context, &error);
+                   goto out;
+               }
+               krb5_free_error_contents(context, &error);
+               send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
+           } else {
+               if (ret_as_reply)
+                   rep.error = error;
+               else
+                   krb5_free_error_contents(context, &error);
+               goto out;
+           }
+       }
+    }
+
+    {
+       krb5_keyblock *key = NULL;
+
+       ret = process_pa_data_to_key(context, ctx, creds, 
+                                    &ctx->as_req, &rep, &key);
+       if (ret)
+           goto out;
+       
+       ret = _krb5_extract_ticket(context,
+                                  &rep,
+                                  creds,
+                                  key,
+                                  NULL,
+                                  KRB5_KU_AS_REP_ENC_PART,
+                                  NULL,
+                                  ctx->nonce,
+                                  FALSE,
+                                  ctx->flags.b.request_anonymous,
+                                  NULL,
+                                  NULL);
+       krb5_free_keyblock(context, key);
+    }
+out:
+    free_METHOD_DATA(&md);
+    memset(&md, 0, sizeof(md));
+
+    if (ret == 0 && ret_as_reply)
+       *ret_as_reply = rep;
+    else
+       krb5_free_kdc_rep (context, &rep);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds(krb5_context context,
+                   krb5_creds *creds,
+                   krb5_principal client,
+                   krb5_prompter_fct prompter,
+                   void *data,
+                   krb5_deltat start_time,
+                   const char *in_tkt_service,
+                   krb5_get_init_creds_opt *options)
+{
+    krb5_get_init_creds_ctx ctx;
+    krb5_kdc_rep kdc_reply;
+    krb5_error_code ret;
+    char buf[BUFSIZ];
+    int done;
+
+    memset(&kdc_reply, 0, sizeof(kdc_reply));
+
+    ret = get_init_creds_common(context, creds, client, start_time,
+                               in_tkt_service, options, &ctx);
+    if (ret)
+       goto out;
+
+    done = 0;
+    while(!done) {
+       memset(&kdc_reply, 0, sizeof(kdc_reply));
+
+       ret = init_cred_loop(context,
+                            options,
+                            prompter,
+                            data,
+                            &ctx,
+                            &ctx.cred,
+                            &kdc_reply);
+       
+       switch (ret) {
+       case 0 :
+           done = 1;
+           break;
+       case KRB5KDC_ERR_KEY_EXPIRED :
+           /* try to avoid recursion */
+
+           /* don't try to change password where then where none */
+           if (prompter == NULL || ctx.password == NULL)
+               goto out;
+
+           krb5_clear_error_string (context);
+
+           if (ctx.in_tkt_service != NULL
+               && strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0)
+               goto out;
+
+           ret = change_password (context,
+                                  client,
+                                  ctx.password,
+                                  buf,
+                                  sizeof(buf),
+                                  prompter,
+                                  data,
+                                  options);
+           if (ret)
+               goto out;
+           ctx.password = buf;
+           break;
+       default:
+           goto out;
+       }
+    }
+
+    if (prompter)
+       print_expire (context,
+                     krb5_principal_get_realm (context, ctx.cred.client),
+                     &kdc_reply,
+                     prompter,
+                     data);
+
+ out:
+    memset (buf, 0, sizeof(buf));
+    free_init_creds_ctx(context, &ctx);
+    krb5_free_kdc_rep (context, &kdc_reply);
+    if (ret == 0)
+       *creds = ctx.cred;
+    else
+       krb5_free_cred_contents (context, &ctx.cred);
+
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_password(krb5_context context,
+                            krb5_creds *creds,
+                            krb5_principal client,
+                            const char *password,
+                            krb5_prompter_fct prompter,
+                            void *data,
+                            krb5_deltat start_time,
+                            const char *in_tkt_service,
+                            krb5_get_init_creds_opt *in_options)
+{
+    krb5_get_init_creds_opt *options;
+    char buf[BUFSIZ];
+    krb5_error_code ret;
+
+    if (in_options == NULL)
+       ret = krb5_get_init_creds_opt_alloc(context, &options);
+    else
+       ret = _krb5_get_init_creds_opt_copy(context, in_options, &options);
+    if (ret)
+       return ret;
+
+    if (password == NULL &&
+       options->opt_private->password == NULL &&
+       options->opt_private->pk_init_ctx == NULL)
+    {
+       krb5_prompt prompt;
+       krb5_data password_data;
+       char *p, *q;
+
+       krb5_unparse_name (context, client, &p);
+       asprintf (&q, "%s's Password: ", p);
+       free (p);
+       prompt.prompt = q;
+       password_data.data   = buf;
+       password_data.length = sizeof(buf);
+       prompt.hidden = 1;
+       prompt.reply  = &password_data;
+       prompt.type   = KRB5_PROMPT_TYPE_PASSWORD;
+
+       ret = (*prompter) (context, data, NULL, NULL, 1, &prompt);
+       free (q);
+       if (ret) {
+           memset (buf, 0, sizeof(buf));
+           krb5_get_init_creds_opt_free(options);
+           ret = KRB5_LIBOS_PWDINTR;
+           krb5_clear_error_string (context);
+           return ret;
+       }
+       password = password_data.data;
+    }
+
+    if (options->opt_private->password == NULL) {
+       ret = krb5_get_init_creds_opt_set_pa_password(context, options,
+                                                     password, NULL);
+       if (ret) {
+           krb5_get_init_creds_opt_free(options);
+           memset(buf, 0, sizeof(buf));
+           return ret;
+       }
+    }
+
+    ret = krb5_get_init_creds(context, creds, client, prompter,
+                             data, start_time, in_tkt_service, options);
+    krb5_get_init_creds_opt_free(options);
+    memset(buf, 0, sizeof(buf));
+    return ret;
+}
+
+static krb5_error_code
+init_creds_keyblock_key_proc (krb5_context context,
+                             krb5_enctype type,
+                             krb5_salt salt,
+                             krb5_const_pointer keyseed,
+                             krb5_keyblock **key)
+{
+    return krb5_copy_keyblock (context, keyseed, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_keyblock(krb5_context context,
+                            krb5_creds *creds,
+                            krb5_principal client,
+                            krb5_keyblock *keyblock,
+                            krb5_deltat start_time,
+                            const char *in_tkt_service,
+                            krb5_get_init_creds_opt *options)
+{
+    struct krb5_get_init_creds_ctx ctx;
+    krb5_error_code ret;
+    
+    ret = get_init_creds_common(context, creds, client, start_time,
+                               in_tkt_service, options, &ctx);
+    if (ret)
+       goto out;
+
+    ret = krb5_get_in_cred (context,
+                           ctx.flags.i,
+                           ctx.addrs,
+                           ctx.etypes,
+                           ctx.pre_auth_types,
+                           NULL,
+                           init_creds_keyblock_key_proc,
+                           keyblock,
+                           NULL,
+                           NULL,
+                           &ctx.cred,
+                           NULL);
+
+    if (ret == 0 && creds)
+       *creds = ctx.cred;
+    else
+       krb5_free_cred_contents (context, &ctx.cred);
+
+ out:
+    free_init_creds_ctx(context, &ctx);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/k524_err.et b/src/kerberosV/src/lib/krb5/k524_err.et
new file mode 100644 (file)
index 0000000..20dffd4
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Error messages for the k524 functions
+#
+# This might look like a com_err file, but is not
+#
+id "$KTH: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $"
+
+error_table k524
+
+prefix KRB524
+error_code BADKEY,             "wrong keytype in ticket"
+error_code BADADDR,            "incorrect network address"
+error_code BADPRINC,           "cannot convert V5 principal"           #unused
+error_code BADREALM,           "V5 realm name longer than V4 maximum"  #unused
+error_code V4ERR,              "kerberos V4 error server"
+error_code ENCFULL,            "encoding too large at server"
+error_code DECEMPTY,           "decoding out of data"                  #unused
+error_code NOTRESP,            "service not responding"                #unused
+end
+
diff --git a/src/kerberosV/src/lib/krb5/kcm.c b/src/kerberosV/src/lib/krb5/kcm.c
new file mode 100644 (file)
index 0000000..46ed715
--- /dev/null
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+#ifdef HAVE_KCM
+/*
+ * Client library for Kerberos Credentials Manager (KCM) daemon
+ */
+
+#ifdef HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+
+#include "kcm.h"
+
+RCSID("$KTH: kcm.c,v 1.6 2005/05/29 14:49:50 lha Exp $");
+
+typedef struct krb5_kcmcache {
+    char *name;
+    struct sockaddr_un path;
+    char *door_path;
+} krb5_kcmcache;
+
+#define KCMCACHE(X)    ((krb5_kcmcache *)(X)->data.data)
+#define CACHENAME(X)   (KCMCACHE(X)->name)
+#define KCMCURSOR(C)   (*(u_int32_t *)(C))
+
+static krb5_error_code
+try_door(krb5_context context, const krb5_kcmcache *k,
+        krb5_data *request_data,
+        krb5_data *response_data)
+{
+#ifdef HAVE_DOOR_CREATE
+    door_arg_t arg;
+    int fd;
+    int ret;
+
+    memset(&arg, 0, sizeof(arg));
+          
+    fd = open(k->door_path, O_RDWR);
+    if (fd < 0)
+       return KRB5_CC_IO;
+
+    arg.data_ptr = request_data->data;
+    arg.data_size = request_data->length;
+    arg.desc_ptr = NULL;
+    arg.desc_num = 0;
+    arg.rbuf = NULL;
+    arg.rsize = 0;
+
+    ret = door_call(fd, &arg);
+    close(fd);
+    if (ret != 0)
+       return KRB5_CC_IO;
+
+    ret = krb5_data_copy(response_data, arg.rbuf, arg.rsize);
+    munmap(arg.rbuf, arg.rsize);
+    if (ret)
+       return ret;
+
+    return 0;
+#else
+    return KRB5_CC_IO;
+#endif
+}
+
+static krb5_error_code
+try_unix_socket(krb5_context context, const krb5_kcmcache *k,
+               krb5_data *request_data,
+               krb5_data *response_data)
+{
+    krb5_error_code ret;
+    int fd;
+
+    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (fd < 0)
+       return KRB5_CC_IO;
+    
+    if (connect(fd, (struct sockaddr *)&k->path, sizeof(k->path)) != 0) {
+       close(fd);
+       return KRB5_CC_IO;
+    }
+    
+    ret = _krb5_send_and_recv_tcp(fd, context->kdc_timeout,
+                                 request_data, response_data);
+    close(fd);
+    return ret;
+}
+    
+static krb5_error_code
+kcm_send_request(krb5_context context,
+                krb5_kcmcache *k,
+                krb5_storage *request,
+                krb5_data *response_data)
+{
+    krb5_error_code ret;
+    krb5_data request_data;
+    int i;
+
+    response_data->data = NULL;
+    response_data->length = 0;
+
+    ret = krb5_storage_to_data(request, &request_data);
+    if (ret) {
+       krb5_clear_error_string(context);
+       return KRB5_CC_NOMEM;
+    }
+
+    ret = KRB5_CC_IO;
+
+    for (i = 0; i < context->max_retries; i++) {
+       ret = try_door(context, k, &request_data, response_data);
+       if (ret == 0 && response_data->length != 0)
+           break;
+       ret = try_unix_socket(context, k, &request_data, response_data);
+       if (ret == 0 && response_data->length != 0)
+           break;
+    }
+
+    krb5_data_free(&request_data);
+
+    if (ret) {
+       krb5_clear_error_string(context);
+       ret = KRB5_CC_IO;
+    }
+
+    return ret;
+}
+
+static krb5_error_code
+kcm_storage_request(krb5_context context,
+                   kcm_operation opcode,
+                   krb5_storage **storage_p)
+{
+    krb5_storage *sp;
+    krb5_error_code ret;
+
+    *storage_p = NULL;
+
+    sp = krb5_storage_emem();
+    if (sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+
+    /* Send MAJOR | VERSION | OPCODE */
+    ret  = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR);
+    if (ret)
+       goto fail;
+    ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MINOR);
+    if (ret)
+       goto fail;
+    ret = krb5_store_int16(sp, opcode);
+    if (ret)
+       goto fail;
+
+    *storage_p = sp;
+ fail:
+    if (ret) {
+       krb5_set_error_string(context, "Failed to encode request");
+       krb5_storage_free(sp);
+    }
+   
+    return ret; 
+}
+
+static krb5_error_code
+kcm_alloc(krb5_context context, const char *name, krb5_ccache *id)
+{
+    krb5_kcmcache *k;
+    const char *path;
+
+    k = malloc(sizeof(*k));
+    if (k == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+
+    if (name != NULL) {
+       k->name = strdup(name);
+       if (k->name == NULL) {
+           free(k);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return KRB5_CC_NOMEM;
+       }
+    } else
+       k->name = NULL;
+
+    path = krb5_config_get_string_default(context, NULL,
+                                         _PATH_KCM_SOCKET,
+                                         "libdefaults", 
+                                         "kcm_socket",
+                                         NULL);
+    
+    k->path.sun_family = AF_UNIX;
+    strlcpy(k->path.sun_path, path, sizeof(k->path.sun_path));
+
+    path = krb5_config_get_string_default(context, NULL,
+                                         _PATH_KCM_DOOR,
+                                         "libdefaults", 
+                                         "kcm_door",
+                                         NULL);
+    k->door_path = strdup(path);
+
+    (*id)->data.data = k;
+    (*id)->data.length = sizeof(*k);
+
+    return 0;
+}
+
+static krb5_error_code
+kcm_call(krb5_context context,
+        krb5_kcmcache *k,
+        krb5_storage *request,
+        krb5_storage **response_p,
+        krb5_data *response_data_p)
+{
+    krb5_data response_data;
+    krb5_error_code ret, status;
+    krb5_storage *response;
+
+    if (response_p != NULL)
+       *response_p = NULL;
+
+    ret = kcm_send_request(context, k, request, &response_data);
+    if (ret) {
+       return ret;
+    }
+
+    response = krb5_storage_from_data(&response_data);
+    if (response == NULL) {
+       krb5_data_free(&response_data);
+       return KRB5_CC_IO;
+    }
+
+    ret = krb5_ret_int32(response, &status);
+    if (ret) {
+       krb5_storage_free(response);
+       krb5_data_free(&response_data);
+       return KRB5_CC_FORMAT;
+    }
+
+    if (status) {
+       krb5_storage_free(response);
+       krb5_data_free(&response_data);
+       return status;
+    }
+
+    if (response_p != NULL) {
+       *response_data_p = response_data;
+       *response_p = response;
+
+       return 0;
+    }
+
+    krb5_storage_free(response);
+    krb5_data_free(&response_data);
+
+    return 0;
+}
+
+static void
+kcm_free(krb5_context context, krb5_ccache *id)
+{
+    krb5_kcmcache *k = KCMCACHE(*id);
+
+    if (k != NULL) {
+       if (k->name != NULL)
+           free(k->name);
+       if (k->door_path)
+           free(k->door_path);
+       memset(k, 0, sizeof(*k));
+       krb5_data_free(&(*id)->data);
+    }
+
+    *id = NULL;
+}
+
+static const char *
+kcm_get_name(krb5_context context,
+            krb5_ccache id)
+{
+    return CACHENAME(id);
+}
+
+static krb5_error_code
+kcm_resolve(krb5_context context, krb5_ccache *id, const char *res)
+{
+    return kcm_alloc(context, res, id);
+}
+
+/*
+ * Request:
+ *
+ * Response:
+ *      NameZ
+ */
+static krb5_error_code
+kcm_gen_new(krb5_context context, krb5_ccache *id)
+{
+    krb5_kcmcache *k;
+    krb5_error_code ret;
+    krb5_storage *request, *response;
+    krb5_data response_data;
+
+    ret = kcm_alloc(context, NULL, id);
+    if (ret)
+       return ret;
+
+    k = KCMCACHE(*id);
+
+    ret = kcm_storage_request(context, KCM_OP_GEN_NEW, &request);
+    if (ret) {
+       kcm_free(context, id);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, &response, &response_data);
+    if (ret) {
+       krb5_storage_free(request);
+       kcm_free(context, id);
+       return ret;
+    }
+
+    ret = krb5_ret_stringz(response, &k->name);
+    if (ret)
+       ret = KRB5_CC_IO;
+
+    krb5_storage_free(request);
+    krb5_storage_free(response);
+    krb5_data_free(&response_data);
+
+    if (ret)
+       kcm_free(context, id);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *      Principal
+ *
+ * Response:
+ *
+ */
+static krb5_error_code
+kcm_initialize(krb5_context context,
+              krb5_ccache id,
+              krb5_principal primary_principal)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_INITIALIZE, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_principal(request, primary_principal);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+static krb5_error_code
+kcm_close(krb5_context context,
+         krb5_ccache id)
+{
+    kcm_free(context, &id);
+    return 0;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *
+ * Response:
+ *
+ */
+static krb5_error_code
+kcm_destroy(krb5_context context,
+           krb5_ccache id)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_DESTROY, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *      Creds
+ *
+ * Response:
+ *
+ */
+static krb5_error_code
+kcm_store_cred(krb5_context context,
+              krb5_ccache id,
+              krb5_creds *creds)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_STORE, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_creds(request, creds);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *      WhichFields
+ *      MatchCreds
+ *
+ * Response:
+ *      Creds
+ *
+ */
+static krb5_error_code
+kcm_retrieve(krb5_context context,
+            krb5_ccache id,
+            krb5_flags which,
+            const krb5_creds *mcred,
+            krb5_creds *creds)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request, *response;
+    krb5_data response_data;
+
+    ret = kcm_storage_request(context, KCM_OP_RETRIEVE, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, which);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_creds_tag(request, (krb5_creds *)mcred);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, &response, &response_data);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_ret_creds(response, creds);
+    if (ret)
+       ret = KRB5_CC_IO;
+
+    krb5_storage_free(request);
+    krb5_storage_free(response);
+    krb5_data_free(&response_data);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *
+ * Response:
+ *      Principal
+ */
+static krb5_error_code
+kcm_get_principal(krb5_context context,
+                 krb5_ccache id,
+                 krb5_principal *principal)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request, *response;
+    krb5_data response_data;
+
+    ret = kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, &response, &response_data);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_ret_principal(response, principal);
+    if (ret)
+       ret = KRB5_CC_IO;
+
+    krb5_storage_free(request);
+    krb5_storage_free(response);
+    krb5_data_free(&response_data);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *
+ * Response:
+ *      Cursor
+ *
+ */
+static krb5_error_code
+kcm_get_first (krb5_context context,
+              krb5_ccache id,
+              krb5_cc_cursor *cursor)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request, *response;
+    krb5_data response_data;
+    u_int32_t tmp;
+
+    ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, &response, &response_data);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_ret_int32(response, &tmp);
+    if (ret)
+       ret = KRB5_CC_IO;
+
+    krb5_storage_free(request);
+    krb5_storage_free(response);
+    krb5_data_free(&response_data);
+
+    if (ret)
+       return ret;
+
+    *cursor = malloc(sizeof(tmp));
+    if (*cursor == NULL)
+       return KRB5_CC_NOMEM;
+
+    KCMCURSOR(*cursor) = tmp;
+
+    return 0;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *      Cursor
+ *
+ * Response:
+ *      Creds
+ */
+static krb5_error_code
+kcm_get_next (krb5_context context,
+               krb5_ccache id,
+               krb5_cc_cursor *cursor,
+               krb5_creds *creds)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request, *response;
+    krb5_data response_data;
+
+    ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, KCMCURSOR(*cursor));
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, &response, &response_data);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_ret_creds(response, creds);
+    if (ret)
+       ret = KRB5_CC_IO;
+
+    krb5_storage_free(request);
+    krb5_storage_free(response);
+    krb5_data_free(&response_data);
+
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *      Cursor
+ *
+ * Response:
+ *
+ */
+static krb5_error_code
+kcm_end_get (krb5_context context,
+            krb5_ccache id,
+            krb5_cc_cursor *cursor)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_END_GET, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, KCMCURSOR(*cursor));
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+  
+    krb5_storage_free(request);
+
+    KCMCURSOR(*cursor) = 0;
+    free(*cursor);
+    *cursor = NULL;
+
+    return ret;
+}
+
+/*
+ * Request:
+ *      NameZ
+ *      WhichFields
+ *      MatchCreds
+ *
+ * Response:
+ *
+ */
+static krb5_error_code
+kcm_remove_cred(krb5_context context,
+               krb5_ccache id,
+               krb5_flags which,
+               krb5_creds *cred)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, which);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_creds_tag(request, cred);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+static krb5_error_code
+kcm_set_flags(krb5_context context,
+             krb5_ccache id,
+             krb5_flags flags)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_SET_FLAGS, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, flags);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+static krb5_error_code
+kcm_get_version(krb5_context context,
+               krb5_ccache id)
+{
+    return 0;
+}
+
+const krb5_cc_ops krb5_kcm_ops = {
+    "KCM",
+    kcm_get_name,
+    kcm_resolve,
+    kcm_gen_new,
+    kcm_initialize,
+    kcm_destroy,
+    kcm_close,
+    kcm_store_cred,
+    kcm_retrieve,
+    kcm_get_principal,
+    kcm_get_first,
+    kcm_get_next,
+    kcm_end_get,
+    kcm_remove_cred,
+    kcm_set_flags,
+    kcm_get_version
+};
+
+krb5_boolean
+_krb5_kcm_is_running(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_ccache_data ccdata;
+    krb5_ccache id = &ccdata;
+    krb5_boolean running;
+
+    ret = kcm_alloc(context, NULL, &id);
+    if (ret)
+       return 0;
+
+    running = (_krb5_kcm_noop(context, id) == 0);
+
+    kcm_free(context, &id);
+
+    return running;
+}
+
+/*
+ * Request:
+ *
+ * Response:
+ *
+ */
+krb5_error_code
+_krb5_kcm_noop(krb5_context context,
+              krb5_ccache id)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_NOOP, &request);
+    if (ret)
+       return ret;
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+
+/*
+ * Request:
+ *      NameZ
+ *      Mode
+ *
+ * Response:
+ *
+ */
+krb5_error_code
+_krb5_kcm_chmod(krb5_context context,
+               krb5_ccache id,
+               u_int16_t mode)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_CHMOD, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int16(request, mode);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+
+/*
+ * Request:
+ *      NameZ
+ *      UID
+ *      GID
+ *
+ * Response:
+ *
+ */
+krb5_error_code
+_krb5_kcm_chown(krb5_context context,
+               krb5_ccache id,
+               u_int32_t uid,
+               u_int32_t gid)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_CHOWN, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, uid);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, gid);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+
+/*
+ * Request:
+ *      NameZ
+ *      ServerPrincipalPresent
+ *      ServerPrincipal OPTIONAL
+ *      Key
+ *
+ * Repsonse:
+ *
+ */
+krb5_error_code
+_krb5_kcm_get_initial_ticket(krb5_context context,
+                            krb5_ccache id,
+                            krb5_principal server,
+                            krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int8(request, (server == NULL) ? 0 : 1);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    if (server != NULL) {
+       ret = krb5_store_principal(request, server);
+       if (ret) {
+           krb5_storage_free(request);
+           return ret;
+       }
+    }
+
+    ret = krb5_store_keyblock(request, *key);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+
+/*
+ * Request:
+ *      NameZ
+ *      KDCFlags
+ *      EncryptionType
+ *      ServerPrincipal
+ *
+ * Repsonse:
+ *
+ */
+krb5_error_code
+_krb5_kcm_get_ticket(krb5_context context,
+                    krb5_ccache id,
+                    krb5_kdc_flags flags,
+                    krb5_enctype enctype,
+                    krb5_principal server)
+{
+    krb5_error_code ret;
+    krb5_kcmcache *k = KCMCACHE(id);
+    krb5_storage *request;
+
+    ret = kcm_storage_request(context, KCM_OP_GET_TICKET, &request);
+    if (ret)
+       return ret;
+
+    ret = krb5_store_stringz(request, k->name);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, flags.i);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_int32(request, enctype);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = krb5_store_principal(request, server);
+    if (ret) {
+       krb5_storage_free(request);
+       return ret;
+    }
+
+    ret = kcm_call(context, k, request, NULL, NULL);
+
+    krb5_storage_free(request);
+    return ret;
+}
+
+
+#endif /* HAVE_KCM */
diff --git a/src/kerberosV/src/lib/krb5/kcm.h b/src/kerberosV/src/lib/krb5/kcm.h
new file mode 100644 (file)
index 0000000..10dfa44
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2005, PADL Software Pty Ltd.
+ * 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 PADL Software nor the names 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 PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 __KCM_H__
+#define __KCM_H__
+
+/*
+ * KCM protocol definitions
+ */
+
+#define KCM_PROTOCOL_VERSION_MAJOR     1
+#define KCM_PROTOCOL_VERSION_MINOR     0
+
+typedef enum kcm_operation {
+    KCM_OP_NOOP,
+    KCM_OP_GET_NAME,
+    KCM_OP_RESOLVE,
+    KCM_OP_GEN_NEW,
+    KCM_OP_INITIALIZE,
+    KCM_OP_DESTROY,
+    KCM_OP_STORE,
+    KCM_OP_RETRIEVE,
+    KCM_OP_GET_PRINCIPAL,
+    KCM_OP_GET_FIRST,
+    KCM_OP_GET_NEXT,
+    KCM_OP_END_GET,
+    KCM_OP_REMOVE_CRED,
+    KCM_OP_SET_FLAGS,
+    KCM_OP_CHOWN,
+    KCM_OP_CHMOD,
+    KCM_OP_GET_INITIAL_TICKET,
+    KCM_OP_GET_TICKET,
+    KCM_OP_MAX
+} kcm_operation;
+
+#define _PATH_KCM_SOCKET      "/var/run/.kcm_socket"
+#define _PATH_KCM_DOOR      "/var/run/.kcm_door"
+
+#endif /* __KCM_H__ */
+
diff --git a/src/kerberosV/src/lib/krb5/kerberos.8 b/src/kerberosV/src/lib/krb5/kerberos.8
new file mode 100644 (file)
index 0000000..230d349
--- /dev/null
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: kerberos.8,v 1.8 2003/07/26 17:05:42 lha Exp $
+.\"
+.Dd September 1, 2000
+.Dt KERBEROS 8
+.Os HEIMDAL
+.Sh NAME
+.Nm kerberos
+.Nd introduction to the Kerberos system
+.Sh DESCRIPTION
+Kerberos is a network authentication system. Its purpose is to
+securely authenticate users and services in an insecure network
+environment.
+.Pp
+This is done with a Kerberos server acting as a trusted third party,
+keeping a database with secret keys for all users and services
+(collectively called
+.Em principals ) .
+.Pp
+Each principal belongs to exactly one
+.Em realm ,
+which is the administrative domain in Kerberos. A realm usually
+corresponds to an organisation, and the realm should normally be
+derived from that organisation's domain name. A realm is served by one
+or more Kerberos servers.
+.Pp
+The authentication process involves exchange of
+.Sq tickets
+and
+.Sq authenticators
+which together prove the principal's identity.
+.Pp
+When you login to the Kerberos system, either through the normal
+system login or with the
+.Xr kinit 1
+program, you acquire a
+.Em ticket granting ticket
+which allows you to get new tickets for other services, such as
+.Ic telnet
+or
+.Ic ssh ,
+without giving your password.
+.Pp
+For more information on how Kerberos works, and other general Kerberos
+questions see the Kerberos FAQ at
+.Pa http://www.nrl.navy.mil/CCS/people/kenh/kerberos-faq.html .
+.Pp
+For setup instructions see the Heimdal Texinfo manual.
+.Sh SEE ALSO
+.Xr kdestroy 1 ,
+.Xr kinit 1 ,
+.Xr klist 1 ,
+.Xr passwd 1 ,
+.Xr telnet 1
+.Sh HISTORY
+The Kerberos authentication system was developed in the late 1980's as
+part of the Athena Project at the Massachusetts Institute of
+Technology. Versions one through three never reached outside MIT, but
+version 4 was (and still is) quite popular, especially in the academic
+community, but is also used in commercial products like the AFS
+filesystem.
+.Pp
+The problems with version 4 are that it has many limitations, the code
+was not too well written (since it had been developed over a long
+time), and it has a number of known security problems. To resolve many
+of these issues work on version five started, and resulted in IETF
+RFC1510 in 1993. Since then much work has been put into the further
+development, and a new RFC will hopefully appear soon.
+.Pp
+This manual page is part of the
+.Nm Heimdal
+Kerberos 5 distribution, which has been in development at the Royal
+Institute of Technology in Stockholm, Sweden, since about 1997.
diff --git a/src/kerberosV/src/lib/krb5/keyblock.c b/src/kerberosV/src/lib/krb5/keyblock.c
new file mode 100644 (file)
index 0000000..603bc59
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keyblock.c,v 1.17 2005/05/18 04:21:31 lha Exp $");
+
+void KRB5_LIB_FUNCTION
+krb5_keyblock_zero(krb5_keyblock *keyblock)
+{
+    keyblock->keytype = 0;
+    krb5_data_zero(&keyblock->keyvalue);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_keyblock_contents(krb5_context context,
+                           krb5_keyblock *keyblock)
+{
+    if(keyblock) {
+       if (keyblock->keyvalue.data != NULL)
+           memset(keyblock->keyvalue.data, 0, keyblock->keyvalue.length);
+       krb5_data_free (&keyblock->keyvalue);
+       keyblock->keytype = ENCTYPE_NULL;
+    }
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_keyblock(krb5_context context,
+                  krb5_keyblock *keyblock)
+{
+    if(keyblock){
+       krb5_free_keyblock_contents(context, keyblock);
+       free(keyblock);
+    }
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_keyblock_contents (krb5_context context,
+                            const krb5_keyblock *inblock,
+                            krb5_keyblock *to)
+{
+    return copy_EncryptionKey(inblock, to);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_keyblock (krb5_context context,
+                   const krb5_keyblock *inblock,
+                   krb5_keyblock **to)
+{
+    krb5_keyblock *k;
+
+    k = malloc (sizeof(*k));
+    if (k == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    *to = k;
+    return krb5_copy_keyblock_contents (context, inblock, k);
+}
+
+krb5_enctype
+krb5_keyblock_get_enctype(const krb5_keyblock *block)
+{
+    return block->keytype;
+}
+
+/*
+ * Fill in `key' with key data of type `enctype' from `data' of length
+ * `size'. Key should be freed using krb5_free_keyblock_contents.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keyblock_init(krb5_context context,
+                  krb5_enctype type,
+                  const void *data,
+                  size_t size,
+                  krb5_keyblock *key)
+{
+    krb5_error_code ret;
+    size_t len;
+
+    memset(key, 0, sizeof(*key));
+
+    ret = krb5_enctype_keysize(context, type, &len);
+    if (ret)
+       return ret;
+
+    if (len != size) {
+       krb5_set_error_string(context, "Encryption key %d is %lu bytes "
+                             "long, %lu was passed in",
+                             type, (unsigned long)len, (unsigned long)size);
+       return KRB5_PROG_ETYPE_NOSUPP;
+    }
+    ret = krb5_data_copy(&key->keyvalue, data, len);
+    if(ret) {
+       krb5_set_error_string(context, "malloc failed: %lu",
+                             (unsigned long)len);
+       return ret;
+    }
+    key->keytype = type;
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/keytab.c b/src/kerberosV/src/lib/krb5/keytab.c
new file mode 100644 (file)
index 0000000..1a6e49f
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keytab.c,v 1.60 2005/05/19 14:04:45 lha Exp $");
+
+/*
+ * Register a new keytab in `ops'
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_register(krb5_context context,
+                const krb5_kt_ops *ops)
+{
+    struct krb5_keytab_data *tmp;
+
+    if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) {
+       krb5_set_error_string(context, "krb5_kt_register; prefix too long");
+       return KRB5_KT_BADNAME;
+    }
+
+    tmp = realloc(context->kt_types,
+                 (context->num_kt_types + 1) * sizeof(*context->kt_types));
+    if(tmp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(&tmp[context->num_kt_types], ops,
+          sizeof(tmp[context->num_kt_types]));
+    context->kt_types = tmp;
+    context->num_kt_types++;
+    return 0;
+}
+
+/*
+ * Resolve the keytab name (of the form `type:residual') in `name'
+ * into a keytab in `id'.
+ * Return 0 or an error
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_resolve(krb5_context context,
+               const char *name,
+               krb5_keytab *id)
+{
+    krb5_keytab k;
+    int i;
+    const char *type, *residual;
+    size_t type_len;
+    krb5_error_code ret;
+
+    residual = strchr(name, ':');
+    if(residual == NULL) {
+       type = "FILE";
+       type_len = strlen(type);
+       residual = name;
+    } else {
+       type = name;
+       type_len = residual - name;
+       residual++;
+    }
+    
+    for(i = 0; i < context->num_kt_types; i++) {
+       if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0)
+           break;
+    }
+    if(i == context->num_kt_types) {
+       krb5_set_error_string(context, "unknown keytab type %.*s", 
+                             (int)type_len, type);
+       return KRB5_KT_UNKNOWN_TYPE;
+    }
+    
+    k = malloc (sizeof(*k));
+    if (k == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(k, &context->kt_types[i], sizeof(*k));
+    k->data = NULL;
+    ret = (*k->resolve)(context, residual, k);
+    if(ret) {
+       free(k);
+       k = NULL;
+    }
+    *id = k;
+    return ret;
+}
+
+/*
+ * copy the name of the default keytab into `name'.
+ * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
+{
+    if (strlcpy (name, context->default_keytab, namesize) >= namesize) {
+       krb5_clear_error_string (context);
+       return KRB5_CONFIG_NOTENUFSPACE;
+    }
+    return 0;
+}
+
+/*
+ * copy the name of the default modify keytab into `name'.
+ * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
+{
+    const char *kt = NULL;
+    if(context->default_keytab_modify == NULL) {
+       if(strncasecmp(context->default_keytab, "ANY:", 4) != 0)
+           kt = context->default_keytab;
+       else {
+           size_t len = strcspn(context->default_keytab + 4, ",");
+           if(len >= namesize) {
+               krb5_clear_error_string(context);
+               return KRB5_CONFIG_NOTENUFSPACE;
+           }
+           strlcpy(name, context->default_keytab + 4, namesize);
+           name[len] = '\0';
+           return 0;
+       }    
+    } else
+       kt = context->default_keytab_modify;
+    if (strlcpy (name, kt, namesize) >= namesize) {
+       krb5_clear_error_string (context);
+       return KRB5_CONFIG_NOTENUFSPACE;
+    }
+    return 0;
+}
+
+/*
+ * Set `id' to the default keytab.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_default(krb5_context context, krb5_keytab *id)
+{
+    return krb5_kt_resolve (context, context->default_keytab, id);
+}
+
+/*
+ * Read the key identified by `(principal, vno, enctype)' from the
+ * keytab in `keyprocarg' (the default if == NULL) into `*key'.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_read_service_key(krb5_context context,
+                        krb5_pointer keyprocarg,
+                        krb5_principal principal,
+                        krb5_kvno vno,
+                        krb5_enctype enctype,
+                        krb5_keyblock **key)
+{
+    krb5_keytab keytab;
+    krb5_keytab_entry entry;
+    krb5_error_code ret;
+
+    if (keyprocarg)
+       ret = krb5_kt_resolve (context, keyprocarg, &keytab);
+    else
+       ret = krb5_kt_default (context, &keytab);
+
+    if (ret)
+       return ret;
+
+    ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry);
+    krb5_kt_close (context, keytab);
+    if (ret)
+       return ret;
+    ret = krb5_copy_keyblock (context, &entry.keyblock, key);
+    krb5_kt_free_entry(context, &entry);
+    return ret;
+}
+
+/*
+ * Return the type of the `keytab' in the string `prefix of length
+ * `prefixsize'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_type(krb5_context context,
+                krb5_keytab keytab,
+                char *prefix,
+                size_t prefixsize)
+{
+    strlcpy(prefix, keytab->prefix, prefixsize);
+    return 0;
+}
+
+/*
+ * Retrieve the name of the keytab `keytab' into `name', `namesize'
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_name(krb5_context context, 
+                krb5_keytab keytab,
+                char *name,
+                size_t namesize)
+{
+    return (*keytab->get_name)(context, keytab, name, namesize);
+}
+
+/*
+ * Finish using the keytab in `id'.  All resources will be released.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_close(krb5_context context, 
+             krb5_keytab id)
+{
+    krb5_error_code ret;
+
+    ret = (*id->close)(context, id);
+    if(ret == 0)
+       free(id);
+    return ret;
+}
+
+/*
+ * Compare `entry' against `principal, vno, enctype'.
+ * Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
+ * Return TRUE if they compare the same, FALSE otherwise.
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_kt_compare(krb5_context context,
+               krb5_keytab_entry *entry, 
+               krb5_const_principal principal,
+               krb5_kvno vno,
+               krb5_enctype enctype)
+{
+    if(principal != NULL && 
+       !krb5_principal_compare(context, entry->principal, principal))
+       return FALSE;
+    if(vno && vno != entry->vno)
+       return FALSE;
+    if(enctype && enctype != entry->keyblock.keytype)
+       return FALSE;
+    return TRUE;
+}
+
+/*
+ * Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
+ * from the keytab `id'.
+ * kvno == 0 is a wildcard and gives the keytab with the highest vno.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_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 tmp;
+    krb5_error_code ret;
+    krb5_kt_cursor cursor;
+
+    if(id->get)
+       return (*id->get)(context, id, principal, kvno, enctype, entry);
+
+    ret = krb5_kt_start_seq_get (context, id, &cursor);
+    if (ret)
+       return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */
+
+    entry->vno = 0;
+    while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) {
+       if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) {
+           /* the file keytab might only store the lower 8 bits of
+              the kvno, so only compare those bits */
+           if (kvno == tmp.vno
+               || (tmp.vno < 256 && kvno % 256 == tmp.vno)) {
+               krb5_kt_copy_entry_contents (context, &tmp, entry);
+               krb5_kt_free_entry (context, &tmp);
+               krb5_kt_end_seq_get(context, id, &cursor);
+               return 0;
+           } else if (kvno == 0 && tmp.vno > entry->vno) {
+               if (entry->vno)
+                   krb5_kt_free_entry (context, entry);
+               krb5_kt_copy_entry_contents (context, &tmp, entry);
+           }
+       }
+       krb5_kt_free_entry(context, &tmp);
+    }
+    krb5_kt_end_seq_get (context, id, &cursor);
+    if (entry->vno) {
+       return 0;
+    } else {
+       char princ[256], kt_name[256], kvno_str[25];
+       char *enctype_str = NULL;
+
+       krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
+       krb5_kt_get_name (context, id, kt_name, sizeof(kt_name));
+       krb5_enctype_to_string(context, enctype, &enctype_str);
+
+       if (kvno)
+           snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
+       else
+           kvno_str[0] = '\0';
+
+       krb5_set_error_string (context,
+                              "failed to find %s%s in keytab %s (%s)",
+                              princ,
+                              kvno_str,
+                              kt_name,
+                              enctype_str ? enctype_str : "unknown enctype");
+       free(enctype_str);
+       return KRB5_KT_NOTFOUND;
+    }
+}
+
+/*
+ * Copy the contents of `in' into `out'.
+ * Return 0 or an error.  */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_copy_entry_contents(krb5_context context,
+                           const krb5_keytab_entry *in,
+                           krb5_keytab_entry *out)
+{
+    krb5_error_code ret;
+
+    memset(out, 0, sizeof(*out));
+    out->vno = in->vno;
+
+    ret = krb5_copy_principal (context, in->principal, &out->principal);
+    if (ret)
+       goto fail;
+    ret = krb5_copy_keyblock_contents (context,
+                                      &in->keyblock,
+                                      &out->keyblock);
+    if (ret)
+       goto fail;
+    out->timestamp = in->timestamp;
+    return 0;
+fail:
+    krb5_kt_free_entry (context, out);
+    return ret;
+}
+
+/*
+ * Free the contents of `entry'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_free_entry(krb5_context context,
+                  krb5_keytab_entry *entry)
+{
+    krb5_free_principal (context, entry->principal);
+    krb5_free_keyblock_contents (context, &entry->keyblock);
+    memset(entry, 0, sizeof(*entry));
+    return 0;
+}
+
+/*
+ * Set `cursor' to point at the beginning of `id'.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_start_seq_get(krb5_context context,
+                     krb5_keytab id,
+                     krb5_kt_cursor *cursor)
+{
+    if(id->start_seq_get == NULL) {
+       krb5_set_error_string(context,
+                             "start_seq_get is not supported in the %s "
+                             " keytab", id->prefix);
+       return HEIM_ERR_OPNOTSUPP;
+    }
+    return (*id->start_seq_get)(context, id, cursor);
+}
+
+/*
+ * Get the next entry from `id' pointed to by `cursor' and advance the
+ * `cursor'.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_next_entry(krb5_context context,
+                  krb5_keytab id,
+                  krb5_keytab_entry *entry,
+                  krb5_kt_cursor *cursor)
+{
+    if(id->next_entry == NULL) {
+       krb5_set_error_string(context,
+                             "next_entry is not supported in the %s "
+                             " keytab", id->prefix);
+       return HEIM_ERR_OPNOTSUPP;
+    }
+    return (*id->next_entry)(context, id, entry, cursor);
+}
+
+/*
+ * Release all resources associated with `cursor'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_end_seq_get(krb5_context context,
+                   krb5_keytab id,
+                   krb5_kt_cursor *cursor)
+{
+    if(id->end_seq_get == NULL) {
+       krb5_set_error_string(context,
+                             "end_seq_get is not supported in the %s "
+                             " keytab", id->prefix);
+       return HEIM_ERR_OPNOTSUPP;
+    }
+    return (*id->end_seq_get)(context, id, cursor);
+}
+
+/*
+ * Add the entry in `entry' to the keytab `id'.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_add_entry(krb5_context context,
+                 krb5_keytab id,
+                 krb5_keytab_entry *entry)
+{
+    if(id->add == NULL) {
+       krb5_set_error_string(context, "Add is not supported in the %s keytab",
+                             id->prefix);
+       return KRB5_KT_NOWRITE;
+    }
+    entry->timestamp = time(NULL);
+    return (*id->add)(context, id,entry);
+}
+
+/*
+ * Remove the entry `entry' from the keytab `id'.
+ * Return 0 or an error.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_remove_entry(krb5_context context,
+                    krb5_keytab id,
+                    krb5_keytab_entry *entry)
+{
+    if(id->remove == NULL) {
+       krb5_set_error_string(context,
+                             "Remove is not supported in the %s keytab",
+                             id->prefix);
+       return KRB5_KT_NOWRITE;
+    }
+    return (*id->remove)(context, id, entry);
+}
diff --git a/src/kerberosV/src/lib/krb5/keytab_any.c b/src/kerberosV/src/lib/krb5/keytab_any.c
new file mode 100644 (file)
index 0000000..f627ab6
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2001-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keytab_any.c,v 1.7 2002/10/21 13:36:59 joda Exp $");
+
+struct any_data {
+    krb5_keytab kt;
+    char *name;
+    struct any_data *next;
+};
+
+static void
+free_list (krb5_context context, struct any_data *a)
+{
+    struct any_data *next;
+
+    for (; a != NULL; a = next) {
+       next = a->next;
+       free (a->name);
+       if(a->kt)
+           krb5_kt_close(context, a->kt);
+       free (a);
+    }
+}
+
+static krb5_error_code
+any_resolve(krb5_context context, const char *name, krb5_keytab id)
+{
+    struct any_data *a, *a0 = NULL, *prev = NULL;
+    krb5_error_code ret;
+    char buf[256];
+
+    while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) {
+       a = malloc(sizeof(*a));
+       if (a == NULL) {
+           ret = ENOMEM;
+           goto fail;
+       }
+       if (a0 == NULL) {
+           a0 = a;
+           a->name = strdup(buf);
+           if (a->name == NULL) {
+               krb5_set_error_string(context, "malloc: out of memory");
+               ret = ENOMEM;
+               goto fail;
+           }
+       } else
+           a->name = NULL;
+       if (prev != NULL)
+           prev->next = a;
+       a->next = NULL;
+       ret = krb5_kt_resolve (context, buf, &a->kt);
+       if (ret)
+           goto fail;
+       prev = a;
+    }
+    if (a0 == NULL) {
+       krb5_set_error_string(context, "empty ANY: keytab");
+       return ENOENT;
+    }
+    id->data = a0;
+    return 0;
+ fail:
+    free_list (context, a0);
+    return ret;
+}
+
+static krb5_error_code
+any_get_name (krb5_context context,
+             krb5_keytab id,
+             char *name,
+             size_t namesize)
+{
+    struct any_data *a = id->data;
+    strlcpy(name, a->name, namesize);
+    return 0;
+}
+
+static krb5_error_code
+any_close (krb5_context context,
+          krb5_keytab id)
+{
+    struct any_data *a = id->data;
+
+    free_list (context, a);
+    return 0;
+}
+
+struct any_cursor_extra_data {
+    struct any_data *a;
+    krb5_kt_cursor cursor;
+};
+
+static krb5_error_code
+any_start_seq_get(krb5_context context, 
+                 krb5_keytab id, 
+                 krb5_kt_cursor *c)
+{
+    struct any_data *a = id->data;
+    struct any_cursor_extra_data *ed;
+    krb5_error_code ret;
+
+    c->data = malloc (sizeof(struct any_cursor_extra_data));
+    if(c->data == NULL){
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ed = (struct any_cursor_extra_data *)c->data;
+    ed->a = a;
+    ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
+    if (ret) {
+       free (c->data);
+       c->data = NULL;
+       return ret;
+    }
+    return 0;
+}
+
+static krb5_error_code
+any_next_entry (krb5_context context,
+               krb5_keytab id,
+               krb5_keytab_entry *entry,
+               krb5_kt_cursor *cursor)
+{
+    krb5_error_code ret, ret2;
+    struct any_cursor_extra_data *ed;
+
+    ed = (struct any_cursor_extra_data *)cursor->data;
+    do {
+       ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor);
+       if (ret == 0)
+           return 0;
+       else if (ret != KRB5_KT_END)
+           return ret;
+
+       ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor);
+       if (ret2)
+           return ret2;
+       while ((ed->a = ed->a->next) != NULL) {
+           ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor);
+           if (ret2 == 0)
+               break;
+       }
+       if (ed->a == NULL) {
+           krb5_clear_error_string (context);
+           return KRB5_KT_END;
+       }
+    } while (1);
+}
+
+static krb5_error_code
+any_end_seq_get(krb5_context context,
+               krb5_keytab id,
+               krb5_kt_cursor *cursor)
+{
+    krb5_error_code ret = 0;
+    struct any_cursor_extra_data *ed;
+
+    ed = (struct any_cursor_extra_data *)cursor->data;
+    if (ed->a != NULL)
+       ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor);
+    free (ed);
+    cursor->data = NULL;
+    return ret;
+}
+
+static krb5_error_code
+any_add_entry(krb5_context context,
+             krb5_keytab id,
+             krb5_keytab_entry *entry)
+{
+    struct any_data *a = id->data;
+    krb5_error_code ret;
+    while(a != NULL) {
+       ret = krb5_kt_add_entry(context, a->kt, entry);
+       if(ret != 0 && ret != KRB5_KT_NOWRITE) {
+           krb5_set_error_string(context, "failed to add entry to %s", 
+                                 a->name);
+           return ret;
+       }
+       a = a->next;
+    }
+    return 0;
+}
+
+static krb5_error_code
+any_remove_entry(krb5_context context,
+                krb5_keytab id,
+                krb5_keytab_entry *entry)
+{
+    struct any_data *a = id->data;
+    krb5_error_code ret;
+    int found = 0;
+    while(a != NULL) {
+       ret = krb5_kt_remove_entry(context, a->kt, entry);
+       if(ret == 0)
+           found++;
+       else {
+           if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) {
+               krb5_set_error_string(context, "failed to remove entry from %s", 
+                                     a->name);
+               return ret;
+           }
+       }
+       a = a->next;
+    }
+    if(!found)
+       return KRB5_KT_NOTFOUND;
+    return 0;
+}
+
+const krb5_kt_ops krb5_any_ops = {
+    "ANY",
+    any_resolve,
+    any_get_name,
+    any_close,
+    NULL, /* get */
+    any_start_seq_get,
+    any_next_entry,
+    any_end_seq_get,
+    any_add_entry,
+    any_remove_entry
+};
diff --git a/src/kerberosV/src/lib/krb5/keytab_file.c b/src/kerberosV/src/lib/krb5/keytab_file.c
new file mode 100644 (file)
index 0000000..b491523
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keytab_file.c,v 1.18 2005/05/31 21:50:43 lha Exp $");
+
+#define KRB5_KT_VNO_1 1
+#define KRB5_KT_VNO_2 2
+#define KRB5_KT_VNO   KRB5_KT_VNO_2
+
+#define KRB5_KT_FL_JAVA 1
+
+
+/* file operations -------------------------------------------- */
+
+struct fkt_data {
+    char *filename;
+    int flags;
+};
+
+static krb5_error_code
+krb5_kt_ret_data(krb5_context context,
+                krb5_storage *sp,
+                krb5_data *data)
+{
+    int ret;
+    int16_t size;
+    ret = krb5_ret_int16(sp, &size);
+    if(ret)
+       return ret;
+    data->length = size;
+    data->data = malloc(size);
+    if (data->data == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = krb5_storage_read(sp, data->data, size);
+    if(ret != size)
+       return (ret < 0)? errno : KRB5_KT_END;
+    return 0;
+}
+
+static krb5_error_code
+krb5_kt_ret_string(krb5_context context,
+                  krb5_storage *sp,
+                  heim_general_string *data)
+{
+    int ret;
+    int16_t size;
+    ret = krb5_ret_int16(sp, &size);
+    if(ret)
+       return ret;
+    *data = malloc(size + 1);
+    if (*data == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = krb5_storage_read(sp, *data, size);
+    (*data)[size] = '\0';
+    if(ret != size)
+       return (ret < 0)? errno : KRB5_KT_END;
+    return 0;
+}
+
+static krb5_error_code
+krb5_kt_store_data(krb5_context context,
+                  krb5_storage *sp,
+                  krb5_data data)
+{
+    int ret;
+    ret = krb5_store_int16(sp, data.length);
+    if(ret < 0)
+       return ret;
+    ret = krb5_storage_write(sp, data.data, data.length);
+    if(ret != data.length){
+       if(ret < 0)
+           return errno;
+       return KRB5_KT_END;
+    }
+    return 0;
+}
+
+static krb5_error_code
+krb5_kt_store_string(krb5_storage *sp,
+                    heim_general_string data)
+{
+    int ret;
+    size_t len = strlen(data);
+    ret = krb5_store_int16(sp, len);
+    if(ret < 0)
+       return ret;
+    ret = krb5_storage_write(sp, data, len);
+    if(ret != len){
+       if(ret < 0)
+           return errno;
+       return KRB5_KT_END;
+    }
+    return 0;
+}
+
+static krb5_error_code
+krb5_kt_ret_keyblock(krb5_context context, krb5_storage *sp, krb5_keyblock *p)
+{
+    int ret;
+    int16_t tmp;
+
+    ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */
+    if(ret) return ret;
+    p->keytype = tmp;
+    ret = krb5_kt_ret_data(context, sp, &p->keyvalue);
+    return ret;
+}
+
+static krb5_error_code
+krb5_kt_store_keyblock(krb5_context context,
+                      krb5_storage *sp, 
+                      krb5_keyblock *p)
+{
+    int ret;
+
+    ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */
+    if(ret) return ret;
+    ret = krb5_kt_store_data(context, sp, p->keyvalue);
+    return ret;
+}
+
+
+static krb5_error_code
+krb5_kt_ret_principal(krb5_context context,
+                     krb5_storage *sp,
+                     krb5_principal *princ)
+{
+    int i;
+    int ret;
+    krb5_principal p;
+    int16_t len;
+    
+    ALLOC(p, 1);
+    if(p == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ret = krb5_ret_int16(sp, &len);
+    if(ret) {
+       krb5_set_error_string(context,
+                             "Failed decoding length of keytab principal");
+       goto out;
+    }
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
+       len--;
+    if (len < 0) {
+       krb5_set_error_string(context, 
+                             "Keytab principal contains invalid length");
+       ret = KRB5_KT_END;
+       goto out;
+    }
+    ret = krb5_kt_ret_string(context, sp, &p->realm);
+    if(ret)
+       goto out;
+    p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val));
+    if(p->name.name_string.val == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+    p->name.name_string.len = len;
+    for(i = 0; i < p->name.name_string.len; i++){
+       ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i);
+       if(ret)
+           goto out;
+    }
+    if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
+       p->name.name_type = KRB5_NT_UNKNOWN;
+    else {
+       int32_t tmp32;
+       ret = krb5_ret_int32(sp, &tmp32);
+       p->name.name_type = tmp32;
+       if (ret)
+           goto out;
+    }
+    *princ = p;
+    return 0;
+out:
+    krb5_free_principal(context, p);
+    return ret;
+}
+
+static krb5_error_code
+krb5_kt_store_principal(krb5_context context,
+                       krb5_storage *sp,
+                       krb5_principal p)
+{
+    int i;
+    int ret;
+    
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
+       ret = krb5_store_int16(sp, p->name.name_string.len + 1);
+    else
+       ret = krb5_store_int16(sp, p->name.name_string.len);
+    if(ret) return ret;
+    ret = krb5_kt_store_string(sp, p->realm);
+    if(ret) return ret;
+    for(i = 0; i < p->name.name_string.len; i++){
+       ret = krb5_kt_store_string(sp, p->name.name_string.val[i]);
+       if(ret)
+           return ret;
+    }
+    if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
+       ret = krb5_store_int32(sp, p->name.name_type);
+       if(ret)
+           return ret;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+fkt_resolve(krb5_context context, const char *name, krb5_keytab id)
+{
+    struct fkt_data *d;
+
+    d = malloc(sizeof(*d));
+    if(d == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    d->filename = strdup(name);
+    if(d->filename == NULL) {
+       free(d);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    d->flags = 0;
+    id->data = d;
+    return 0;
+}
+
+static krb5_error_code
+fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id)
+{
+    krb5_error_code ret;
+
+    ret = fkt_resolve(context, name, id);
+    if (ret == 0) {
+       struct fkt_data *d = id->data;
+       d->flags |= KRB5_KT_FL_JAVA;
+    }
+    return ret;
+}
+
+static krb5_error_code
+fkt_close(krb5_context context, krb5_keytab id)
+{
+    struct fkt_data *d = id->data;
+    free(d->filename);
+    free(d);
+    return 0;
+}
+
+static krb5_error_code 
+fkt_get_name(krb5_context context, 
+            krb5_keytab id, 
+            char *name, 
+            size_t namesize)
+{
+    /* This function is XXX */
+    struct fkt_data *d = id->data;
+    strlcpy(name, d->filename, namesize);
+    return 0;
+}
+
+static void
+storage_set_flags(krb5_context context, krb5_storage *sp, int vno)
+{
+    int flags = 0;
+    switch(vno) {
+    case KRB5_KT_VNO_1:
+       flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS;
+       flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE;
+       flags |= KRB5_STORAGE_HOST_BYTEORDER;
+       break;
+    case KRB5_KT_VNO_2:
+       break;
+    default:
+       krb5_warnx(context, 
+                  "storage_set_flags called with bad vno (%d)", vno);
+    }
+    krb5_storage_set_flags(sp, flags);
+}
+
+static krb5_error_code
+fkt_start_seq_get_int(krb5_context context, 
+                     krb5_keytab id, 
+                     int flags,
+                     int exclusive,
+                     krb5_kt_cursor *c)
+{
+    int8_t pvno, tag;
+    krb5_error_code ret;
+    struct fkt_data *d = id->data;
+    
+    c->fd = open (d->filename, flags);
+    if (c->fd < 0) {
+       ret = errno;
+       krb5_set_error_string(context, "%s: %s", d->filename,
+                             strerror(ret));
+       return ret;
+    }
+    ret = _krb5_xlock(context, c->fd, exclusive, d->filename);
+    if (ret) {
+       close(c->fd);
+       return ret;
+    }
+    c->sp = krb5_storage_from_fd(c->fd);
+    krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
+    ret = krb5_ret_int8(c->sp, &pvno);
+    if(ret) {
+       krb5_storage_free(c->sp);
+       _krb5_xunlock(context, c->fd);
+       close(c->fd);
+       krb5_clear_error_string(context);
+       return ret;
+    }
+    if(pvno != 5) {
+       krb5_storage_free(c->sp);
+       _krb5_xunlock(context, c->fd);
+       close(c->fd);
+       krb5_clear_error_string (context);
+       return KRB5_KEYTAB_BADVNO;
+    }
+    ret = krb5_ret_int8(c->sp, &tag);
+    if (ret) {
+       krb5_storage_free(c->sp);
+       _krb5_xunlock(context, c->fd);
+       close(c->fd);
+       krb5_clear_error_string(context);
+       return ret;
+    }
+    id->version = tag;
+    storage_set_flags(context, c->sp, id->version);
+    return 0;
+}
+
+static krb5_error_code
+fkt_start_seq_get(krb5_context context, 
+                 krb5_keytab id, 
+                 krb5_kt_cursor *c)
+{
+    return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c);
+}
+
+static krb5_error_code
+fkt_next_entry_int(krb5_context context, 
+                  krb5_keytab id, 
+                  krb5_keytab_entry *entry, 
+                  krb5_kt_cursor *cursor,
+                  off_t *start,
+                  off_t *end)
+{
+    int32_t len;
+    int ret;
+    int8_t tmp8;
+    int32_t tmp32;
+    off_t pos, curpos;
+
+    pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
+loop:
+    ret = krb5_ret_int32(cursor->sp, &len);
+    if (ret)
+       return ret;
+    if(len < 0) {
+       pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR);
+       goto loop;
+    }
+    ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal);
+    if (ret)
+       goto out;
+    ret = krb5_ret_int32(cursor->sp, &tmp32);
+    entry->timestamp = tmp32;
+    if (ret)
+       goto out;
+    ret = krb5_ret_int8(cursor->sp, &tmp8);
+    if (ret)
+       goto out;
+    entry->vno = tmp8;
+    ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock);
+    if (ret)
+       goto out;
+    /* there might be a 32 bit kvno here
+     * if it's zero, assume that the 8bit one was right,
+     * otherwise trust the new value */
+    curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
+    if(len + 4 + pos - curpos == 4) {
+       ret = krb5_ret_int32(cursor->sp, &tmp32);
+       if (ret == 0 && tmp32 != 0) {
+           entry->vno = tmp32;
+       }
+    }
+    if(start) *start = pos;
+    if(end) *end = *start + 4 + len;
+ out:
+    krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET);
+    return ret;
+}
+
+static krb5_error_code
+fkt_next_entry(krb5_context context, 
+              krb5_keytab id, 
+              krb5_keytab_entry *entry, 
+              krb5_kt_cursor *cursor)
+{
+    return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL);
+}
+
+static krb5_error_code
+fkt_end_seq_get(krb5_context context, 
+               krb5_keytab id,
+               krb5_kt_cursor *cursor)
+{
+    krb5_storage_free(cursor->sp);
+    _krb5_xunlock(context, cursor->fd);
+    close(cursor->fd);
+    return 0;
+}
+
+static krb5_error_code
+fkt_setup_keytab(krb5_context context,
+                krb5_keytab id,
+                krb5_storage *sp)
+{
+    krb5_error_code ret;
+    ret = krb5_store_int8(sp, 5);
+    if(ret)
+       return ret;
+    if(id->version == 0)
+       id->version = KRB5_KT_VNO;
+    return krb5_store_int8 (sp, id->version);
+}
+                
+static krb5_error_code
+fkt_add_entry(krb5_context context,
+             krb5_keytab id,
+             krb5_keytab_entry *entry)
+{
+    int ret;
+    int fd;
+    krb5_storage *sp;
+    struct fkt_data *d = id->data;
+    krb5_data keytab;
+    int32_t len;
+    
+    fd = open (d->filename, O_RDWR | O_BINARY);
+    if (fd < 0) {
+       fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600);
+       if (fd < 0) {
+           ret = errno;
+           krb5_set_error_string(context, "open(%s): %s", d->filename,
+                                 strerror(ret));
+           return ret;
+       }
+       ret = _krb5_xlock(context, fd, 1, d->filename);
+       if (ret) {
+           close(fd);
+           return ret;
+       }
+       sp = krb5_storage_from_fd(fd);
+       krb5_storage_set_eof_code(sp, KRB5_KT_END);
+       ret = fkt_setup_keytab(context, id, sp);
+       if(ret) {
+           goto out;
+       }
+       storage_set_flags(context, sp, id->version);
+    } else {
+       int8_t pvno, tag;
+       ret = _krb5_xlock(context, fd, 1, d->filename);
+       if (ret) {
+           close(fd);
+           return ret;
+       }
+       sp = krb5_storage_from_fd(fd);
+       krb5_storage_set_eof_code(sp, KRB5_KT_END);
+       ret = krb5_ret_int8(sp, &pvno);
+       if(ret) {
+           /* we probably have a zero byte file, so try to set it up
+               properly */
+           ret = fkt_setup_keytab(context, id, sp);
+           if(ret) {
+               krb5_set_error_string(context, "%s: keytab is corrupted: %s", 
+                                     d->filename, strerror(ret));
+               goto out;
+           }
+           storage_set_flags(context, sp, id->version);
+       } else {
+           if(pvno != 5) {
+               ret = KRB5_KEYTAB_BADVNO;
+               krb5_set_error_string(context, "%s: %s", 
+                                     d->filename, strerror(ret));
+               goto out;
+           }
+           ret = krb5_ret_int8 (sp, &tag);
+           if (ret) {
+               krb5_set_error_string(context, "%s: reading tag: %s", 
+                                     d->filename, strerror(ret));
+               goto out;
+           }
+           id->version = tag;
+           storage_set_flags(context, sp, id->version);
+       }
+    }
+
+    {
+       krb5_storage *emem;
+       emem = krb5_storage_emem();
+       if(emem == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string (context, "malloc: out of memory");
+           goto out;
+       }
+       ret = krb5_kt_store_principal(context, emem, entry->principal);
+       if(ret) {
+           krb5_storage_free(emem);
+           goto out;
+       }
+       ret = krb5_store_int32 (emem, entry->timestamp);
+       if(ret) {
+           krb5_storage_free(emem);
+           goto out;
+       }
+       ret = krb5_store_int8 (emem, entry->vno % 256);
+       if(ret) {
+           krb5_storage_free(emem);
+           goto out;
+       }
+       ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock);
+       if(ret) {
+           krb5_storage_free(emem);
+           goto out;
+       }
+       if ((d->flags & KRB5_KT_FL_JAVA) == 0) {
+           ret = krb5_store_int32 (emem, entry->vno);
+           if (ret) {
+               krb5_storage_free(emem);
+               goto out;
+           }
+       }
+
+       ret = krb5_storage_to_data(emem, &keytab);
+       krb5_storage_free(emem);
+       if(ret)
+           goto out;
+    }
+    
+    while(1) {
+       ret = krb5_ret_int32(sp, &len);
+       if(ret == KRB5_KT_END) {
+           len = keytab.length;
+           break;
+       }
+       if(len < 0) {
+           len = -len;
+           if(len >= keytab.length) {
+               krb5_storage_seek(sp, -4, SEEK_CUR);
+               break;
+           }
+       }
+       krb5_storage_seek(sp, len, SEEK_CUR);
+    }
+    ret = krb5_store_int32(sp, len);
+    if(krb5_storage_write(sp, keytab.data, keytab.length) < 0)
+       ret = errno;
+    memset(keytab.data, 0, keytab.length);
+    krb5_data_free(&keytab);
+  out:
+    krb5_storage_free(sp);
+    _krb5_xunlock(context, fd);
+    close(fd);
+    return ret;
+}
+
+static krb5_error_code
+fkt_remove_entry(krb5_context context,
+                krb5_keytab id,
+                krb5_keytab_entry *entry)
+{
+    krb5_keytab_entry e;
+    krb5_kt_cursor cursor;
+    off_t pos_start, pos_end;
+    int found = 0;
+    krb5_error_code ret;
+    
+    ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, 1, &cursor);
+    if(ret != 0) 
+       goto out; /* return other error here? */
+    while(fkt_next_entry_int(context, id, &e, &cursor, 
+                            &pos_start, &pos_end) == 0) {
+       if(krb5_kt_compare(context, &e, entry->principal, 
+                          entry->vno, entry->keyblock.keytype)) {
+           int32_t len;
+           unsigned char buf[128];
+           found = 1;
+           krb5_storage_seek(cursor.sp, pos_start, SEEK_SET);
+           len = pos_end - pos_start - 4;
+           krb5_store_int32(cursor.sp, -len);
+           memset(buf, 0, sizeof(buf));
+           while(len > 0) {
+               krb5_storage_write(cursor.sp, buf, min(len, sizeof(buf)));
+               len -= min(len, sizeof(buf));
+           }
+       }
+       krb5_kt_free_entry(context, &e);
+    }
+    krb5_kt_end_seq_get(context, id, &cursor);
+  out:
+    if (!found) {
+       krb5_clear_error_string (context);
+       return KRB5_KT_NOTFOUND;
+    }
+    return 0;
+}
+
+const krb5_kt_ops krb5_fkt_ops = {
+    "FILE",
+    fkt_resolve,
+    fkt_get_name,
+    fkt_close,
+    NULL, /* get */
+    fkt_start_seq_get,
+    fkt_next_entry,
+    fkt_end_seq_get,
+    fkt_add_entry,
+    fkt_remove_entry
+};
+
+const krb5_kt_ops krb5_wrfkt_ops = {
+    "WRFILE",
+    fkt_resolve,
+    fkt_get_name,
+    fkt_close,
+    NULL, /* get */
+    fkt_start_seq_get,
+    fkt_next_entry,
+    fkt_end_seq_get,
+    fkt_add_entry,
+    fkt_remove_entry
+};
+
+const krb5_kt_ops krb5_javakt_ops = {
+    "JAVA14",
+    fkt_resolve_java14,
+    fkt_get_name,
+    fkt_close,
+    NULL, /* get */
+    fkt_start_seq_get,
+    fkt_next_entry,
+    fkt_end_seq_get,
+    fkt_add_entry,
+    fkt_remove_entry
+};
diff --git a/src/kerberosV/src/lib/krb5/keytab_keyfile.c b/src/kerberosV/src/lib/krb5/keytab_keyfile.c
new file mode 100644 (file)
index 0000000..992deee
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keytab_keyfile.c,v 1.16 2005/01/08 22:57:18 lha Exp $");
+
+/* afs keyfile operations --------------------------------------- */
+
+/*
+ * Minimum tools to handle the AFS KeyFile.
+ * 
+ * Format of the KeyFile is:
+ * <int32_t numkeys> {[<int32_t kvno> <char[8] deskey>] * numkeys}
+ *
+ * It just adds to the end of the keyfile, deleting isn't implemented.
+ * Use your favorite text/hex editor to delete keys.
+ *
+ */
+
+#define AFS_SERVERTHISCELL "/usr/afs/etc/ThisCell"
+#define AFS_SERVERMAGICKRBCONF "/usr/afs/etc/krb.conf"
+
+struct akf_data {
+    int num_entries;
+    char *filename;
+    char *cell;
+    char *realm;
+};
+
+/*
+ * set `d->cell' and `d->realm'
+ */
+
+static int
+get_cell_and_realm (krb5_context context,
+                   struct akf_data *d)
+{
+    FILE *f;
+    char buf[BUFSIZ], *cp;
+    int ret;
+
+    f = fopen (AFS_SERVERTHISCELL, "r");
+    if (f == NULL) {
+       ret = errno;
+       krb5_set_error_string (context, "open %s: %s", AFS_SERVERTHISCELL,
+                              strerror(ret));
+       return ret;
+    }
+    if (fgets (buf, sizeof(buf), f) == NULL) {
+       fclose (f);
+       krb5_set_error_string (context, "no cell in %s", AFS_SERVERTHISCELL);
+       return EINVAL;
+    }
+    buf[strcspn(buf, "\n")] = '\0';
+    fclose(f);
+
+    d->cell = strdup (buf);
+    if (d->cell == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    f = fopen (AFS_SERVERMAGICKRBCONF, "r");
+    if (f != NULL) {
+       if (fgets (buf, sizeof(buf), f) == NULL) {
+           fclose (f);
+           krb5_set_error_string (context, "no realm in %s",
+                                  AFS_SERVERMAGICKRBCONF);
+           return EINVAL;
+       }
+       buf[strcspn(buf, "\n")] = '\0';
+       fclose(f);
+    }
+    /* uppercase */
+    for (cp = buf; *cp != '\0'; cp++)
+       *cp = toupper((unsigned char)*cp);
+    
+    d->realm = strdup (buf);
+    if (d->realm == NULL) {
+       free (d->cell);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+/*
+ * init and get filename
+ */
+
+static krb5_error_code
+akf_resolve(krb5_context context, const char *name, krb5_keytab id)
+{
+    int ret;
+    struct akf_data *d = malloc(sizeof (struct akf_data));
+
+    if (d == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    
+    d->num_entries = 0;
+    ret = get_cell_and_realm (context, d);
+    if (ret) {
+       free (d);
+       return ret;
+    }
+    d->filename = strdup (name);
+    if (d->filename == NULL) {
+       free (d->cell);
+       free (d->realm);
+       free (d);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    id->data = d;
+    
+    return 0;
+}
+
+/*
+ * cleanup
+ */
+
+static krb5_error_code
+akf_close(krb5_context context, krb5_keytab id)
+{
+    struct akf_data *d = id->data;
+
+    free (d->filename);
+    free (d->cell);
+    free (d);
+    return 0;
+}
+
+/*
+ * Return filename
+ */
+
+static krb5_error_code 
+akf_get_name(krb5_context context, 
+            krb5_keytab id, 
+            char *name, 
+            size_t name_sz)
+{
+    struct akf_data *d = id->data;
+
+    strlcpy (name, d->filename, name_sz);
+    return 0;
+}
+
+/*
+ * Init 
+ */
+
+static krb5_error_code
+akf_start_seq_get(krb5_context context, 
+                 krb5_keytab id, 
+                 krb5_kt_cursor *c)
+{
+    int32_t ret;
+    struct akf_data *d = id->data;
+
+    c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600);
+    if (c->fd < 0) {
+       ret = errno;
+       krb5_set_error_string(context, "open(%s): %s", d->filename,
+                             strerror(ret));
+       return ret;
+    }
+
+    c->sp = krb5_storage_from_fd(c->fd);
+    ret = krb5_ret_int32(c->sp, &d->num_entries);
+    if(ret) {
+       krb5_storage_free(c->sp);
+       close(c->fd);
+       krb5_clear_error_string (context);
+       if(ret == KRB5_KT_END)
+           return KRB5_KT_NOTFOUND;
+       return ret;
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+akf_next_entry(krb5_context context, 
+              krb5_keytab id, 
+              krb5_keytab_entry *entry, 
+              krb5_kt_cursor *cursor)
+{
+    struct akf_data *d = id->data;
+    int32_t kvno;
+    off_t pos;
+    int ret;
+
+    pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
+
+    if ((pos - 4) / (4 + 8) >= d->num_entries)
+       return KRB5_KT_END;
+
+    ret = krb5_make_principal (context, &entry->principal,
+                              d->realm, "afs", d->cell, NULL);
+    if (ret)
+       goto out;
+
+    ret = krb5_ret_int32(cursor->sp, &kvno);
+    if (ret) {
+       krb5_free_principal (context, entry->principal);
+       goto out;
+    }
+
+    entry->vno = kvno;
+
+    entry->keyblock.keytype         = ETYPE_DES_CBC_MD5;
+    entry->keyblock.keyvalue.length = 8;
+    entry->keyblock.keyvalue.data   = malloc (8);
+    if (entry->keyblock.keyvalue.data == NULL) {
+       krb5_free_principal (context, entry->principal);
+       krb5_set_error_string (context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ret = krb5_storage_read(cursor->sp, entry->keyblock.keyvalue.data, 8);
+    if(ret != 8)
+       ret = (ret < 0) ? errno : KRB5_KT_END;
+    else
+       ret = 0;
+
+    entry->timestamp = time(NULL);
+
+ out:
+    krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET);
+    return ret;
+}
+
+static krb5_error_code
+akf_end_seq_get(krb5_context context, 
+               krb5_keytab id,
+               krb5_kt_cursor *cursor)
+{
+    krb5_storage_free(cursor->sp);
+    close(cursor->fd);
+    return 0;
+}
+
+static krb5_error_code
+akf_add_entry(krb5_context context,
+             krb5_keytab id,
+             krb5_keytab_entry *entry)
+{
+    struct akf_data *d = id->data;
+    int fd, created = 0;
+    krb5_error_code ret;
+    int32_t len;
+    krb5_storage *sp;
+
+
+    if (entry->keyblock.keyvalue.length != 8 
+       || entry->keyblock.keytype != ETYPE_DES_CBC_MD5)
+       return 0;
+
+    fd = open (d->filename, O_RDWR | O_BINARY);
+    if (fd < 0) {
+       fd = open (d->filename,
+                  O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600);
+       if (fd < 0) {
+           ret = errno;
+           krb5_set_error_string(context, "open(%s): %s", d->filename,
+                                 strerror(ret));
+           return ret;
+       }
+       created = 1;
+    }
+
+    sp = krb5_storage_from_fd(fd);
+    if(sp == NULL) {
+       close(fd);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    if (created)
+       len = 0;
+    else {
+       if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) {
+           ret = errno;
+           krb5_storage_free(sp);
+           close(fd);
+           krb5_set_error_string (context, "seek: %s", strerror(ret));
+           return ret;
+       }
+           
+       ret = krb5_ret_int32(sp, &len);
+       if(ret) {
+           krb5_storage_free(sp);
+           close(fd);
+           return ret;
+       }
+    }
+    len++;
+       
+    if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) {
+       ret = errno;
+       krb5_storage_free(sp);
+       close(fd);
+       krb5_set_error_string (context, "seek: %s", strerror(ret));
+       return ret;
+    }
+       
+    ret = krb5_store_int32(sp, len);
+    if(ret) {
+       krb5_storage_free(sp);
+       close(fd);
+       return ret;
+    }
+               
+
+    if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) {
+       ret = errno;
+       krb5_storage_free(sp);
+       close(fd);
+       krb5_set_error_string (context, "seek: %s", strerror(ret));
+       return ret;
+    }
+       
+    ret = krb5_store_int32(sp, entry->vno);
+    if(ret) {
+       krb5_storage_free(sp);
+       close(fd);
+       return ret;
+    }
+    ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 
+                            entry->keyblock.keyvalue.length);
+    if(ret != entry->keyblock.keyvalue.length) {
+       krb5_storage_free(sp);
+       close(fd);
+       if(ret < 0)
+           return errno;
+       return ENOTTY;
+    }
+    krb5_storage_free(sp);
+    close (fd);
+    return 0;
+}
+
+const krb5_kt_ops krb5_akf_ops = {
+    "AFSKEYFILE",
+    akf_resolve,
+    akf_get_name,
+    akf_close,
+    NULL, /* get */
+    akf_start_seq_get,
+    akf_next_entry,
+    akf_end_seq_get,
+    akf_add_entry,
+    NULL /* remove */
+};
diff --git a/src/kerberosV/src/lib/krb5/keytab_krb4.c b/src/kerberosV/src/lib/krb5/keytab_krb4.c
new file mode 100644 (file)
index 0000000..5efeb88
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keytab_krb4.c,v 1.13 2005/05/19 04:13:18 lha Exp $");
+
+struct krb4_kt_data {
+    char *filename;
+};
+
+static krb5_error_code
+krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id)
+{
+    struct krb4_kt_data *d;
+
+    d = malloc (sizeof(*d));
+    if (d == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    d->filename = strdup (name);
+    if (d->filename == NULL) {
+       free(d);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    id->data = d;
+    return 0;
+}
+
+static krb5_error_code
+krb4_kt_get_name (krb5_context context,
+                 krb5_keytab id,
+                 char *name,
+                 size_t name_sz)
+{
+    struct krb4_kt_data *d = id->data;
+
+    strlcpy (name, d->filename, name_sz);
+    return 0;
+}
+
+static krb5_error_code
+krb4_kt_close (krb5_context context,
+              krb5_keytab id)
+{
+    struct krb4_kt_data *d = id->data;
+
+    free (d->filename);
+    free (d);
+    return 0;
+}
+
+struct krb4_cursor_extra_data {
+    krb5_keytab_entry entry;
+    int num;
+};
+
+static int
+open_flock(const char *filename, int flags, int mode)
+{
+    int lock_mode;
+    int tries = 0;
+    int fd = open(filename, flags, mode);
+    if(fd < 0)
+       return fd;
+    if((flags & O_ACCMODE) == O_RDONLY)
+       lock_mode = LOCK_SH | LOCK_NB;
+    else
+       lock_mode = LOCK_EX | LOCK_NB;
+    while(flock(fd, lock_mode) < 0) {
+       if(++tries < 5) {
+           sleep(1);
+       } else {
+           close(fd);
+           return -1;
+       }
+    }
+    return fd;
+}
+
+
+
+static krb5_error_code
+krb4_kt_start_seq_get_int (krb5_context context,
+                          krb5_keytab id,
+                          int flags,
+                          krb5_kt_cursor *c)
+{
+    struct krb4_kt_data *d = id->data;
+    struct krb4_cursor_extra_data *ed;
+    int ret;
+
+    ed = malloc (sizeof(*ed));
+    if (ed == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ed->entry.principal = NULL;
+    ed->num = -1;
+    c->data = ed;
+    c->fd = open_flock (d->filename, flags, 0);
+    if (c->fd < 0) {
+       ret = errno;
+       free (ed);
+       krb5_set_error_string(context, "open(%s): %s", d->filename,
+                             strerror(ret));
+       return ret;
+    }
+    c->sp = krb5_storage_from_fd(c->fd);
+    if(c->sp == NULL) {
+       close(c->fd);
+       free(ed);
+       return ENOMEM;
+    }
+    krb5_storage_set_eof_code(c->sp, KRB5_KT_END);
+    return 0;
+}
+
+static krb5_error_code
+krb4_kt_start_seq_get (krb5_context context,
+                      krb5_keytab id,
+                      krb5_kt_cursor *c)
+{
+    return krb4_kt_start_seq_get_int (context, id, O_BINARY | O_RDONLY, c);
+}
+
+static krb5_error_code
+read_v4_entry (krb5_context context,
+              struct krb4_kt_data *d,
+              krb5_kt_cursor *c,
+              struct krb4_cursor_extra_data *ed)
+{
+    unsigned char des_key[8];
+    krb5_error_code ret;
+    char *service, *instance, *realm;
+    int8_t kvno;
+
+    ret = krb5_ret_stringz(c->sp, &service);
+    if (ret)
+       return ret;
+    ret = krb5_ret_stringz(c->sp, &instance);
+    if (ret) {
+       free (service);
+       return ret;
+    }
+    ret = krb5_ret_stringz(c->sp, &realm);
+    if (ret) {
+       free (service);
+       free (instance);
+       return ret;
+    }
+    ret = krb5_425_conv_principal (context, service, instance, realm,
+                                  &ed->entry.principal);
+    free (service);
+    free (instance);
+    free (realm);
+    if (ret)
+       return ret;
+    ret = krb5_ret_int8(c->sp, &kvno);
+    if (ret) {
+       krb5_free_principal (context, ed->entry.principal);
+       return ret;
+    }
+    ret = krb5_storage_read(c->sp, des_key, sizeof(des_key));
+    if (ret < 0) {
+       krb5_free_principal(context, ed->entry.principal);
+       return ret;
+    }
+    if (ret < 8) {
+       krb5_free_principal(context, ed->entry.principal);
+       return EINVAL;
+    }
+    ed->entry.vno = kvno;
+    ret = krb5_data_copy (&ed->entry.keyblock.keyvalue,
+                         des_key, sizeof(des_key));
+    if (ret)
+       return ret;
+    ed->entry.timestamp = time(NULL);
+    ed->num = 0;
+    return 0;
+}
+
+static krb5_error_code
+krb4_kt_next_entry (krb5_context context,
+                   krb5_keytab id,
+                   krb5_keytab_entry *entry,
+                   krb5_kt_cursor *c)
+{
+    krb5_error_code ret;
+    struct krb4_kt_data *d = id->data;
+    struct krb4_cursor_extra_data *ed = c->data;
+    const krb5_enctype keytypes[] = {ETYPE_DES_CBC_MD5,
+                                    ETYPE_DES_CBC_MD4,
+                                    ETYPE_DES_CBC_CRC};
+
+    if (ed->num == -1) {
+       ret = read_v4_entry (context, d, c, ed);
+       if (ret)
+           return ret;
+    }
+    ret = krb5_kt_copy_entry_contents (context,
+                                      &ed->entry,
+                                      entry);
+    if (ret)
+       return ret;
+    entry->keyblock.keytype = keytypes[ed->num];
+    if (++ed->num == 3) {
+       krb5_kt_free_entry (context, &ed->entry);
+       ed->num = -1;
+    }
+    return 0;
+}
+
+static krb5_error_code
+krb4_kt_end_seq_get (krb5_context context,
+                    krb5_keytab id,
+                    krb5_kt_cursor *c)
+{
+    struct krb4_cursor_extra_data *ed = c->data;
+
+    krb5_storage_free (c->sp);
+    if (ed->num != -1)
+       krb5_kt_free_entry (context, &ed->entry);
+    free (c->data);
+    close (c->fd);
+    return 0;
+}
+
+static krb5_error_code
+krb4_store_keytab_entry(krb5_context context, 
+                       krb5_keytab_entry *entry, 
+                       krb5_storage *sp)
+{
+    krb5_error_code ret;
+#define ANAME_SZ 40
+#define INST_SZ 40
+#define REALM_SZ 40
+    char service[ANAME_SZ];
+    char instance[INST_SZ];
+    char realm[REALM_SZ];
+    ret = krb5_524_conv_principal (context, entry->principal,
+                                  service, instance, realm);
+    if (ret)
+       return ret;
+    if (entry->keyblock.keyvalue.length == 8
+       && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) {
+       ret = krb5_store_stringz(sp, service);
+       ret = krb5_store_stringz(sp, instance);
+       ret = krb5_store_stringz(sp, realm);
+       ret = krb5_store_int8(sp, entry->vno);
+       ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 8);
+    }
+    return 0;
+}
+
+static krb5_error_code
+krb4_kt_add_entry (krb5_context context,
+                  krb5_keytab id,
+                  krb5_keytab_entry *entry)
+{
+    struct krb4_kt_data *d = id->data;
+    krb5_storage *sp;
+    krb5_error_code ret;
+    int fd;
+
+    fd = open_flock (d->filename, O_WRONLY | O_APPEND | O_BINARY, 0);
+    if (fd < 0) {
+       fd = open_flock (d->filename,
+                  O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600);
+       if (fd < 0) {
+           ret = errno;
+           krb5_set_error_string(context, "open(%s): %s", d->filename,
+                                 strerror(ret));
+           return ret;
+       }
+    }
+    sp = krb5_storage_from_fd(fd);
+    if(sp == NULL) {
+       close(fd);
+       return ENOMEM;
+    }
+    krb5_storage_set_eof_code(sp, KRB5_KT_END);
+    ret = krb4_store_keytab_entry(context, entry, sp);
+    krb5_storage_free(sp);
+    if(close (fd) < 0)
+       return errno;
+    return ret;
+}
+
+static krb5_error_code
+krb4_kt_remove_entry(krb5_context context,
+                krb5_keytab id,
+                krb5_keytab_entry *entry)
+{
+    struct krb4_kt_data *d = id->data;
+    krb5_error_code ret;
+    krb5_keytab_entry e;
+    krb5_kt_cursor cursor;
+    krb5_storage *sp;
+    int remove_flag = 0;
+    
+    sp = krb5_storage_emem();
+    if (sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = krb5_kt_start_seq_get(context, id, &cursor);
+    if (ret) {
+       krb5_storage_free(sp);
+       return ret;
+    }  
+    while(krb5_kt_next_entry(context, id, &e, &cursor) == 0) {
+       if(!krb5_kt_compare(context, &e, entry->principal, 
+                           entry->vno, entry->keyblock.keytype)) {
+           ret = krb4_store_keytab_entry(context, &e, sp);
+           if(ret) {
+               krb5_kt_free_entry(context, &e);
+               krb5_storage_free(sp);
+               return ret;
+           }
+       } else
+           remove_flag = 1;
+       krb5_kt_free_entry(context, &e);
+    }
+    krb5_kt_end_seq_get(context, id, &cursor);
+    if(remove_flag) {
+       int fd;
+       unsigned char buf[1024];
+       ssize_t n;
+       krb5_data data;
+       struct stat st;
+
+       krb5_storage_to_data(sp, &data);
+       krb5_storage_free(sp);
+
+       fd = open_flock (d->filename, O_RDWR | O_BINARY, 0);
+       if(fd < 0) {
+           memset(data.data, 0, data.length);
+           krb5_data_free(&data);
+           if(errno == EACCES || errno == EROFS) 
+               return KRB5_KT_NOWRITE;
+           return errno;
+       }
+
+       if(write(fd, data.data, data.length) != data.length) {
+           memset(data.data, 0, data.length);
+           krb5_data_free(&data);
+           close(fd);
+           krb5_set_error_string(context, "failed writing to \"%s\"", d->filename);
+           return errno;
+       }
+       memset(data.data, 0, data.length);
+       if(fstat(fd, &st) < 0) {
+           krb5_data_free(&data);
+           close(fd);
+           krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename);
+           return errno;
+       }
+       st.st_size -= data.length;
+       memset(buf, 0, sizeof(buf));
+       while(st.st_size > 0) {
+           n = min(st.st_size, sizeof(buf));
+           n = write(fd, buf, n);
+           if(n <= 0) {
+               krb5_data_free(&data);
+               close(fd);
+               krb5_set_error_string(context, "failed writing to \"%s\"", d->filename);
+               return errno;
+               
+           }
+           st.st_size -= n;
+       }
+       if(ftruncate(fd, data.length) < 0) {
+           krb5_data_free(&data);
+           close(fd);
+           krb5_set_error_string(context, "failed truncating \"%s\"", d->filename);
+           return errno;
+       }
+       krb5_data_free(&data);
+       if(close(fd) < 0) {
+           krb5_set_error_string(context, "error closing \"%s\"", d->filename);
+           return errno;
+       }
+       return 0;
+    } else {
+       krb5_storage_free(sp);
+       return KRB5_KT_NOTFOUND;
+    }
+}
+
+
+const krb5_kt_ops krb4_fkt_ops = {
+    "krb4",
+    krb4_kt_resolve,
+    krb4_kt_get_name,
+    krb4_kt_close,
+    NULL,                      /* get */
+    krb4_kt_start_seq_get,
+    krb4_kt_next_entry,
+    krb4_kt_end_seq_get,
+    krb4_kt_add_entry,         /* add_entry */
+    krb4_kt_remove_entry       /* remove_entry */
+};
+
+const krb5_kt_ops krb5_srvtab_fkt_ops = {
+    "SRVTAB",
+    krb4_kt_resolve,
+    krb4_kt_get_name,
+    krb4_kt_close,
+    NULL,                      /* get */
+    krb4_kt_start_seq_get,
+    krb4_kt_next_entry,
+    krb4_kt_end_seq_get,
+    krb4_kt_add_entry,         /* add_entry */
+    krb4_kt_remove_entry       /* remove_entry */
+};
diff --git a/src/kerberosV/src/lib/krb5/keytab_memory.c b/src/kerberosV/src/lib/krb5/keytab_memory.c
new file mode 100644 (file)
index 0000000..e5222f8
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: keytab_memory.c,v 1.6.2.1 2006/02/03 14:35:42 lha Exp $");
+
+/* memory operations -------------------------------------------- */
+
+struct mkt_data {
+    krb5_keytab_entry *entries;
+    int num_entries;
+};
+
+static krb5_error_code
+mkt_resolve(krb5_context context, const char *name, krb5_keytab id)
+{
+    struct mkt_data *d;
+    d = malloc(sizeof(*d));
+    if(d == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    d->entries = NULL;
+    d->num_entries = 0;
+    id->data = d;
+    return 0;
+}
+
+static krb5_error_code
+mkt_close(krb5_context context, krb5_keytab id)
+{
+    struct mkt_data *d = id->data;
+    int i;
+    for(i = 0; i < d->num_entries; i++)
+       krb5_kt_free_entry(context, &d->entries[i]);
+    free(d->entries);
+    free(d);
+    return 0;
+}
+
+static krb5_error_code 
+mkt_get_name(krb5_context context, 
+            krb5_keytab id, 
+            char *name, 
+            size_t namesize)
+{
+    strlcpy(name, "", namesize);
+    return 0;
+}
+
+static krb5_error_code
+mkt_start_seq_get(krb5_context context, 
+                 krb5_keytab id, 
+                 krb5_kt_cursor *c)
+{
+    /* XXX */
+    c->fd = 0;
+    return 0;
+}
+
+static krb5_error_code
+mkt_next_entry(krb5_context context, 
+              krb5_keytab id, 
+              krb5_keytab_entry *entry, 
+              krb5_kt_cursor *c)
+{
+    struct mkt_data *d = id->data;
+    if(c->fd >= d->num_entries)
+       return KRB5_KT_END;
+    return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry);
+}
+
+static krb5_error_code
+mkt_end_seq_get(krb5_context context, 
+               krb5_keytab id,
+               krb5_kt_cursor *cursor)
+{
+    return 0;
+}
+
+static krb5_error_code
+mkt_add_entry(krb5_context context,
+             krb5_keytab id,
+             krb5_keytab_entry *entry)
+{
+    struct mkt_data *d = id->data;
+    krb5_keytab_entry *tmp;
+    tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries));
+    if(tmp == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    d->entries = tmp;
+    return krb5_kt_copy_entry_contents(context, entry, 
+                                      &d->entries[d->num_entries++]);
+}
+
+static krb5_error_code
+mkt_remove_entry(krb5_context context,
+                krb5_keytab id,
+                krb5_keytab_entry *entry)
+{
+    struct mkt_data *d = id->data;
+    krb5_keytab_entry *e, *end;
+    int found = 0;
+    
+    if (d->num_entries == 0) {
+       krb5_clear_error_string(context);
+        return KRB5_KT_NOTFOUND;
+    }
+
+    /* do this backwards to minimize copying */
+    for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) {
+       if(krb5_kt_compare(context, e, entry->principal, 
+                          entry->vno, entry->keyblock.keytype)) {
+           krb5_kt_free_entry(context, e);
+           memmove(e, e + 1, (end - e - 1) * sizeof(*e));
+           memset(end - 1, 0, sizeof(*end));
+           d->num_entries--;
+           end--;
+           found = 1;
+       }
+    }
+    if (!found) {
+       krb5_clear_error_string (context);
+       return KRB5_KT_NOTFOUND;
+    }
+    e = realloc(d->entries, d->num_entries * sizeof(*d->entries));
+    if(e != NULL || d->num_entries == 0)
+       d->entries = e;
+    return 0;
+}
+
+const krb5_kt_ops krb5_mkt_ops = {
+    "MEMORY",
+    mkt_resolve,
+    mkt_get_name,
+    mkt_close,
+    NULL, /* get */
+    mkt_start_seq_get,
+    mkt_next_entry,
+    mkt_end_seq_get,
+    mkt_add_entry,
+    mkt_remove_entry
+};
diff --git a/src/kerberosV/src/lib/krb5/krb5-private.h b/src/kerberosV/src/lib/krb5/krb5-private.h
new file mode 100644 (file)
index 0000000..5d65157
--- /dev/null
@@ -0,0 +1,351 @@
+/* This is a generated file */
+#ifndef __krb5_private_h__
+#define __krb5_private_h__
+
+#include <stdarg.h>
+
+#ifndef KRB5_LIB_FUNCTION
+#if defined(_WIN32)
+#define KRB5_LIB_FUNCTION _stdcall
+#else
+#define KRB5_LIB_FUNCTION
+#endif
+#endif
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_PKCS5_PBKDF2 (
+       krb5_context /*context*/,
+       krb5_cksumtype /*cktype*/,
+       krb5_data /*password*/,
+       krb5_salt /*salt*/,
+       u_int32_t /*iter*/,
+       krb5_keytype /*type*/,
+       krb5_keyblock */*key*/);
+
+void KRB5_LIB_FUNCTION
+_krb5_aes_cts_encrypt (
+       const unsigned char */*in*/,
+       unsigned char */*out*/,
+       size_t /*len*/,
+       const void */*aes_key*/,
+       unsigned char */*ivec*/,
+       const int /*encrypt*/);
+
+void
+_krb5_crc_init_table (void);
+
+u_int32_t
+_krb5_crc_update (
+       const char */*p*/,
+       size_t /*len*/,
+       u_int32_t /*res*/);
+
+krb5_error_code
+_krb5_expand_default_cc_name (
+       krb5_context /*context*/,
+       const char */*str*/,
+       char **/*res*/);
+
+int
+_krb5_extract_ticket (
+       krb5_context /*context*/,
+       krb5_kdc_rep */*rep*/,
+       krb5_creds */*creds*/,
+       krb5_keyblock */*key*/,
+       krb5_const_pointer /*keyseed*/,
+       krb5_key_usage /*key_usage*/,
+       krb5_addresses */*addrs*/,
+       unsigned /*nonce*/,
+       krb5_boolean /*allow_server_mismatch*/,
+       krb5_boolean /*ignore_cname*/,
+       krb5_decrypt_proc /*decrypt_proc*/,
+       krb5_const_pointer /*decryptarg*/);
+
+krb5_error_code
+_krb5_get_default_principal_local (
+       krb5_context /*context*/,
+       krb5_principal */*princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_get_host_realm_int (
+       krb5_context /*context*/,
+       const char */*host*/,
+       krb5_boolean /*use_dns*/,
+       krb5_realm **/*realms*/);
+
+krb5_error_code
+_krb5_get_init_creds_opt_copy (
+       krb5_context /*context*/,
+       const krb5_get_init_creds_opt */*in*/,
+       krb5_get_init_creds_opt **/*out*/);
+
+void KRB5_LIB_FUNCTION
+_krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+_krb5_get_int (
+       void */*buffer*/,
+       unsigned long */*value*/,
+       size_t /*size*/);
+
+krb5_error_code
+_krb5_get_krbtgt (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_realm /*realm*/,
+       krb5_creds **/*cred*/);
+
+krb5_error_code
+_krb5_kcm_chmod (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       u_int16_t /*mode*/);
+
+krb5_error_code
+_krb5_kcm_chown (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       u_int32_t /*uid*/,
+       u_int32_t /*gid*/);
+
+krb5_error_code
+_krb5_kcm_get_initial_ticket (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_principal /*server*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code
+_krb5_kcm_get_ticket (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_kdc_flags /*flags*/,
+       krb5_enctype /*enctype*/,
+       krb5_principal /*server*/);
+
+krb5_boolean
+_krb5_kcm_is_running (krb5_context /*context*/);
+
+krb5_error_code
+_krb5_kcm_noop (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_cr_err_reply (
+       krb5_context /*context*/,
+       const char */*name*/,
+       const char */*inst*/,
+       const char */*realm*/,
+       u_int32_t /*time_ws*/,
+       u_int32_t /*e*/,
+       const char */*e_string*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_create_auth_reply (
+       krb5_context /*context*/,
+       const char */*pname*/,
+       const char */*pinst*/,
+       const char */*prealm*/,
+       int32_t /*time_ws*/,
+       int /*n*/,
+       u_int32_t /*x_date*/,
+       unsigned char /*kvno*/,
+       const krb5_data */*cipher*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_create_ciph (
+       krb5_context /*context*/,
+       const krb5_keyblock */*session*/,
+       const char */*service*/,
+       const char */*instance*/,
+       const char */*realm*/,
+       u_int32_t /*life*/,
+       unsigned char /*kvno*/,
+       const krb5_data */*ticket*/,
+       u_int32_t /*kdc_time*/,
+       const krb5_keyblock */*key*/,
+       krb5_data */*enc_data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_create_ticket (
+       krb5_context /*context*/,
+       unsigned char /*flags*/,
+       const char */*pname*/,
+       const char */*pinstance*/,
+       const char */*prealm*/,
+       int32_t /*paddress*/,
+       const krb5_keyblock */*session*/,
+       int16_t /*life*/,
+       int32_t /*life_sec*/,
+       const char */*sname*/,
+       const char */*sinstance*/,
+       const krb5_keyblock */*key*/,
+       krb5_data */*enc_data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_decomp_ticket (
+       krb5_context /*context*/,
+       const krb5_data */*enc_ticket*/,
+       const krb5_keyblock */*key*/,
+       const char */*local_realm*/,
+       char **/*sname*/,
+       char **/*sinstance*/,
+       struct _krb5_krb_auth_data */*ad*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_dest_tkt (
+       krb5_context /*context*/,
+       const char */*tkfile*/);
+
+void KRB5_LIB_FUNCTION
+_krb5_krb_free_auth_data (
+       krb5_context /*context*/,
+       struct _krb5_krb_auth_data */*ad*/);
+
+time_t KRB5_LIB_FUNCTION
+_krb5_krb_life_to_time (
+       int /*start*/,
+       int /*life_*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_rd_req (
+       krb5_context /*context*/,
+       krb5_data */*authent*/,
+       const char */*service*/,
+       const char */*instance*/,
+       const char */*local_realm*/,
+       int32_t /*from_addr*/,
+       const krb5_keyblock */*key*/,
+       struct _krb5_krb_auth_data */*ad*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_tf_setup (
+       krb5_context /*context*/,
+       struct credentials */*v4creds*/,
+       const char */*tkfile*/,
+       int /*append*/);
+
+int KRB5_LIB_FUNCTION
+_krb5_krb_time_to_life (
+       time_t /*start*/,
+       time_t /*end*/);
+
+krb5_error_code
+_krb5_mk_req_internal (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       const krb5_flags /*ap_req_options*/,
+       krb5_data */*in_data*/,
+       krb5_creds */*in_creds*/,
+       krb5_data */*outbuf*/,
+       krb5_key_usage /*checksum_usage*/,
+       krb5_key_usage /*encrypt_usage*/);
+
+void KRB5_LIB_FUNCTION
+_krb5_n_fold (
+       const void */*str*/,
+       size_t /*len*/,
+       void */*key*/,
+       size_t /*size*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_oid_to_enctype (
+       krb5_context /*context*/,
+       const heim_oid */*oid*/,
+       krb5_enctype */*etype*/);
+
+void KRB5_LIB_FUNCTION
+_krb5_pk_cert_free (struct krb5_pk_cert */*cert*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_create_sign (
+       krb5_context /*context*/,
+       const heim_oid */*eContentType*/,
+       krb5_data */*eContent*/,
+       struct krb5_pk_identity */*id*/,
+       krb5_data */*sd_data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_load_openssl_id (
+       krb5_context /*context*/,
+       struct krb5_pk_identity **/*ret_id*/,
+       const char */*user_id*/,
+       const char */*x509_anchors*/,
+       krb5_prompter_fct /*prompter*/,
+       void */*prompter_data*/,
+       char */*password*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_mk_ContentInfo (
+       krb5_context /*context*/,
+       const krb5_data */*buf*/,
+       const heim_oid */*oid*/,
+       struct ContentInfo */*content_info*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_mk_padata (
+       krb5_context /*context*/,
+       void */*c*/,
+       const KDC_REQ_BODY */*req_body*/,
+       unsigned /*nonce*/,
+       METHOD_DATA */*md*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_rd_pa_reply (
+       krb5_context /*context*/,
+       void */*c*/,
+       krb5_enctype /*etype*/,
+       unsigned /*nonce*/,
+       PA_DATA */*pa*/,
+       krb5_keyblock **/*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_verify_sign (
+       krb5_context /*context*/,
+       const char */*data*/,
+       size_t /*length*/,
+       struct krb5_pk_identity */*id*/,
+       heim_oid */*contentType*/,
+       krb5_data */*content*/,
+       struct krb5_pk_cert **/*signer*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_principal2principalname (
+       PrincipalName */*p*/,
+       const krb5_principal /*from*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_principalname2krb5_principal (
+       krb5_principal */*principal*/,
+       const PrincipalName /*from*/,
+       const Realm /*realm*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+_krb5_put_int (
+       void */*buffer*/,
+       unsigned long /*value*/,
+       size_t /*size*/);
+
+int
+_krb5_send_and_recv_tcp (
+       int /*fd*/,
+       time_t /*tmout*/,
+       const krb5_data */*req*/,
+       krb5_data */*rep*/);
+
+int
+_krb5_xlock (
+       krb5_context /*context*/,
+       int /*fd*/,
+       krb5_boolean /*exclusive*/,
+       const char */*filename*/);
+
+int
+_krb5_xunlock (
+       krb5_context /*context*/,
+       int /*fd*/);
+
+#endif /* __krb5_private_h__ */
diff --git a/src/kerberosV/src/lib/krb5/krb5-protos.h b/src/kerberosV/src/lib/krb5/krb5-protos.h
new file mode 100644 (file)
index 0000000..068edd5
--- /dev/null
@@ -0,0 +1,3385 @@
+/* This is a generated file */
+#ifndef __krb5_protos_h__
+#define __krb5_protos_h__
+
+#include <stdarg.h>
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(x)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef KRB5_LIB_FUNCTION
+#if defined(_WIN32)
+#define KRB5_LIB_FUNCTION _stdcall
+#else
+#define KRB5_LIB_FUNCTION
+#endif
+#endif
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb524_convert_creds_kdc (
+       krb5_context /*context*/,
+       krb5_creds */*in_cred*/,
+       struct credentials */*v4creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb524_convert_creds_kdc_ccache (
+       krb5_context /*context*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*in_cred*/,
+       struct credentials */*v4creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_425_conv_principal (
+       krb5_context /*context*/,
+       const char */*name*/,
+       const char */*instance*/,
+       const char */*realm*/,
+       krb5_principal */*princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_425_conv_principal_ext (
+       krb5_context /*context*/,
+       const char */*name*/,
+       const char */*instance*/,
+       const char */*realm*/,
+       krb5_boolean (*/*func*/)(krb5_context, krb5_principal),
+       krb5_boolean /*resolve*/,
+       krb5_principal */*princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_524_conv_principal (
+       krb5_context /*context*/,
+       const krb5_principal /*principal*/,
+       char */*name*/,
+       char */*instance*/,
+       char */*realm*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_abort (
+       krb5_context /*context*/,
+       krb5_error_code /*code*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__ ((noreturn, format (printf, 3, 4)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_abortx (
+       krb5_context /*context*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__ ((noreturn, format (printf, 2, 3)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_acl_match_file (
+       krb5_context /*context*/,
+       const char */*file*/,
+       const char */*format*/,
+       ...);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_acl_match_string (
+       krb5_context /*context*/,
+       const char */*string*/,
+       const char */*format*/,
+       ...);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_add_et_list (
+       krb5_context /*context*/,
+       void (*/*func*/)(struct et_list **));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_add_extra_addresses (
+       krb5_context /*context*/,
+       krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_add_ignore_addresses (
+       krb5_context /*context*/,
+       krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_addlog_dest (
+       krb5_context /*context*/,
+       krb5_log_facility */*f*/,
+       const char */*orig*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_addlog_func (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/,
+       int /*min*/,
+       int /*max*/,
+       krb5_log_log_func_t /*log*/,
+       krb5_log_close_func_t /*close*/,
+       void */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_addr2sockaddr (
+       krb5_context /*context*/,
+       const krb5_address */*addr*/,
+       struct sockaddr */*sa*/,
+       krb5_socklen_t */*sa_size*/,
+       int /*port*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_address_compare (
+       krb5_context /*context*/,
+       const krb5_address */*addr1*/,
+       const krb5_address */*addr2*/);
+
+int KRB5_LIB_FUNCTION
+krb5_address_order (
+       krb5_context /*context*/,
+       const krb5_address */*addr1*/,
+       const krb5_address */*addr2*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_address_prefixlen_boundary (
+       krb5_context /*context*/,
+       const krb5_address */*inaddr*/,
+       unsigned long /*prefixlen*/,
+       krb5_address */*low*/,
+       krb5_address */*high*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_address_search (
+       krb5_context /*context*/,
+       const krb5_address */*addr*/,
+       const krb5_addresses */*addrlist*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_aname_to_localname (
+       krb5_context /*context*/,
+       krb5_const_principal /*aname*/,
+       size_t /*lnsize*/,
+       char */*lname*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_anyaddr (
+       krb5_context /*context*/,
+       int /*af*/,
+       struct sockaddr */*sa*/,
+       krb5_socklen_t */*sa_size*/,
+       int /*port*/);
+
+void KRB5_LIB_FUNCTION
+krb5_appdefault_boolean (
+       krb5_context /*context*/,
+       const char */*appname*/,
+       krb5_const_realm /*realm*/,
+       const char */*option*/,
+       krb5_boolean /*def_val*/,
+       krb5_boolean */*ret_val*/);
+
+void KRB5_LIB_FUNCTION
+krb5_appdefault_string (
+       krb5_context /*context*/,
+       const char */*appname*/,
+       krb5_const_realm /*realm*/,
+       const char */*option*/,
+       const char */*def_val*/,
+       char **/*ret_val*/);
+
+void KRB5_LIB_FUNCTION
+krb5_appdefault_time (
+       krb5_context /*context*/,
+       const char */*appname*/,
+       krb5_const_realm /*realm*/,
+       const char */*option*/,
+       time_t /*def_val*/,
+       time_t */*ret_val*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_append_addresses (
+       krb5_context /*context*/,
+       krb5_addresses */*dest*/,
+       const krb5_addresses */*source*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_addflags (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t /*addflags*/,
+       int32_t */*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_free (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_genaddrs (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int /*fd*/,
+       int /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_generatelocalsubkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getaddrs (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_address **/*local_addr*/,
+       krb5_address **/*remote_addr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getauthenticator (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_authenticator */*authenticator*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getcksumtype (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_cksumtype */*cksumtype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getflags (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t */*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock **/*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getkeytype (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keytype */*keytype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getlocalseqnumber (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t */*seqnumber*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getlocalsubkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock **/*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getrcache (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_rcache */*rcache*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_getremotesubkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock **/*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_init (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_removeflags (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t /*removeflags*/,
+       int32_t */*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setaddrs (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_address */*local_addr*/,
+       krb5_address */*remote_addr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setaddrs_from_fd (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       void */*p_fd*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setcksumtype (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_cksumtype /*cksumtype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setflags (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock */*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setkeytype (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keytype /*keytype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setlocalseqnumber (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t /*seqnumber*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setlocalsubkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock */*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setrcache (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_rcache /*rcache*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setremoteseqnumber (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t /*seqnumber*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setremotesubkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock */*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_con_setuserkey (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_keyblock */*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_auth_getremoteseqnumber (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       int32_t */*seqnumber*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_ap_req (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       krb5_creds */*cred*/,
+       krb5_flags /*ap_options*/,
+       krb5_data /*authenticator*/,
+       krb5_data */*retdata*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_authenticator (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_enctype /*enctype*/,
+       krb5_creds */*cred*/,
+       Checksum */*cksum*/,
+       Authenticator **/*auth_result*/,
+       krb5_data */*result*/,
+       krb5_key_usage /*usage*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal (
+       krb5_context /*context*/,
+       krb5_principal */*principal*/,
+       int /*rlen*/,
+       krb5_const_realm /*realm*/,
+       ...);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal_ext (
+       krb5_context /*context*/,
+       krb5_principal */*principal*/,
+       int /*rlen*/,
+       krb5_const_realm /*realm*/,
+       ...);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal_va (
+       krb5_context /*context*/,
+       krb5_principal */*principal*/,
+       int /*rlen*/,
+       krb5_const_realm /*realm*/,
+       va_list /*ap*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal_va_ext (
+       krb5_context /*context*/,
+       krb5_principal */*principal*/,
+       int /*rlen*/,
+       krb5_const_realm /*realm*/,
+       va_list /*ap*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_block_size (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       size_t */*blocksize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_checksum_length (
+       krb5_context /*context*/,
+       krb5_cksumtype /*cksumtype*/,
+       size_t */*length*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_decrypt (
+       krb5_context /*context*/,
+       const krb5_keyblock /*key*/,
+       krb5_keyusage /*usage*/,
+       const krb5_data */*ivec*/,
+       krb5_enc_data */*input*/,
+       krb5_data */*output*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_encrypt_length (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       size_t /*inputlen*/,
+       size_t */*length*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_enctype_compare (
+       krb5_context /*context*/,
+       krb5_enctype /*e1*/,
+       krb5_enctype /*e2*/,
+       krb5_boolean */*similar*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_get_checksum (
+       krb5_context /*context*/,
+       const krb5_checksum */*cksum*/,
+       krb5_cksumtype */*type*/,
+       krb5_data **/*data*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_is_coll_proof_cksum (krb5_cksumtype /*ctype*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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_LIB_FUNCTION
+krb5_c_make_random_key (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       krb5_keyblock */*random_key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_set_checksum (
+       krb5_context /*context*/,
+       krb5_checksum */*cksum*/,
+       krb5_cksumtype /*type*/,
+       const krb5_data */*data*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_valid_cksumtype (krb5_cksumtype /*ctype*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_valid_enctype (krb5_enctype /*etype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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*/);
+
+void KRB5_LIB_FUNCTION
+krb5_cc_clear_mcred (krb5_creds */*mcred*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_close (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_copy_cache (
+       krb5_context /*context*/,
+       const krb5_ccache /*from*/,
+       krb5_ccache /*to*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_copy_cache_match (
+       krb5_context /*context*/,
+       const krb5_ccache /*from*/,
+       krb5_ccache /*to*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds * /*mcreds*/,
+       unsigned int */*matched*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_default (
+       krb5_context /*context*/,
+       krb5_ccache */*id*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_cc_default_name (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_destroy (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_end_seq_get (
+       krb5_context /*context*/,
+       const krb5_ccache /*id*/,
+       krb5_cc_cursor */*cursor*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_gen_new (
+       krb5_context /*context*/,
+       const krb5_cc_ops */*ops*/,
+       krb5_ccache */*id*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_cc_get_name (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/);
+
+const krb5_cc_ops *
+krb5_cc_get_ops (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/);
+
+const krb5_cc_ops *
+krb5_cc_get_prefix_ops (
+       krb5_context /*context*/,
+       const char */*prefix*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_principal (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_principal */*principal*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_cc_get_type (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_version (
+       krb5_context /*context*/,
+       const krb5_ccache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_initialize (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_principal /*primary_principal*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_new_unique (
+       krb5_context /*context*/,
+       const char */*type*/,
+       const char */*hint*/,
+       krb5_ccache */*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_next_cred (
+       krb5_context /*context*/,
+       const krb5_ccache /*id*/,
+       krb5_cc_cursor */*cursor*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_next_cred_match (
+       krb5_context /*context*/,
+       const krb5_ccache /*id*/,
+       krb5_cc_cursor * /*cursor*/,
+       krb5_creds * /*creds*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds * /*mcreds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_register (
+       krb5_context /*context*/,
+       const krb5_cc_ops */*ops*/,
+       krb5_boolean /*override*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_remove_cred (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_flags /*which*/,
+       krb5_creds */*cred*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_resolve (
+       krb5_context /*context*/,
+       const char */*name*/,
+       krb5_ccache */*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_retrieve_cred (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds */*mcreds*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_set_default_name (
+       krb5_context /*context*/,
+       const char */*name*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_set_flags (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_flags /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_start_seq_get (
+       krb5_context /*context*/,
+       const krb5_ccache /*id*/,
+       krb5_cc_cursor */*cursor*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_store_cred (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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_LIB_FUNCTION
+krb5_check_transited (
+       krb5_context /*context*/,
+       krb5_const_realm /*client_realm*/,
+       krb5_const_realm /*server_realm*/,
+       krb5_realm */*realms*/,
+       int /*num_realms*/,
+       int */*bad_realm*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_check_transited_realms (
+       krb5_context /*context*/,
+       const char *const */*realms*/,
+       int /*num_realms*/,
+       int */*bad_realm*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_checksum_disable (
+       krb5_context /*context*/,
+       krb5_cksumtype /*type*/);
+
+void KRB5_LIB_FUNCTION
+krb5_checksum_free (
+       krb5_context /*context*/,
+       krb5_checksum */*cksum*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_checksum_is_collision_proof (
+       krb5_context /*context*/,
+       krb5_cksumtype /*type*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_checksum_is_keyed (
+       krb5_context /*context*/,
+       krb5_cksumtype /*type*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_checksumsize (
+       krb5_context /*context*/,
+       krb5_cksumtype /*type*/,
+       size_t */*size*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cksumtype_valid (
+       krb5_context /*context*/,
+       krb5_cksumtype /*ctype*/);
+
+void KRB5_LIB_FUNCTION
+krb5_clear_error_string (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_closelog (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_compare_creds (
+       krb5_context /*context*/,
+       krb5_flags /*whichfields*/,
+       const krb5_creds * /*mcreds*/,
+       const krb5_creds * /*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_file_free (
+       krb5_context /*context*/,
+       krb5_config_section */*s*/);
+
+void KRB5_LIB_FUNCTION
+krb5_config_free_strings (char **/*strings*/);
+
+const void *
+krb5_config_get (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       int /*type*/,
+       ...);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_get_bool (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       ...);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_get_bool_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       krb5_boolean /*def_value*/,
+       ...);
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_int (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       ...);
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_int_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       int /*def_value*/,
+       ...);
+
+const krb5_config_binding *
+krb5_config_get_list (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       ...);
+
+const void *
+krb5_config_get_next (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       const krb5_config_binding **/*pointer*/,
+       int /*type*/,
+       ...);
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_get_string (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       ...);
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_get_string_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       const char */*def_value*/,
+       ...);
+
+char**
+krb5_config_get_strings (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       ...);
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_time (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       ...);
+
+int KRB5_LIB_FUNCTION
+krb5_config_get_time_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       int /*def_value*/,
+       ...);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_file (
+       krb5_context /*context*/,
+       const char */*fname*/,
+       krb5_config_section **/*res*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_file_multi (
+       krb5_context /*context*/,
+       const char */*fname*/,
+       krb5_config_section **/*res*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_config_parse_string_multi (
+       krb5_context /*context*/,
+       const char */*string*/,
+       krb5_config_section **/*res*/);
+
+const void *
+krb5_config_vget (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       int /*type*/,
+       va_list /*args*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_vget_bool (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       va_list /*args*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_config_vget_bool_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       krb5_boolean /*def_value*/,
+       va_list /*args*/);
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_int (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       va_list /*args*/);
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_int_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       int /*def_value*/,
+       va_list /*args*/);
+
+const krb5_config_binding *
+krb5_config_vget_list (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       va_list /*args*/);
+
+const void *
+krb5_config_vget_next (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       const krb5_config_binding **/*pointer*/,
+       int /*type*/,
+       va_list /*args*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_vget_string (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       va_list /*args*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_config_vget_string_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       const char */*def_value*/,
+       va_list /*args*/);
+
+char ** KRB5_LIB_FUNCTION
+krb5_config_vget_strings (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       va_list /*args*/);
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_time (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       va_list /*args*/);
+
+int KRB5_LIB_FUNCTION
+krb5_config_vget_time_default (
+       krb5_context /*context*/,
+       const krb5_config_section */*c*/,
+       int /*def_value*/,
+       va_list /*args*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_address (
+       krb5_context /*context*/,
+       const krb5_address */*inaddr*/,
+       krb5_address */*outaddr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_addresses (
+       krb5_context /*context*/,
+       const krb5_addresses */*inaddr*/,
+       krb5_addresses */*outaddr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_checksum (
+       krb5_context /*context*/,
+       const krb5_checksum */*old*/,
+       krb5_checksum **/*new*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_creds (
+       krb5_context /*context*/,
+       const krb5_creds */*incred*/,
+       krb5_creds **/*outcred*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_creds_contents (
+       krb5_context /*context*/,
+       const krb5_creds */*incred*/,
+       krb5_creds */*c*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_data (
+       krb5_context /*context*/,
+       const krb5_data */*indata*/,
+       krb5_data **/*outdata*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_host_realm (
+       krb5_context /*context*/,
+       const krb5_realm */*from*/,
+       krb5_realm **/*to*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_keyblock (
+       krb5_context /*context*/,
+       const krb5_keyblock */*inblock*/,
+       krb5_keyblock **/*to*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_keyblock_contents (
+       krb5_context /*context*/,
+       const krb5_keyblock */*inblock*/,
+       krb5_keyblock */*to*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_principal (
+       krb5_context /*context*/,
+       krb5_const_principal /*inprinc*/,
+       krb5_principal */*outprinc*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_ticket (
+       krb5_context /*context*/,
+       const krb5_ticket */*from*/,
+       krb5_ticket **/*to*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_create_checksum (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       krb5_key_usage /*usage*/,
+       int /*type*/,
+       void */*data*/,
+       size_t /*len*/,
+       Checksum */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_destroy (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_get_checksum_type (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       krb5_cksumtype */*type*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_get_params (
+       krb5_context /*context*/,
+       const krb5_crypto /*crypto*/,
+       const krb5_data */*params*/,
+       krb5_data */*ivec*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getblocksize (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       size_t */*blocksize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getconfoundersize (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       size_t */*confoundersize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getenctype (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       krb5_enctype */*enctype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_getpadsize (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       size_t */*padsize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_init (
+       krb5_context /*context*/,
+       const krb5_keyblock */*key*/,
+       krb5_enctype /*etype*/,
+       krb5_crypto */*crypto*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_set_params (
+       krb5_context /*context*/,
+       const krb5_crypto /*crypto*/,
+       const krb5_data */*ivec*/,
+       krb5_data */*params*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_data_alloc (
+       krb5_data */*p*/,
+       int /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_data_copy (
+       krb5_data */*p*/,
+       const void */*data*/,
+       size_t /*len*/);
+
+void KRB5_LIB_FUNCTION
+krb5_data_free (krb5_data */*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_data_realloc (
+       krb5_data */*p*/,
+       int /*len*/);
+
+void KRB5_LIB_FUNCTION
+krb5_data_zero (krb5_data */*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_Authenticator (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       Authenticator */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_ETYPE_INFO (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       ETYPE_INFO */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_ETYPE_INFO2 (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       ETYPE_INFO2 */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncAPRepPart (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       EncAPRepPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncASRepPart (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       EncASRepPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncKrbCredPart (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       EncKrbCredPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncTGSRepPart (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       EncTGSRepPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_EncTicketPart (
+       krb5_context /*context*/,
+       const void */*data*/,
+       size_t /*length*/,
+       EncTicketPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_ap_req (
+       krb5_context /*context*/,
+       const krb5_data */*inbuf*/,
+       krb5_ap_req */*ap_req*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       unsigned /*usage*/,
+       void */*data*/,
+       size_t /*len*/,
+       krb5_data */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt_EncryptedData (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       unsigned /*usage*/,
+       const EncryptedData */*e*/,
+       krb5_data */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt_ivec (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       unsigned /*usage*/,
+       void */*data*/,
+       size_t /*len*/,
+       krb5_data */*result*/,
+       void */*ivec*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt_ticket (
+       krb5_context /*context*/,
+       Ticket */*ticket*/,
+       krb5_keyblock */*key*/,
+       EncTicketPart */*out*/,
+       krb5_flags /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_derive_key (
+       krb5_context /*context*/,
+       const krb5_keyblock */*key*/,
+       krb5_enctype /*etype*/,
+       const void */*constant*/,
+       size_t /*constant_len*/,
+       krb5_keyblock **/*derived_key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_domain_x500_decode (
+       krb5_context /*context*/,
+       krb5_data /*tr*/,
+       char ***/*realms*/,
+       int */*num_realms*/,
+       const char */*client_realm*/,
+       const char */*server_realm*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_domain_x500_encode (
+       char **/*realms*/,
+       int /*num_realms*/,
+       krb5_data */*encoding*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_eai_to_heim_errno (
+       int /*eai_errno*/,
+       int /*system_error*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_Authenticator (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       Authenticator */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_ETYPE_INFO (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       ETYPE_INFO */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_ETYPE_INFO2 (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       ETYPE_INFO2 */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncAPRepPart (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       EncAPRepPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncASRepPart (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       EncASRepPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncKrbCredPart (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       EncKrbCredPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncTGSRepPart (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       EncTGSRepPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encode_EncTicketPart (
+       krb5_context /*context*/,
+       void */*data*/,
+       size_t /*length*/,
+       EncTicketPart */*t*/,
+       size_t */*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encrypt (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       unsigned /*usage*/,
+       void */*data*/,
+       size_t /*len*/,
+       krb5_data */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encrypt_EncryptedData (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       unsigned /*usage*/,
+       void */*data*/,
+       size_t /*len*/,
+       int /*kvno*/,
+       EncryptedData */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_encrypt_ivec (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       unsigned /*usage*/,
+       void */*data*/,
+       size_t /*len*/,
+       krb5_data */*result*/,
+       void */*ivec*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_disable (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_keysize (
+       krb5_context /*context*/,
+       krb5_enctype /*type*/,
+       size_t */*keysize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_to_keytype (
+       krb5_context /*context*/,
+       krb5_enctype /*etype*/,
+       krb5_keytype */*keytype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_to_oid (
+       krb5_context /*context*/,
+       krb5_enctype /*etype*/,
+       heim_oid */*oid*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_to_string (
+       krb5_context /*context*/,
+       krb5_enctype /*etype*/,
+       char **/*string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_enctype_valid (
+       krb5_context /*context*/,
+       krb5_enctype /*etype*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_enctypes_compatible_keys (
+       krb5_context /*context*/,
+       krb5_enctype /*etype1*/,
+       krb5_enctype /*etype2*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_err (
+       krb5_context /*context*/,
+       int /*eval*/,
+       krb5_error_code /*code*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__ ((noreturn, format (printf, 4, 5)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_error_from_rd_error (
+       krb5_context /*context*/,
+       const krb5_error */*error*/,
+       const krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_errx (
+       krb5_context /*context*/,
+       int /*eval*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__ ((noreturn, format (printf, 3, 4)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_expand_hostname (
+       krb5_context /*context*/,
+       const char */*orig_hostname*/,
+       char **/*new_hostname*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_expand_hostname_realms (
+       krb5_context /*context*/,
+       const char */*orig_hostname*/,
+       char **/*new_hostname*/,
+       char ***/*realms*/);
+
+PA_DATA *
+krb5_find_padata (
+       PA_DATA */*val*/,
+       unsigned /*len*/,
+       int /*type*/,
+       int */*index*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_format_time (
+       krb5_context /*context*/,
+       time_t /*t*/,
+       char */*s*/,
+       size_t /*len*/,
+       krb5_boolean /*include_time*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_address (
+       krb5_context /*context*/,
+       krb5_address */*address*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_addresses (
+       krb5_context /*context*/,
+       krb5_addresses */*addresses*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_ap_rep_enc_part (
+       krb5_context /*context*/,
+       krb5_ap_rep_enc_part */*val*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_authenticator (
+       krb5_context /*context*/,
+       krb5_authenticator */*authenticator*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_checksum (
+       krb5_context /*context*/,
+       krb5_checksum */*cksum*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_checksum_contents (
+       krb5_context /*context*/,
+       krb5_checksum */*cksum*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_config_files (char **/*filenames*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_context (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_cred_contents (
+       krb5_context /*context*/,
+       krb5_creds */*c*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_creds (
+       krb5_context /*context*/,
+       krb5_creds */*c*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_creds_contents (
+       krb5_context /*context*/,
+       krb5_creds */*c*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_data (
+       krb5_context /*context*/,
+       krb5_data */*p*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_data_contents (
+       krb5_context /*context*/,
+       krb5_data */*data*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_error (
+       krb5_context /*context*/,
+       krb5_error */*error*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_error_contents (
+       krb5_context /*context*/,
+       krb5_error */*error*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_error_string (
+       krb5_context /*context*/,
+       char */*str*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_host_realm (
+       krb5_context /*context*/,
+       krb5_realm */*realmlist*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_kdc_rep (
+       krb5_context /*context*/,
+       krb5_kdc_rep */*rep*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_keyblock (
+       krb5_context /*context*/,
+       krb5_keyblock */*keyblock*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_keyblock_contents (
+       krb5_context /*context*/,
+       krb5_keyblock */*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_krbhst (
+       krb5_context /*context*/,
+       char **/*hostlist*/);
+
+void KRB5_LIB_FUNCTION
+krb5_free_principal (
+       krb5_context /*context*/,
+       krb5_principal /*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_salt (
+       krb5_context /*context*/,
+       krb5_salt /*salt*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_ticket (
+       krb5_context /*context*/,
+       krb5_ticket */*ticket*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_fwd_tgt_creds (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       const char */*hostname*/,
+       krb5_principal /*client*/,
+       krb5_principal /*server*/,
+       krb5_ccache /*ccache*/,
+       int /*forwardable*/,
+       krb5_data */*out_data*/);
+
+void KRB5_LIB_FUNCTION
+krb5_generate_random_block (
+       void */*buf*/,
+       size_t /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_random_keyblock (
+       krb5_context /*context*/,
+       krb5_enctype /*type*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_seq_number (
+       krb5_context /*context*/,
+       const krb5_keyblock */*key*/,
+       u_int32_t */*seqno*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_subkey (
+       krb5_context /*context*/,
+       const krb5_keyblock */*key*/,
+       krb5_keyblock **/*subkey*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_generate_subkey_extended (
+       krb5_context /*context*/,
+       const krb5_keyblock */*key*/,
+       krb5_enctype /*etype*/,
+       krb5_keyblock **/*subkey*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_all_client_addrs (
+       krb5_context /*context*/,
+       krb5_addresses */*res*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_all_server_addrs (
+       krb5_context /*context*/,
+       krb5_addresses */*res*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_cred_from_kdc (
+       krb5_context /*context*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*in_creds*/,
+       krb5_creds **/*out_creds*/,
+       krb5_creds ***/*ret_tgts*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_cred_from_kdc_opt (
+       krb5_context /*context*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*in_creds*/,
+       krb5_creds **/*out_creds*/,
+       krb5_creds ***/*ret_tgts*/,
+       krb5_flags /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_credentials (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*in_creds*/,
+       krb5_creds **/*out_creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_credentials_with_flags (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       krb5_kdc_flags /*flags*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*in_creds*/,
+       krb5_creds **/*out_creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_config_files (char ***/*pfilenames*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_in_tkt_etypes (
+       krb5_context /*context*/,
+       krb5_enctype **/*etypes*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_principal (
+       krb5_context /*context*/,
+       krb5_principal */*princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_realm (
+       krb5_context /*context*/,
+       krb5_realm */*realm*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_default_realms (
+       krb5_context /*context*/,
+       krb5_realm **/*realms*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_get_err_text (
+       krb5_context /*context*/,
+       krb5_error_code /*code*/);
+
+char * KRB5_LIB_FUNCTION
+krb5_get_error_string (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_extra_addresses (
+       krb5_context /*context*/,
+       krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_fcache_version (
+       krb5_context /*context*/,
+       int */*version*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_forwarded_creds (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_ccache /*ccache*/,
+       krb5_flags /*flags*/,
+       const char */*hostname*/,
+       krb5_creds */*in_creds*/,
+       krb5_data */*out_data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_host_realm (
+       krb5_context /*context*/,
+       const char */*host*/,
+       krb5_realm **/*realms*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_ignore_addresses (
+       krb5_context /*context*/,
+       krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_cred (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       const krb5_addresses */*addrs*/,
+       const krb5_enctype */*etypes*/,
+       const krb5_preauthtype */*ptypes*/,
+       const krb5_preauthdata */*preauth*/,
+       krb5_key_proc /*key_proc*/,
+       krb5_const_pointer /*keyseed*/,
+       krb5_decrypt_proc /*decrypt_proc*/,
+       krb5_const_pointer /*decryptarg*/,
+       krb5_creds */*creds*/,
+       krb5_kdc_rep */*ret_as_reply*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       const krb5_addresses */*addrs*/,
+       const krb5_enctype */*etypes*/,
+       const krb5_preauthtype */*ptypes*/,
+       krb5_key_proc /*key_proc*/,
+       krb5_const_pointer /*keyseed*/,
+       krb5_decrypt_proc /*decrypt_proc*/,
+       krb5_const_pointer /*decryptarg*/,
+       krb5_creds */*creds*/,
+       krb5_ccache /*ccache*/,
+       krb5_kdc_rep */*ret_as_reply*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt_with_keytab (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       krb5_addresses */*addrs*/,
+       const krb5_enctype */*etypes*/,
+       const krb5_preauthtype */*pre_auth_types*/,
+       krb5_keytab /*keytab*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*creds*/,
+       krb5_kdc_rep */*ret_as_reply*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt_with_password (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       krb5_addresses */*addrs*/,
+       const krb5_enctype */*etypes*/,
+       const krb5_preauthtype */*pre_auth_types*/,
+       const char */*password*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*creds*/,
+       krb5_kdc_rep */*ret_as_reply*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_in_tkt_with_skey (
+       krb5_context /*context*/,
+       krb5_flags /*options*/,
+       krb5_addresses */*addrs*/,
+       const krb5_enctype */*etypes*/,
+       const krb5_preauthtype */*pre_auth_types*/,
+       const krb5_keyblock */*key*/,
+       krb5_ccache /*ccache*/,
+       krb5_creds */*creds*/,
+       krb5_kdc_rep */*ret_as_reply*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds (
+       krb5_context /*context*/,
+       krb5_creds */*creds*/,
+       krb5_principal /*client*/,
+       krb5_prompter_fct /*prompter*/,
+       void */*data*/,
+       krb5_deltat /*start_time*/,
+       const char */*in_tkt_service*/,
+       krb5_get_init_creds_opt */*options*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_keyblock (
+       krb5_context /*context*/,
+       krb5_creds */*creds*/,
+       krb5_principal /*client*/,
+       krb5_keyblock */*keyblock*/,
+       krb5_deltat /*start_time*/,
+       const char */*in_tkt_service*/,
+       krb5_get_init_creds_opt */*options*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_keytab (
+       krb5_context /*context*/,
+       krb5_creds */*creds*/,
+       krb5_principal /*client*/,
+       krb5_keytab /*keytab*/,
+       krb5_deltat /*start_time*/,
+       const char */*in_tkt_service*/,
+       krb5_get_init_creds_opt */*options*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_alloc (
+       krb5_context /*context*/,
+       krb5_get_init_creds_opt **/*opt*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_free (krb5_get_init_creds_opt */*opt*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_init (krb5_get_init_creds_opt */*opt*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_address_list (
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_addresses */*addresses*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_anonymous (
+       krb5_get_init_creds_opt */*opt*/,
+       int /*anonymous*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_default_flags (
+       krb5_context /*context*/,
+       const char */*appname*/,
+       krb5_const_realm /*realm*/,
+       krb5_get_init_creds_opt */*opt*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_etype_list (
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_enctype */*etype_list*/,
+       int /*etype_list_length*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_forwardable (
+       krb5_get_init_creds_opt */*opt*/,
+       int /*forwardable*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_pa_password (
+       krb5_context /*context*/,
+       krb5_get_init_creds_opt */*opt*/,
+       const char */*password*/,
+       krb5_s2k_proc /*key_proc*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_pac_request (
+       krb5_context /*context*/,
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_boolean /*req_pac*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_pkinit (
+       krb5_context /*context*/,
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_principal /*principal*/,
+       const char */*user_id*/,
+       const char */*x509_anchors*/,
+       int /*flags*/,
+       krb5_prompter_fct /*prompter*/,
+       void */*prompter_data*/,
+       char */*password*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_preauth_list (
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_preauthtype */*preauth_list*/,
+       int /*preauth_list_length*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_proxiable (
+       krb5_get_init_creds_opt */*opt*/,
+       int /*proxiable*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_renew_life (
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_deltat /*renew_life*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_salt (
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_data */*salt*/);
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_tkt_life (
+       krb5_get_init_creds_opt */*opt*/,
+       krb5_deltat /*tkt_life*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_password (
+       krb5_context /*context*/,
+       krb5_creds */*creds*/,
+       krb5_principal /*client*/,
+       const char */*password*/,
+       krb5_prompter_fct /*prompter*/,
+       void */*data*/,
+       krb5_deltat /*start_time*/,
+       const char */*in_tkt_service*/,
+       krb5_get_init_creds_opt */*in_options*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_kdc_cred (
+       krb5_context /*context*/,
+       krb5_ccache /*id*/,
+       krb5_kdc_flags /*flags*/,
+       krb5_addresses */*addresses*/,
+       Ticket */*second_ticket*/,
+       krb5_creds */*in_creds*/,
+       krb5_creds **out_creds );
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krb524hst (
+       krb5_context /*context*/,
+       const krb5_realm */*realm*/,
+       char ***/*hostlist*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krb_admin_hst (
+       krb5_context /*context*/,
+       const krb5_realm */*realm*/,
+       char ***/*hostlist*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krb_changepw_hst (
+       krb5_context /*context*/,
+       const krb5_realm */*realm*/,
+       char ***/*hostlist*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krbhst (
+       krb5_context /*context*/,
+       const krb5_realm */*realm*/,
+       char ***/*hostlist*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_pw_salt (
+       krb5_context /*context*/,
+       krb5_const_principal /*principal*/,
+       krb5_salt */*salt*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_server_rcache (
+       krb5_context /*context*/,
+       const krb5_data */*piece*/,
+       krb5_rcache */*id*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_get_use_admin_kdc (krb5_context /*context*/);
+
+size_t
+krb5_get_wrapped_length (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       size_t /*data_len*/);
+
+int KRB5_LIB_FUNCTION
+krb5_getportbyname (
+       krb5_context /*context*/,
+       const char */*service*/,
+       const char */*proto*/,
+       int /*default_port*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_h_addr2addr (
+       krb5_context /*context*/,
+       int /*af*/,
+       const char */*haddr*/,
+       krb5_address */*addr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_h_addr2sockaddr (
+       krb5_context /*context*/,
+       int /*af*/,
+       const char */*addr*/,
+       struct sockaddr */*sa*/,
+       krb5_socklen_t */*sa_size*/,
+       int /*port*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_h_errno_to_heim_errno (int /*eai_errno*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_have_error_string (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_hmac (
+       krb5_context /*context*/,
+       krb5_cksumtype /*cktype*/,
+       const void */*data*/,
+       size_t /*len*/,
+       unsigned /*usage*/,
+       krb5_keyblock */*key*/,
+       Checksum */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_context (krb5_context */*context*/);
+
+void KRB5_LIB_FUNCTION
+krb5_init_ets (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_etype (
+       krb5_context /*context*/,
+       unsigned */*len*/,
+       krb5_enctype **/*val*/,
+       const krb5_enctype */*etypes*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_initlog (
+       krb5_context /*context*/,
+       const char */*program*/,
+       krb5_log_facility **/*fac*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_is_thread_safe (void);
+
+krb5_enctype
+krb5_keyblock_get_enctype (const krb5_keyblock */*block*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keyblock_init (
+       krb5_context /*context*/,
+       krb5_enctype /*type*/,
+       const void */*data*/,
+       size_t /*size*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keyblock_key_proc (
+       krb5_context /*context*/,
+       krb5_keytype /*type*/,
+       krb5_data */*salt*/,
+       krb5_const_pointer /*keyseed*/,
+       krb5_keyblock **/*key*/);
+
+void KRB5_LIB_FUNCTION
+krb5_keyblock_zero (krb5_keyblock */*keyblock*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytab_key_proc (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       krb5_salt /*salt*/,
+       krb5_const_pointer /*keyseed*/,
+       krb5_keyblock **/*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_enctypes (
+       krb5_context /*context*/,
+       krb5_keytype /*keytype*/,
+       unsigned */*len*/,
+       krb5_enctype **/*val*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_enctypes_default (
+       krb5_context /*context*/,
+       krb5_keytype /*keytype*/,
+       unsigned */*len*/,
+       krb5_enctype **/*val*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_keytype_to_string (
+       krb5_context /*context*/,
+       krb5_keytype /*keytype*/,
+       char **/*string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_format_string (
+       krb5_context /*context*/,
+       const krb5_krbhst_info */*host*/,
+       char */*hostname*/,
+       size_t /*hostlen*/);
+
+void KRB5_LIB_FUNCTION
+krb5_krbhst_free (
+       krb5_context /*context*/,
+       krb5_krbhst_handle /*handle*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_get_addrinfo (
+       krb5_context /*context*/,
+       krb5_krbhst_info */*host*/,
+       struct addrinfo **/*ai*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_init (
+       krb5_context /*context*/,
+       const char */*realm*/,
+       unsigned int /*type*/,
+       krb5_krbhst_handle */*handle*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_init_flags (
+       krb5_context /*context*/,
+       const char */*realm*/,
+       unsigned int /*type*/,
+       int /*flags*/,
+       krb5_krbhst_handle */*handle*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_next (
+       krb5_context /*context*/,
+       krb5_krbhst_handle /*handle*/,
+       krb5_krbhst_info **/*host*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_next_as_string (
+       krb5_context /*context*/,
+       krb5_krbhst_handle /*handle*/,
+       char */*hostname*/,
+       size_t /*hostlen*/);
+
+void KRB5_LIB_FUNCTION
+krb5_krbhst_reset (
+       krb5_context /*context*/,
+       krb5_krbhst_handle /*handle*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_add_entry (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/,
+       krb5_keytab_entry */*entry*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_close (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_kt_compare (
+       krb5_context /*context*/,
+       krb5_keytab_entry */*entry*/,
+       krb5_const_principal /*principal*/,
+       krb5_kvno /*vno*/,
+       krb5_enctype /*enctype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_copy_entry_contents (
+       krb5_context /*context*/,
+       const krb5_keytab_entry */*in*/,
+       krb5_keytab_entry */*out*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_default (
+       krb5_context /*context*/,
+       krb5_keytab */*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_default_modify_name (
+       krb5_context /*context*/,
+       char */*name*/,
+       size_t /*namesize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_default_name (
+       krb5_context /*context*/,
+       char */*name*/,
+       size_t /*namesize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_end_seq_get (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/,
+       krb5_kt_cursor */*cursor*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_free_entry (
+       krb5_context /*context*/,
+       krb5_keytab_entry */*entry*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_entry (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/,
+       krb5_const_principal /*principal*/,
+       krb5_kvno /*kvno*/,
+       krb5_enctype /*enctype*/,
+       krb5_keytab_entry */*entry*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_name (
+       krb5_context /*context*/,
+       krb5_keytab /*keytab*/,
+       char */*name*/,
+       size_t /*namesize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_get_type (
+       krb5_context /*context*/,
+       krb5_keytab /*keytab*/,
+       char */*prefix*/,
+       size_t /*prefixsize*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_next_entry (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/,
+       krb5_keytab_entry */*entry*/,
+       krb5_kt_cursor */*cursor*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 KRB5_LIB_FUNCTION
+krb5_kt_register (
+       krb5_context /*context*/,
+       const krb5_kt_ops */*ops*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_remove_entry (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/,
+       krb5_keytab_entry */*entry*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_resolve (
+       krb5_context /*context*/,
+       const char */*name*/,
+       krb5_keytab */*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_start_seq_get (
+       krb5_context /*context*/,
+       krb5_keytab /*id*/,
+       krb5_kt_cursor */*cursor*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_kuserok (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       const char */*luser*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_log (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/,
+       int /*level*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__((format (printf, 4, 5)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_log_msg (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/,
+       int /*level*/,
+       char **/*reply*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__((format (printf, 5, 6)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_make_addrport (
+       krb5_context /*context*/,
+       krb5_address **/*res*/,
+       const krb5_address */*addr*/,
+       int16_t /*port*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_make_principal (
+       krb5_context /*context*/,
+       krb5_principal */*principal*/,
+       krb5_const_realm /*realm*/,
+       ...);
+
+size_t KRB5_LIB_FUNCTION
+krb5_max_sockaddr_size (void);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_error (
+       krb5_context /*context*/,
+       krb5_error_code /*error_code*/,
+       const char */*e_text*/,
+       const krb5_data */*e_data*/,
+       const krb5_principal /*client*/,
+       const krb5_principal /*server*/,
+       time_t */*client_time*/,
+       int */*client_usec*/,
+       krb5_data */*reply*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 KRB5_LIB_FUNCTION
+krb5_mk_rep (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_data */*outbuf*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_req (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       const krb5_flags /*ap_req_options*/,
+       const char */*service*/,
+       const char */*hostname*/,
+       krb5_data */*in_data*/,
+       krb5_ccache /*ccache*/,
+       krb5_data */*outbuf*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_req_exact (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       const krb5_flags /*ap_req_options*/,
+       const krb5_principal /*server*/,
+       krb5_data */*in_data*/,
+       krb5_ccache /*ccache*/,
+       krb5_data */*outbuf*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_req_extended (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       const krb5_flags /*ap_req_options*/,
+       krb5_data */*in_data*/,
+       krb5_creds */*in_creds*/,
+       krb5_data */*outbuf*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_safe (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       const krb5_data */*userdata*/,
+       krb5_data */*outbuf*/,
+       krb5_replay_data */*outdata*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_net_read (
+       krb5_context /*context*/,
+       void */*p_fd*/,
+       void */*buf*/,
+       size_t /*len*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_net_write (
+       krb5_context /*context*/,
+       void */*p_fd*/,
+       const void */*buf*/,
+       size_t /*len*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_net_write_block (
+       krb5_context /*context*/,
+       void */*p_fd*/,
+       const void */*buf*/,
+       size_t /*len*/,
+       time_t /*timeout*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_openlog (
+       krb5_context /*context*/,
+       const char */*program*/,
+       krb5_log_facility **/*fac*/);
+
+int KRB5_LIB_FUNCTION
+krb5_padata_add (
+       krb5_context /*context*/,
+       METHOD_DATA */*md*/,
+       int /*type*/,
+       void */*buf*/,
+       size_t /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_parse_address (
+       krb5_context /*context*/,
+       const char */*string*/,
+       krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_parse_name (
+       krb5_context /*context*/,
+       const char */*name*/,
+       krb5_principal */*principal*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_passwd_result_to_string (
+       krb5_context /*context*/,
+       int /*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_password_key_proc (
+       krb5_context /*context*/,
+       krb5_enctype /*type*/,
+       krb5_salt /*salt*/,
+       krb5_const_pointer /*keyseed*/,
+       krb5_keyblock **/*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_prepend_config_files (
+       const char */*filelist*/,
+       char **/*pq*/,
+       char ***/*ret_pp*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_prepend_config_files_default (
+       const char */*filelist*/,
+       char ***/*pfilenames*/);
+
+krb5_realm*
+krb5_princ_realm (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/);
+
+void KRB5_LIB_FUNCTION
+krb5_princ_set_realm (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       krb5_realm */*realm*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_principal_compare (
+       krb5_context /*context*/,
+       krb5_const_principal /*princ1*/,
+       krb5_const_principal /*princ2*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_principal_compare_any_realm (
+       krb5_context /*context*/,
+       krb5_const_principal /*princ1*/,
+       krb5_const_principal /*princ2*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_principal_get_comp_string (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       unsigned int /*component*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_principal_get_realm (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/);
+
+int KRB5_LIB_FUNCTION
+krb5_principal_get_type (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_principal_match (
+       krb5_context /*context*/,
+       krb5_const_principal /*princ*/,
+       krb5_const_principal /*pattern*/);
+
+void KRB5_LIB_FUNCTION
+krb5_principal_set_type (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       int /*type*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_print_address (
+       const krb5_address */*addr*/,
+       char */*str*/,
+       size_t /*len*/,
+       size_t */*ret_len*/);
+
+int KRB5_LIB_FUNCTION
+krb5_program_setup (
+       krb5_context */*context*/,
+       int /*argc*/,
+       char **/*argv*/,
+       struct getargs */*args*/,
+       int /*num_args*/,
+       void (*/*usage*/)(int, struct getargs*, int));
+
+int KRB5_LIB_FUNCTION
+krb5_prompter_posix (
+       krb5_context /*context*/,
+       void */*data*/,
+       const char */*name*/,
+       const char */*banner*/,
+       int /*num_prompts*/,
+       krb5_prompt prompts[]);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_random_to_key (
+       krb5_context /*context*/,
+       krb5_enctype /*type*/,
+       const void */*data*/,
+       size_t /*size*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_close (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_default (
+       krb5_context /*context*/,
+       krb5_rcache */*id*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_default_name (krb5_context /*context*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_default_type (krb5_context /*context*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_destroy (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_expunge (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_get_lifespan (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/,
+       krb5_deltat */*auth_lifespan*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_get_name (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/);
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_get_type (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_initialize (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/,
+       krb5_deltat /*auth_lifespan*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_recover (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_resolve (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/,
+       const char */*name*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_resolve_full (
+       krb5_context /*context*/,
+       krb5_rcache */*id*/,
+       const char */*string_name*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_resolve_type (
+       krb5_context /*context*/,
+       krb5_rcache */*id*/,
+       const char */*type*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_store (
+       krb5_context /*context*/,
+       krb5_rcache /*id*/,
+       krb5_donot_replay */*rep*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_cred (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_data */*in_data*/,
+       krb5_creds ***/*ret_creds*/,
+       krb5_replay_data */*outdata*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_cred2 (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       krb5_ccache /*ccache*/,
+       krb5_data */*in_data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_error (
+       krb5_context /*context*/,
+       krb5_data */*msg*/,
+       KRB_ERROR */*result*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 KRB5_LIB_FUNCTION
+krb5_rd_rep (
+       krb5_context /*context*/,
+       krb5_auth_context /*auth_context*/,
+       const krb5_data */*inbuf*/,
+       krb5_ap_rep_enc_part **/*repl*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 KRB5_LIB_FUNCTION
+krb5_rd_req_with_keyblock (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       const krb5_data */*inbuf*/,
+       krb5_const_principal /*server*/,
+       krb5_keyblock */*keyblock*/,
+       krb5_flags */*ap_req_options*/,
+       krb5_ticket **/*ticket*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 KRB5_LIB_FUNCTION
+krb5_read_message (
+       krb5_context /*context*/,
+       krb5_pointer /*p_fd*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_read_priv_message (
+       krb5_context /*context*/,
+       krb5_auth_context /*ac*/,
+       krb5_pointer /*p_fd*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_read_safe_message (
+       krb5_context /*context*/,
+       krb5_auth_context /*ac*/,
+       krb5_pointer /*p_fd*/,
+       krb5_data */*data*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_realm_compare (
+       krb5_context /*context*/,
+       krb5_const_principal /*princ1*/,
+       krb5_const_principal /*princ2*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_recvauth (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       krb5_pointer /*p_fd*/,
+       const char */*appl_version*/,
+       krb5_principal /*server*/,
+       int32_t /*flags*/,
+       krb5_keytab /*keytab*/,
+       krb5_ticket **/*ticket*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_recvauth_match_version (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       krb5_pointer /*p_fd*/,
+       krb5_boolean (*/*match_appl_version*/)(const void *, const char*),
+       const void */*match_data*/,
+       krb5_principal /*server*/,
+       int32_t /*flags*/,
+       krb5_keytab /*keytab*/,
+       krb5_ticket **/*ticket*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_address (
+       krb5_storage */*sp*/,
+       krb5_address */*adr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_addrs (
+       krb5_storage */*sp*/,
+       krb5_addresses */*adr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_authdata (
+       krb5_storage */*sp*/,
+       krb5_authdata */*auth*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_creds (
+       krb5_storage */*sp*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_creds_tag (
+       krb5_storage */*sp*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_data (
+       krb5_storage */*sp*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_int16 (
+       krb5_storage */*sp*/,
+       int16_t */*value*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_int32 (
+       krb5_storage */*sp*/,
+       int32_t */*value*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_int8 (
+       krb5_storage */*sp*/,
+       int8_t */*value*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_keyblock (
+       krb5_storage */*sp*/,
+       krb5_keyblock */*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_principal (
+       krb5_storage */*sp*/,
+       krb5_principal */*princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_string (
+       krb5_storage */*sp*/,
+       char **/*string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_stringz (
+       krb5_storage */*sp*/,
+       char **/*string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_times (
+       krb5_storage */*sp*/,
+       krb5_times */*times*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_salttype_to_string (
+       krb5_context /*context*/,
+       krb5_enctype /*etype*/,
+       krb5_salttype /*stype*/,
+       char **/*string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendauth (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       krb5_pointer /*p_fd*/,
+       const 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 **/*ret_error*/,
+       krb5_ap_rep_enc_part **/*rep_result*/,
+       krb5_creds **/*out_creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto (
+       krb5_context /*context*/,
+       const krb5_data */*send_data*/,
+       krb5_krbhst_handle /*handle*/,
+       krb5_data */*receive*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_kdc (
+       krb5_context /*context*/,
+       const krb5_data */*send_data*/,
+       const krb5_realm */*realm*/,
+       krb5_data */*receive*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_kdc_flags (
+       krb5_context /*context*/,
+       const krb5_data */*send_data*/,
+       const krb5_realm */*realm*/,
+       krb5_data */*receive*/,
+       int /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_config_files (
+       krb5_context /*context*/,
+       char **/*filenames*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_default_in_tkt_etypes (
+       krb5_context /*context*/,
+       const krb5_enctype */*etypes*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_default_realm (
+       krb5_context /*context*/,
+       const char */*realm*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_error_string (
+       krb5_context /*context*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__((format (printf, 2, 3)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_extra_addresses (
+       krb5_context /*context*/,
+       const krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_fcache_version (
+       krb5_context /*context*/,
+       int /*version*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_ignore_addresses (
+       krb5_context /*context*/,
+       const krb5_addresses */*addresses*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_password (
+       krb5_context /*context*/,
+       krb5_creds */*creds*/,
+       char */*newpw*/,
+       krb5_principal /*targprinc*/,
+       int */*result_code*/,
+       krb5_data */*result_code_string*/,
+       krb5_data */*result_string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_password_using_ccache (
+       krb5_context /*context*/,
+       krb5_ccache /*ccache*/,
+       char */*newpw*/,
+       krb5_principal /*targprinc*/,
+       int */*result_code*/,
+       krb5_data */*result_code_string*/,
+       krb5_data */*result_string*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_real_time (
+       krb5_context /*context*/,
+       krb5_timestamp /*sec*/,
+       int32_t /*usec*/);
+
+void KRB5_LIB_FUNCTION
+krb5_set_use_admin_kdc (
+       krb5_context /*context*/,
+       krb5_boolean /*flag*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_warn_dest (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sname_to_principal (
+       krb5_context /*context*/,
+       const char */*hostname*/,
+       const char */*sname*/,
+       int32_t /*type*/,
+       krb5_principal */*ret_princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sock_to_principal (
+       krb5_context /*context*/,
+       int /*sock*/,
+       const char */*sname*/,
+       int32_t /*type*/,
+       krb5_principal */*ret_princ*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sockaddr2address (
+       krb5_context /*context*/,
+       const struct sockaddr */*sa*/,
+       krb5_address */*addr*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sockaddr2port (
+       krb5_context /*context*/,
+       const struct sockaddr */*sa*/,
+       int16_t */*port*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_sockaddr_uninteresting (const struct sockaddr */*sa*/);
+
+void KRB5_LIB_FUNCTION
+krb5_std_usage (
+       int /*code*/,
+       struct getargs */*args*/,
+       int /*num_args*/);
+
+void KRB5_LIB_FUNCTION
+krb5_storage_clear_flags (
+       krb5_storage */*sp*/,
+       krb5_flags /*flags*/);
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_emem (void);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_storage_free (krb5_storage */*sp*/);
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_from_data (krb5_data */*data*/);
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_from_fd (int /*fd*/);
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_from_mem (
+       void */*buf*/,
+       size_t /*len*/);
+
+krb5_flags KRB5_LIB_FUNCTION
+krb5_storage_get_byteorder (
+       krb5_storage */*sp*/,
+       krb5_flags /*byteorder*/);
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_storage_is_flags (
+       krb5_storage */*sp*/,
+       krb5_flags /*flags*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_storage_read (
+       krb5_storage */*sp*/,
+       void */*buf*/,
+       size_t /*len*/);
+
+off_t KRB5_LIB_FUNCTION
+krb5_storage_seek (
+       krb5_storage */*sp*/,
+       off_t /*offset*/,
+       int /*whence*/);
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_byteorder (
+       krb5_storage */*sp*/,
+       krb5_flags /*byteorder*/);
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_eof_code (
+       krb5_storage */*sp*/,
+       int /*code*/);
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_flags (
+       krb5_storage */*sp*/,
+       krb5_flags /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_storage_to_data (
+       krb5_storage */*sp*/,
+       krb5_data */*data*/);
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_storage_write (
+       krb5_storage */*sp*/,
+       const void */*buf*/,
+       size_t /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_address (
+       krb5_storage */*sp*/,
+       krb5_address /*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_addrs (
+       krb5_storage */*sp*/,
+       krb5_addresses /*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_authdata (
+       krb5_storage */*sp*/,
+       krb5_authdata /*auth*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_creds (
+       krb5_storage */*sp*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_creds_tag (
+       krb5_storage */*sp*/,
+       krb5_creds */*creds*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_data (
+       krb5_storage */*sp*/,
+       krb5_data /*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_int16 (
+       krb5_storage */*sp*/,
+       int16_t /*value*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_int32 (
+       krb5_storage */*sp*/,
+       int32_t /*value*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_int8 (
+       krb5_storage */*sp*/,
+       int8_t /*value*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_keyblock (
+       krb5_storage */*sp*/,
+       krb5_keyblock /*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_principal (
+       krb5_storage */*sp*/,
+       krb5_principal /*p*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_string (
+       krb5_storage */*sp*/,
+       const char */*s*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_stringz (
+       krb5_storage */*sp*/,
+       const char */*s*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_times (
+       krb5_storage */*sp*/,
+       krb5_times /*times*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_deltat (
+       const char */*string*/,
+       krb5_deltat */*deltat*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_enctype (
+       krb5_context /*context*/,
+       const char */*string*/,
+       krb5_enctype */*etype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       const char */*password*/,
+       krb5_principal /*principal*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_data (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       krb5_data /*password*/,
+       krb5_principal /*principal*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_data_salt (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       krb5_data /*password*/,
+       krb5_salt /*salt*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_data_salt_opaque (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       krb5_data /*password*/,
+       krb5_salt /*salt*/,
+       krb5_data /*opaque*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_derived (
+       krb5_context /*context*/,
+       const void */*str*/,
+       size_t /*len*/,
+       krb5_enctype /*etype*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_salt (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       const char */*password*/,
+       krb5_salt /*salt*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_key_salt_opaque (
+       krb5_context /*context*/,
+       krb5_enctype /*enctype*/,
+       const char */*password*/,
+       krb5_salt /*salt*/,
+       krb5_data /*opaque*/,
+       krb5_keyblock */*key*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_keytype (
+       krb5_context /*context*/,
+       const char */*string*/,
+       krb5_keytype */*keytype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_salttype (
+       krb5_context /*context*/,
+       krb5_enctype /*etype*/,
+       const char */*string*/,
+       krb5_salttype */*salttype*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ticket_get_authorization_data_type (
+       krb5_context /*context*/,
+       krb5_ticket */*ticket*/,
+       int /*type*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ticket_get_client (
+       krb5_context /*context*/,
+       const krb5_ticket */*ticket*/,
+       krb5_principal */*client*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ticket_get_server (
+       krb5_context /*context*/,
+       const krb5_ticket */*ticket*/,
+       krb5_principal */*server*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_timeofday (
+       krb5_context /*context*/,
+       krb5_timestamp */*timeret*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name (
+       krb5_context /*context*/,
+       krb5_const_principal /*principal*/,
+       char **/*name*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_fixed (
+       krb5_context /*context*/,
+       krb5_const_principal /*principal*/,
+       char */*name*/,
+       size_t /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_fixed_short (
+       krb5_context /*context*/,
+       krb5_const_principal /*principal*/,
+       char */*name*/,
+       size_t /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_short (
+       krb5_context /*context*/,
+       krb5_const_principal /*principal*/,
+       char **/*name*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_us_timeofday (
+       krb5_context /*context*/,
+       krb5_timestamp */*sec*/,
+       int32_t */*usec*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vabort (
+       krb5_context /*context*/,
+       krb5_error_code /*code*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__ ((noreturn, format (printf, 3, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vabortx (
+       krb5_context /*context*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__ ((noreturn, format (printf, 2, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_ap_req (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       krb5_ap_req */*ap_req*/,
+       krb5_const_principal /*server*/,
+       krb5_keyblock */*keyblock*/,
+       krb5_flags /*flags*/,
+       krb5_flags */*ap_req_options*/,
+       krb5_ticket **/*ticket*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_ap_req2 (
+       krb5_context /*context*/,
+       krb5_auth_context */*auth_context*/,
+       krb5_ap_req */*ap_req*/,
+       krb5_const_principal /*server*/,
+       krb5_keyblock */*keyblock*/,
+       krb5_flags /*flags*/,
+       krb5_flags */*ap_req_options*/,
+       krb5_ticket **/*ticket*/,
+       krb5_key_usage /*usage*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_authenticator_checksum (
+       krb5_context /*context*/,
+       krb5_auth_context /*ac*/,
+       void */*data*/,
+       size_t /*len*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_checksum (
+       krb5_context /*context*/,
+       krb5_crypto /*crypto*/,
+       krb5_key_usage /*usage*/,
+       void */*data*/,
+       size_t /*len*/,
+       Checksum */*cksum*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 */*options*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_init_creds_opt_init (krb5_verify_init_creds_opt */*options*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_init_creds_opt_set_ap_req_nofail (
+       krb5_verify_init_creds_opt */*options*/,
+       int /*ap_req_nofail*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_init (krb5_verify_opt */*opt*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_ccache (
+       krb5_verify_opt */*opt*/,
+       krb5_ccache /*ccache*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_flags (
+       krb5_verify_opt */*opt*/,
+       unsigned int /*flags*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_keytab (
+       krb5_verify_opt */*opt*/,
+       krb5_keytab /*keytab*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_secure (
+       krb5_verify_opt */*opt*/,
+       krb5_boolean /*secure*/);
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_service (
+       krb5_verify_opt */*opt*/,
+       const char */*service*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_user (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       krb5_ccache /*ccache*/,
+       const char */*password*/,
+       krb5_boolean /*secure*/,
+       const char */*service*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_user_lrealm (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       krb5_ccache /*ccache*/,
+       const char */*password*/,
+       krb5_boolean /*secure*/,
+       const char */*service*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_user_opt (
+       krb5_context /*context*/,
+       krb5_principal /*principal*/,
+       const char */*password*/,
+       krb5_verify_opt */*opt*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verr (
+       krb5_context /*context*/,
+       int /*eval*/,
+       krb5_error_code /*code*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__ ((noreturn, format (printf, 4, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verrx (
+       krb5_context /*context*/,
+       int /*eval*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__ ((noreturn, format (printf, 3, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vlog (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/,
+       int /*level*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__((format (printf, 4, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vlog_msg (
+       krb5_context /*context*/,
+       krb5_log_facility */*fac*/,
+       char **/*reply*/,
+       int /*level*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__((format (printf, 5, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vset_error_string (
+       krb5_context /*context*/,
+       const char */*fmt*/,
+       va_list /*args*/)
+    __attribute__ ((format (printf, 2, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vwarn (
+       krb5_context /*context*/,
+       krb5_error_code /*code*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__ ((format (printf, 3, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vwarnx (
+       krb5_context /*context*/,
+       const char */*fmt*/,
+       va_list /*ap*/)
+    __attribute__ ((format (printf, 2, 0)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_warn (
+       krb5_context /*context*/,
+       krb5_error_code /*code*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__ ((format (printf, 3, 4)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_warnx (
+       krb5_context /*context*/,
+       const char */*fmt*/,
+       ...)
+    __attribute__ ((format (printf, 2, 3)));
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_write_message (
+       krb5_context /*context*/,
+       krb5_pointer /*p_fd*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_write_priv_message (
+       krb5_context /*context*/,
+       krb5_auth_context /*ac*/,
+       krb5_pointer /*p_fd*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_write_safe_message (
+       krb5_context /*context*/,
+       krb5_auth_context /*ac*/,
+       krb5_pointer /*p_fd*/,
+       krb5_data */*data*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_xfree (void */*ptr*/);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __krb5_protos_h__ */
diff --git a/src/kerberosV/src/lib/krb5/krb5-v4compat.h b/src/kerberosV/src/lib/krb5/krb5-v4compat.h
new file mode 100644 (file)
index 0000000..ca78c0b
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: krb5-v4compat.h,v 1.6 2005/04/23 19:38:16 lha Exp $ */
+
+#ifndef __KRB5_V4COMPAT_H__
+#define __KRB5_V4COMPAT_H__
+
+/* 
+ * This file must only be included with v4 compat glue stuff in
+ * heimdal sources.
+ *
+ * It MUST NOT be installed.
+ */
+
+#define                KRB_PROT_VERSION        4
+
+#define                AUTH_MSG_KDC_REQUEST                     (1<<1)
+#define        AUTH_MSG_KDC_REPLY                       (2<<1)
+#define                AUTH_MSG_APPL_REQUEST                    (3<<1)
+#define                AUTH_MSG_APPL_REQUEST_MUTUAL             (4<<1)
+#define                AUTH_MSG_ERR_REPLY                       (5<<1)
+#define                AUTH_MSG_PRIVATE                         (6<<1)
+#define                AUTH_MSG_SAFE                            (7<<1)
+#define                AUTH_MSG_APPL_ERR                        (8<<1)
+#define                AUTH_MSG_KDC_FORWARD                     (9<<1)
+#define                AUTH_MSG_KDC_RENEW                      (10<<1)
+#define        AUTH_MSG_DIE                            (63<<1)
+
+/* values for kerb error codes */
+
+#define                KERB_ERR_OK                              0
+#define                KERB_ERR_NAME_EXP                        1
+#define                KERB_ERR_SERVICE_EXP                     2
+#define                KERB_ERR_AUTH_EXP                        3
+#define                KERB_ERR_PKT_VER                         4
+#define                KERB_ERR_NAME_MAST_KEY_VER               5
+#define                KERB_ERR_SERV_MAST_KEY_VER               6
+#define                KERB_ERR_BYTE_ORDER                      7
+#define                KERB_ERR_PRINCIPAL_UNKNOWN               8
+#define                KERB_ERR_PRINCIPAL_NOT_UNIQUE            9
+#define                KERB_ERR_NULL_KEY                       10
+#define                KERB_ERR_TIMEOUT                        11
+
+
+/* Error codes returned from the KDC */
+#define                KDC_OK          0       /* Request OK */
+#define                KDC_NAME_EXP    1       /* Principal expired */
+#define                KDC_SERVICE_EXP 2       /* Service expired */
+#define                KDC_AUTH_EXP    3       /* Auth expired */
+#define                KDC_PKT_VER     4       /* Protocol version unknown */
+#define                KDC_P_MKEY_VER  5       /* Wrong master key version */
+#define                KDC_S_MKEY_VER  6       /* Wrong master key version */
+#define                KDC_BYTE_ORDER  7       /* Byte order unknown */
+#define                KDC_PR_UNKNOWN  8       /* Principal unknown */
+#define                KDC_PR_N_UNIQUE 9       /* Principal not unique */
+#define                KDC_NULL_KEY   10       /* Principal has null key */
+#define                KDC_GEN_ERR    20       /* Generic error from KDC */
+
+/* General definitions */
+#define                KSUCCESS        0
+#define                KFAILURE        255
+
+/* Values returned by rd_ap_req */
+#define                RD_AP_OK        0       /* Request authentic */
+#define                RD_AP_UNDEC    31       /* Can't decode authenticator */
+#define                RD_AP_EXP      32       /* Ticket expired */
+#define                RD_AP_NYV      33       /* Ticket not yet valid */
+#define                RD_AP_REPEAT   34       /* Repeated request */
+#define                RD_AP_NOT_US   35       /* The ticket isn't for us */
+#define                RD_AP_INCON    36       /* Request is inconsistent */
+#define                RD_AP_TIME     37       /* delta_t too big */
+#define                RD_AP_BADD     38       /* Incorrect net address */
+#define                RD_AP_VERSION  39       /* protocol version mismatch */
+#define                RD_AP_MSG_TYPE 40       /* invalid msg type */
+#define                RD_AP_MODIFIED 41       /* message stream modified */
+#define                RD_AP_ORDER    42       /* message out of order */
+#define                RD_AP_UNAUTHOR 43       /* unauthorized request */
+
+/* */
+
+#define                MAX_KTXT_LEN    1250
+
+#define        ANAME_SZ        40
+#define                REALM_SZ        40
+#define                SNAME_SZ        40
+#define                INST_SZ         40
+
+struct ktext {
+    unsigned int length;               /* Length of the text */
+    unsigned char dat[MAX_KTXT_LEN];   /* The data itself */
+    u_int32_t mbz;             /* zero to catch runaway strings */
+};
+
+struct credentials {
+    char    service[ANAME_SZ]; /* Service name */
+    char    instance[INST_SZ]; /* Instance */
+    char    realm[REALM_SZ];   /* Auth domain */
+    char    session[8];                /* Session key */
+    int     lifetime;          /* Lifetime */
+    int     kvno;              /* Key version number */
+    struct ktext ticket_st;    /* The ticket itself */
+    int32_t    issue_date;     /* The issue time */
+    char    pname[ANAME_SZ];   /* Principal's name */
+    char    pinst[INST_SZ];    /* Principal's instance */
+};
+
+#define TKTLIFENUMFIXED 64
+#define TKTLIFEMINFIXED 0x80
+#define TKTLIFEMAXFIXED 0xBF
+#define TKTLIFENOEXPIRE 0xFF
+#define MAXTKTLIFETIME (30*24*3600)    /* 30 days */
+#ifndef NEVERDATE
+#define NEVERDATE ((time_t)0x7fffffffL)
+#endif
+
+#define                KERB_ERR_NULL_KEY       10
+
+#define        CLOCK_SKEW      5*60
+
+#ifndef TKT_ROOT
+#define TKT_ROOT "/tmp/tkt"
+#endif
+
+struct _krb5_krb_auth_data {
+    int8_t  k_flags;           /* Flags from ticket */
+    char    *pname;            /* Principal's name */
+    char    *pinst;            /* His Instance */
+    char    *prealm;           /* His Realm */
+    u_int32_t checksum;                /* Data checksum (opt) */
+    krb5_keyblock session;     /* Session Key */
+    unsigned char life;                /* Life of ticket */
+    u_int32_t time_sec;                /* Time ticket issued */
+    u_int32_t address;         /* Address in ticket */
+};
+
+time_t         _krb5_krb_life_to_time (int, int);
+int            _krb5_krb_time_to_life (time_t, time_t);
+krb5_error_code        _krb5_krb_tf_setup (krb5_context, struct credentials *,
+                                   const char *, int);
+krb5_error_code        _krb5_krb_dest_tkt(krb5_context, const char *);
+
+#define krb_time_to_life       _krb5_krb_time_to_life
+#define krb_life_to_time       _krb5_krb_life_to_time
+
+#endif /*  __KRB5_V4COMPAT_H__ */
diff --git a/src/kerberosV/src/lib/krb5/krb5.3 b/src/kerberosV/src/lib/krb5/krb5.3
new file mode 100644 (file)
index 0000000..ff771ba
--- /dev/null
@@ -0,0 +1,492 @@
+.\" Copyright (c) 2001, 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5.3,v 1.35 2005/05/25 13:18:33 lha Exp $
+.\"
+.Dd March 21, 2004
+.Dt KRB5 3
+.Os
+.Sh NAME
+.Nm krb5
+.Nd Kerberos 5 library
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Sh DESCRIPTION
+These functions constitute the Kerberos 5 library,
+.Em libkrb5 .
+.Sh LIST OF FUNCTIONS
+.sp 2
+.nf
+.ta \w'krb5_ticket_get_authorization_data_type.3'u+2n +\w'Description goes here'u
+\fIName/Page\fP        \fIDescription\fP
+.ta \w'krb5_ticket_get_authorization_data_type.3'u+2n +\w'Description goes here'u+6nC
+.sp 5p
+krb524_convert_creds_kdc.3
+krb524_convert_creds_kdc_cache.3
+krb5_425_conv_principal.3
+krb5_425_conv_principal_ext.3
+krb5_524_conv_principal.3
+krb5_abort.3
+krb5_abortx.3
+krb5_acl_match_file.3
+krb5_acl_match_string.3
+krb5_add_et_list.3
+krb5_add_extra_addresses.3
+krb5_add_ignore_addresses.3
+krb5_addlog_dest.3
+krb5_addlog_func.3
+krb5_addr2sockaddr.3
+krb5_address.3
+krb5_address_compare.3
+krb5_address_order.3
+krb5_address_search.3
+krb5_addresses.3
+krb5_aname_to_localname.3
+krb5_anyaddr.3
+krb5_appdefault_boolean.3
+krb5_appdefault_string.3
+krb5_appdefault_time.3
+krb5_append_addresses.3
+krb5_auth_con_addflags.3
+krb5_auth_con_free.3
+krb5_auth_con_genaddrs.3
+krb5_auth_con_generatelocalsubkey.3
+krb5_auth_con_getaddrs.3
+krb5_auth_con_getauthenticator.3
+krb5_auth_con_getcksumtype.3
+krb5_auth_con_getflags.3
+krb5_auth_con_getkey.3
+krb5_auth_con_getkeytype.3
+krb5_auth_con_getlocalseqnumber.3
+krb5_auth_con_getlocalsubkey.3
+krb5_auth_con_getrcache.3
+krb5_auth_con_getremotesubkey.3
+krb5_auth_con_getuserkey.3
+krb5_auth_con_init.3
+krb5_auth_con_initivector.3
+krb5_auth_con_removeflags.3
+krb5_auth_con_setaddrs.3
+krb5_auth_con_setaddrs_from_fd.3
+krb5_auth_con_setcksumtype.3
+krb5_auth_con_setflags.3
+krb5_auth_con_setivector.3
+krb5_auth_con_setkey.3
+krb5_auth_con_setkeytype.3
+krb5_auth_con_setlocalseqnumber.3
+krb5_auth_con_setlocalsubkey.3
+krb5_auth_con_setrcache.3
+krb5_auth_con_setremoteseqnumber.3
+krb5_auth_con_setremotesubkey.3
+krb5_auth_con_setuserkey.3
+krb5_auth_context.3
+krb5_auth_getremoteseqnumber.3
+krb5_build_principal.3
+krb5_build_principal_ext.3
+krb5_build_principal_va.3
+krb5_build_principal_va_ext.3
+krb5_c_block_size.3
+krb5_c_checksum_length.3
+krb5_c_decrypt.3
+krb5_c_encrypt.3
+krb5_c_encrypt_length.3
+krb5_c_enctype_compare.3
+krb5_c_get_checksum.3
+krb5_c_is_coll_proof_cksum.3
+krb5_c_is_keyed_cksum.3
+krb5_c_make_checksum.3
+krb5_c_make_random_key.3
+krb5_c_set_checksum.3
+krb5_c_valid_cksumtype.3
+krb5_c_valid_enctype.3
+krb5_c_verify_checksum.3
+krb5_cc_close.3
+krb5_cc_copy_cache.3
+krb5_cc_default.3
+krb5_cc_default_name.3
+krb5_cc_destroy.3
+krb5_cc_end_seq_get.3
+krb5_cc_gen_new.3
+krb5_cc_get_name.3
+krb5_cc_get_ops.3
+krb5_cc_get_principal.3
+krb5_cc_get_type.3
+krb5_cc_get_version.3
+krb5_cc_initialize.3
+krb5_cc_new_unique.3
+krb5_cc_next_cred.3
+krb5_cc_register.3
+krb5_cc_remove_cred.3
+krb5_cc_resolve.3
+krb5_cc_retrieve_cred.3
+krb5_cc_set_default_name.3
+krb5_cc_set_flags.3
+krb5_cc_store_cred.3
+krb5_change_password.3
+krb5_check_transited.3
+krb5_check_transited_realms.3
+krb5_checksum_disable.3
+krb5_checksum_free.3
+krb5_checksum_is_collision_proof.3
+krb5_checksum_is_keyed.3
+krb5_checksumsize.3
+krb5_clear_error_string.3
+krb5_closelog.3
+krb5_config_file_free.3
+krb5_config_free_strings.3
+krb5_config_get.3
+krb5_config_get_bool.3
+krb5_config_get_bool_default.3
+krb5_config_get_int.3
+krb5_config_get_int_default.3
+krb5_config_get_list.3
+krb5_config_get_next.3
+krb5_config_get_string.3
+krb5_config_get_string_default.3
+krb5_config_get_strings.3
+krb5_config_get_time.3
+krb5_config_get_time_default.3
+krb5_config_parse_file.3
+krb5_config_parse_file_multi.3
+krb5_config_vget.3
+krb5_config_vget_bool.3
+krb5_config_vget_bool_default.3
+krb5_config_vget_int.3
+krb5_config_vget_int_default.3
+krb5_config_vget_list.3
+krb5_config_vget_next.3
+krb5_config_vget_string.3
+krb5_config_vget_string_default.3
+krb5_config_vget_strings.3
+krb5_config_vget_time.3
+krb5_config_vget_time_default.3
+krb5_context.3
+krb5_copy_address.3
+krb5_copy_addresses.3
+krb5_copy_checksum.3
+krb5_copy_data.3
+krb5_copy_host_realm.3
+krb5_copy_keyblock.3
+krb5_copy_keyblock_contents.3
+krb5_copy_principal.3
+krb5_copy_ticket.3
+krb5_create_checksum.3
+krb5_creds.3
+krb5_crypto_destroy.3
+krb5_crypto_get_checksum_type.3
+krb5_crypto_getblocksize.3
+krb5_crypto_getconfoundersize.3
+krb5_crypto_getenctype.3
+krb5_crypto_getpadsize.3
+krb5_crypto_init.3
+krb5_data_alloc.3
+krb5_data_copy.3
+krb5_data_free.3
+krb5_data_realloc.3
+krb5_data_zero.3
+krb5_decrypt.3
+krb5_decrypt_EncryptedData.3
+krb5_domain_x500_decode.3
+krb5_domain_x500_encode.3
+krb5_eai_to_heim_errno.3
+krb5_encrypt.3
+krb5_encrypt_EncryptedData.3
+krb5_enctype_disable.3
+krb5_enctype_to_string.3
+krb5_enctype_valid.3
+krb5_err.3
+krb5_errx.3
+krb5_expand_hostname.3
+krb5_expand_hostname_realms.3
+krb5_find_padata.3
+krb5_format_time.3
+krb5_free_address.3
+krb5_free_addresses.3
+krb5_free_authenticator.3
+krb5_free_checksum.3
+krb5_free_checksum_contents.3
+krb5_free_config_files.3
+krb5_free_context.3
+krb5_free_data.3
+krb5_free_data_contents.3
+krb5_free_error_string.3
+krb5_free_host_realm.3
+krb5_free_kdc_rep.3
+krb5_free_keyblock.3
+krb5_free_keyblock_contents.3
+krb5_free_krbhst.3
+krb5_free_principal.3
+krb5_free_ticket.3
+krb5_free_salt.3
+krb5_fwd_tgt_creds.3
+krb5_generate_random_block.3
+krb5_generate_random_keyblock.3
+krb5_generate_subkey.3
+krb5_get_all_client_addrs.3
+krb5_get_all_server_addrs.3
+krb5_get_cred_from_kdc.3
+krb5_get_cred_from_kdc_opt.3
+krb5_get_credentials.3
+krb5_get_credentials_with_flags.3
+krb5_get_default_config_files.3
+krb5_get_default_principal.3
+krb5_get_default_realm.3
+krb5_get_default_realms.3
+krb5_get_err_text.3
+krb5_get_error_string.3
+krb5_get_extra_addresses.3
+krb5_get_fcache_version.3
+krb5_get_forwarded_creds.3
+krb5_get_host_realm.3
+krb5_get_ignore_addresses.3
+krb5_get_in_cred.3
+krb5_get_in_tkt.3
+krb5_get_in_tkt_with_keytab.3
+krb5_get_in_tkt_with_password.3
+krb5_get_in_tkt_with_skey.3
+krb5_get_init_creds.3
+krb5_get_init_creds_keytab.3
+krb5_get_init_creds_opt_alloc.3
+krb5_get_init_creds_opt_free.3
+krb5_get_init_creds_opt_free_pkinit.3
+krb5_get_init_creds_opt_init.3
+krb5_get_init_creds_opt_set_address_list.3
+krb5_get_init_creds_opt_set_anonymous.3
+krb5_get_init_creds_opt_set_default_flags.3
+krb5_get_init_creds_opt_set_etype_list.3
+krb5_get_init_creds_opt_set_forwardable.3
+krb5_get_init_creds_opt_set_pa_password.3
+krb5_get_init_creds_opt_set_paq_request.3
+krb5_get_init_creds_opt_set_pkinit.3
+krb5_get_init_creds_opt_set_preauth_list.3
+krb5_get_init_creds_opt_set_proxiable.3
+krb5_get_init_creds_opt_set_renew_life.3
+krb5_get_init_creds_opt_set_salt.3
+krb5_get_init_creds_opt_set_tkt_life.3
+krb5_get_init_creds_password.3
+krb5_get_kdc_cred.3
+krb5_get_krb524hst.3
+krb5_get_krb_admin_hst.3
+krb5_get_krb_changepw_hst.3
+krb5_get_krbhst.3
+krb5_get_pw_salt.3
+krb5_get_server_rcache.3
+krb5_get_use_admin_kdc.3
+krb5_get_wrapped_length.3
+krb5_getportbyname.3
+krb5_h_addr2addr.3
+krb5_h_addr2sockaddr.3
+krb5_h_errno_to_heim_errno.3
+krb5_have_error_string.3
+krb5_hmac.3
+krb5_init_context.3
+krb5_init_ets.3
+krb5_initlog.3
+krb5_keyblock_get_enctype.3
+krb5_keyblock_zero.3
+krb5_keytab_entry.3
+krb5_krbhst_format_string.3
+krb5_krbhst_free.3
+krb5_krbhst_get_addrinfo.3
+krb5_krbhst_init.3
+krb5_krbhst_init_flags.3
+krb5_krbhst_next.3
+krb5_krbhst_next_as_string.3
+krb5_krbhst_reset.3
+krb5_kt_add_entry.3
+krb5_kt_close.3
+krb5_kt_compare.3
+krb5_kt_copy_entry_contents.3
+krb5_kt_cursor.3
+krb5_kt_default.3
+krb5_kt_default_modify_name.3
+krb5_kt_default_name.3
+krb5_kt_end_seq_get.3
+krb5_kt_free_entry.3
+krb5_kt_get_entry.3
+krb5_kt_get_name.3
+krb5_kt_get_type.3
+krb5_kt_next_entry.3
+krb5_kt_ops.3
+krb5_kt_read_service_key.3
+krb5_kt_register.3
+krb5_kt_remove_entry.3
+krb5_kt_resolve.3.3
+krb5_kt_start_seq_get
+krb5_kuserok.3
+krb5_log.3
+krb5_log_msg.3
+krb5_make_addrport.3
+krb5_make_principal.3
+krb5_max_sockaddr_size.3
+krb5_openlog.3
+krb5_padata_add.3
+krb5_parse_address.3
+krb5_parse_name.3
+krb5_passwd_result_to_string.3
+krb5_password_key_proc.3
+krb5_prepend_config_files.3
+krb5_prepend_config_files_default.3
+krb5_princ_realm.3
+krb5_princ_set_realm.3
+krb5_principal.3
+krb5_principal_compare.3
+krb5_principal_compare_any_realm.3
+krb5_principal_get_comp_string.3
+krb5_principal_get_realm.3
+krb5_principal_get_type.3
+krb5_principal_match.3
+krb5_principal_set_type.3
+krb5_print_address.3
+krb5_rc_close.3
+krb5_rc_default.3
+krb5_rc_default_name.3
+krb5_rc_default_type.3
+krb5_rc_destroy.3
+krb5_rc_expunge.3
+krb5_rc_get_lifespan.3
+krb5_rc_get_name.3
+krb5_rc_get_type.3
+krb5_rc_initialize.3
+krb5_rc_recover.3
+krb5_rc_resolve.3
+krb5_rc_resolve_full.3
+krb5_rc_resolve_type.3
+krb5_rc_store.3
+krb5_rcache.3
+krb5_realm_compare.3
+krb5_ret_address.3
+krb5_ret_addrs.3
+krb5_ret_authdata.3
+krb5_ret_creds.3
+krb5_ret_data.3
+krb5_ret_int16.3
+krb5_ret_int32.3
+krb5_ret_int8.3
+krb5_ret_keyblock.3
+krb5_ret_principal.3
+krb5_ret_string.3
+krb5_ret_stringz.3
+krb5_ret_times.3
+krb5_set_config_files.3
+krb5_set_default_realm.3
+krb5_set_error_string.3
+krb5_set_extra_addresses.3
+krb5_set_fcache_version.3
+krb5_set_ignore_addresses.3
+krb5_set_password.3
+krb5_set_password_using_ccache.3
+krb5_set_real_time.3
+krb5_set_use_admin_kdc.3
+krb5_set_warn_dest.3
+krb5_sname_to_principal.3
+krb5_sock_to_principal.3
+krb5_sockaddr2address.3
+krb5_sockaddr2port.3
+krb5_sockaddr_uninteresting.3
+krb5_storage.3
+krb5_storage_clear_flags.3
+krb5_storage_emem.3
+krb5_storage_free.3
+krb5_storage_from_data.3
+krb5_storage_from_fd.3
+krb5_storage_from_mem.3
+krb5_storage_get_byteorder.3
+krb5_storage_is_flags.3
+krb5_storage_read.3
+krb5_storage_seek.3
+krb5_storage_set_byteorder.3
+krb5_storage_set_eof_code.3
+krb5_storage_set_flags.3
+krb5_storage_to_data.3
+krb5_storage_write.3
+krb5_store_address.3
+krb5_store_addrs.3
+krb5_store_authdata.3
+krb5_store_creds.3
+krb5_store_data.3
+krb5_store_int16.3
+krb5_store_int32.3
+krb5_store_int8.3
+krb5_store_keyblock.3
+krb5_store_principal.3
+krb5_store_string.3
+krb5_store_stringz.3
+krb5_store_times.3
+krb5_string_to_deltat.3
+krb5_string_to_enctype.3
+krb5_string_to_key.3
+krb5_string_to_key_data.3
+krb5_string_to_key_data_salt.3
+krb5_string_to_key_data_salt_opaque.3
+krb5_string_to_key_derived.3
+krb5_string_to_key_salt.3
+krb5_string_to_key_salt_opaque.3
+krb5_ticket.3
+krb5_ticket_get_authorization_data_type.3
+krb5_ticket_get_client.3
+krb5_ticket_get_server.3
+krb5_timeofday.3
+krb5_unparse_name.3
+krb5_unparse_name_fixed.3
+krb5_unparse_name_fixed_short.3
+krb5_unparse_name_short.3
+krb5_us_timeofday.3
+krb5_vabort.3
+krb5_vabortx.3
+krb5_verify_checksum.3
+krb5_verify_init_creds.3
+krb5_verify_init_creds_opt_init.3
+krb5_verify_init_creds_opt_set_ap_req_nofail.3
+krb5_verify_opt_init.3
+krb5_verify_opt_set_ccache.3
+krb5_verify_opt_set_flags.3
+krb5_verify_opt_set_keytab.3
+krb5_verify_opt_set_secure.3
+krb5_verify_opt_set_service.3
+krb5_verify_user.3
+krb5_verify_user_lrealm.3
+krb5_verify_user_opt.3
+krb5_verr.3
+krb5_verrx.3
+krb5_vlog.3
+krb5_vlog_msg.3
+krb5_vset_error_string.3
+krb5_vwarn.3
+krb5_vwarnx.3
+krb5_warn.3
+krb5_warnx.3
+.ta
+.Fi
+.Sh SEE ALSO
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5.conf.5 b/src/kerberosV/src/lib/krb5/krb5.conf.5
new file mode 100644 (file)
index 0000000..c071edb
--- /dev/null
@@ -0,0 +1,516 @@
+.\" Copyright (c) 1999 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5.conf.5,v 1.60 2005/05/29 13:14:50 lha Exp $
+.\"
+.Dd May  4, 2005
+.Dt KRB5.CONF 5
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5.conf
+.Nd configuration file for Kerberos 5
+.Sh SYNOPSIS
+.In krb5.h
+.Sh DESCRIPTION
+The
+.Nm
+file specifies several configuration parameters for the Kerberos 5
+library, as well as for some programs.
+.Pp
+The file consists of one or more sections, containing a number of
+bindings.
+The value of each binding can be either a string or a list of other
+bindings.
+The grammar looks like:
+.Bd -literal -offset indent
+file:
+       /* empty */
+       sections
+
+sections:
+       section sections
+       section
+
+section:
+       '[' section_name ']' bindings
+
+section_name:
+       STRING
+
+bindings:
+       binding bindings
+       binding
+
+binding:
+       name '=' STRING
+       name '=' '{' bindings '}'
+
+name:
+       STRING
+
+.Ed
+.Li STRINGs
+consists of one or more non-whitespace characters.
+.Pp
+STRINGs that are specified later in this man-page uses the following
+notation.
+.Bl -tag -width "xxx" -offset indent
+.It boolean
+values can be either yes/true or no/false.
+.It time
+values can be a list of year, month, day, hour, min, second.
+Example: 1 month 2 days 30 min.
+If no unit is given, seconds is assumed.
+.It etypes
+valid encryption types are: des-cbc-crc, des-cbc-md4, des-cbc-md5,
+des3-cbc-sha1, arcfour-hmac-md5, aes128-cts-hmac-sha1-96, and
+aes256-cts-hmac-sha1-96 .
+.It address
+an address can be either a IPv4 or a IPv6 address.
+.El
+.Pp
+Currently recognised sections and bindings are:
+.Bl -tag -width "xxx" -offset indent
+.It Li [appdefaults]
+Specifies the default values to be used for Kerberos applications.
+You can specify defaults per application, realm, or a combination of
+these.
+The preference order is:
+.Bl -enum -compact
+.It
+.Va application Va realm Va option
+.It
+.Va application Va option
+.It
+.Va realm Va option
+.It
+.Va option
+.El
+.Pp
+The supported options are:
+.Bl -tag -width "xxx" -offset indent
+.It Li forwardable = Va boolean
+When obtaining initial credentials, make the credentials forwardable.
+.It Li proxiable = Va boolean
+When obtaining initial credentials, make the credentials proxiable.
+.It Li no-addresses = Va boolean
+When obtaining initial credentials, request them for an empty set of
+addresses, making the tickets valid from any address.
+.It Li ticket_lifetime = Va time
+Default ticket lifetime.
+.It Li renew_lifetime = Va time
+Default renewable ticket lifetime.
+.It Li encrypt = Va boolean
+Use encryption, when available.
+.It Li forward = Va boolean
+Forward credentials to remote host (for
+.Xr rsh 1 ,
+.Xr telnet 1 ,
+etc).
+.El
+.It Li [libdefaults]
+.Bl -tag -width "xxx" -offset indent
+.It Li default_realm = Va REALM
+Default realm to use, this is also known as your
+.Dq local realm .
+The default is the result of
+.Fn krb5_get_host_realm "local hostname" .
+.It Li clockskew = Va time
+Maximum time differential (in seconds) allowed when comparing
+times.
+Default is 300 seconds (five minutes).
+.It Li kdc_timeout = Va time
+Maximum time to wait for a reply from the kdc, default is 3 seconds.
+.It Li v4_name_convert
+.It Li v4_instance_resolve
+These are described in the
+.Xr krb5_425_conv_principal  3
+manual page.
+.It Li capath = {
+.Bl -tag -width "xxx" -offset indent
+.It Va destination-realm Li = Va next-hop-realm
+.It ...
+.It Li }
+.El
+This is deprecated, see the 
+.Li capaths
+section below.
+.It Li default_cc_name = Va ccname
+the default credentials cache name.
+The string can contain variables that are expanded on runtime.
+Only support variable now is
+.Li %{uid}
+that expands to the current user id.
+.It Li default_etypes = Va etypes ...
+A list of default encryption types to use.
+.It Li default_etypes_des = Va etypes ...
+A list of default encryption types to use when requesting a DES credential.
+.It Li default_keytab_name = Va keytab
+The keytab to use if no other is specified, default is
+.Dq FILE:/etc/kerberosV/krb5.keytab .
+.It Li dns_lookup_kdc = Va boolean
+Use DNS SRV records to lookup KDC services location.
+.It Li dns_lookup_realm = Va boolean
+Use DNS TXT records to lookup domain to realm mappings.
+.It Li kdc_timesync = Va boolean
+Try to keep track of the time differential between the local machine
+and the KDC, and then compensate for that when issuing requests.
+.It Li max_retries = Va number
+The max number of times to try to contact each KDC.
+.It Li large_msg_size = Va number
+The threshold where protocols with tiny maximum message sizes are not
+considered usable to send messages to the KDC.
+.It Li ticket_lifetime = Va time
+Default ticket lifetime.
+.It Li renew_lifetime = Va time
+Default renewable ticket lifetime.
+.It Li forwardable = Va boolean
+When obtaining initial credentials, make the credentials forwardable.
+This option is also valid in the [realms] section.
+.It Li proxiable = Va boolean
+When obtaining initial credentials, make the credentials proxiable.
+This option is also valid in the [realms] section.
+.It Li verify_ap_req_nofail = Va boolean
+If enabled, failure to verify credentials against a local key is a
+fatal error.
+The application has to be able to read the corresponding service key
+for this to work.
+Some applications, like
+.Xr su 1 ,
+enable this option unconditionally.
+.It Li warn_pwexpire = Va time
+How soon to warn for expiring password.
+Default is seven days.
+.It Li http_proxy = Va proxy-spec
+A HTTP-proxy to use when talking to the KDC via HTTP.
+.It Li dns_proxy = Va proxy-spec
+Enable using DNS via HTTP.
+.It Li extra_addresses = Va address ...
+A list of addresses to get tickets for along with all local addresses.
+.It Li time_format = Va string
+How to print time strings in logs, this string is passed to
+.Xr strftime 3 .
+.It Li date_format = Va string
+How to print date strings in logs, this string is passed to
+.Xr strftime 3 .
+.It Li log_utc = Va boolean
+Write log-entries using UTC instead of your local time zone.
+.It Li scan_interfaces = Va boolean
+Scan all network interfaces for addresses, as opposed to simply using
+the address associated with the system's host name.
+.It Li fcache_version = Va int
+Use file credential cache format version specified.
+.It Li krb4_get_tickets = Va boolean
+Also get Kerberos 4 tickets in
+.Nm kinit ,
+.Nm login ,
+and other programs.
+This option is also valid in the [realms] section.
+.It Li fcc-mit-ticketflags = Va boolean
+Use MIT compatible format for file credential cache.
+It's the field ticketflags that is stored in reverse bit order for
+older than Heimdal 0.7.
+Setting this flag to
+.Dv TRUE
+make it store the MIT way, this is default for Heimdal 0.7.
+.El
+.It Li [domain_realm]
+This is a list of mappings from DNS domain to Kerberos realm.
+Each binding in this section looks like:
+.Pp
+.Dl domain = realm
+.Pp
+The domain can be either a full name of a host or a trailing
+component, in the latter case the domain-string should start with a
+period.
+The trailing component only matches hosts that are in the same domain, ie
+.Dq .example.com
+matches
+.Dq foo.example.com ,
+but not
+.Dq foo.test.example.com .
+.Pp
+The realm may be the token `dns_locate', in which case the actual
+realm will be determined using DNS (independently of the setting
+of the `dns_lookup_realm' option).
+.It Li [realms]
+.Bl -tag -width "xxx" -offset indent
+.It Va REALM Li = {
+.Bl -tag -width "xxx" -offset indent
+.It Li kdc = Va [service/]host[:port]
+Specifies a list of kdcs for this realm.
+If the optional
+.Va port
+is absent, the
+default value for the
+.Dq kerberos/udp
+.Dq kerberos/tcp ,
+and
+.Dq http/tcp
+port (depending on service) will be used.
+The kdcs will be used in the order that they are specified.
+.Pp
+The optional
+.Va service
+specifies over what medium the kdc should be
+contacted.
+Possible services are
+.Dq udp ,
+.Dq tcp ,
+and
+.Dq http .
+Http can also be written as
+.Dq http:// .
+Default service is
+.Dq udp
+and
+.Dq tcp .
+.It Li admin_server = Va host[:port]
+Specifies the admin server for this realm, where all the modifications
+to the database are performed.
+.It Li kpasswd_server = Va host[:port]
+Points to the server where all the password changes are performed.
+If there is no such entry, the kpasswd port on the admin_server host
+will be tried.
+.It Li krb524_server = Va host[:port]
+Points to the server that does 524 conversions.
+If it is not mentioned, the krb524 port on the kdcs will be tried.
+.It Li v4_instance_convert
+.It Li v4_name_convert
+.It Li default_domain
+See
+.Xr krb5_425_conv_principal 3 .
+.It Li tgs_require_subkey
+a boolan variable that defaults to false.
+Old DCE secd (pre 1.1) might need this to be true.
+.El
+.It Li }
+.El
+.It Li [capaths]
+.Bl -tag -width "xxx" -offset indent
+.It Va client-realm Li = {
+.Bl -tag -width "xxx" -offset indent
+.It Va server-realm Li = Va hop-realm ...
+This serves two purposes. First the first listed
+.Va hop-realm
+tells a client which realm it should contact in order to ultimately
+obtain credentials for a service in the
+.Va server-realm .
+Secondly, it tells the KDC (and other servers) which realms are
+allowed in a multi-hop traversal from
+.Va client-realm 
+to
+.Va server-realm .
+Except for the client case, the order of the realms are not important.
+.El
+.It Va }
+.El
+.It Li [logging]
+.Bl -tag -width "xxx" -offset indent
+.It Va entity Li = Va destination
+Specifies that
+.Va entity
+should use the specified
+.Li destination
+for logging.
+See the
+.Xr krb5_openlog 3
+manual page for a list of defined destinations.
+.El
+.It Li [kdc]
+.Bl -tag -width "xxx" -offset indent
+.It Li database Li = {
+.Bl -tag -width "xxx" -offset indent
+.It Li dbname Li = Va DATABASENAME
+Use this database for this realm.
+See the info documetation how to configure diffrent database backends.
+.It Li realm Li = Va REALM
+Specifies the realm that will be stored in this database.
+It realm isn't set, it will used as the default database, there can
+only be one entry that doesn't have a
+.Li realm
+stanza.
+.It Li mkey_file Li = Pa FILENAME
+Use this keytab file for the master key of this database.
+If not specified
+.Va DATABASENAME Ns .mkey
+will be used.
+.It Li acl_file Li = PA FILENAME
+Use this file for the ACL list of this database.
+.It Li log_file Li = Pa FILENAME
+Use this file as the log of changes performed to the database.
+This file is used by
+.Nm ipropd-master
+for propagating changes to slaves.
+.El
+.It Li }
+.It Li max-request = Va SIZE
+Maximum size of a kdc request.
+.It Li require-preauth = Va BOOL
+If set pre-authentication is required.
+Since krb4 requests are not pre-authenticated they will be rejected.
+.It Li ports = Va "list of ports"
+List of ports the kdc should listen to.
+.It Li addresses = Va "list of interfaces"
+List of addresses the kdc should bind to.
+.It Li enable-kerberos4 = Va BOOL
+Turn on Kerberos 4 support.
+.It Li v4-realm = Va REALM
+To what realm v4 requests should be mapped.
+.It Li enable-524 = Va BOOL
+Should the Kerberos 524 converting facility be turned on.
+Default is the same as
+.Va enable-kerberos4 .
+.It Li enable-http = Va BOOL
+Should the kdc answer kdc-requests over http.
+.It Li enable-kaserver = Va BOOL
+If this kdc should emulate the AFS kaserver.
+.It Li check-ticket-addresses = Va BOOL
+Verify the addresses in the tickets used in tgs requests.
+.\" XXX
+.It Li allow-null-ticket-addresses = Va BOOL
+Allow address-less tickets.
+.\" XXX
+.It Li allow-anonymous = Va BOOL
+If the kdc is allowed to hand out anonymous tickets.
+.It Li encode_as_rep_as_tgs_rep = Va BOOL
+Encode as-rep as tgs-rep tobe compatible with mistakes older DCE secd did.
+.\" XXX
+.It Li kdc_warn_pwexpire = Va TIME
+The time before expiration that the user should be warned that her
+password is about to expire.
+.It Li logging = Va Logging
+What type of logging the kdc should use, see also [logging]/kdc.
+.It Li use_2b = {
+.Bl -tag -width "xxx" -offset indent
+.It Va principal Li = Va BOOL
+boolean value if the 524 daemon should return AFS 2b tokens for
+.Fa principal .
+.It ...
+.El
+.It Li }
+.It Li hdb-ldap-structural-object Va structural object
+If the LDAP backend is used for storing principals, this is the
+structural object that will be used when creating and when reading
+objects.
+The default value is account .
+.It Li hdb-ldap-create-base Va creation dn
+is the dn that will be appended to the principal when creating entries.
+Default value is the search dn.
+.El
+.It Li [kadmin]
+.Bl -tag -width "xxx" -offset indent
+.It Li require-preauth = Va BOOL
+If pre-authentication is required to talk to the kadmin server.
+.It Li password_lifetime = Va time
+If a principal already have its password set for expiration, this is
+the time it will be valid for after a change.
+.It Li default_keys = Va keytypes...
+For each entry in
+.Va default_keys
+try to parse it as a sequence of
+.Va etype:salttype:salt
+syntax of this if something like:
+.Pp
+[(des|des3|etype):](pw-salt|afs3-salt)[:string]
+.Pp
+If
+.Ar etype
+is omitted it means everything, and if string is omitted it means the
+default salt string (for that principal and encryption type).
+Additional special values of keytypes are:
+.Bl -tag -width "xxx" -offset indent
+.It Li v5
+The Kerberos 5 salt
+.Va pw-salt
+.It Li v4
+The Kerberos 4 salt
+.Va des:pw-salt:
+.El
+.It Li use_v4_salt = Va BOOL
+When true, this is the same as
+.Pp
+.Va default_keys = Va des3:pw-salt Va v4
+.Pp
+and is only left for backwards compatibility.
+.El
+.El
+.Sh ENVIRONMENT
+.Ev KRB5_CONFIG
+points to the configuration file to read.
+.Sh FILES
+.Bl -tag -width "/etc/kerberosV/krb5.conf"
+.It Pa /etc/kerberosV/krb5.conf
+configuration file for Kerberos 5.
+.El
+.Sh EXAMPLES
+.Bd -literal -offset indent
+[libdefaults]
+       default_realm = FOO.SE
+[domain_realm]
+       .foo.se = FOO.SE
+       .bar.se = FOO.SE
+[realms]
+       FOO.SE = {
+               kdc = kerberos.foo.se
+               v4_name_convert = {
+                       rcmd = host
+               }
+               v4_instance_convert = {
+                       xyz = xyz.bar.se
+               }
+               default_domain = foo.se
+       }
+[logging]
+       kdc = FILE:/var/heimdal/kdc.log
+       kdc = SYSLOG:INFO
+       default = SYSLOG:INFO:USER
+.Ed
+.Sh DIAGNOSTICS
+Since
+.Nm
+is read and parsed by the krb5 library, there is not a lot of
+opportunities for programs to report parsing errors in any useful
+format.
+To help overcome this problem, there is a program
+.Nm verify_krb5_conf
+that reads
+.Nm
+and tries to emit useful diagnostics from parsing errors.
+Note that this program does not have any way of knowing what options
+are actually used and thus cannot warn about unknown or misspelled
+ones.
+.Sh SEE ALSO
+.Xr kinit 1 ,
+.Xr krb5_425_conv_principal 3 ,
+.Xr krb5_openlog 3 ,
+.Xr strftime 3 ,
+.Xr verify_krb5_conf 8
diff --git a/src/kerberosV/src/lib/krb5/krb5.h b/src/kerberosV/src/lib/krb5/krb5.h
new file mode 100644 (file)
index 0000000..d7f07ad
--- /dev/null
@@ -0,0 +1,753 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: krb5.h,v 1.236.2.1 2005/10/12 12:42:09 lha Exp $ */
+
+#ifndef __KRB5_H__
+#define __KRB5_H__
+
+#include <time.h>
+#include <kerberosV/krb5-types.h>
+
+#include <kerberosV/asn1_err.h>
+#include <kerberosV/krb5_err.h>
+#include <kerberosV/heim_err.h>
+#include <kerberosV/k524_err.h>
+
+#include <kerberosV/krb5_asn1.h>
+
+/* name confusion with MIT */
+#ifndef KRB5KDC_ERR_KEY_EXP
+#define KRB5KDC_ERR_KEY_EXP KRB5KDC_ERR_KEY_EXPIRED
+#endif
+
+/* simple constants */
+
+#ifndef TRUE
+#define TRUE  1
+#define FALSE 0
+#endif
+
+typedef int krb5_boolean;
+
+typedef int32_t krb5_error_code;
+
+typedef int krb5_kvno;
+
+typedef u_int32_t krb5_flags;
+
+typedef void *krb5_pointer;
+typedef const void *krb5_const_pointer;
+
+struct krb5_crypto_data;
+typedef struct krb5_crypto_data *krb5_crypto;
+
+typedef CKSUMTYPE krb5_cksumtype;
+
+typedef Checksum krb5_checksum;
+
+typedef ENCTYPE krb5_enctype;
+
+typedef heim_octet_string krb5_data;
+
+/* PKINIT related forward declarations */
+struct ContentInfo;
+struct krb5_pk_identity;
+struct krb5_pk_cert;
+
+/* krb5_enc_data is a mit compat structure */
+typedef struct krb5_enc_data {
+    krb5_enctype enctype;
+    krb5_kvno kvno;
+    krb5_data ciphertext;
+} krb5_enc_data;
+
+/* alternative names */
+enum {
+    ENCTYPE_NULL               = ETYPE_NULL,
+    ENCTYPE_DES_CBC_CRC                = ETYPE_DES_CBC_CRC,
+    ENCTYPE_DES_CBC_MD4                = ETYPE_DES_CBC_MD4,
+    ENCTYPE_DES_CBC_MD5                = ETYPE_DES_CBC_MD5,
+    ENCTYPE_DES3_CBC_MD5       = ETYPE_DES3_CBC_MD5,
+    ENCTYPE_OLD_DES3_CBC_SHA1  = ETYPE_OLD_DES3_CBC_SHA1,
+    ENCTYPE_SIGN_DSA_GENERATE  = ETYPE_SIGN_DSA_GENERATE,
+    ENCTYPE_ENCRYPT_RSA_PRIV   = ETYPE_ENCRYPT_RSA_PRIV,
+    ENCTYPE_ENCRYPT_RSA_PUB    = ETYPE_ENCRYPT_RSA_PUB,
+    ENCTYPE_DES3_CBC_SHA1      = ETYPE_DES3_CBC_SHA1,
+    ENCTYPE_AES128_CTS_HMAC_SHA1_96 = ETYPE_AES128_CTS_HMAC_SHA1_96,
+    ENCTYPE_AES256_CTS_HMAC_SHA1_96 = ETYPE_AES256_CTS_HMAC_SHA1_96,
+    ENCTYPE_ARCFOUR_HMAC       = ETYPE_ARCFOUR_HMAC_MD5,
+    ENCTYPE_ARCFOUR_HMAC_MD5   = ETYPE_ARCFOUR_HMAC_MD5,
+    ENCTYPE_ARCFOUR_HMAC_MD5_56        = ETYPE_ARCFOUR_HMAC_MD5_56,
+    ENCTYPE_ENCTYPE_PK_CROSS   = ETYPE_ENCTYPE_PK_CROSS,
+    ENCTYPE_DES_CBC_NONE       = ETYPE_DES_CBC_NONE,
+    ENCTYPE_DES3_CBC_NONE      = ETYPE_DES3_CBC_NONE,
+    ENCTYPE_DES_CFB64_NONE     = ETYPE_DES_CFB64_NONE,
+    ENCTYPE_DES_PCBC_NONE      = ETYPE_DES_PCBC_NONE
+};
+
+typedef PADATA_TYPE krb5_preauthtype;
+
+typedef enum krb5_key_usage {
+    KRB5_KU_PA_ENC_TIMESTAMP = 1,
+    /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the
+       client key (section 5.4.1) */
+    KRB5_KU_TICKET = 2,
+    /* AS-REP Ticket and TGS-REP Ticket (includes tgs session key or
+       application session key), encrypted with the service key
+       (section 5.4.2) */
+    KRB5_KU_AS_REP_ENC_PART = 3,
+    /* AS-REP encrypted part (includes tgs session key or application
+       session key), encrypted with the client key (section 5.4.2) */
+    KRB5_KU_TGS_REQ_AUTH_DAT_SESSION = 4,
+    /* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs
+       session key (section 5.4.1) */
+    KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY = 5,
+    /* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs
+          authenticator subkey (section 5.4.1) */
+    KRB5_KU_TGS_REQ_AUTH_CKSUM = 6,
+    /* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, keyed
+       with the tgs session key (sections 5.3.2, 5.4.1) */
+    KRB5_KU_TGS_REQ_AUTH = 7,
+    /* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes tgs
+       authenticator subkey), encrypted with the tgs session key
+       (section 5.3.2) */
+    KRB5_KU_TGS_REP_ENC_PART_SESSION = 8,
+    /* TGS-REP encrypted part (includes application session key),
+       encrypted with the tgs session key (section 5.4.2) */
+    KRB5_KU_TGS_REP_ENC_PART_SUB_KEY = 9,
+    /* TGS-REP encrypted part (includes application session key),
+       encrypted with the tgs authenticator subkey (section 5.4.2) */
+    KRB5_KU_AP_REQ_AUTH_CKSUM = 10,
+    /* AP-REQ Authenticator cksum, keyed with the application session
+       key (section 5.3.2) */
+    KRB5_KU_AP_REQ_AUTH = 11,
+    /* AP-REQ Authenticator (includes application authenticator
+       subkey), encrypted with the application session key (section
+       5.3.2) */
+    KRB5_KU_AP_REQ_ENC_PART = 12,
+    /* AP-REP encrypted part (includes application session subkey),
+       encrypted with the application session key (section 5.5.2) */
+    KRB5_KU_KRB_PRIV = 13,
+    /* KRB-PRIV encrypted part, encrypted with a key chosen by the
+       application (section 5.7.1) */
+    KRB5_KU_KRB_CRED = 14,
+    /* KRB-CRED encrypted part, encrypted with a key chosen by the
+       application (section 5.8.1) */
+    KRB5_KU_KRB_SAFE_CKSUM = 15,
+    /* KRB-SAFE cksum, keyed with a key chosen by the application
+       (section 5.6.1) */
+    KRB5_KU_OTHER_ENCRYPTED = 16,
+    /* Data which is defined in some specification outside of
+       Kerberos to be encrypted using an RFC1510 encryption type. */
+    KRB5_KU_OTHER_CKSUM = 17,
+    /* Data which is defined in some specification outside of
+       Kerberos to be checksummed using an RFC1510 checksum type. */
+    KRB5_KU_KRB_ERROR = 18,
+    /* Krb-error checksum */
+    KRB5_KU_AD_KDC_ISSUED = 19,
+    /* AD-KDCIssued checksum */
+    KRB5_KU_MANDATORY_TICKET_EXTENSION = 20,
+    /* Checksum for Mandatory Ticket Extensions */
+    KRB5_KU_AUTH_DATA_TICKET_EXTENSION = 21,
+    /* Checksum in Authorization Data in Ticket Extensions */
+    KRB5_KU_USAGE_SEAL = 22,
+    /* seal in GSSAPI krb5 mechanism */
+    KRB5_KU_USAGE_SIGN = 23,
+    /* sign in GSSAPI krb5 mechanism */
+    KRB5_KU_USAGE_SEQ = 24,
+    /* SEQ in GSSAPI krb5 mechanism */
+    KRB5_KU_USAGE_ACCEPTOR_SEAL = 22,
+    /* acceptor sign in GSSAPI CFX krb5 mechanism */
+    KRB5_KU_USAGE_ACCEPTOR_SIGN = 23,
+    /* acceptor seal in GSSAPI CFX krb5 mechanism */
+    KRB5_KU_USAGE_INITIATOR_SEAL = 24,       
+    /* initiator sign in GSSAPI CFX krb5 mechanism */
+    KRB5_KU_USAGE_INITIATOR_SIGN = 25,
+    /* initiator seal in GSSAPI CFX krb5 mechanism */
+    KRB5_KU_PA_SERVER_REFERRAL_DATA = 22,
+    /* encrypted server referral data */
+    KRB5_KU_SAM_CHECKSUM = 25,
+    /* Checksum for the SAM-CHECKSUM field */
+    KRB5_KU_SAM_ENC_TRACK_ID = 26,
+    /* Encryption of the SAM-TRACK-ID field */
+    KRB5_KU_PA_SERVER_REFERRAL = 26,
+    /* Keyusage for the server referral in a TGS req */
+    KRB5_KU_SAM_ENC_NONCE_SAD = 27
+    /* Encryption of the SAM-NONCE-OR-SAD field */
+} krb5_key_usage;
+
+typedef krb5_key_usage krb5_keyusage;
+
+typedef enum krb5_salttype {
+    KRB5_PW_SALT = KRB5_PADATA_PW_SALT,
+    KRB5_AFS3_SALT = KRB5_PADATA_AFS3_SALT
+}krb5_salttype;
+
+typedef struct krb5_salt {
+    krb5_salttype salttype;
+    krb5_data saltvalue;
+} krb5_salt;
+
+typedef ETYPE_INFO krb5_preauthinfo;
+
+typedef struct {
+    krb5_preauthtype type;
+    krb5_preauthinfo info; /* list of preauthinfo for this type */
+} krb5_preauthdata_entry;
+
+typedef struct krb5_preauthdata {
+    unsigned len;
+    krb5_preauthdata_entry *val;
+}krb5_preauthdata;
+
+typedef enum krb5_address_type { 
+    KRB5_ADDRESS_INET     =   2,
+    KRB5_ADDRESS_INET6    =  24,
+    KRB5_ADDRESS_ADDRPORT = 256,
+    KRB5_ADDRESS_IPPORT   = 257
+} krb5_address_type;
+
+enum {
+  AP_OPTS_USE_SESSION_KEY = 1,
+  AP_OPTS_MUTUAL_REQUIRED = 2,
+  AP_OPTS_USE_SUBKEY = 4               /* library internal */
+};
+
+typedef HostAddress krb5_address;
+
+typedef HostAddresses krb5_addresses;
+
+typedef enum krb5_keytype { 
+    KEYTYPE_NULL       = 0,
+    KEYTYPE_DES                = 1,
+    KEYTYPE_DES3       = 7,
+    KEYTYPE_AES128     = 17,
+    KEYTYPE_AES256     = 18,
+    KEYTYPE_ARCFOUR    = 23,
+    KEYTYPE_ARCFOUR_56 = 24,
+    KEYTYPE_RC2                = -0x1005,
+    KEYTYPE_AES192     = -0x1006
+} krb5_keytype;
+
+typedef EncryptionKey krb5_keyblock;
+
+typedef AP_REQ krb5_ap_req;
+
+struct krb5_cc_ops;
+
+#define KRB5_DEFAULT_CCFILE_ROOT "/tmp/krb5cc_"
+
+#define KRB5_DEFAULT_CCROOT "FILE:" KRB5_DEFAULT_CCFILE_ROOT
+
+#define KRB5_ACCEPT_NULL_ADDRESSES(C)                                   \
+    krb5_config_get_bool_default((C), NULL, TRUE,                       \
+                                "libdefaults", "accept_null_addresses", \
+                                NULL)
+
+typedef void *krb5_cc_cursor;
+
+typedef struct krb5_ccache_data {
+    const struct krb5_cc_ops *ops;
+    krb5_data data;
+}krb5_ccache_data;
+
+typedef struct krb5_ccache_data *krb5_ccache;
+
+typedef struct krb5_context_data *krb5_context;
+
+typedef Realm krb5_realm;
+typedef const char *krb5_const_realm; /* stupid language */
+
+#define krb5_realm_length(r) strlen(r)
+#define krb5_realm_data(r) (r)
+
+typedef Principal krb5_principal_data;
+typedef struct Principal *krb5_principal;
+typedef const struct Principal *krb5_const_principal;
+
+typedef time_t krb5_deltat;
+typedef time_t krb5_timestamp;
+
+typedef struct krb5_times {
+  krb5_timestamp authtime;
+  krb5_timestamp starttime;
+  krb5_timestamp endtime;
+  krb5_timestamp renew_till;
+} krb5_times;
+
+typedef union {
+    TicketFlags b;
+    krb5_flags i;
+} krb5_ticket_flags;
+
+/* options for krb5_get_in_tkt() */
+#define KDC_OPT_FORWARDABLE            (1 << 1)
+#define KDC_OPT_FORWARDED              (1 << 2)
+#define KDC_OPT_PROXIABLE              (1 << 3)
+#define KDC_OPT_PROXY                  (1 << 4)
+#define KDC_OPT_ALLOW_POSTDATE         (1 << 5)
+#define KDC_OPT_POSTDATED              (1 << 6)
+#define KDC_OPT_RENEWABLE              (1 << 8)
+#define KDC_OPT_REQUEST_ANONYMOUS      (1 << 14)
+#define KDC_OPT_DISABLE_TRANSITED_CHECK        (1 << 26)
+#define KDC_OPT_RENEWABLE_OK           (1 << 27)
+#define KDC_OPT_ENC_TKT_IN_SKEY                (1 << 28)
+#define KDC_OPT_RENEW                  (1 << 30)
+#define KDC_OPT_VALIDATE               (1 << 31)
+
+typedef union {
+    KDCOptions b;
+    krb5_flags i;
+} krb5_kdc_flags;
+
+/* flags for krb5_verify_ap_req */
+
+#define KRB5_VERIFY_AP_REQ_IGNORE_INVALID      (1 << 0)
+
+#define KRB5_GC_CACHED                 (1U << 0)
+#define KRB5_GC_USER_USER              (1U << 1)
+#define KRB5_GC_EXPIRED_OK             (1U << 2)
+
+/* constants for compare_creds (and cc_retrieve_cred) */
+#define KRB5_TC_DONT_MATCH_REALM       (1U << 31)
+#define KRB5_TC_MATCH_KEYTYPE          (1U << 30)
+#define KRB5_TC_MATCH_KTYPE            KRB5_TC_MATCH_KEYTYPE    /* MIT name */
+#define KRB5_TC_MATCH_SRV_NAMEONLY     (1 << 29)
+#define KRB5_TC_MATCH_FLAGS_EXACT      (1 << 28)
+#define KRB5_TC_MATCH_FLAGS            (1 << 27)
+#define KRB5_TC_MATCH_TIMES_EXACT      (1 << 26)
+#define KRB5_TC_MATCH_TIMES            (1 << 25)
+#define KRB5_TC_MATCH_AUTHDATA         (1 << 24)
+#define KRB5_TC_MATCH_2ND_TKT          (1 << 23)
+#define KRB5_TC_MATCH_IS_SKEY          (1 << 22)
+
+typedef AuthorizationData krb5_authdata;
+
+typedef KRB_ERROR krb5_error;
+
+typedef struct krb5_creds {
+    krb5_principal client;
+    krb5_principal server;
+    krb5_keyblock session;
+    krb5_times times;
+    krb5_data ticket;
+    krb5_data second_ticket;
+    krb5_authdata authdata;
+    krb5_addresses addresses;
+    krb5_ticket_flags flags;
+} krb5_creds;
+
+typedef struct krb5_cc_ops {
+    const char *prefix;
+    const char* (*get_name)(krb5_context, krb5_ccache);
+    krb5_error_code (*resolve)(krb5_context, krb5_ccache *, const char *);
+    krb5_error_code (*gen_new)(krb5_context, krb5_ccache *);
+    krb5_error_code (*init)(krb5_context, krb5_ccache, krb5_principal);
+    krb5_error_code (*destroy)(krb5_context, krb5_ccache);
+    krb5_error_code (*close)(krb5_context, krb5_ccache);
+    krb5_error_code (*store)(krb5_context, krb5_ccache, krb5_creds*);
+    krb5_error_code (*retrieve)(krb5_context, krb5_ccache, 
+                               krb5_flags, const krb5_creds*, krb5_creds *);
+    krb5_error_code (*get_princ)(krb5_context, krb5_ccache, krb5_principal*);
+    krb5_error_code (*get_first)(krb5_context, krb5_ccache, krb5_cc_cursor *);
+    krb5_error_code (*get_next)(krb5_context, krb5_ccache, 
+                               krb5_cc_cursor*, krb5_creds*);
+    krb5_error_code (*end_get)(krb5_context, krb5_ccache, krb5_cc_cursor*);
+    krb5_error_code (*remove_cred)(krb5_context, krb5_ccache, 
+                                  krb5_flags, krb5_creds*);
+    krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags);
+    int (*get_version)(krb5_context, krb5_ccache);
+} krb5_cc_ops;
+
+struct krb5_log_facility;
+
+struct krb5_config_binding {
+    enum { krb5_config_string, krb5_config_list } type;
+    char *name;
+    struct krb5_config_binding *next;
+    union {
+       char *string;
+       struct krb5_config_binding *list;
+       void *generic;
+    } u;
+};
+
+typedef struct krb5_config_binding krb5_config_binding;
+
+typedef krb5_config_binding krb5_config_section;
+
+typedef struct krb5_context_data {
+    krb5_enctype *etypes;
+    krb5_enctype *etypes_des;
+    char **default_realms;
+    time_t max_skew;
+    time_t kdc_timeout;
+    unsigned max_retries;
+    int32_t kdc_sec_offset;
+    int32_t kdc_usec_offset;
+    krb5_config_section *cf;
+    struct et_list *et_list;
+    struct krb5_log_facility *warn_dest;
+    krb5_cc_ops *cc_ops;
+    int num_cc_ops;
+    const char *http_proxy;
+    const char *time_fmt;
+    krb5_boolean log_utc;
+    const char *default_keytab;
+    const char *default_keytab_modify;
+    krb5_boolean use_admin_kdc;
+    krb5_addresses *extra_addresses;
+    krb5_boolean scan_interfaces;      /* `ifconfig -a' */
+    krb5_boolean srv_lookup;           /* do SRV lookups */
+    krb5_boolean srv_try_txt;          /* try TXT records also */
+    int32_t fcache_vno;                        /* create cache files w/ this
+                                           version */
+    int num_kt_types;                  /* # of registered keytab types */
+    struct krb5_keytab_data *kt_types;  /* registered keytab types */
+    const char *date_fmt;
+    char *error_string;
+    char error_buf[256];
+    krb5_addresses *ignore_addresses;
+    char *default_cc_name;
+    int pkinit_flags;
+    void *mutex;                       /* protects error_string/error_buf */
+    int large_msg_size;
+} krb5_context_data;
+
+enum {
+    KRB5_PKINIT_WIN2K          = 1,    /* wire compatible with Windows 2k */
+    KRB5_PKINIT_PACKET_CABLE   = 2     /* use packet cable standard */
+};
+
+typedef struct krb5_ticket {
+    EncTicketPart ticket;
+    krb5_principal client;
+    krb5_principal server;
+} krb5_ticket;
+
+typedef Authenticator krb5_authenticator_data;
+
+typedef krb5_authenticator_data *krb5_authenticator;
+
+struct krb5_rcache_data;
+typedef struct krb5_rcache_data *krb5_rcache;
+typedef Authenticator krb5_donot_replay;
+
+#define KRB5_STORAGE_HOST_BYTEORDER                    0x01 /* old */
+#define KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS    0x02
+#define KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE            0x04
+#define KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE            0x08
+#define KRB5_STORAGE_BYTEORDER_MASK                    0x60
+#define KRB5_STORAGE_BYTEORDER_BE                      0x00 /* default */
+#define KRB5_STORAGE_BYTEORDER_LE                      0x20
+#define KRB5_STORAGE_BYTEORDER_HOST                    0x40
+#define KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER                0x80
+
+struct krb5_storage_data;
+typedef struct krb5_storage_data krb5_storage;
+
+typedef struct krb5_keytab_entry {
+    krb5_principal principal;
+    krb5_kvno vno;
+    krb5_keyblock keyblock;
+    u_int32_t timestamp;
+} krb5_keytab_entry;
+
+typedef struct krb5_kt_cursor {
+    int fd;
+    krb5_storage *sp;
+    void *data;
+} krb5_kt_cursor;
+
+struct krb5_keytab_data;
+
+typedef struct krb5_keytab_data *krb5_keytab;
+
+#define KRB5_KT_PREFIX_MAX_LEN 30
+
+struct krb5_keytab_data {
+    const char *prefix;
+    krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab);
+    krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t);
+    krb5_error_code (*close)(krb5_context, krb5_keytab);
+    krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal, 
+                          krb5_kvno, krb5_enctype, krb5_keytab_entry*);
+    krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
+    krb5_error_code (*next_entry)(krb5_context, krb5_keytab, 
+                                 krb5_keytab_entry*, krb5_kt_cursor*);
+    krb5_error_code (*end_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
+    krb5_error_code (*add)(krb5_context, krb5_keytab, krb5_keytab_entry*);
+    krb5_error_code (*remove)(krb5_context, krb5_keytab, krb5_keytab_entry*);
+    void *data;
+    int32_t version;
+};
+
+typedef struct krb5_keytab_data krb5_kt_ops;
+
+struct krb5_keytab_key_proc_args {
+    krb5_keytab keytab;
+    krb5_principal principal;
+};
+
+typedef struct krb5_keytab_key_proc_args krb5_keytab_key_proc_args;
+
+typedef struct krb5_replay_data {
+    krb5_timestamp timestamp;
+    int32_t usec;
+    u_int32_t seq;
+} krb5_replay_data;
+
+/* flags for krb5_auth_con_setflags */
+enum {
+    KRB5_AUTH_CONTEXT_DO_TIME                  = 1,
+    KRB5_AUTH_CONTEXT_RET_TIME                 = 2,
+    KRB5_AUTH_CONTEXT_DO_SEQUENCE              = 4,
+    KRB5_AUTH_CONTEXT_RET_SEQUENCE             = 8,
+    KRB5_AUTH_CONTEXT_PERMIT_ALL               = 16,
+    KRB5_AUTH_CONTEXT_USE_SUBKEY               = 32,
+    KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED     = 64
+};
+
+/* flags for krb5_auth_con_genaddrs */
+enum {
+    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR       = 1,
+    KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR  = 3,
+    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR      = 4,
+    KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR = 12
+};
+
+typedef struct krb5_auth_context_data {
+    unsigned int flags;
+
+    krb5_address *local_address;
+    krb5_address *remote_address;
+    int16_t local_port;
+    int16_t remote_port;
+    krb5_keyblock *keyblock;
+    krb5_keyblock *local_subkey;
+    krb5_keyblock *remote_subkey;
+
+    u_int32_t local_seqnumber;
+    u_int32_t remote_seqnumber;
+
+    krb5_authenticator authenticator;
+  
+    krb5_pointer i_vector;
+  
+    krb5_rcache rcache;
+
+    krb5_keytype keytype;      /* Â¿requested key type ? */
+    krb5_cksumtype cksumtype;  /* Â¡requested checksum type! */
+  
+}krb5_auth_context_data, *krb5_auth_context;
+
+typedef struct {
+    KDC_REP kdc_rep;
+    EncKDCRepPart enc_part;
+    KRB_ERROR error;
+} krb5_kdc_rep;
+
+extern const char *heimdal_version, *heimdal_long_version;
+
+typedef void (*krb5_log_log_func_t)(const char*, const char*, void*);
+typedef void (*krb5_log_close_func_t)(void*);
+
+typedef struct krb5_log_facility {
+    char *program;
+    int len;
+    struct facility *val;
+} krb5_log_facility;
+
+typedef EncAPRepPart krb5_ap_rep_enc_part;
+
+#define KRB5_RECVAUTH_IGNORE_VERSION 1
+
+#define KRB5_SENDAUTH_VERSION "KRB5_SENDAUTH_V1.0"
+
+#define KRB5_TGS_NAME_SIZE (6)
+#define KRB5_TGS_NAME ("krbtgt")
+
+/* variables */
+
+extern const char *krb5_config_file;
+extern const char *krb5_defkeyname;
+
+typedef enum {
+    KRB5_PROMPT_TYPE_PASSWORD          = 0x1,
+    KRB5_PROMPT_TYPE_NEW_PASSWORD      = 0x2,
+    KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN = 0x3,
+    KRB5_PROMPT_TYPE_PREAUTH           = 0x4
+} krb5_prompt_type;
+
+typedef struct _krb5_prompt {
+    const char *prompt;
+    int hidden;
+    krb5_data *reply;
+    krb5_prompt_type type;
+} krb5_prompt;
+
+typedef int (*krb5_prompter_fct)(krb5_context context,
+                                void *data,
+                                const char *name,
+                                const char *banner,
+                                int num_prompts,
+                                krb5_prompt prompts[]);
+typedef krb5_error_code (*krb5_key_proc)(krb5_context context,
+                                        krb5_enctype type,
+                                        krb5_salt salt,
+                                        krb5_const_pointer keyseed,
+                                        krb5_keyblock **key);
+typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context context,
+                                            krb5_keyblock *key,
+                                            krb5_key_usage usage,
+                                            krb5_const_pointer decrypt_arg,
+                                            krb5_kdc_rep *dec_rep);
+typedef krb5_error_code (*krb5_s2k_proc)(krb5_context context,
+                                        krb5_enctype type,
+                                        krb5_const_pointer keyseed,
+                                        krb5_salt salt,
+                                        krb5_data *s2kparms,
+                                        krb5_keyblock **key);
+
+struct _krb5_get_init_creds_opt_private;
+
+typedef struct _krb5_get_init_creds_opt {
+    krb5_flags flags;
+    krb5_deltat tkt_life;
+    krb5_deltat renew_life;
+    int forwardable;
+    int proxiable;
+    int anonymous;
+    krb5_enctype *etype_list;
+    int etype_list_length;
+    krb5_addresses *address_list;
+    /* XXX the next three should not be used, as they may be
+       removed later */
+    krb5_preauthtype *preauth_list;
+    int preauth_list_length;
+    krb5_data *salt;
+    struct _krb5_get_init_creds_opt_private *opt_private;
+} 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_ANONYMOUS      0x0100
+#define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK        0x0200
+
+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
+
+typedef struct krb5_verify_opt {
+    unsigned int flags;
+    krb5_ccache ccache;
+    krb5_keytab keytab;
+    krb5_boolean secure;
+    const char *service;
+} krb5_verify_opt;
+
+#define KRB5_VERIFY_LREALMS            1
+#define KRB5_VERIFY_NO_ADDRESSES       2
+
+extern const krb5_cc_ops krb5_acc_ops;
+extern const krb5_cc_ops krb5_fcc_ops;
+extern const krb5_cc_ops krb5_mcc_ops;
+extern const krb5_cc_ops krb5_kcm_ops;
+
+extern const krb5_kt_ops krb5_fkt_ops;
+extern const krb5_kt_ops krb5_wrfkt_ops;
+extern const krb5_kt_ops krb5_javakt_ops;
+extern const krb5_kt_ops krb5_mkt_ops;
+extern const krb5_kt_ops krb5_akf_ops;
+extern const krb5_kt_ops krb4_fkt_ops;
+extern const krb5_kt_ops krb5_srvtab_fkt_ops;
+extern const krb5_kt_ops krb5_any_ops;
+
+#define KRB5_KPASSWD_VERS_CHANGEPW      1
+#define KRB5_KPASSWD_VERS_SETPW         0xff80
+
+#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
+#define KRB5_KPASSWD_ACCESSDENIED 5
+#define KRB5_KPASSWD_BAD_VERSION 6
+#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7
+
+#define KPASSWD_PORT 464
+
+/* types for the new krbhst interface */
+struct krb5_krbhst_data;
+typedef struct krb5_krbhst_data *krb5_krbhst_handle;
+
+#define KRB5_KRBHST_KDC                1
+#define KRB5_KRBHST_ADMIN      2
+#define KRB5_KRBHST_CHANGEPW   3
+#define KRB5_KRBHST_KRB524     4
+
+typedef struct krb5_krbhst_info {
+    enum { KRB5_KRBHST_UDP,
+          KRB5_KRBHST_TCP,
+          KRB5_KRBHST_HTTP } proto;
+    unsigned short port;
+    unsigned short def_port;
+    struct addrinfo *ai;
+    struct krb5_krbhst_info *next;
+    char hostname[1]; /* has to come last */
+} krb5_krbhst_info;
+
+/* flags for krb5_krbhst_init_flags (and krb5_send_to_kdc_flags) */
+enum {
+    KRB5_KRBHST_FLAGS_MASTER      = 1,
+    KRB5_KRBHST_FLAGS_LARGE_MSG          = 2
+};
+
+struct credentials; /* this is to keep the compiler happy */
+struct getargs;
+struct sockaddr;
+
+#include <kerberosV/krb5-protos.h>
+
+#endif /* __KRB5_H__ */
+
diff --git a/src/kerberosV/src/lib/krb5/krb524_convert_creds_kdc.3 b/src/kerberosV/src/lib/krb5/krb524_convert_creds_kdc.3
new file mode 100644 (file)
index 0000000..77697e8
--- /dev/null
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb524_convert_creds_kdc.3,v 1.2 2005/05/25 13:19:16 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt KRB524_CONVERT_CREDS_KDC 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb524_convert_creds_kdc ,
+.Nm krb524_convert_creds_kdc_ccache
+.Nd converts Kerberos 5 credentials to Kerberos 4 credentials
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb524_convert_creds_kdc
+.Fa "krb5_context context"
+.Fa "krb5_creds *in_cred"
+.Fa "struct credentials *v4creds"
+.Fc
+.Ft krb5_error_code
+.Fo krb524_convert_creds_kdc_ccache
+.Fa "krb5_context context"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *in_cred"
+.Fa "struct credentials *v4creds"
+.Fc
+.Sh DESCRIPTION
+Convert the Kerberos 5 credential to Kerberos 4 credential.
+This is done by sending them to the 524 service in the KDC.
+.Pp
+.Fn krb524_convert_creds_kdc
+converts the Kerberos 5 credential in
+.Fa in_cred
+to Kerberos 4 credential that is stored in
+.Fa credentials .
+.Pp
+.Fn krb524_convert_creds_kdc_ccache
+is diffrent from
+.Fn krb524_convert_creds_kdc
+in that way that if
+.Fa in_cred
+doesn't contain a DES session key, then a new one is fetched from the
+KDC and stored in the cred cache
+.Fa ccache ,
+and then the KDC is queried to convert the credential.
+.Pp
+This interfaces are used to make the migration to Kerberos 5 from
+Kerberos 4 easier.
+There are few services that still need Kerberos 4, and this is mainly
+for compatibility for those services.
+Some services, like AFS, really have Kerberos 5 supports, but still
+uses the 524 interface to make the migration easier.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_425_conv_principal.3 b/src/kerberosV/src/lib/krb5/krb5_425_conv_principal.3
new file mode 100644 (file)
index 0000000..114cd6a
--- /dev/null
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_425_conv_principal.3,v 1.12 2003/09/03 00:13:07 lha Exp $
+.\"
+.Dd September  3, 2003
+.Dt KRB5_425_CONV_PRINCIPAL 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_425_conv_principal ,
+.Nm krb5_425_conv_principal_ext ,
+.Nm krb5_524_conv_principal
+.Nd converts to and from version 4 principals
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_425_conv_principal "krb5_context context" "const char *name" "const char *instance" "const char *realm" "krb5_principal *principal"
+.Ft krb5_error_code
+.Fn krb5_425_conv_principal_ext "krb5_context context" "const char *name" "const char *instance" "const char *realm" "krb5_boolean (*func)(krb5_context, krb5_principal)" "krb5_boolean resolve" "krb5_principal *principal"
+.Ft krb5_error_code
+.Fn krb5_524_conv_principal "krb5_context context" "const krb5_principal principal" "char *name" "char *instance" "char *realm"
+.Sh DESCRIPTION
+Converting between version 4 and version 5 principals can at best be
+described as a mess.
+.Pp
+A version 4 principal consists of a name, an instance, and a realm. A
+version 5 principal consists of one or more components, and a
+realm. In some cases also the first component/name will differ between
+version 4 and version 5.  Furthermore the second component of a host
+principal will be the fully qualified domain name of the host in
+question, while the instance of a version 4 principal will only
+contain the first part (short hostname).  Because of these problems
+the conversion between principals will have to be site customized.
+.Pp
+.Fn krb5_425_conv_principal_ext
+will try to convert a version 4 principal, given by
+.Fa name ,
+.Fa instance ,
+and
+.Fa realm ,
+to a version 5 principal. This can result in several possible
+principals, and if
+.Fa func
+is non-NULL, it will be called for each candidate principal.
+.Fa func
+should return true if the principal was
+.Dq good .
+To accomplish this,
+.Fn krb5_425_conv_principal_ext
+will look up the name in
+.Pa krb5.conf .
+It first looks in the
+.Li v4_name_convert/host
+subsection, which should contain a list of version 4 names whose
+instance should be treated as a hostname. This list can be specified
+for each realm (in the
+.Li realms
+section), or in the
+.Li libdefaults
+section.  If the name is found the resulting name of the principal
+will be the value of this binding. The instance is then first looked
+up in
+.Li v4_instance_convert
+for the specified realm. If found the resulting value will be used as
+instance (this can be used for special cases), no further attempts
+will be made to find a conversion if this fails (with
+.Fa func ) .
+If the
+.Fa resolve
+parameter is true, the instance will be looked up with
+.Fn gethostbyname .
+This can be a time consuming, error prone, and unsafe operation.  Next
+a list of hostnames will be created from the instance and the
+.Li v4_domains
+variable, which should contain a list of possible domains for the
+specific realm.
+.Pp
+On the other hand, if the name is not found in a
+.Li host
+section, it is looked up in a
+.Li v4_name_convert/plain
+binding. If found here the name will be converted, but the instance
+will be untouched.
+.Pp
+This list of default host-type conversions is compiled-in:
+.Bd -literal -offset indent
+v4_name_convert = {
+       host = {
+               ftp = ftp
+               hprop = hprop
+               imap = imap
+               pop = pop
+               rcmd = host
+               smtp = smtp
+       }
+}
+.Ed
+.Pp
+It will only be used if there isn't an entry for these names in the
+config file, so you can override these defaults.
+.Pp
+.Fn krb5_425_conv_principal
+will call
+.Fn krb5_425_conv_principal_ext
+with
+.Dv NULL
+as
+.Fa func ,
+and the value of
+.Li v4_instance_resolve
+(from the
+.Li libdefaults
+section) as
+.Fa resolve .
+.Pp
+.Fn krb5_524_conv_principal
+basically does the opposite of
+.Fn krb5_425_conv_principal ,
+it just doesn't have to look up any names, but will instead truncate
+instances found to belong to a host principal. The
+.Fa name ,
+.Fa instance ,
+and
+.Fa realm
+should be at least 40 characters long.
+.Sh EXAMPLES
+Since this is confusing an example is in place.
+.Pp
+Assume that we have the
+.Dq foo.com ,
+and
+.Dq bar.com
+domains that have shared a single version 4 realm, FOO.COM. The version 4
+.Pa krb.realms
+file looked like:
+.Bd -literal -offset indent
+foo.com                FOO.COM
+\&.foo.com     FOO.COM
+\&.bar.com     FOO.COM
+.Ed
+.Pp
+A
+.Pa krb5.conf
+file that covers this case might look like:
+.Bd -literal -offset indent
+[libdefaults]
+       v4_instance_resolve = yes
+[realms]
+       FOO.COM = {
+               kdc = kerberos.foo.com
+               v4_instance_convert = {
+                       foo = foo.com
+               }
+               v4_domains = foo.com
+       }
+.Ed
+.Pp
+With this setup and the following host table:
+.Bd -literal -offset indent
+foo.com
+a-host.foo.com
+b-host.bar.com
+.Ed
+the following conversions will be made:
+.Bd -literal -offset indent
+rcmd.a-host    -\*(Gt host/a-host.foo.com
+ftp.b-host     -\*(Gt ftp/b-host.bar.com
+pop.foo                -\*(Gt pop/foo.com
+ftp.other      -\*(Gt ftp/other.foo.com
+other.a-host   -\*(Gt other/a-host
+.Ed
+.Pp
+The first three are what you expect. If you remove the
+.Dq v4_domains ,
+the fourth entry will result in an error (since the host
+.Dq other
+can't be found). Even if
+.Dq a-host
+is a valid host name, the last entry will not be converted, since the
+.Dq other
+name is not known to represent a host-type principal.
+If you turn off
+.Dq v4_instance_resolve
+the second example will result in
+.Dq ftp/b-host.foo.com
+(because of the default domain). And all of this is of course only
+valid if you have working name resolving.
+.Sh SEE ALSO
+.Xr krb5_build_principal 3 ,
+.Xr krb5_free_principal 3 ,
+.Xr krb5_parse_name 3 ,
+.Xr krb5_sname_to_principal 3 ,
+.Xr krb5_unparse_name 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_acl_match_file.3 b/src/kerberosV/src/lib/krb5/krb5_acl_match_file.3
new file mode 100644 (file)
index 0000000..e790a62
--- /dev/null
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_acl_match_file.3,v 1.2 2004/03/31 04:23:18 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt KRB5_ACL_MATCH_FILE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_acl_match_file ,
+.Nm krb5_acl_match_string
+.Nd ACL matching functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.Ft krb5_error_code
+.Fo krb5_acl_match_file
+.Fa "krb5_context context"
+.Fa "const char *file"
+.Fa "const char *format"
+.Fa "..."
+.Fc
+.Ft krb5_error_code
+.Fo krb5_acl_match_string
+.Fa "krb5_context context"
+.Fa "const char *string"
+.Fa "const char *format"
+.Fa "..."
+.Fc
+.Sh DESCRIPTION
+.Nm krb5_acl_match_file
+matches ACL format against each line in a file.
+Lines starting with # are treated like comments and ignored.
+.Pp
+.Nm krb5_acl_match_string
+matches ACL format against a string.
+.Pp
+The ACL format has three format specifiers: s, f and r.
+Each specifier will retrieve one argument from the variable arguments
+for either matching or storing data.
+The input string is split up using " " and "\et" as a delimiter; multiple
+" " and "\et" in a row are considered to be the same.
+.Pp
+.Bl -tag -width "fXX" -offset indent
+.It s
+Matches a string using
+.Xr strcmp 3
+(case sensitive).
+.It f
+Matches the string with
+.Xr fnmatch 3 .
+The
+.Fa flags
+argument (the last argument) passed to the fnmatch function is 0.
+.It r
+Returns a copy of the string in the char ** passed in; the copy must be
+freed with
+.Xr free 3 .
+There is no need to
+.Xr free 3
+the string on error: the function will clean up and set the pointer to
+.Dv NULL .
+.El
+.Pp
+All unknown format specifiers cause an error.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+char *s;
+
+ret = krb5_acl_match_string(context, "foo", "s", "foo");
+if (ret)
+    krb5_errx(context, 1, "acl didn't match");
+ret = krb5_acl_match_string(context, "foo foo baz/kaka",
+    "ss", "foo", &s, "foo/*");
+if (ret) {
+    /* no need to free(s) on error */
+    assert(s == NULL);
+    krb5_errx(context, 1, "acl didn't match");
+}
+free(s);
+.Ed
+.Sh SEE ALSO
+.Xr krb5 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_address.3 b/src/kerberosV/src/lib/krb5/krb5_address.3
new file mode 100644 (file)
index 0000000..48eec56
--- /dev/null
@@ -0,0 +1,359 @@
+.\" Copyright (c) 2003, 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_address.3,v 1.10 2005/04/24 07:52:03 lha Exp $
+.\"
+.Dd April 24, 2005
+.Dt KRB5_ADDRESS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_address ,
+.Nm krb5_addresses ,
+.Nm krb5_sockaddr2address ,
+.Nm krb5_sockaddr2port ,
+.Nm krb5_addr2sockaddr ,
+.Nm krb5_max_sockaddr_size ,
+.Nm krb5_sockaddr_uninteresting ,
+.Nm krb5_h_addr2sockaddr ,
+.Nm krb5_h_addr2addr ,
+.Nm krb5_anyaddr ,
+.Nm krb5_print_address ,
+.Nm krb5_parse_address ,
+.Nm krb5_address_order ,
+.Nm krb5_address_compare ,
+.Nm krb5_address_search ,
+.Nm krb5_free_address ,
+.Nm krb5_free_addresses ,
+.Nm krb5_copy_address ,
+.Nm krb5_copy_addresses ,
+.Nm krb5_append_addresses ,
+.Nm krb5_make_addrport
+.Nd manage addresses in Kerberos
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fo krb5_sockaddr2address
+.Fa "krb5_context context"
+.Fa "const struct sockaddr *sa"
+.Fa "krb5_address *addr"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_sockaddr2port
+.Fa "krb5_context context"
+.Fa "const struct sockaddr *sa"
+.Fa "int16_t *port"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_addr2sockaddr
+.Fa "krb5_context context"
+.Fa "const krb5_address *addr"
+.Fa "struct sockaddr *sa"
+.Fa "krb5_socklen_t *sa_size"
+.Fa "int port"
+.Fc
+.Ft size_t
+.Fo krb5_max_sockaddr_size
+.Fa "void"
+.Fc
+.Ft "krb5_boolean"
+.Fo krb5_sockaddr_uninteresting
+.Fa "const struct sockaddr *sa"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_h_addr2sockaddr
+.Fa "krb5_context context"
+.Fa "int af"
+.Fa "const char *addr"
+.Fa "struct sockaddr *sa"
+.Fa "krb5_socklen_t *sa_size"
+.Fa "int port"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_h_addr2addr
+.Fa "krb5_context context"
+.Fa "int af"
+.Fa "const char *haddr"
+.Fa "krb5_address *addr"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_anyaddr
+.Fa "krb5_context context"
+.Fa "int af"
+.Fa "struct sockaddr *sa"
+.Fa "krb5_socklen_t *sa_size"
+.Fa "int port"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_print_address
+.Fa "const krb5_address *addr"
+.Fa "char *str"
+.Fa "size_t len"
+.Fa "size_t *ret_len"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_parse_address
+.Fa "krb5_context context"
+.Fa "const char *string"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft int
+.Fo "krb5_address_order"
+.Fa "krb5_context context"
+.Fa "const krb5_address *addr1"
+.Fa "const krb5_address *addr2"
+.Fc
+.Ft "krb5_boolean"
+.Fo krb5_address_compare
+.Fa "krb5_context context"
+.Fa "const krb5_address *addr1"
+.Fa "const krb5_address *addr2"
+.Fc
+.Ft "krb5_boolean"
+.Fo krb5_address_search
+.Fa "krb5_context context"
+.Fa "const krb5_address *addr"
+.Fa "const krb5_addresses *addrlist"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_address
+.Fa "krb5_context context"
+.Fa "krb5_address *address"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_addresses
+.Fa "krb5_context context"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_address
+.Fa "krb5_context context"
+.Fa "const krb5_address *inaddr"
+.Fa "krb5_address *outaddr"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_addresses
+.Fa "krb5_context context"
+.Fa "const krb5_addresses *inaddr"
+.Fa "krb5_addresses *outaddr"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_append_addresses
+.Fa "krb5_context context"
+.Fa "krb5_addresses *dest"
+.Fa "const krb5_addresses *source"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_make_addrport
+.Fa "krb5_context context"
+.Fa "krb5_address **res"
+.Fa "const krb5_address *addr"
+.Fa "int16_t port"
+.Fc
+.Sh DESCRIPTION
+The
+.Li krb5_address
+structure holds a address that can be used in Kerberos API
+calls. There are help functions to set and extract address information
+of the address.
+.Pp
+The
+.Li krb5_addresses
+structure holds a set of krb5_address:es.
+.Pp
+.Fn krb5_sockaddr2address
+stores a address a
+.Li "struct sockaddr"
+.Fa sa
+in the krb5_address
+.Fa addr .
+.Pp
+.Fn krb5_sockaddr2port
+extracts a
+.Fa port
+(if possible) from a
+.Li "struct sockaddr"
+.Fa sa .
+.Pp
+.Fn krb5_addr2sockaddr
+sets the
+struct sockaddr
+.Fa sockaddr
+from
+.Fa addr
+and
+.Fa port .
+The argument
+.Fa sa_size
+should initially contain the size of the
+.Fa sa ,
+and after the call, it will contain the actual length of the address.
+.Pp
+.Fn krb5_max_sockaddr_size
+returns the max size of the
+.Li struct sockaddr
+that the Kerberos library will return.
+.Pp
+.Fn krb5_sockaddr_uninteresting
+returns
+.Dv TRUE
+for all
+.Fa sa
+that the kerberos library thinks are uninteresting.
+One example are link local addresses.
+.Pp
+.Fn krb5_h_addr2sockaddr
+initializes a
+.Li "struct sockaddr"
+.Fa sa
+from
+.Fa af
+and the
+.Li "struct hostent"
+(see
+.Xr gethostbyname 3 )
+.Fa h_addr_list
+component.
+The argument
+.Fa sa_size
+should initially contain the size of the
+.Fa sa ,
+and after the call, it will contain the actual length of the address.
+.Pp
+.Fn krb5_h_addr2addr
+works like
+.Fn krb5_h_addr2sockaddr
+with the exception that it operates on a
+.Li krb5_address
+instead of a
+.Li struct sockaddr .
+.Pp
+.Fn krb5_anyaddr
+fills in a
+.Li "struct sockaddr"
+.Fa sa
+that can be used to
+.Xr bind 2
+to.
+The argument
+.Fa sa_size
+should initially contain the size of the
+.Fa sa ,
+and after the call, it will contain the actual length of the address.
+.Pp
+.Fn krb5_print_address
+prints the address in
+.Fa addr
+to the string
+.Fa string
+that have the length
+.Fa len .
+If
+.Fa ret_len
+is not
+.Dv NULL ,
+it will be filled with the length of the string if size were unlimited (not
+including the final
+.Ql \e0 ) .
+.Pp
+.Fn krb5_parse_address
+Returns the resolved hostname in
+.Fa string
+to the
+.Li krb5_addresses
+.Fa addresses .
+.Pp
+.Fn krb5_address_order
+compares the addresses
+.Fa addr1
+and
+.Fa addr2
+so that it can be used for sorting addresses. If the addresses are the
+same address
+.Fa krb5_address_order
+will return 0.
+.Pp
+.Fn krb5_address_compare
+compares the addresses
+.Fa addr1
+and
+.Fa addr2 .
+Returns
+.Dv TRUE
+if the two addresses are the same.
+.Pp
+.Fn krb5_address_search
+checks if the address
+.Fa addr
+is a member of the address set list
+.Fa addrlist .
+.Pp
+.Fn krb5_free_address
+frees the data stored in the
+.Fa address
+that is alloced with any of the krb5_address functions.
+.Pp
+.Fn krb5_free_addresses
+frees the data stored in the
+.Fa addresses
+that is alloced with any of the krb5_address functions.
+.Pp
+.Fn krb5_copy_address
+copies the content of address
+.Fa inaddr
+to
+.Fa outaddr .
+.Pp
+.Fn krb5_copy_addresses
+copies the content of the address list
+.Fa inaddr
+to
+.Fa outaddr .
+.Pp
+.Fn krb5_append_addresses
+adds the set of addresses in
+.Fa source
+to
+.Fa dest .
+While copying the addresses, duplicates are also sorted out.
+.Pp
+.Fn krb5_make_addrport
+allocates and creates an
+krb5_address in
+.Fa res
+of type KRB5_ADDRESS_ADDRPORT from
+.Fa ( addr , port ) .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_aname_to_localname.3 b/src/kerberosV/src/lib/krb5/krb5_aname_to_localname.3
new file mode 100644 (file)
index 0000000..5edc7b2
--- /dev/null
@@ -0,0 +1,80 @@
+.\" Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_aname_to_localname.3,v 1.4 2005/04/24 07:37:52 lha Exp $
+.\"
+.Dd April 24, 2005
+.Dt KRB5_ANAME_TO_LOCALNAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_aname_to_localname
+.Nd converts a principal to a system local name
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_boolean
+.Fo krb5_aname_to_localname
+.Fa "krb5_context context"
+.Fa "krb5_const_principal name"
+.Fa "size_t lnsize"
+.Fa "char *lname"
+.Fc
+.Sh DESCRIPTION
+This function takes a principal
+.Fa name ,
+verifies its in the local realm (using
+.Fn krb5_get_default_realms )
+and then returns the local name of the principal.
+.Pp
+If
+.Fa name
+isn't in one of the local realms an error is returned.
+.Pp
+If the size
+.Fa ( lnsize )
+of the local name
+.Fa ( lname )
+is to small, an error is returned.
+.Pp
+.Fn krb5_aname_to_localname
+should only be use by application that implements protocols that
+doesn't transport the login name and thus needs to convert a principal
+to a local name.
+.Pp
+Protocols should be designed so that the it autheticates using
+Kerberos, send over the login name and then verifies in the principal
+that authenticated is allowed to login and the login name.
+A way to check if a user is allowed to login is using the function
+.Fn krb5_kuserok .
+.Sh SEE ALSO
+.Xr krb5_get_default_realms 3 ,
+.Xr krb5_kuserok 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_appdefault.3 b/src/kerberosV/src/lib/krb5/krb5_appdefault.3
new file mode 100644 (file)
index 0000000..9e04263
--- /dev/null
@@ -0,0 +1,88 @@
+.\" Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_appdefault.3,v 1.11 2003/05/26 14:08:52 lha Exp $
+.\"
+.Dd July 25, 2000
+.Dt KRB5_APPDEFAULT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_appdefault_boolean ,
+.Nm krb5_appdefault_string ,
+.Nm krb5_appdefault_time
+.Nd get application configuration value
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft void
+.Fn krb5_appdefault_boolean "krb5_context context" "const char *appname" "krb5_realm realm" "const char *option" "krb5_boolean def_val" "krb5_boolean *ret_val"
+.Ft void
+.Fn krb5_appdefault_string "krb5_context context" "const char *appname" "krb5_realm realm" "const char *option" "const char *def_val" "char **ret_val"
+.Ft void
+.Fn krb5_appdefault_time "krb5_context context" "const char *appname" "krb5_realm realm" "const char *option" "time_t def_val" "time_t *ret_val"
+.Sh DESCRIPTION
+These functions get application defaults from the
+.Dv appdefaults
+section of the
+.Xr krb5.conf 5
+configuration file. These defaults can be specified per application,
+and/or per realm.
+.Pp
+These values will be looked for in
+.Xr krb5.conf 5 ,
+in order of descending importance.
+.Bd -literal -offset indent
+[appdefaults]
+       appname = {
+               realm = {
+                       option = value
+               }
+       }
+       appname = {
+               option = value
+       }
+       realm = {
+               option = value
+       }
+       option = value
+.Ed
+.Fa appname
+is the name of the application, and
+.Fa realm
+is the realm name. If the realm is omitted it will not be used for
+resolving values.
+.Fa def_val
+is the value to return if no value is found in
+.Xr krb5.conf 5 .
+.Sh SEE ALSO
+.Xr krb5_config 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_auth_context.3 b/src/kerberosV/src/lib/krb5/krb5_auth_context.3
new file mode 100644 (file)
index 0000000..7fbd824
--- /dev/null
@@ -0,0 +1,395 @@
+.\" Copyright (c) 2001 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_auth_context.3,v 1.17 2005/05/25 13:47:58 lha Exp $
+.\"
+.Dd May 17, 2005
+.Dt KRB5_AUTH_CONTEXT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_auth_con_addflags ,
+.Nm krb5_auth_con_free ,
+.Nm krb5_auth_con_genaddrs ,
+.Nm krb5_auth_con_generatelocalsubkey ,
+.Nm krb5_auth_con_getaddrs ,
+.Nm krb5_auth_con_getauthenticator ,
+.Nm krb5_auth_con_getflags ,
+.Nm krb5_auth_con_getkey ,
+.Nm krb5_auth_con_getlocalsubkey ,
+.Nm krb5_auth_con_getrcache ,
+.Nm krb5_auth_con_getremotesubkey ,
+.Nm krb5_auth_con_getuserkey ,
+.Nm krb5_auth_con_init ,
+.Nm krb5_auth_con_initivector ,
+.Nm krb5_auth_con_removeflags ,
+.Nm krb5_auth_con_setaddrs ,
+.Nm krb5_auth_con_setaddrs_from_fd ,
+.Nm krb5_auth_con_setflags ,
+.Nm krb5_auth_con_setivector ,
+.Nm krb5_auth_con_setkey ,
+.Nm krb5_auth_con_setlocalsubkey ,
+.Nm krb5_auth_con_setrcache ,
+.Nm krb5_auth_con_setremotesubkey ,
+.Nm krb5_auth_con_setuserkey ,
+.Nm krb5_auth_context ,
+.Nm krb5_auth_getcksumtype ,
+.Nm krb5_auth_getkeytype ,
+.Nm krb5_auth_getlocalseqnumber ,
+.Nm krb5_auth_getremoteseqnumber ,
+.Nm krb5_auth_setcksumtype ,
+.Nm krb5_auth_setkeytype ,
+.Nm krb5_auth_setlocalseqnumber ,
+.Nm krb5_auth_setremoteseqnumber ,
+.Nm krb5_free_authenticator
+.Nd manage authentication on connection level
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_auth_con_init
+.Fa "krb5_context context"
+.Fa "krb5_auth_context *auth_context"
+.Fc
+.Ft void
+.Fo krb5_auth_con_free
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_setflags
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "int32_t flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_getflags
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "int32_t *flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_addflags
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "int32_t addflags"
+.Fa "int32_t *flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_removeflags
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "int32_t removelags"
+.Fa "int32_t *flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_setaddrs
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "krb5_address *local_addr"
+.Fa "krb5_address *remote_addr"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_getaddrs
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "krb5_address **local_addr"
+.Fa "krb5_address **remote_addr"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_genaddrs
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "int fd"
+.Fa "int flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_setaddrs_from_fd
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "void *p_fd"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_getkey
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "krb5_keyblock **keyblock"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_getlocalsubkey
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "krb5_keyblock **keyblock"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_getremotesubkey
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "krb5_keyblock **keyblock"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_generatelocalsubkey
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_initivector
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_auth_con_setivector
+.Fa "krb5_context context"
+.Fa "krb5_auth_context *auth_context"
+.Fa "krb5_pointer ivector"
+.Fc
+.Ft void
+.Fo krb5_free_authenticator
+.Fa "krb5_context context"
+.Fa "krb5_authenticator *authenticator"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm krb5_auth_context
+structure holds all context related to an authenticated connection, in
+a similar way to
+.Nm krb5_context
+that holds the context for the thread or process.
+.Nm krb5_auth_context
+is used by various functions that are directly related to
+authentication between the server/client. Example of data that this
+structure contains are various flags, addresses of client and server,
+port numbers, keyblocks (and subkeys), sequence numbers, replay cache,
+and checksum-type.
+.Pp
+.Fn krb5_auth_con_init
+allocates and initializes the
+.Nm krb5_auth_context
+structure. Default values can be changed with
+.Fn krb5_auth_con_setcksumtype
+and
+.Fn krb5_auth_con_setflags .
+The
+.Nm auth_context
+structure must be freed by
+.Fn krb5_auth_con_free .
+.Pp
+.Fn krb5_auth_con_getflags ,
+.Fn krb5_auth_con_setflags ,
+.Fn krb5_auth_con_addflags
+and
+.Fn krb5_auth_con_removeflags
+gets and modifies the flags for a
+.Nm krb5_auth_context
+structure. Possible flags to set are:
+.Bl -tag -width Ds
+.It Dv KRB5_AUTH_CONTEXT_DO_SEQUENCE
+Generate and check sequence-number on each packet.
+.It Dv KRB5_AUTH_CONTEXT_DO_TIME
+Check timestamp on incoming packets.
+.It Dv KRB5_AUTH_CONTEXT_RET_SEQUENCE , Dv KRB5_AUTH_CONTEXT_RET_TIME
+Return sequence numbers and time stamps in the outdata parameters.
+.It Dv KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED
+will force
+.Fn krb5_get_forwarded_creds
+and
+.Fn krb5_fwd_tgt_creds
+to create unencrypted )
+.Dv ENCTYPE_NULL )
+credentials.
+This is for use with old MIT server and JAVA based servers as
+they can't handle encrypted
+.Dv KRB-CRED .
+Note that sending such
+.Dv KRB-CRED
+is clear exposes crypto keys and tickets and is insecure,
+make sure the packet is encrypted in the protocol.
+.Xr krb5_rd_cred 3 ,
+.Xr krb5_rd_priv 3 ,
+.Xr krb5_rd_safe 3 ,
+.Xr krb5_mk_priv 3
+and
+.Xr krb5_mk_safe 3 .
+Setting this flag requires that parameter to be passed to these
+functions.
+.Pp
+The flags
+.Dv KRB5_AUTH_CONTEXT_DO_TIME
+also modifies the behavior the function
+.Fn krb5_get_forwarded_creds
+by removing the timestamp in the forward credential message, this have
+backward compatibility problems since not all versions of the heimdal
+supports timeless credentional messages.
+Is very useful since it always the sender of the message to cache
+forward message and thus avoiding a round trip to the KDC for each
+time a credential is forwarded.
+The same functionality can be obtained by using address-less tickets.
+.\".It Dv KRB5_AUTH_CONTEXT_PERMIT_ALL
+.El
+.Pp
+.Fn krb5_auth_con_setaddrs ,
+.Fn krb5_auth_con_setaddrs_from_fd
+and
+.Fn krb5_auth_con_getaddrs
+gets and sets the addresses that are checked when a packet is received.
+It is mandatory to set an address for the remote
+host. If the local address is not set, it iss deduced from the underlaying
+operating system.
+.Fn krb5_auth_con_getaddrs
+will call
+.Fn krb5_free_address
+on any address that is passed in
+.Fa local_addr
+or
+.Fa remote_addr .
+.Fn krb5_auth_con_setaddr
+allows passing in a
+.Dv NULL
+pointer as
+.Fa local_addr
+and
+.Fa remote_addr ,
+in that case it will just not set that address.
+.Pp
+.Fn krb5_auth_con_setaddrs_from_fd
+fetches the addresses from a file descriptor.
+.Pp
+.Fn krb5_auth_con_genaddrs
+fetches the address information from the given file descriptor
+.Fa fd
+depending on the bitmap argument
+.Fa flags .
+.Pp
+Possible values on
+.Fa flags
+are:
+.Bl -tag -width Ds
+.It Va KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR
+fetches the local address from
+.Fa fd .
+.It Va KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR
+fetches the remote address from
+.Fa fd .
+.El
+.Pp
+.Fn krb5_auth_con_setkey ,
+.Fn krb5_auth_con_setuserkey
+and
+.Fn krb5_auth_con_getkey
+gets and sets the key used for this auth context. The keyblock returned by
+.Fn krb5_auth_con_getkey
+should be freed with
+.Fn krb5_free_keyblock .
+The keyblock send into
+.Fn krb5_auth_con_setkey
+is copied into the
+.Nm krb5_auth_context ,
+and thus no special handling is needed.
+.Dv NULL
+is not a valid keyblock to
+.Fn krb5_auth_con_setkey .
+.Pp
+.Fn krb5_auth_con_setuserkey
+is only useful when doing user to user authentication.
+.Fn krb5_auth_con_setkey
+is equivalent to
+.Fn krb5_auth_con_setuserkey .
+.Pp
+.Fn krb5_auth_con_getlocalsubkey ,
+.Fn krb5_auth_con_setlocalsubkey ,
+.Fn krb5_auth_con_getremotesubkey
+and
+.Fn krb5_auth_con_setremotesubkey
+gets and sets the keyblock for the local and remote subkey.
+The keyblock returned by
+.Fn krb5_auth_con_getlocalsubkey
+and
+.Fn krb5_auth_con_getremotesubkey
+must be freed with
+.Fn krb5_free_keyblock .
+.Pp
+.Fn krb5_auth_setcksumtype
+and
+.Fn krb5_auth_getcksumtype
+sets and gets the checksum type that should be used for this
+connection.
+.Pp
+.Fn krb5_auth_con_generatelocalsubkey
+generates a local subkey that have the same encryption type as
+.Fa key .
+.Pp
+.Fn krb5_auth_getremoteseqnumber
+.Fn krb5_auth_setremoteseqnumber ,
+.Fn krb5_auth_getlocalseqnumber
+and
+.Fn krb5_auth_setlocalseqnumber
+gets and sets the sequence-number for the local and remote
+sequence-number counter.
+.Pp
+.Fn krb5_auth_setkeytype
+and
+.Fn krb5_auth_getkeytype
+gets and gets the keytype of the keyblock in
+.Nm krb5_auth_context .
+.Pp
+.Fn krb5_auth_con_getauthenticator
+Retrieves the authenticator that was used during mutual
+authentication. The
+.Dv authenticator
+returned should be freed by calling
+.Fn krb5_free_authenticator .
+.Pp
+.Fn krb5_auth_con_getrcache
+and
+.Fn krb5_auth_con_setrcache
+gets and sets the replay-cache.
+.Pp
+.Fn krb5_auth_con_initivector
+allocates memory for and zeros the initial vector in the
+.Fa auth_context
+keyblock.
+.Pp
+.Fn krb5_auth_con_setivector
+sets the i_vector portion of
+.Fa auth_context
+to
+.Fa ivector .
+.Pp
+.Fn krb5_free_authenticator
+free the content of
+.Fa authenticator
+and
+.Fa authenticator
+itself.
+.Sh SEE ALSO
+.Xr krb5_context 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_c_make_checksum.3 b/src/kerberosV/src/lib/krb5/krb5_c_make_checksum.3
new file mode 100644 (file)
index 0000000..01b40cb
--- /dev/null
@@ -0,0 +1,279 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_c_make_checksum.3,v 1.8 2004/03/20 11:18:14 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt KRB5_C_MAKE_CHECKSUM 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_c_block_size ,
+.Nm krb5_c_decrypt ,
+.Nm krb5_c_encrypt ,
+.Nm krb5_c_encrypt_length ,
+.Nm krb5_c_enctype_compare ,
+.Nm krb5_c_get_checksum ,
+.Nm krb5_c_is_coll_proof_cksum ,
+.Nm krb5_c_is_keyed_cksum ,
+.Nm krb5_c_make_checksum ,
+.Nm krb5_c_make_random_key ,
+.Nm krb5_c_set_checksum ,
+.Nm krb5_c_valid_cksumtype ,
+.Nm krb5_c_valid_enctype ,
+.Nm krb5_c_verify_checksum ,
+.Nm krb5_c_checksum_length
+.Nd Kerberos 5 crypto API
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fo krb5_c_block_size
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "size_t *blocksize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_decrypt
+.Fa "krb5_context context"
+.Fa "const krb5_keyblock key"
+.Fa "krb5_keyusage usage"
+.Fa "const krb5_data *ivec"
+.Fa "krb5_enc_data *input"
+.Fa "krb5_data *output"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_encrypt
+.Fa "krb5_context context"
+.Fa "const krb5_keyblock *key"
+.Fa "krb5_keyusage usage"
+.Fa "const krb5_data *ivec"
+.Fa "const krb5_data *input"
+.Fa "krb5_enc_data *output"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_encrypt_length
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "size_t inputlen"
+.Fa "size_t *length"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_enctype_compare
+.Fa "krb5_context context"
+.Fa "krb5_enctype e1"
+.Fa "krb5_enctype e2"
+.Fa "krb5_boolean *similar"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_make_random_key
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_keyblock *random_key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_make_checksum
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype cksumtype"
+.Fa "const krb5_keyblock *key"
+.Fa "krb5_keyusage usage"
+.Fa "const krb5_data *input"
+.Fa "krb5_checksum *cksum"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_verify_checksum
+.Fa "krb5_context context
+.Fa "const krb5_keyblock *key"
+.Fa "krb5_keyusage usage"
+.Fa "const krb5_data *data"
+.Fa "const krb5_checksum *cksum"
+.Fa "krb5_boolean *valid"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_checksum_length
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype cksumtype"
+.Fa "size_t *length"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_get_checksum
+.Fa "krb5_context context"
+.Fa "const krb5_checksum *cksum"
+.Fa "krb5_cksumtype *type"
+.Fa "krb5_data **data"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_c_set_checksum
+.Fa "krb5_context context"
+.Fa "krb5_checksum *cksum"
+.Fa "krb5_cksumtype type"
+.Fa "const krb5_data *data"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_c_valid_enctype
+.Fa krb5_enctype etype"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_c_valid_cksumtype
+.Fa "krb5_cksumtype ctype"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_c_is_coll_proof_cksum
+.Fa "krb5_cksumtype ctype"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_c_is_keyed_cksum
+.Fa "krb5_cksumtype ctype"
+.Fc
+.Sh DESCRIPTION
+The functions starting with krb5_c are compat functions with MIT kerberos.
+.Pp
+The
+.Li krb5_enc_data
+structure holds and encrypted data.
+There are two public accessable members of
+.Li krb5_enc_data .
+.Li enctype
+that holds the encryption type of the data encrypted and
+.Li ciphertext
+that is a
+.Ft krb5_data
+that might contain the encrypted data.
+.Pp
+.Fn krb5_c_block_size
+returns the blocksize of the encryption type.
+.Pp
+.Fn krb5_c_decrypt
+decrypts
+.Fa input
+and store the data in
+.Fa output.
+If 
+.Fa ivec
+is
+.Dv NULL
+the default initialization vector for that encryption type will be used.
+.Pp
+.Fn krb5_c_encrypt
+encrypts the plaintext in
+.Fa input
+and store the ciphertext in
+.Fa output .
+.Pp
+.Fn krb5_c_encrypt_length
+returns the length the encrypted data given the plaintext length.
+.Pp
+.Fn krb5_c_enctype_compare
+compares to encryption types and returns if they use compatible
+encryption key types.
+.Pp
+.Fn krb5_c_make_checksum
+creates a checksum
+.Fa cksum
+with the checksum type
+.Fa cksumtype
+of the data in
+.Fa data .
+.Fa key
+and
+.Fa usage
+are used if the checksum is a keyed checksum type.
+Returns 0 or an error code.
+.Pp
+.Fn krb5_c_verify_checksum
+verifies the checksum
+of
+.Fa data
+in
+.Fa cksum
+that was created with
+.Fa key
+using the key usage
+.Fa usage .
+.Fa verify
+is set to non-zero if the checksum verifies correctly and zero if not.
+Returns 0 or an error code.
+.Pp
+.Fn krb5_c_checksum_length
+returns the length of the checksum.
+.Pp
+.Fn krb5_c_set_checksum
+sets the
+.Li krb5_checksum
+structure given
+.Fa type
+and
+.Fa data .
+The content of
+.Fa cksum
+should be freeed with
+.Fn krb5_c_free_checksum_contents .
+.Pp
+.Fn krb5_c_get_checksum
+retrieves the components of the
+.Li krb5_checksum .
+structure.
+.Fa data
+should be free with
+.Fn krb5_free_data .
+If some either of
+.Fa data
+or
+.Fa checksum
+is not needed for the application, 
+.Dv NULL
+can be passed in.
+.Pp
+.Fn krb5_c_valid_enctype
+returns true if
+.Fa etype
+is a valid encryption type.
+.Pp
+.Fn krb5_c_valid_cksumtype
+returns true if
+.Fa ctype
+is a valid checksum type.
+.Pp
+.Fn krb5_c_is_keyed_cksum
+return true if
+.Fa ctype
+is a keyed checksum type.
+.Pp
+.Fn krb5_c_is_coll_proof_cksum
+returns true if
+.Fa ctype
+is a collition proof checksum type.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_create_checksum 3 ,
+.Xr krb5_free_data 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_ccache.3 b/src/kerberosV/src/lib/krb5/krb5_ccache.3
new file mode 100644 (file)
index 0000000..fb8a925
--- /dev/null
@@ -0,0 +1,437 @@
+.\" Copyright (c) 2003-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_ccache.3,v 1.13 2005/04/24 13:57:33 lha Exp $
+.\"
+.Dd April 24, 2005
+.Dt KRB5_CCACHE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_ccache ,
+.Nm krb5_cc_cursor ,
+.Nm krb5_cc_ops ,
+.Nm krb5_fcc_ops ,
+.Nm krb5_mcc_ops ,
+.Nm krb5_cc_clear_mcred ,
+.Nm krb5_cc_close ,
+.Nm krb5_cc_copy_cache ,
+.Nm krb5_cc_default ,
+.Nm krb5_cc_default_name ,
+.Nm krb5_cc_destroy ,
+.Nm krb5_cc_end_seq_get ,
+.Nm krb5_cc_gen_new ,
+.Nm krb5_cc_get_name ,
+.Nm krb5_cc_get_ops ,
+.Nm krb5_cc_get_prefix_ops ,
+.Nm krb5_cc_get_principal ,
+.Nm krb5_cc_get_type ,
+.Nm krb5_cc_get_version ,
+.Nm krb5_cc_initialize ,
+.Nm krb5_cc_next_cred ,
+.Nm krb5_cc_next_cred_match ,
+.Nm krb5_cc_new_unique ,
+.Nm krb5_cc_register ,
+.Nm krb5_cc_remove_cred ,
+.Nm krb5_cc_resolve ,
+.Nm krb5_cc_retrieve_cred ,
+.Nm krb5_cc_set_default_name ,
+.Nm krb5_cc_set_flags ,
+.Nm krb5_cc_store_cred
+.Nd manage credential cache
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "struct krb5_ccache;"
+.Pp
+.Li "struct krb5_cc_cursor;"
+.Pp
+.Li "struct krb5_cc_ops;"
+.Pp
+.Li "struct krb5_cc_ops *krb5_fcc_ops;"
+.Pp
+.Li "struct krb5_cc_ops *krb5_mcc_ops;"
+.Pp
+.Ft void
+.Fo krb5_cc_clear_mcred
+.Fa "krb5_creds *mcred"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_close
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_copy_cache
+.Fa "krb5_context *context"
+.Fa "const krb5_ccache from"
+.Fa "krb5_ccache to"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_default
+.Fa "krb5_context *context"
+.Fa "krb5_ccache *id"
+.Fc
+.Ft "const char *"
+.Fo krb5_cc_default_name
+.Fa "krb5_context *context"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_destroy
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_end_seq_get
+.Fa "krb5_context *context"
+.Fa "const krb5_ccache id"
+.Fa "krb5_cc_cursor *cursor"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_gen_new
+.Fa "krb5_context *context"
+.Fa "const krb5_cc_ops *ops"
+.Fa "krb5_ccache *id"
+.Fc
+.Ft "const char *"
+.Fo krb5_cc_get_name
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_get_principal
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fa "krb5_principal *principal"
+.Fc
+.Ft "const char *"
+.Fo krb5_cc_get_type
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fc
+.Ft "const krb5_cc_ops *"
+.Fo krb5_cc_get_ops
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fc
+.Ft "const krb5_cc_ops *"
+.Fo krb5_cc_get_prefix_ops
+.Fa "krb5_context context"
+.Fa "const char *prefix"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_get_version
+.Fa "krb5_context *context"
+.Fa "const krb5_ccache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_initialize
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fa "krb5_principal primary_principal"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_register
+.Fa "krb5_context *context"
+.Fa "const krb5_cc_ops *ops"
+.Fa "krb5_boolean override"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_resolve
+.Fa "krb5_context *context"
+.Fa "const char *name"
+.Fa "krb5_ccache *id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_retrieve_cred
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fa "krb5_flags whichfields"
+.Fa "const krb5_creds *mcreds"
+.Fa "krb5_creds *creds"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_remove_cred
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fa "krb5_flags which"
+.Fa "krb5_creds *cred"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_set_default_name
+.Fa "krb5_context *context"
+.Fa "const char *name"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_store_cred
+.Fa "krb5_context *context"
+.Fa "krb5_ccache id"
+.Fa "krb5_creds *creds"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_set_flags
+.Fa "krb5_context *context"
+.Fa "krb5_cc_set_flags id"
+.Fa "krb5_flags flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_next_cred
+.Fa "krb5_context *context"
+.Fa "const krb5_ccache id"
+.Fa "krb5_cc_cursor *cursor"
+.Fa "krb5_creds *creds"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_next_cred_match
+.Fa "krb5_context *context"
+.Fa "const krb5_ccache id"
+.Fa "krb5_cc_cursor *cursor"
+.Fa "krb5_creds *creds"
+.Fa "krb5_flags whichfields"
+.Fa "const krb5_creds *mcreds"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cc_new_unique
+.Fa "krb5_context context"
+.Fa "const char *type"
+.Fa "const char *hint"
+.Fa "krb5_ccache *id"
+.Fc
+.Sh DESCRIPTION
+The
+.Li krb5_ccache
+structure holds a Kerberos credential cache.
+.Pp
+The
+.Li krb5_cc_cursor
+structure holds current position in a credential cache when
+iterating over the cache.
+.Pp
+The
+.Li krb5_cc_ops
+structure holds a set of operations that can me preformed on a
+credential cache.
+.Pp
+There is no component inside
+.Li krb5_ccache ,
+.Li krb5_cc_cursor
+nor
+.Li krb5_fcc_ops
+that is directly referable.
+.Pp
+The
+.Li krb5_creds
+holds a Kerberos credential, see manpage for
+.Xr krb5_creds 3 .
+.Pp
+.Fn krb5_cc_default_name
+and
+.Fn krb5_cc_set_default_name
+gets and sets the default name for the
+.Fa context .
+.Pp
+.Fn krb5_cc_default
+opens the default credential cache in
+.Fa id .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_gen_new
+generates a new credential cache of type
+.Fa ops
+in
+.Fa id .
+Return 0 or an error code.
+The Heimdal version of this function also runs
+.Fn krb5_cc_initialize
+on the credential cache, but since the MIT version doesn't, portable
+code must call krb5_cc_initialize.
+.Pp
+.Fn krb5_cc_new_unique
+generates a new unique credential cache of
+.Fa type
+in
+.Fa id .
+If type is
+.Dv NULL ,
+the library chooses the default credential cache type.
+The supplied
+.Fa hint
+(that can be
+.Dv NULL )
+is a string that the credential cache type can use to base the name of
+the credential on, this is to make its easier for the user to
+differentiate the credentials.
+The returned credential cache
+.Fa id
+should be freed using
+.Fn krb5_cc_close
+or
+.Fn krb5_cc_destroy .
+Returns 0 or an error code.
+.Pp
+.Fn krb5_cc_resolve
+finds and allocates a credential cache in
+.Fa id
+from the specification in
+.Fa residual .
+If the credential cache name doesn't contain any colon (:), interpret it as a
+file name.
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_initialize
+creates a new credential cache in
+.Fa id
+for
+.Fa primary_principal .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_close
+stops using the credential cache
+.Fa id
+and frees the related resources.
+Return 0 or an error code.
+.Fn krb5_cc_destroy
+removes the credential cache
+and closes (by calling
+.Fn krb5_cc_close )
+.Fa id .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_copy_cache
+copys the contents of
+.Fa from
+to
+.Fa to .
+.Pp
+.Fn krb5_cc_get_name
+returns the name of the credential cache
+.Fa id .
+.Pp
+.Fn krb5_cc_get_principal
+returns the principal of
+.Fa id
+in
+.Fa principal .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_get_type
+returns the type of the credential cache
+.Fa id .
+.Pp
+.Fn krb5_cc_get_ops
+returns the ops of the credential cache
+.Fa id .
+.Pp
+.Fn krb5_cc_get_version
+returns the version of
+.Fa id .
+.Pp
+.Fn krb5_cc_register
+Adds a new credential cache type with operations
+.Fa ops ,
+overwriting any existing one if
+.Fa override .
+Return an error code or 0.
+.Pp
+.Fn krb5_cc_get_prefix_ops
+Get the cc ops that is registered in
+.Fa context
+to handle the
+.Fa prefix .
+Returns
+.Dv NULL
+if ops not found.
+.Pp
+.Fn krb5_cc_remove_cred
+removes the credential identified by
+.Fa ( cred ,
+.Fa which )
+from
+.Fa id .
+.Pp
+.Fn krb5_cc_store_cred
+stores
+.Fa creds
+in the credential cache
+.Fa id .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_set_flags
+sets the flags of
+.Fa id
+to
+.Fa flags .
+.Pp
+.Fn krb5_cc_clear_mcred
+clears the
+.Fa mcreds
+argument so its reset and can be used with
+.Fa krb5_cc_retrieve_cred .
+.Pp
+.Fn krb5_cc_retrieve_cred ,
+retrieves the credential identified by
+.Fa mcreds
+(and
+.Fa whichfields )
+from
+.Fa id
+in
+.Fa creds .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_next_cred
+retrieves the next cred pointed to by
+.Fa ( id ,
+.Fa cursor )
+in
+.Fa creds ,
+and advance
+.Fa cursor .
+Return 0 or an error code.
+.Pp
+.Fn krb5_cc_next_cred_match
+is similar to
+.Fn krb5_cc_next_cred
+except that it will only return creds matching 
+.Fa whichfields
+and
+.Fa mcreds
+(as interpreted by 
+.Xr krb5_compare_creds 3 . )
+.Pp
+.Fn krb5_cc_end_seq_get
+Destroys the cursor
+.Fa cursor .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_ccapi.h b/src/kerberosV/src/lib/krb5/krb5_ccapi.h
new file mode 100644 (file)
index 0000000..0a53ed4
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: krb5_ccapi.h,v 1.1 2004/09/11 04:00:42 lha Exp $ */
+
+#ifndef KRB5_CCAPI_H
+#define KRB5_CCAPI_H 1
+
+#include <krb5-types.h>
+
+enum {
+    cc_credentials_v5 = 2
+};
+
+enum {
+    ccapi_version_3 = 3
+};
+
+enum {
+    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 */
+};
+
+typedef int32_t cc_int32;
+typedef u_int32_t cc_uint32;
+typedef struct cc_context_t *cc_context_t;
+typedef struct cc_ccache_t *cc_ccache_t;
+typedef struct cc_ccache_iterator_t *cc_ccache_iterator_t;
+typedef struct cc_credentials_v5_t cc_credentials_v5_t;
+typedef struct cc_credentials_t *cc_credentials_t;
+typedef struct cc_credentials_iterator_t *cc_credentials_iterator_t;
+typedef struct cc_string_t *cc_string_t;
+typedef time_t cc_time_t;
+
+typedef struct cc_data {
+    cc_uint32 type;
+    cc_uint32 length;
+    void *data;
+} cc_data;
+
+struct cc_credentials_v5_t {
+    char *client;
+    char *server;
+    cc_data keyblock;
+    cc_time_t authtime;
+    cc_time_t starttime;
+    cc_time_t endtime;
+    cc_time_t renew_till;
+    cc_uint32 is_skey;
+    cc_uint32 ticket_flags; /* XXX ticket flags undefined */
+    cc_data **addresses;
+    cc_data ticket;
+    cc_data second_ticket;
+    cc_data **authdata;
+};
+
+
+typedef struct cc_string_functions {
+    cc_int32 (*release)(cc_string_t);
+} cc_string_functions;
+
+struct cc_string_t {
+    const char *data;
+    const cc_string_functions *func;
+};
+
+typedef struct cc_credentials_union {
+    cc_int32 version;
+    union {
+       cc_credentials_v5_t* credentials_v5;
+    } credentials;
+} cc_credentials_union;
+
+struct cc_credentials_functions {
+    cc_int32 (*release)(cc_credentials_t);
+    cc_int32 (*compare)(cc_credentials_t, cc_credentials_t, cc_uint32*);
+};
+
+struct cc_credentials_t {
+    const cc_credentials_union* data;
+    const struct cc_credentials_functions* func;
+};
+
+struct cc_credentials_iterator_functions {
+    cc_int32 (*release)(cc_credentials_iterator_t);
+    cc_int32 (*next)(cc_credentials_iterator_t, cc_credentials_t*);
+};
+
+struct cc_credentials_iterator_t {
+    const struct cc_credentials_iterator_functions *func;
+};
+
+struct cc_ccache_iterator_functions {
+    cc_int32 (*release) (cc_ccache_iterator_t);
+    cc_int32 (*next)(cc_ccache_iterator_t, cc_ccache_t*);
+};
+
+struct cc_ccache_iterator_t {
+    const struct cc_ccache_iterator_functions* func;
+};
+
+typedef struct cc_ccache_functions {
+    cc_int32 (*release)(cc_ccache_t);
+    cc_int32 (*destroy)(cc_ccache_t);
+    cc_int32 (*set_default)(cc_ccache_t);
+    cc_int32 (*get_credentials_version)(cc_ccache_t, cc_uint32*);
+    cc_int32 (*get_name)(cc_ccache_t ccache,cc_string_t*);
+    cc_int32 (*get_principal)(cc_ccache_t, cc_uint32, cc_string_t*);
+    cc_int32 (*set_principal)(cc_ccache_t, cc_uint32, const char*);
+    cc_int32 (*store_credentials)(cc_ccache_t, const cc_credentials_union*);
+    cc_int32 (*remove_credentials)(cc_ccache_t, cc_credentials_t);
+    cc_int32 (*new_credentials_iterator)(cc_ccache_t,
+                                        cc_credentials_iterator_t*);
+    cc_int32 (*move)(cc_ccache_t source, cc_ccache_t);
+    cc_int32 (*lock)(cc_ccache_t, cc_uint32, cc_uint32);
+    cc_int32 (*unlock)(cc_ccache_t);
+    cc_int32 (*get_last_default_time)(cc_ccache_t, cc_time_t*);
+    cc_int32 (*get_change_time)(cc_ccache_t ccache, cc_time_t*);
+    cc_int32 (*compare)(cc_ccache_t, cc_ccache_t, cc_uint32*);
+    cc_int32 (*get_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t *);
+    cc_int32 (*set_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t);
+    cc_int32 (*clear_kdc_time_offset)(cc_ccache_t, cc_int32);
+} cc_ccache_functions;
+
+struct cc_ccache_t {
+    const cc_ccache_functions *func;
+};
+
+struct  cc_context_functions {
+    cc_int32 (*release)(cc_context_t);
+    cc_int32 (*get_change_time)(cc_context_t, cc_time_t *);
+    cc_int32 (*get_default_ccache_name)(cc_context_t, cc_string_t*);
+    cc_int32 (*open_ccache)(cc_context_t, const char*, cc_ccache_t *);
+    cc_int32 (*open_default_ccache)(cc_context_t, cc_ccache_t*);
+    cc_int32 (*create_ccache)(cc_context_t,const char*, cc_uint32,
+                             const char*, cc_ccache_t*);
+    cc_int32 (*create_default_ccache)(cc_context_t, cc_uint32,
+                                     const char*, cc_ccache_t*);
+    cc_int32 (*create_new_ccache)(cc_context_t, cc_uint32,
+                                 const char*, cc_ccache_t*);
+    cc_int32 (*new_ccache_iterator)(cc_context_t, cc_ccache_iterator_t*);
+    cc_int32 (*lock)(cc_context_t, cc_uint32, cc_uint32);
+    cc_int32 (*unlock)(cc_context_t);
+    cc_int32 (*compare)(cc_context_t, cc_context_t, cc_uint32*);
+};
+
+struct cc_context_t {
+    const struct cc_context_functions* func;
+};
+
+typedef cc_int32 
+(*cc_initialize_func)(cc_context_t*, cc_int32, cc_int32 *, char const **);
+
+#endif /* KRB5_CCAPI_H */
diff --git a/src/kerberosV/src/lib/krb5/krb5_check_transited.3 b/src/kerberosV/src/lib/krb5/krb5_check_transited.3
new file mode 100644 (file)
index 0000000..a4d1fbe
--- /dev/null
@@ -0,0 +1,106 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_check_transited.3,v 1.1 2004/07/20 09:38:30 lha Exp $
+.\"
+.Dd July 20, 2004
+.Dt KRB5_CHECK_TRANSITED 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_check_transited ,
+.Nm krb5_check_transited_realms ,
+.Nm krb5_domain_x500_decode ,
+.Nm krb5_domain_x500_encode
+.Nd realm transit verification and encoding/decoding functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_check_transited
+.Fa "krb5_context context"
+.Fa "krb5_const_realm client_realm"
+.Fa "krb5_const_realm server_realm"
+.Fa "krb5_realm *realms"
+.Fa "int num_realms"
+.Fa "int *bad_realm"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_check_transited_realms
+.Fa "krb5_context context"
+.Fa "const char *const *realms"
+.Fa "int num_realms"
+.Fa "int *bad_realm"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_domain_x500_decode
+.Fa "krb5_context context"
+.Fa "krb5_data tr"
+.Fa "char ***realms"
+.Fa "int *num_realms"
+.Fa "const char *client_realm"
+.Fa "const char *server_realm"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_domain_x500_encode
+.Fa "char **realms"
+.Fa "int num_realms"
+.Fa "krb5_data *encoding"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_check_transited
+checks the path from
+.Fa client_realm
+to
+.Fa server_realm
+where
+.Fa realms
+and
+.Fa num_realms
+is the realms between them.
+If the function returns an error value, 
+.Fa bad_realm
+will be set to the realm in the list causing the error.
+.Fn krb5_check_transited
+is used internally by the KDC and libkrb5 and should not be called by
+client applications.
+.Pp
+.Fn krb5_check_transited_realms
+is deprecated.
+.Pp
+.Fn krb5_domain_x500_encode
+and
+.Fn krb5_domain_x500_decode
+encodes and decodes the realm names in the X500 format that Kerberos
+uses to describe the transited realms in krbtgts.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_compare_creds.3 b/src/kerberosV/src/lib/krb5/krb5_compare_creds.3
new file mode 100644 (file)
index 0000000..cf3a9c2
--- /dev/null
@@ -0,0 +1,104 @@
+.\" Copyright (c) 2004-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_compare_creds.3,v 1.2 2005/05/10 09:20:51 lha Exp $
+.\"
+.Dd May 10, 2005
+.Dt KRB5_COMPARE_CREDS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_compare_creds
+.Nd compare Kerberos 5 credentials
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_boolean
+.Fo krb5_compare_creds
+.Fa "krb5_context context"
+.Fa "krb5_flags whichfields"
+.Fa "const krb5_creds *mcreds"
+.Fa "const krb5_creds *creds"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_compare_creds
+compares
+.Fa mcreds
+(usually filled in by the application)
+to
+.Fa creds
+(most often from a credentials cache)
+and return
+.Dv TRUE
+if they are equal.
+Unless
+.Va mcreds-\*[Gt]server
+is
+.Dv NULL ,
+the service of the credentials are always compared.  If the client
+name in
+.Fa mcreds
+is present, the client names are also compared. This function is
+normally only called indirectly via
+.Xr krb5_cc_retrieve_cred 3 .
+.Pp
+The following flags, set in
+.Fa whichfields ,
+affects the comparison:
+.Bl -tag -width KRB5_TC_MATCH_SRV_NAMEONLY -compact -offset indent
+.It KRB5_TC_MATCH_SRV_NAMEONLY
+Consider all realms equal when comparing the service principal.
+.It KRB5_TC_MATCH_KEYTYPE
+Compare enctypes.
+.It KRB5_TC_MATCH_FLAGS_EXACT
+Make sure that the ticket flags are identical.
+.It KRB5_TC_MATCH_FLAGS
+Make sure that all ticket flags set in
+.Fa mcreds
+are also present  in
+.Fa creds .
+.It KRB5_TC_MATCH_TIMES_EXACT
+Compares the ticket times exactly.
+.It KRB5_TC_MATCH_TIMES
+Compares only the expiration times of the creds.
+.It KRB5_TC_MATCH_AUTHDATA
+Compares the authdata fields.
+.It KRB5_TC_MATCH_2ND_TKT
+Compares the second tickets (used by user-to-user authentication).
+.It KRB5_TC_MATCH_IS_SKEY
+Compares the existance of the second ticket.
+.El
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_cc_retrieve_cred 3 ,
+.Xr krb5_creds 3 ,
+.Xr krb5_get_init_creds 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_config.3 b/src/kerberosV/src/lib/krb5/krb5_config.3
new file mode 100644 (file)
index 0000000..bffbde3
--- /dev/null
@@ -0,0 +1,294 @@
+.\" Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\"
+.\" $KTH: krb5_config.3,v 1.8 2004/03/20 18:15:01 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt KRB5_CONFIG_GET 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_config_file_free ,
+.Nm krb5_config_free_strings ,
+.Nm krb5_config_get ,
+.Nm krb5_config_get_bool ,
+.Nm krb5_config_get_bool_default ,
+.Nm krb5_config_get_int ,
+.Nm krb5_config_get_int_default ,
+.Nm krb5_config_get_list ,
+.Nm krb5_config_get_next ,
+.Nm krb5_config_get_string ,
+.Nm krb5_config_get_string_default ,
+.Nm krb5_config_get_strings ,
+.Nm krb5_config_get_time ,
+.Nm krb5_config_get_time_default ,
+.Nm krb5_config_parse_file ,
+.Nm krb5_config_parse_file_multi ,
+.Nm krb5_config_vget ,
+.Nm krb5_config_vget_bool ,
+.Nm krb5_config_vget_bool_default ,
+.Nm krb5_config_vget_int ,
+.Nm krb5_config_vget_int_default ,
+.Nm krb5_config_vget_list ,
+.Nm krb5_config_vget_next ,
+.Nm krb5_config_vget_string ,
+.Nm krb5_config_vget_string_default ,
+.Nm krb5_config_vget_strings ,
+.Nm krb5_config_vget_time ,
+.Nm krb5_config_vget_time_default
+.Nd get configuration value
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_config_file_free
+.Fa "krb5_context context"
+.Fa "krb5_config_section *s"
+.Fc
+.Ft void
+.Fo krb5_config_free_strings
+.Fa "char **strings"
+.Fc
+.Ft "const void *"
+.Fo krb5_config_get
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "int type"
+.Fa "..."
+.Fc
+.Ft krb5_boolean
+.Fo krb5_config_get_bool
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "..."
+.Fc
+.Ft krb5_boolean
+.Fo krb5_config_get_bool_default
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "krb5_boolean def_value"
+.Fa "..."
+.Fc
+.Ft int
+.Fo krb5_config_get_int
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "..."
+.Fc
+.Ft int
+.Fo krb5_config_get_int_default
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "int def_value"
+.Fa "..."
+.Fc
+.Ft const char*
+.Fo krb5_config_get_string
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "..."
+.Fc
+.Ft const char*
+.Fo krb5_config_get_string_default
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "const char *def_value"
+.Fa "..."
+.Fc
+.Ft "char**"
+.Fo krb5_config_get_strings
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "..."
+.Fc
+.Ft int
+.Fo krb5_config_get_time
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "..."
+.Fc
+.Ft int
+.Fo krb5_config_get_time_default
+.Fa "krb5_context context"
+.Fa "krb5_config_section *c"
+.Fa "int def_value"
+.Fa "..."
+.Fc
+.Ft krb5_error_code
+.Fo krb5_config_parse_file
+.Fa "krb5_context context"
+.Fa "const char *fname"
+.Fa "krb5_config_section **res"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_config_parse_file_multi
+.Fa "krb5_context context"
+.Fa "const char *fname"
+.Fa "krb5_config_section **res"
+.Fc
+.Ft "const void *"
+.Fo krb5_config_vget
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "int type"
+.Fa "va_list args"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_config_vget_bool
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "va_list args"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_config_vget_bool_default
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "krb5_boolean def_value"
+.Fa "va_list args"
+.Fc
+.Ft int
+.Fo krb5_config_vget_int
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "va_list args"
+.Fc
+.Ft int
+.Fo krb5_config_vget_int_default
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "int def_value"
+.Fa "va_list args"
+.Fc
+.Ft "const krb5_config_binding *"
+.Fo krb5_config_vget_list
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "va_list args"
+.Fc
+.Ft "const void *"
+.Fo krb5_config_vget_next
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "const krb5_config_binding **pointer"
+.Fa "int type"
+.Fa "va_list args"
+.Fc
+.Ft "const char *"
+.Fo krb5_config_vget_string
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "va_list args"
+.Fc
+.Ft "const char *"
+.Fo krb5_config_vget_string_default
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "const char *def_value"
+.Fa "va_list args"
+.Fc
+.Ft char **
+.Fo krb5_config_vget_strings
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "va_list args"
+.Fc
+.Ft int
+.Fo krb5_config_vget_time
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "va_list args"
+.Fc
+.Ft int
+.Fo krb5_config_vget_time_default
+.Fa "krb5_context context"
+.Fa "const krb5_config_section *c"
+.Fa "int def_value"
+.Fa "va_list args"
+.Fc
+.Sh DESCRIPTION
+These functions get values from the
+.Xr krb5.conf 5
+configuration file, or another configuration database specified by the
+.Fa c
+parameter.
+.Pp
+The variable arguments should be a list of strings naming each
+subsection to look for. For example:
+.Bd -literal -offset indent
+krb5_config_get_bool_default(context, NULL, FALSE, 
+     "libdefaults", "log_utc", NULL);
+.Ed
+.Pp
+gets the boolean value for the
+.Dv log_utc
+option, defaulting to
+.Dv FALSE .
+.Pp
+.Fn krb5_config_get_bool_default
+will convert the option value to a boolean value, where
+.Sq yes ,
+.Sq true ,
+and any non-zero number means
+.Dv TRUE ,
+and any other value
+.Dv FALSE .
+.Pp
+.Fn krb5_config_get_int_default
+will convert the value to an integer.
+.Pp
+.Fn krb5_config_get_time_default
+will convert the value to a period of time (not a time stamp) in
+seconds, so the string
+.Sq 2 weeks
+will be converted to
+1209600 (2 * 7 * 24 * 60 * 60).
+.Pp
+.Fn krb5_config_free_strings
+free
+.Fa strings
+as returned by
+.Fn krb5_config_get_strings
+and
+.Fn krb5_config_vget_strings .
+.Pp
+.Fn krb5_config_file_free
+free the result of
+.Fn krb5_config_parse_file
+and
+.Fn krb5_config_parse_file_multi .
+.Sh SEE ALSO
+.Xr krb5_appdefault 3 ,
+.Xr krb5_init_context 3 ,
+.Xr krb5.conf 5
+.Sh BUGS
+For the default functions, other than for the string case, there's no
+way to tell whether there was a value specified or not.
diff --git a/src/kerberosV/src/lib/krb5/krb5_context.3 b/src/kerberosV/src/lib/krb5/krb5_context.3
new file mode 100644 (file)
index 0000000..bf8b17c
--- /dev/null
@@ -0,0 +1,56 @@
+.\" Copyright (c) 2001 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_context.3,v 1.7 2003/05/26 14:08:54 lha Exp $
+.\"
+.Dd January 21, 2001
+.Dt KRB5_CONTEXT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_context
+.Nd krb5 state structure
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Sh DESCRIPTION
+The
+.Nm
+structure is designed to hold all per thread state. All global
+variables that are context specific are stored in this structure,
+including default encryption types, credentials-cache (ticket file), and
+default realms.
+.Pp
+The internals of the structure should never be accessed directly,
+functions exist for extracting information.
+.Sh SEE ALSO
+.Xr krb5_init_context 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_create_checksum.3 b/src/kerberosV/src/lib/krb5/krb5_create_checksum.3
new file mode 100644 (file)
index 0000000..0eacfa3
--- /dev/null
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1999-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_create_checksum.3,v 1.13 2005/01/08 20:52:19 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt NAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_checksum ,
+.Nm krb5_checksum_disable ,
+.Nm krb5_checksum_is_collision_proof ,
+.Nm krb5_checksum_is_keyed ,
+.Nm krb5_checksumsize ,
+.Nm krb5_cksumtype_valid ,
+.Nm krb5_copy_checksum ,
+.Nm krb5_create_checksum ,
+.Nm krb5_crypto_get_checksum_type
+.Nm krb5_free_checksum ,
+.Nm krb5_free_checksum_contents ,
+.Nm krb5_hmac ,
+.Nm krb5_verify_checksum
+.Nd creates, handles and verifies checksums
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "typedef Checksum krb5_checksum;"
+.Ft void
+.Fo krb5_checksum_disable
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype type"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_checksum_is_collision_proof
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype type"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_checksum_is_keyed
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype type"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_cksumtype_valid
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype ctype"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_checksumsize
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype type"
+.Fa "size_t *size"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_create_checksum
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage_or_type"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "Checksum *result"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_verify_checksum
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "krb5_key_usage usage"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "Checksum *cksum"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_crypto_get_checksum_type
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "krb5_cksumtype *type"
+.Fc
+.Ft void
+.Fo krb5_free_checksum
+.Fa "krb5_context context"
+.Fa "krb5_checksum *cksum"
+.Fc
+.Ft void
+.Fo krb5_free_checksum_contents
+.Fa "krb5_context context"
+.Fa "krb5_checksum *cksum"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_hmac
+.Fa "krb5_context context"
+.Fa "krb5_cksumtype cktype"
+.Fa "const void *data"
+.Fa "size_t len"
+.Fa "unsigned usage"
+.Fa "krb5_keyblock *key"
+.Fa "Checksum *result"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_checksum
+.Fa "krb5_context context"
+.Fa "const krb5_checksum *old"
+.Fa "krb5_checksum **new"
+.Fc
+.Sh DESCRIPTION
+The
+.Li krb5_checksum
+structure holds a Kerberos checksum.
+There is no component inside
+.Li krb5_checksum
+that is directly referable.
+.Pp
+The functions are used to create and verify checksums.
+.Fn krb5_create_checksum
+creates a checksum of the specified data, and puts it in
+.Fa result .
+If
+.Fa crypto
+is
+.Dv NULL ,
+.Fa usage_or_type
+specifies the checksum type to use; it must not be keyed. Otherwise
+.Fa crypto
+is an encryption context created by
+.Fn krb5_crypto_init ,
+and
+.Fa usage_or_type
+specifies a key-usage.
+.Pp
+.Fn krb5_verify_checksum
+verifies the
+.Fa checksum
+against the provided data.
+.Pp
+.Fn krb5_checksum_is_collision_proof
+returns true is the specified checksum is collision proof (that it's
+very unlikely that two strings has the same hash value, and that it's
+hard to find two strings that has the same hash). Examples of
+collision proof checksums are MD5, and SHA1, while CRC32 is not.
+.Pp
+.Fn krb5_checksum_is_keyed
+returns true if the specified checksum type is keyed (that the hash
+value is a function of both the data, and a separate key). Examples of
+keyed hash algorithms are HMAC-SHA1-DES3, and RSA-MD5-DES. The
+.Dq plain
+hash functions MD5, and SHA1 are not keyed.
+.Pp
+.Fn krb5_crypto_get_checksum_type
+returns the checksum type that will be used when creating a checksum for the given
+.Fa crypto
+context.
+This function is useful in combination with
+.Fn krb5_checksumsize
+when you want to know the size a checksum will
+use when you create it.
+.Pp
+.Fn krb5_cksumtype_valid
+returns 0 or an error if the checksumtype is implemented and not
+currently disabled in this kerberos library.
+.Pp
+.Fn krb5_checksumsize
+returns the size of the outdata of checksum function.
+.Pp
+.Fn krb5_copy_checksum
+returns a copy of the checksum
+.Fn krb5_free_checksum
+should use used to free the
+.Fa new
+checksum.
+.Pp
+.Fn krb5_free_checksum
+free the checksum and the content of the checksum.
+.Pp
+.Fn krb5_free_checksum_contents
+frees the content of checksum in
+.Fa cksum .
+.Pp
+.Fn krb5_hmac
+calculates the HMAC over
+.Fa data
+(with length
+.Fa len )
+using the keyusage
+.Fa usage
+and keyblock
+.Fa key .
+Note that keyusage is not always used in checksums.
+.Pp
+.Nm krb5_checksum_disable
+globally disables the checksum type. 
+.\" .Sh EXAMPLE
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr krb5_crypto_init 3 ,
+.Xr krb5_encrypt 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_creds.3 b/src/kerberosV/src/lib/krb5/krb5_creds.3
new file mode 100644 (file)
index 0000000..f488e71
--- /dev/null
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_creds.3,v 1.3 2004/04/25 19:29:53 joda Exp $
+.\"
+.Dd March 21, 2004
+.Dt KRB5_CREDS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_creds ,
+.Nm krb5_copy_creds ,
+.Nm krb5_copy_creds_contents ,
+.Nm krb5_free_creds ,
+.Nm krb5_free_cred_contents
+.Nd Kerberos 5 credential handling functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_copy_creds
+.Fa "krb5_context context"
+.Fa "const krb5_creds *incred"
+.Fa "krb5_creds **outcred"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_creds_contents
+.Fa "krb5_context context"
+.Fa "const krb5_creds *incred"
+.Fa "krb5_creds *outcred"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_creds
+.Fa "krb5_context context"
+.Fa "krb5_creds *outcred"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_cred_contents
+.Fa "krb5_context context"
+.Fa "krb5_creds *cred"
+.Fc
+.Sh DESCRIPTION
+.Vt krb5_creds
+holds Kerberos credentials:
+.Bd -literal -offset
+typedef struct krb5_creds {
+    krb5_principal     client;
+    krb5_principal     server;
+    krb5_keyblock      session;
+    krb5_times         times;
+    krb5_data          ticket;
+    krb5_data          second_ticket;
+    krb5_authdata      authdata;
+    krb5_addresses     addresses;
+    krb5_ticket_flags  flags;
+} krb5_creds;
+.Ed
+.Pp
+.Fn krb5_copy_creds
+makes a copy of
+.Fa incred
+to
+.Fa outcred .
+.Fa outcred
+should be freed with
+.Fn krb5_free_creds
+by the caller.
+.Pp
+.Fn krb5_copy_creds_contents
+makes a copy of the content of
+.Fa incred
+to
+.Fa outcreds .
+.Fa outcreds
+should be freed by the called with
+.Fn krb5_free_creds_contents .
+.Pp
+.Fn krb5_free_creds
+frees the content of the 
+.Fa cred
+structure and the structure itself.
+.Pp
+.Fn krb5_free_cred_contents
+frees the content of the
+.Fa cred
+structure.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_compare_creds 3 ,
+.Xr krb5_get_init_creds 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_crypto_init.3 b/src/kerberosV/src/lib/krb5/krb5_crypto_init.3
new file mode 100644 (file)
index 0000000..e5476a7
--- /dev/null
@@ -0,0 +1,67 @@
+.\" Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_crypto_init.3,v 1.9 2004/03/20 12:00:01 lha Exp $
+.\"
+.Dd April 7, 1999
+.Dt NAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_crypto_destroy ,
+.Nm krb5_crypto_init
+.Nd encryption support in krb5
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_crypto_init "krb5_context context" "krb5_keyblock *key" "krb5_enctype enctype" "krb5_crypto *crypto"
+.Ft krb5_error_code
+.Fn krb5_crypto_destroy "krb5_context context" "krb5_crypto crypto"
+.Sh DESCRIPTION
+Heimdal exports parts of the Kerberos crypto interface for applications.
+.Pp
+Each kerberos encrytion/checksum function takes a crypto context.
+.Pp
+To setup and destroy crypto contextes there are two functions
+.Fn krb5_crypto_init
+and
+.Fn krb5_crypto_destroy .
+The encryption type to use is taken from the key, but can be overridden
+with the
+.Fa enctype parameter .
+This can be useful for encryptions types which is compatiable (DES for
+example).
+.\" .Sh EXAMPLE
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr krb5_create_checksum 3 ,
+.Xr krb5_encrypt 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_data.3 b/src/kerberosV/src/lib/krb5/krb5_data.3
new file mode 100644 (file)
index 0000000..6664b84
--- /dev/null
@@ -0,0 +1,151 @@
+.\" Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_data.3,v 1.7 2005/04/24 07:40:35 lha Exp $
+.\"
+.Dd April 24, 2005
+.Dt KRB5_DATA 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_data ,
+.Nm krb5_data_zero ,
+.Nm krb5_data_free ,
+.Nm krb5_free_data_contents ,
+.Nm krb5_free_data ,
+.Nm krb5_data_alloc ,
+.Nm krb5_data_realloc ,
+.Nm krb5_data_copy ,
+.Nm krb5_copy_data
+.Nd operates on the Kerberos datatype krb5_data
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "struct krb5_data;"
+.Ft void
+.Fn krb5_data_zero "krb5_data *p"
+.Ft void
+.Fn krb5_data_free "krb5_data *p"
+.Ft void
+.Fn krb5_free_data_contents "krb5_context context" "krb5_data *p"
+.Ft void
+.Fn krb5_free_data "krb5_context context" "krb5_data *p"
+.Ft krb5_error_code
+.Fn krb5_data_alloc "krb5_data *p" "int len"
+.Ft krb5_error_code
+.Fn krb5_data_realloc "krb5_data *p" "int len"
+.Ft krb5_error_code
+.Fn krb5_data_copy "krb5_data *p" "const void *data" "size_t len"
+.Ft krb5_error_code
+.Fn krb5_copy_data "krb5_context context" "const krb5_data *indata" "krb5_data **outdata"
+.Sh DESCRIPTION
+The
+.Li krb5_data
+structure holds a data element.
+The structure contains two public accessible elements
+.Fa length
+(the length of data)
+and
+.Fa data
+(the data itself).
+The structure must always be initiated and freed by the functions
+documented in this manual.
+.Pp
+.Fn krb5_data_zero
+resets the content of
+.Fa p .
+.Pp
+.Fn krb5_data_free
+free the data in
+.Fa p
+and reset the content of the structure with
+.Fn krb5_data_zero .
+.Pp
+.Fn krb5_free_data_contents
+works the same way as
+.Fa krb5_data_free .
+The diffrence is that krb5_free_data_contents is more portable (exists
+in MIT api).
+.Pp
+.Fn krb5_free_data
+frees the data in
+.Fa p
+and
+.Fa p
+itself.
+.Pp
+.Fn krb5_data_alloc
+allocates
+.Fa len
+bytes in
+.Fa p .
+Returns 0 or an error.
+.Pp
+.Fn  krb5_data_realloc
+reallocates the length of
+.Fa p
+to the length in
+.Fa len .
+Returns 0 or an error.
+.Pp
+.Fn krb5_data_copy
+copies the
+.Fa data
+that have the length
+.Fa len
+into
+.Fa p .
+.Fa p
+is not freed so the calling function should make sure the
+.Fa p
+doesn't contain anything needs to be freed.
+Returns 0 or an error.
+.Pp
+.Fn krb5_copy_data
+copies the
+.Li krb5_data
+in
+.Fa indata
+to
+.Fa outdata .
+.Fa outdata
+is not freed so the calling function should make sure the
+.Fa outdata
+doesn't contain anything needs to be freed.
+.Fa outdata
+should be freed using
+.Fn krb5_free_data .
+Returns 0 or an error.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_storage 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_eai_to_heim_errno.3 b/src/kerberosV/src/lib/krb5/krb5_eai_to_heim_errno.3
new file mode 100644 (file)
index 0000000..e4fb98d
--- /dev/null
@@ -0,0 +1,68 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_eai_to_heim_errno.3,v 1.1 2004/08/03 11:13:46 lha Exp $
+.\"
+.Dd April 13, 2004
+.Dt KRB5_EAI_TO_HEIM_ERRNO 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_eai_to_heim_errno ,
+.Nm krb5_h_errno_to_heim_errno
+.Nd convert resolver error code to com_err error codes
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_eai_to_heim_errno
+.Fa "int eai_errno"
+.Fa "int system_error"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_h_errno_to_heim_errno
+.Fa "int eai_errno"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_eai_to_heim_errno
+and
+.Fn krb5_h_errno_to_heim_errno
+convert
+.Xr getaddrinfo 3 ,
+.Xr getnameinfo 3 ,
+and
+.Xr h_errno 3
+to com_err error code that are used by Heimdal, this is useful for for
+function returning kerberos errors and needs to communicate failures
+from resolver function.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_encrypt.3 b/src/kerberosV/src/lib/krb5/krb5_encrypt.3
new file mode 100644 (file)
index 0000000..df6fb27
--- /dev/null
@@ -0,0 +1,267 @@
+.\" Copyright (c) 1999 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_encrypt.3,v 1.15.4.1 2005/10/26 10:06:18 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt KRB5_ENCRYPT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_crypto_getblocksize ,
+.Nm krb5_crypto_getconfoundersize
+.Nm krb5_crypto_getenctype ,
+.Nm krb5_crypto_getpadsize ,
+.Nm krb5_decrypt ,
+.Nm krb5_decrypt_EncryptedData ,
+.Nm krb5_decrypt_ivec ,
+.Nm krb5_decrypt_ticket ,
+.Nm krb5_encrypt ,
+.Nm krb5_encrypt_EncryptedData ,
+.Nm krb5_encrypt_ivec ,
+.Nm krb5_enctype_disable ,
+.Nm krb5_enctype_keysize ,
+.Nm krb5_enctype_to_string ,
+.Nm krb5_enctype_valid ,
+.Nm krb5_get_wrapped_length ,
+.Nm krb5_string_to_enctype
+.Nd "encrypt and decrypt data, set and get encryption type parameters"
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_encrypt
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "krb5_data *result"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_encrypt_EncryptedData
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "int kvno"
+.Fa "EncryptedData *result"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_encrypt_ivec
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "krb5_data *result"
+.Fa "void *ivec"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_decrypt
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "krb5_data *result"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_decrypt_EncryptedData
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage"
+.Fa "EncryptedData *e"
+.Fa "krb5_data *result"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_decrypt_ivec
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "unsigned usage"
+.Fa "void *data"
+.Fa "size_t len"
+.Fa "krb5_data *result"
+.Fa "void *ivec"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_decrypt_ticket
+.Fa "krb5_context context"
+.Fa "Ticket *ticket"
+.Fa "krb5_keyblock *key"
+.Fa "EncTicketPart *out"
+.Fa "krb5_flags flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_crypto_getblocksize
+.Fa "krb5_context context"
+.Fa "size_t *blocksize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_crypto_getenctype
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "krb5_enctype *enctype"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_crypto_getpadsize
+.Fa "krb5_context context"
+.Fa size_t *padsize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_crypto_getconfoundersize
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto
+.Fa size_t *confoundersize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_enctype_keysize
+.Fa "krb5_context context"
+.Fa "krb5_enctype type"
+.Fa "size_t *keysize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_enctype
+.Fa "krb5_context context"
+.Fa "const char *string"
+.Fa "krb5_enctype *etype"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_enctype_to_string
+.Fa "krb5_context context"
+.Fa "krb5_enctype etype"
+.Fa "char **string"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_enctype_valid
+.Fa "krb5_context context"
+.Fa "krb5_enctype etype"
+.Fc
+.Ft void
+.Fo krb5_enctype_disable
+.Fa "krb5_context context"
+.Fa "krb5_enctype etype"
+.Fc
+.Ft size_t
+.Fo krb5_get_wrapped_length
+.Fa "krb5_context context"
+.Fa "krb5_crypto crypto"
+.Fa "size_t data_len"
+.Fc
+.Sh DESCRIPTION
+These functions are used to encrypt and decrypt data.
+.Pp
+.Fn krb5_encrypt_ivec
+puts the encrypted version of
+.Fa data
+(of size
+.Fa len )
+in
+.Fa result .
+If the encryption type supports using derived keys,
+.Fa usage
+should be the appropriate key-usage.
+.Fa ivec
+is a pointer to a initial IV, its modified to the end IV at the end of
+the round.
+Ivec should be the size of 
+If
+.Dv NULL
+is passed in, the default IV is used.
+.Fn krb5_encrypt
+does the same as
+.Fn krb5_encrypt_ivec
+but with
+.Fa ivec
+being
+.Dv NULL .
+.Fn krb5_encrypt_EncryptedData
+does the same as
+.Fn krb5_encrypt ,
+but it puts the encrypted data in a
+.Fa EncryptedData
+structure instead. If
+.Fa kvno
+is not zero, it will be put in the (optional)
+.Fa kvno
+field in the
+.Fa EncryptedData .
+.Pp
+.Fn krb5_decrypt_ivec ,
+.Fn krb5_decrypt ,
+and
+.Fn krb5_decrypt_EncryptedData
+works similarly.
+.Pp
+.Fn krb5_decrypt_ticket
+decrypts the encrypted part of 
+.Fa ticket
+with
+.Fa key .
+.Fn krb5_decrypt_ticket
+also verifies the timestamp in the ticket, invalid flag and if the KDC
+haven't verified the transited path, the transit path.
+.Pp
+.Fn krb5_enctype_keysize ,
+.Fn krb5_crypto_getconfoundersize ,
+.Fn krb5_crypto_getblocksize ,
+.Fn krb5_crypto_getenctype ,
+.Fn krb5_crypto_getpadsize
+all returns various (sometimes) useful information from a crypto context.
+.Pp
+.Fn krb5_enctype_to_string
+converts a encryption type number to a string that can be printable
+and stored. The strings returned should be freed with
+.Xr free 3 .
+.Pp
+.Fn krb5_string_to_enctype
+converts a encryption type strings to a encryption type number that
+can use used for other Kerberos crypto functions.
+.Pp
+.Fn krb5_enctype_valid
+returns 0 if the encrypt is supported and not disabled, otherwise and
+error code is returned.
+.Pp
+.Fn krb5_enctype_disable
+(globally, for all contextes) disables the
+.Fa enctype .
+.Pp
+.Fn krb5_get_wrapped_length
+returns the size of an encrypted packet by
+.Fa crypto
+of length
+.Fa data_len .
+.\" .Sh EXAMPLE
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr krb5_create_checksum 3 ,
+.Xr krb5_crypto_init 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_err.et b/src/kerberosV/src/lib/krb5/krb5_err.et
new file mode 100644 (file)
index 0000000..8089966
--- /dev/null
@@ -0,0 +1,258 @@
+#
+# Error messages for the krb5 library
+#
+# This might look like a com_err file, but is not
+#
+id "$KTH: krb5_err.et,v 1.12 2004/10/14 15:30:29 lha Exp $"
+
+error_table krb5
+
+prefix KRB5KDC_ERR
+error_code NONE,               "No error"
+error_code NAME_EXP,           "Client's entry in database has expired"
+error_code SERVICE_EXP,                "Server's entry in database has expired"
+error_code BAD_PVNO,           "Requested protocol version not supported"
+error_code C_OLD_MAST_KVNO,    "Client's key is encrypted in an old master key"
+error_code S_OLD_MAST_KVNO,    "Server's key is encrypted in an old master key"
+error_code C_PRINCIPAL_UNKNOWN,        "Client not found in Kerberos database"
+error_code S_PRINCIPAL_UNKNOWN,        "Server not found in Kerberos database"
+error_code PRINCIPAL_NOT_UNIQUE,"Principal has multiple entries in Kerberos database"
+error_code NULL_KEY,           "Client or server has a null key"
+error_code CANNOT_POSTDATE,    "Ticket is ineligible for postdating"
+error_code NEVER_VALID,                "Requested effective lifetime is negative or too short"
+error_code POLICY,             "KDC policy rejects request"
+error_code BADOPTION,          "KDC can't fulfill requested option"
+error_code ETYPE_NOSUPP,       "KDC has no support for encryption type"
+error_code SUMTYPE_NOSUPP,     "KDC has no support for checksum type"
+error_code PADATA_TYPE_NOSUPP, "KDC has no support for padata type"
+error_code TRTYPE_NOSUPP,      "KDC has no support for transited type"
+error_code CLIENT_REVOKED,     "Clients credentials have been revoked"
+error_code SERVICE_REVOKED,    "Credentials for server have been revoked"
+error_code TGT_REVOKED,                "TGT has been revoked"
+error_code CLIENT_NOTYET,      "Client not yet valid - try again later"
+error_code SERVICE_NOTYET,     "Server not yet valid - try again later"
+error_code KEY_EXPIRED,                "Password has expired"
+error_code PREAUTH_FAILED,     "Preauthentication failed"
+error_code PREAUTH_REQUIRED,   "Additional pre-authentication required"
+error_code SERVER_NOMATCH,     "Requested server and ticket don't match"
+
+# 27-30 are reserved
+index 31
+prefix KRB5KRB_AP
+error_code ERR_BAD_INTEGRITY,  "Decrypt integrity check failed"
+error_code ERR_TKT_EXPIRED,    "Ticket expired"
+error_code ERR_TKT_NYV,                "Ticket not yet valid"
+error_code ERR_REPEAT,         "Request is a replay"
+error_code ERR_NOT_US,         "The ticket isn't for us"
+error_code ERR_BADMATCH,       "Ticket/authenticator don't match"
+error_code ERR_SKEW,           "Clock skew too great"
+error_code ERR_BADADDR,                "Incorrect net address"
+error_code ERR_BADVERSION,     "Protocol version mismatch"
+error_code ERR_MSG_TYPE,       "Invalid message type"
+error_code ERR_MODIFIED,       "Message stream modified"
+error_code ERR_BADORDER,       "Message out of order"
+error_code ERR_ILL_CR_TKT,     "Invalid cross-realm ticket"
+error_code ERR_BADKEYVER,      "Key version is not available"
+error_code ERR_NOKEY,          "Service key not available"
+error_code ERR_MUT_FAIL,       "Mutual authentication failed"
+error_code ERR_BADDIRECTION,   "Incorrect message direction"
+error_code ERR_METHOD,         "Alternative authentication method required"
+error_code ERR_BADSEQ,         "Incorrect sequence number in message"
+error_code ERR_INAPP_CKSUM,    "Inappropriate type of checksum in message"
+error_code PATH_NOT_ACCEPTED,  "Policy rejects transited path"
+
+prefix KRB5KRB_ERR
+error_code RESPONSE_TOO_BIG,   "Response too big for UDP, retry with TCP"
+# 53-59 are reserved
+index 60
+error_code GENERIC,            "Generic error (see e-text)"
+error_code FIELD_TOOLONG,      "Field is too long for this implementation"
+
+# pkinit
+index 62
+prefix KRB5_KDC_ERR
+error_code CLIENT_NOT_TRUSTED, "Client not trusted"
+error_code KDC_NOT_TRUSTED,    "KDC not trusted"
+error_code INVALID_SIG,                "Invalid signature"
+error_code KEY_SIZE,           "Key size too small/key too weak"
+error_code CERTIFICATE_MISMATCH, "Certificate mismatch"
+
+prefix KRB5_AP_ERR
+error_code USER_TO_USER_REQUIRED, "User to user required"
+
+index 70
+prefix KRB5_KDC_ERROR
+error_code CANT_VERIFY_CERTIFICATE, "Cannot verify certificate"
+error_code INVALID_CERTIFICATE,        "Invalid certificate"
+error_code REVOKED_CERTIFICATE,        "Revoked certificate"
+error_code REVOCATION_STATUS_UNKNOWN, "Revocation status unknown"
+error_code REVOCATION_STATUS_UNAVAILABLE, "Revocation status unknown"
+error_code CLIENT_NAME_MISMATCH,       "Client name mismatch"
+index 75
+error_code KDC_NAME_MISMATCH,  "KDC name mismatch"
+
+# 76-79 are reserved
+
+index 80
+prefix KRB5_IAKERB
+error_code ERR_KDC_NOT_FOUND,  "IAKERB proxy could not find a KDC"
+error_code ERR_KDC_NO_RESPONSE,        "IAKERB proxy never reeived a response from a KDC"
+
+# 82-127 are reserved
+
+index 128
+prefix
+error_code KRB5_ERR_RCSID,     "$KTH: krb5_err.et,v 1.12 2004/10/14 15:30:29 lha Exp $"
+
+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,         "Invalid character in component name"
+error_code KRB5_PARSE_MALFORMED,       "Malformed representation of principal"
+
+error_code KRB5_CONFIG_CANTOPEN,       "Can't open/find configuration file"
+error_code KRB5_CONFIG_BADFORMAT,      "Improper format of 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 file permissions incorrect"
+error_code KRB5_FCC_NOFILE,            "No credentials cache file found"
+error_code KRB5_FCC_INTERNAL,          "Internal file credentials cache error"
+error_code KRB5_CC_WRITE,              "Error writing to credentials cache file"
+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_code KRB5_REALM_CANT_RESOLVE,    "Cannot resolve KDC for 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"
+
+index 238
+error_code KRB5_OBSOLETE_FN,   "Program called an obsolete, deleted function"
+
+index 245
+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_NOSUPP,      "Credential cache function not supported"
+error_code KRB5_DELTAT_BADFORMAT,      "Invalid format of Kerberos lifetime or clock skew string"
+
+end
diff --git a/src/kerberosV/src/lib/krb5/krb5_expand_hostname.3 b/src/kerberosV/src/lib/krb5/krb5_expand_hostname.3
new file mode 100644 (file)
index 0000000..7cc1cdc
--- /dev/null
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_expand_hostname.3,v 1.2 2004/07/26 17:56:54 lha Exp $
+.\"
+.Dd March 21, 2004
+.Dt KRB5_EXPAND_HOSTNAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_expand_hostname ,
+.Nm krb5_expand_hostname_realms
+.Nd Kerberos 5 host name canonicalization functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fo krb5_expand_hostname
+.Fa "krb5_context context"
+.Fa "const char *orig_hostname"
+.Fa "char **new_hostname"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_expand_hostname_realms
+.Fa "krb5_context context"
+.Fa "const char *orig_hostname"
+.Fa "char **new_hostname"
+.Fa "char ***realms"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_expand_hostname
+tries to make
+.Fa orig_hostname
+into a more canonical one in the newly allocated space returned in
+.Fa new_hostname .
+Caller must free the hostname with
+.Xr free 3 .
+.Pp
+.Fn krb5_expand_hostname_realms
+expands
+.Fa orig_hostname
+to a name we believe to be a hostname in newly
+allocated space in
+.Fa new_hostname
+and return the realms
+.Fa new_hostname
+is belive to belong to in
+.Fa realms .
+.Fa Realms
+is a array terminated with
+.Dv NULL .
+Caller must free the
+.Fa realms
+with
+.Fn krb5_free_host_realm 
+and
+.Fa new_hostname
+with
+.Xr free 3 .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_free_host_realm 3 ,
+.Xr krb5_get_host_realm 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_find_padata.3 b/src/kerberosV/src/lib/krb5/krb5_find_padata.3
new file mode 100644 (file)
index 0000000..2be6eef
--- /dev/null
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_find_padata.3,v 1.1 2004/03/21 13:17:41 lha Exp $
+.\"
+.Dd March 21, 2004
+.Dt KRB5_FIND_PADATA 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_find_padata ,
+.Nm krb5_padata_add
+.Nd Kerberos 5 pre-authentication data handling functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft "PA_DATA *"
+.Fo krb5_find_padata
+.Fa "PA_DATA *val"
+.Fa "unsigned len"
+.Fa "int type"
+.Fa "int *index"
+.Fc
+.Ft int
+.Fo krb5_padata_add
+.Fa "krb5_context context"
+.Fa "METHOD_DATA *md"
+.Fa "int type"
+.Fa "void *buf"
+.Fa "size_t len"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_find_padata
+tries to find the pre-authentication data entry of type
+.Fa type
+in the array
+.Fa val
+of length
+.Fa len .
+The search is started at entry pointed out by
+.Fa *index
+(zero based indexing).
+If the type isn't found,
+.Dv NULL
+is returned.
+.Pp
+.Fn krb5_padata_add
+adds a pre-authentication data entry of type
+.Fa type
+pointed out by
+.Fa buf
+and
+.Fa len
+to
+.Fa md .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_generate_random_block.3 b/src/kerberosV/src/lib/krb5/krb5_generate_random_block.3
new file mode 100644 (file)
index 0000000..50e34c3
--- /dev/null
@@ -0,0 +1,57 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_generate_random_block.3,v 1.1 2004/03/21 13:35:39 lha Exp $
+.\"
+.Dd March 21, 2004
+.Dt KRB5_GENERATE_RANDOM_BLOCK 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_generate_random_block
+.Nd Kerberos 5 random functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft void
+.Fo krb5_generate_random_block
+.Fa "void *buf"
+.Fa "size_t len"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_generate_random_block
+generates a cryptographically strong pseudo-random block into the buffer
+.Fa buf
+of length
+.Fa len .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_get_all_client_addrs.3 b/src/kerberosV/src/lib/krb5/krb5_get_all_client_addrs.3
new file mode 100644 (file)
index 0000000..23c4542
--- /dev/null
@@ -0,0 +1,74 @@
+.\" Copyright (c) 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_get_all_client_addrs.3,v 1.8 2003/05/26 14:08:56 lha Exp $
+.\"
+.Dd July 1, 2001
+.Dt KRB5_GET_ADDRS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_all_client_addrs ,
+.Nm krb5_get_all_server_addrs
+.Nd return local addresses
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft "krb5_error_code"
+.Fn krb5_get_all_client_addrs "krb5_context context" "krb5_addresses *addrs"
+.Ft "krb5_error_code"
+.Fn krb5_get_all_server_addrs "krb5_context context" "krb5_addresses *addrs"
+.Sh DESCRIPTION
+These functions return in
+.Fa addrs
+a list of addresses associated with the local
+host.
+.Pp
+The server variant returns all configured interface addresses (if
+possible), including loop-back addresses. This is useful if you want
+to create sockets to listen to.
+.Pp
+The client version will also scan local interfaces (can be turned off
+by setting
+.Li libdefaults/scan_interfaces
+to false in
+.Pa krb5.conf ) ,
+but will not include loop-back addresses, unless there are no other
+addresses found. It will remove all addresses included in
+.Li libdefaults/ignore_addresses
+but will unconditionally include addresses in
+.Li libdefaults/extra_addresses .
+.Pp
+The returned addresses should be freed by calling
+.Fn krb5_free_addresses .
+.\".Sh EXAMPLE
+.Sh SEE ALSO
+.Xr krb5_free_addresses 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_get_credentials.3 b/src/kerberosV/src/lib/krb5/krb5_get_credentials.3
new file mode 100644 (file)
index 0000000..c48f0c7
--- /dev/null
@@ -0,0 +1,143 @@
+.\" Copyright (c) 2004 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_get_credentials.3,v 1.3 2005/05/18 04:07:38 lha Exp $
+.\"
+.Dd July 26, 2004
+.Dt KRB5_GET_CREDENTIALS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_credentials ,
+.Nm krb5_get_credentials_with_flags ,
+.Nm krb5_get_cred_from_kdc ,
+.Nm krb5_get_cred_from_kdc_opt ,
+.Nm krb5_get_kdc_cred
+.Nd get credentials from the KDC using krbtgt
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_get_credentials
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *in_creds"
+.Fa "krb5_creds **out_creds"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_credentials
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "krb5_kdc_flags flags"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *in_creds"
+.Fa "krb5_creds **out_creds"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_cred_from_kdc
+.Fa "krb5_context context"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *in_creds"
+.Fa "krb5_creds **out_creds"
+.Fa "krb5_creds ***ret_tgts"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_cred_from_kdc_opt
+.Fa "krb5_context context"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *in_creds"
+.Fa "krb5_creds **out_creds"
+.Fa "krb5_creds ***ret_tgts"
+.Fa "krb5_flags flags"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_kdc_cred
+.Fa "krb5_context context"
+.Fa "krb5_ccache id"
+.Fa "krb5_kdc_flags flags"
+.Fa "krb5_addresses *addresses"
+.Fa "Ticket  *second_ticket"
+.Fa "krb5_creds *in_creds"
+.Fa "krb5_creds **out_creds"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_get_credentials_with_flags
+get credentials by first looking in the
+.Fa ccache
+and if doesn't exists or is expired, fetch the credential from the KDC
+using the krbtgt in
+.Fa ccache .
+Valid flags to pass into
+.Fa options
+argument are:
+.Pp
+.Bl -tag -width "KRB5_GC_USER_USER" -compact
+.It KRB5_GC_CACHED
+Only check the
+.Fa ccache ,
+don't got out on network to fetch credential.
+.It KRB5_GC_USER_USER
+request a user to user ticket.
+This options doesn't store the resulting user to user credential in
+the
+.Fa ccache .
+.It KRB5_GC_EXPIRED_OK
+returns the credential even if its expired, default behavior is trying
+to refetch the credential from the KDC.
+.El
+.Pp
+.Fa Flags
+are KDCOptions, note the caller must fill in the bit-field and not
+use the integer associated structure.
+.Pp
+.Fn krb5_get_credentials
+works the same way as
+.Fn krb5_get_credentials_with_flags
+except that the
+.Fa flags
+field is missing.
+.Pp
+.Fn krb5_get_cred_from_kdc
+and
+.Fn krb5_get_cred_from_kdc_opt
+fetches the credential from the KDC very much like
+.Fn krb5_get_credentials, but doesn't look in the
+.Fa ccache
+if the credential exists there first.
+.Pp
+.Fn krb5_get_kdc_cred
+does the same as the functions above, but the caller must fill in all
+the information andits closer to the wire protocol.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_get_forwarded_creds 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_get_forwarded_creds.3 b/src/kerberosV/src/lib/krb5/krb5_get_forwarded_creds.3
new file mode 100644 (file)
index 0000000..9be15f5
--- /dev/null
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_get_forwarded_creds.3,v 1.1 2004/07/26 13:34:33 lha Exp $
+.\"
+.Dd July 26, 2004
+.Dt KRB5_GET_FORWARDED_CREDS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_forwarded_creds ,
+.Nm krb5_fwd_tgt_creds
+.Nd get forwarded credentials from the KDC
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_get_forwarded_creds
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_flags flags"
+.Fa "const char *hostname"
+.Fa "krb5_creds *in_creds"
+.Fa "krb5_data *out_data"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_fwd_tgt_creds
+.Fa "krb5_context context"
+.Fa "krb5_auth_context auth_context"
+.Fa "const char *hostname"
+.Fa "krb5_principal client"
+.Fa "krb5_principal server"
+.Fa "krb5_ccache ccache"
+.Fa "int forwardable"
+.Fa "krb5_data *out_data"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_get_forwarded_creds
+and
+.Fn krb5_fwd_tgt_creds
+get tickets forwarded to
+.Fa hostname.
+If the tickets that are forwarded are address-less, the forwarded
+tickets will also be address-less, otherwise
+.Fa hostname
+will be used for figure out the address to forward the ticket too.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_get_credentials 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_get_in_cred.3 b/src/kerberosV/src/lib/krb5/krb5_get_in_cred.3
new file mode 100644 (file)
index 0000000..73d904a
--- /dev/null
@@ -0,0 +1,274 @@
+.\" Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_get_in_cred.3,v 1.3 2004/07/26 16:22:23 lha Exp $
+.\"
+.Dd May 31, 2003
+.Dt KRB5_GET_IN_TKT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_in_tkt ,
+.Nm krb5_get_in_cred ,
+.Nm krb5_get_in_tkt_with_password ,
+.Nm krb5_get_in_tkt_with_keytab ,
+.Nm krb5_get_in_tkt_with_skey ,
+.Nm krb5_free_kdc_rep ,
+.Nm krb5_password_key_proc
+.Nd deprecated initial authentication functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fo krb5_get_in_tkt
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "const krb5_addresses *addrs"
+.Fa "const krb5_enctype *etypes"
+.Fa "const krb5_preauthtype *ptypes"
+.Fa "krb5_key_proc key_proc"
+.Fa "krb5_const_pointer keyseed"
+.Fa "krb5_decrypt_proc decrypt_proc"
+.Fa "krb5_const_pointer decryptarg"
+.Fa "krb5_creds *creds"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_kdc_rep *ret_as_reply"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_in_cred
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "const krb5_addresses *addrs"
+.Fa "const krb5_enctype *etypes"
+.Fa "const krb5_preauthtype *ptypes"
+.Fa "const krb5_preauthdata *preauth"
+.Fa "krb5_key_proc key_proc"
+.Fa "krb5_const_pointer keyseed"
+.Fa "krb5_decrypt_proc decrypt_proc"
+.Fa "krb5_const_pointer decryptarg"
+.Fa "krb5_creds *creds"
+.Fa "krb5_kdc_rep *ret_as_reply"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_in_tkt_with_password
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "krb5_addresses *addrs"
+.Fa "const krb5_enctype *etypes"
+.Fa "const krb5_preauthtype *pre_auth_types"
+.Fa "const char *password"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *creds"
+.Fa "krb5_kdc_rep *ret_as_reply"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_in_tkt_with_keytab
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "krb5_addresses *addrs"
+.Fa "const krb5_enctype *etypes"
+.Fa "const krb5_preauthtype *pre_auth_types"
+.Fa "krb5_keytab keytab"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *creds"
+.Fa "krb5_kdc_rep *ret_as_reply"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_in_tkt_with_skey
+.Fa "krb5_context context"
+.Fa "krb5_flags options"
+.Fa "krb5_addresses *addrs"
+.Fa "const krb5_enctype *etypes"
+.Fa "const krb5_preauthtype *pre_auth_types"
+.Fa "const krb5_keyblock *key"
+.Fa "krb5_ccache ccache"
+.Fa "krb5_creds *creds"
+.Fa "krb5_kdc_rep *ret_as_reply"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_kdc_rep
+.Fa "krb5_context context"
+.Fa "krb5_kdc_rep *rep"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_password_key_proc
+.Fa "krb5_context context"
+.Fa "krb5_enctype type"
+.Fa "krb5_salt salt"
+.Fa "krb5_const_pointer keyseed"
+.Fa "krb5_keyblock **key"
+.Fc
+.Sh DESCRIPTION
+.Bf Em
+All the functions in this manual page are deprecated in the MIT
+implementation, and will soon deprecated in Heimdal too, don't use them.
+.Ef
+.Pp
+Getting initial credential ticket for a principal.
+.Nm krb5_get_in_cred
+is the function all other krb5_get_in function uses to fetch tickets.
+The other krb5_get_in function are more specialized and therefor
+somewhat easier to use.
+.Pp
+If your need is only to verify a user and password, consider using
+.Xr krb5_verify_user 3
+instead, it have a much simpler interface.
+.Pp
+.Nm krb5_get_in_tkt
+and
+.Nm krb5_get_in_cred
+fetches initial credential, queries after key using the
+.Fa key_proc
+argument.
+The differences between the two function is that
+.Nm krb5_get_in_tkt
+stores the credential in a
+.Li krb5_creds
+while
+.Nm krb5_get_in_cred
+stores the credential in a
+.Li krb5_ccache .
+.Pp
+.Nm krb5_get_in_tkt_with_password ,
+.Nm krb5_get_in_tkt_with_keytab ,
+and
+.Nm krb5_get_in_tkt_with_skey
+does the same work as
+.Nm krb5_get_in_cred
+but are more specialized.
+.Pp
+.Nm krb5_get_in_tkt_with_password
+uses the clients password to authenticate.
+If the password argument is
+.DV NULL
+the user user queried with the default password query function.
+.Pp
+.Nm krb5_get_in_tkt_with_keytab
+searches the given keytab for a service entry for the client principal.
+If the keytab is
+.Dv NULL
+the default keytab is used.
+.Pp
+.Nm krb5_get_in_tkt_with_skey
+uses a key to get the initial credential.
+.Pp
+There are some common arguments to the krb5_get_in functions, these are:
+.Pp
+.Fa options
+are the
+.Dv KDC_OPT
+flags.
+.Pp
+.Fa etypes
+is a
+.Dv NULL
+terminated array of encryption types that the client approves.
+.Pp
+.Fa addrs
+a list of the addresses that the initial ticket.
+If it is
+.Dv NULL
+the list will be generated by the library.
+.Pp
+.Fa pre_auth_types
+a
+.Dv NULL
+terminated array of pre-authentication types.
+If
+.Fa pre_auth_types
+is
+.Dv NULL
+the function will try without pre-authentication and return those
+pre-authentication that the KDC returned.
+.Pp
+.Fa ret_as_reply
+will (if not
+.Dv NULL )
+be filled in with the response of the KDC and should be free with
+.Fn krb5_free_kdc_rep .
+.Pp
+.Fa key_proc
+is a pointer to a function that should return a key salted appropriately.
+Using
+.Dv NULL
+will use the default password query function.
+.Pp
+.Fa decrypt_proc
+Using
+.Dv NULL
+will use the default decryption function.
+.Pp
+.Fa decryptarg
+will be passed to the decryption function
+.Fa decrypt_proc .
+.Pp
+.Fa creds
+creds should be filled in with the template for a credential that
+should be requested.
+The client and server elements of the creds structure must be filled in.
+Upon return of the function it will be contain the content of the
+requested credential
+.Fa ( krb5_get_in_cred ) ,
+or it will be freed with
+.Xr krb5_free_creds 3
+(all the other krb5_get_in functions).
+.Pp
+.Fa ccache
+will store the credential in the credential cache
+.Fa ccache .
+The credential cache will not be initialized, thats up the the caller.
+.Pp
+.Nm krb5_password_key_proc
+is a library function that is suitable using as the
+.Fa krb5_key_proc
+argument to
+.Nm krb5_get_in_cred
+or
+.Nm krb5_get_in_tkt .
+.Fa keyseed
+should be a pointer to a
+.Dv NUL
+terminated string or
+.Dv NULL .
+.Nm krb5_password_key_proc
+will query the user for the pass on the console if the password isn't
+given as the argument
+.Fa keyseed .
+.Pp
+.Fn krb5_free_kdc_rep
+frees the content of
+.Fa rep .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_verify_user 3 ,
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_get_init_creds.3 b/src/kerberosV/src/lib/krb5/krb5_get_init_creds.3
new file mode 100644 (file)
index 0000000..44f1ed3
--- /dev/null
@@ -0,0 +1,365 @@
+.\" Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_get_init_creds.3,v 1.10 2005/05/10 09:20:58 lha Exp $
+.\"
+.Dd May 10, 2005
+.Dt KRB5_GET_INIT_CREDS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_init_creds ,
+.Nm krb5_get_init_creds_keytab ,
+.Nm krb5_get_init_creds_opt ,
+.Nm krb5_get_init_creds_opt_alloc ,
+.Nm krb5_get_init_creds_opt_free ,
+.Nm krb5_get_init_creds_opt_init ,
+.Nm krb5_get_init_creds_opt_set_address_list ,
+.Nm krb5_get_init_creds_opt_set_anonymous ,
+.Nm krb5_get_init_creds_opt_set_default_flags ,
+.Nm krb5_get_init_creds_opt_set_etype_list ,
+.Nm krb5_get_init_creds_opt_set_forwardable ,
+.Nm krb5_get_init_creds_opt_set_pa_password ,
+.Nm krb5_get_init_creds_opt_set_paq_request ,
+.Nm krb5_get_init_creds_opt_set_preauth_list ,
+.Nm krb5_get_init_creds_opt_set_proxiable ,
+.Nm krb5_get_init_creds_opt_set_renew_life ,
+.Nm krb5_get_init_creds_opt_set_salt ,
+.Nm krb5_get_init_creds_opt_set_tkt_life ,
+.Nm krb5_get_init_creds_password ,
+.Nm krb5_prompt ,
+.Nm krb5_prompter_posix
+.Nd Kerberos 5 initial authentication functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_get_init_creds_opt;
+.Pp
+.Ft krb5_error_code
+.Fo krb5_get_init_creds_opt_alloc
+.Fa "krb5_context context"
+.Fa "krb5_get_init_creds_opt **opt"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_free
+.Fa "krb5_get_init_creds_opt *opt"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_init
+.Fa "krb5_get_init_creds_opt *opt"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_address_list
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_anonymous
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "int anonymous"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_default_flags
+.Fa "krb5_context context"
+.Fa "const char *appname"
+.Fa "krb5_const_realm realm"
+.Fa "krb5_get_init_creds_opt *opt"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_etype_list
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_enctype *etype_list"
+.Fa "int etype_list_length"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_forwardable
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "int forwardable"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_init_creds_opt_set_pa_password
+.Fa "krb5_context context"
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "const char *password"
+.Fa "krb5_s2k_proc key_proc"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_init_creds_opt_set_paq_request
+.Fa "krb5_context context"
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_boolean req_pac"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_init_creds_opt_set_pkinit
+.Fa "krb5_context context"
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "const char *cert_file"
+.Fa "const char *key_file"
+.Fa "const char *x509_anchors"
+.Fa "int flags"
+.Fa "char *password"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_preauth_list
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_preauthtype *preauth_list"
+.Fa "int preauth_list_length"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_proxiable
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "int proxiable"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_renew_life
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_deltat renew_life"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_salt
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_data *salt"
+.Fc
+.Ft void
+.Fo krb5_get_init_creds_opt_set_tkt_life
+.Fa "krb5_get_init_creds_opt *opt"
+.Fa "krb5_deltat tkt_life"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_init_creds
+.Fa "krb5_context context"
+.Fa "krb5_creds *creds"
+.Fa "krb5_principal client"
+.Fa "krb5_prompter_fct prompter"
+.Fa "void *prompter_data"
+.Fa "krb5_deltat start_time"
+.Fa "const char *in_tkt_service"
+.Fa "krb5_get_init_creds_opt *options"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_init_creds_password
+.Fa "krb5_context context"
+.Fa "krb5_creds *creds"
+.Fa "krb5_principal client"
+.Fa "const char *password"
+.Fa "krb5_prompter_fct prompter"
+.Fa "void *prompter_data"
+.Fa "krb5_deltat start_time"
+.Fa "const char *in_tkt_service"
+.Fa "krb5_get_init_creds_opt *in_options"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_init_creds_keytab
+.Fa "krb5_context context"
+.Fa "krb5_creds *creds"
+.Fa "krb5_principal client"
+.Fa "krb5_keytab keytab"
+.Fa "krb5_deltat start_time"
+.Fa "const char *in_tkt_service"
+.Fa "krb5_get_init_creds_opt *options"
+.Fc
+.Ft int
+.Fo krb5_prompter_posix
+.Fa "krb5_context context"
+.Fa "void *data"
+.Fa "const char *name"
+.Fa "const char *banner"
+.Fa "int num_prompts"
+.Fa "krb5_prompt prompts[]"
+.Fc
+.Sh DESCRIPTION
+Getting initial credential ticket for a principal.
+That may include changing an expired password, and doing preauthentication.
+This interface that replaces the deprecated
+.Fa krb5_in_tkt
+and 
+.Fa krb5_in_cred
+functions.
+.Pp
+If you only want to verify a username and password, consider using
+.Xr krb5_verify_user 3
+instead, since it also verifies that initial credentials with using a
+keytab to make sure the response was from the KDC.
+.Pp
+First a
+.Li krb5_get_init_creds_opt
+structure is initialized
+with
+.Fn krb5_get_init_creds_opt_alloc
+or
+.Fn krb5_get_init_creds_opt_init .
+.Fn krb5_get_init_creds_opt_alloc
+allocates a extendible structures that needs to be freed with
+.Fn krb5_get_init_creds_opt_free .
+The structure may be modified by any of the
+.Fn krb5_get_init_creds_opt_set
+functions to change request parameters and authentication information.
+.Pp
+If the caller want to use the default options,
+.Dv NULL
+can be passed instead.
+.Pp
+The the actual request to the KDC is done by any of the
+.Fn krb5_get_init_creds ,
+.Fn krb5_get_init_creds_password ,
+or
+.Fn krb5_get_init_creds_keytab
+functions.
+.Fn krb5_get_init_creds
+is the least specialized function and can, with the right in data,
+behave like the latter two.
+The latter two are there for compatibility with older releases and
+they are slightly easier to use.
+.Pp
+.Li krb5_prompt
+is a structure containing the following elements:
+.Bd -literal
+typedef struct {
+    const char *prompt;
+    int hidden;
+    krb5_data *reply;
+    krb5_prompt_type type
+} krb5_prompt;
+.Ed
+.Pp
+.Fa prompt
+is the prompt that should shown to the user
+If
+.Fa hidden
+is set, the prompter function shouldn't echo the output to the display
+device.
+.Fa reply
+must be preallocated; it will not be allocated by the prompter
+function.
+Possible values for the
+.Fa type
+element are:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It KRB5_PROMPT_TYPE_PASSWORD
+.It KRB5_PROMPT_TYPE_NEW_PASSWORD
+.It KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN
+.It KRB5_PROMPT_TYPE_PREAUTH
+.El
+.Pp
+.Fn krb5_prompter_posix
+is the default prompter function in a POSIX environment.
+It matches the
+.Fa krb5_prompter_fct
+and can be used in the
+.Fa krb5_get_init_creds
+functions.
+.Fn krb5_prompter_posix
+doesn't require
+.Fa prompter_data.
+.Pp
+If the
+.Fa start_time
+is zero, then the requested ticket will be valid
+beginning immediately.
+Otherwise, the
+.Fa start_time
+indicates how far in the future the ticket should be postdated.
+.Pp
+If the
+.Fa in_tkt_service
+name is
+.Dv non-NULL ,
+that principal name will be
+used as the server name for the initial ticket request.
+The realm of the name specified will be ignored and will be set to the
+realm of the client name.
+If no in_tkt_service name is specified,
+krbtgt/CLIENT-REALM@CLIENT-REALM will be used.
+.Pp
+For the rest of arguments, a configuration or library default will be
+used if no value is specified in the options structure.
+.Pp
+.Fn krb5_get_init_creds_opt_set_address_list
+sets the list of
+.Fa addresses
+that is should be stored in the ticket.
+.Pp
+.Fn krb5_get_init_creds_opt_set_anonymous
+make the request anonymous if the
+.Fa anonymous
+parameter is non-zero.
+.Pp
+.Fn krb5_get_init_creds_opt_set_default_flags
+sets the default flags using the configuration file.
+.Pp
+.Fn krb5_get_init_creds_opt_set_etype_list
+set a list of enctypes that the client is willing to support in the
+request.
+.Pp
+.Fn krb5_get_init_creds_opt_set_forwardable
+request a forwardable ticket.
+.Pp
+.Fn krb5_get_init_creds_opt_set_pa_password
+set the
+.Fa password
+and
+.Fa key_proc
+that is going to be used to get a new ticket.
+.Fa password
+or
+.Fa key_proc
+can be
+.Dv NULL
+if the caller wants to use the default values.
+If the
+.Fa password
+is unset and needed, the user will be prompted for it.
+.Pp
+.Fn krb5_get_init_creds_opt_set_paq_request
+sets the password that is going to be used to get a new ticket.
+.Pp
+.Fn krb5_get_init_creds_opt_set_preauth_list
+sets the list of client-supported preauth types.
+.Pp
+.Fn krb5_get_init_creds_opt_set_proxiable
+makes the request proxiable.
+.Pp
+.Fn krb5_get_init_creds_opt_set_renew_life
+sets the requested renewable lifetime.
+.Pp
+.Fn krb5_get_init_creds_opt_set_salt
+sets the salt that is going to be used in the request.
+.Pp
+.Fn krb5_get_init_creds_opt_set_tkt_life
+sets requested ticket lifetime.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_creds 3 ,
+.Xr krb5_verify_user 3 ,
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_get_krbhst.3 b/src/kerberosV/src/lib/krb5/krb5_get_krbhst.3
new file mode 100644 (file)
index 0000000..5e77275
--- /dev/null
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_get_krbhst.3,v 1.9 2005/04/24 07:42:27 lha Exp $
+.\"
+.Dd April 24, 2005
+.Dt KRB5_GET_KRBHST 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_krbhst ,
+.Nm krb5_get_krb_admin_hst ,
+.Nm krb5_get_krb_changepw_hst ,
+.Nm krb5_get_krb524hst ,
+.Nm krb5_free_krbhst
+.Nd lookup Kerberos KDC hosts
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_get_krbhst "krb5_context context" "const krb5_realm *realm" "char ***hostlist"
+.Ft krb5_error_code
+.Fn krb5_get_krb_admin_hst "krb5_context context" "const krb5_realm *realm" "char ***hostlist"
+.Ft krb5_error_code
+.Fn krb5_get_krb_changepw_hst "krb5_context context" "const krb5_realm *realm" "char ***hostlist"
+.Ft krb5_error_code
+.Fn krb5_get_krb524hst "krb5_context context" "const krb5_realm *realm" "char ***hostlist"
+.Ft krb5_error_code
+.Fn krb5_free_krbhst "krb5_context context" "char **hostlist"
+.Sh DESCRIPTION
+These functions implement the old API to get a list of Kerberos hosts,
+and are thus similar to the
+.Fn krb5_krbhst_init
+functions. However, since these functions returns
+.Em all
+hosts in one go, they potentially have to do more lookups than
+necessary. These functions remain for compatibility reasons.
+.Pp
+After a call to one of these functions,
+.Fa hostlist
+is a
+.Dv NULL
+terminated list of strings, pointing to the requested Kerberos hosts. These should be freed with
+.Fn krb5_free_krbhst
+when done with.
+.Sh EXAMPLES
+The following code will print the KDCs of the realm
+.Dq MY.REALM .
+.Bd -literal -offset indent
+char **hosts, **p;
+krb5_get_krbhst(context, "MY.REALM", &hosts);
+for(p = hosts; *p; p++)
+    printf("%s\\n", *p);
+krb5_free_krbhst(context, hosts);
+.Ed
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr krb5_krbhst_init 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_getportbyname.3 b/src/kerberosV/src/lib/krb5/krb5_getportbyname.3
new file mode 100644 (file)
index 0000000..3e3c96b
--- /dev/null
@@ -0,0 +1,67 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_getportbyname.3,v 1.1 2004/08/15 16:04:16 lha Exp $
+.\"
+.Dd August 15, 2004
+.Dt NAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_getportbyname
+.Nd get port number by name
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft int
+.Fo krb5_getportbyname
+.Fa "krb5_context context"
+.Fa "const char *service"
+.Fa "const char *proto"
+.Fa "int default_port"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_getportbyname
+gets the port number for
+.Fa service /
+.Fa proto
+pair from the global service table for and returns it in network order.
+If its not found in the global table, the
+.Fa default_port
+(given in host order)
+is returned.
+.Sh EXAMPLE
+.Bd -literal
+int port = krb5_getportbyname(context, "kerberos", "tcp", 88);
+.Ed
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr krb5 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_init_context.3 b/src/kerberosV/src/lib/krb5/krb5_init_context.3
new file mode 100644 (file)
index 0000000..bdac3c2
--- /dev/null
@@ -0,0 +1,259 @@
+.\" Copyright (c) 2001 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_init_context.3,v 1.15 2004/12/08 17:50:00 lha Exp $
+.\"
+.Dd December  8, 2004
+.Dt KRB5_CONTEXT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_context ,
+.Nm krb5_init_context ,
+.Nm krb5_free_context ,
+.Nm krb5_init_ets ,
+.Nm krb5_add_et_list ,
+.Nm krb5_add_extra_addresses ,
+.Nm krb5_add_ignore_addresses ,
+.Nm krb5_get_extra_addresses ,
+.Nm krb5_get_ignore_addresses ,
+.Nm krb5_set_extra_addresses ,
+.Nm krb5_set_ignore_addresses ,
+.Nm krb5_set_fcache_version ,
+.Nm krb5_get_fcache_version ,
+.Nm krb5_set_config_files ,
+.Nm krb5_prepend_config_files ,
+.Nm krb5_prepend_config_files_default ,
+.Nm krb5_get_default_config_files ,
+.Nm krb5_free_config_files ,
+.Nm krb5_set_use_admin_kdc ,
+.Nm krb5_get_use_admin_kdc
+.Nd create, modify and delete krb5_context structures
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "struct krb5_context;"
+.Pp
+.Ft krb5_error_code
+.Fo krb5_init_context
+.Fa "krb5_context *context"
+.Fc
+.Ft void
+.Fo krb5_free_context
+.Fa "krb5_context context"
+.Fc
+.Ft void
+.Fo krb5_init_ets
+.Fa "krb5_context context"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_add_et_list
+.Fa "krb5_context context"
+.Fa "void (*func)(struct et_list **)"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_add_extra_addresses
+.Fa "krb5_context context"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_extra_addresses
+.Fa "krb5_context context"
+.Fa "const krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_extra_addresses
+.Fa "krb5_context context"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_add_ignore_addresses
+.Fa "krb5_context context"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_ignore_addresses
+.Fa "krb5_context context"
+.Fa "const krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_ignore_addresses
+.Fa "krb5_context context"
+.Fa "krb5_addresses *addresses"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_fcache_version
+.Fa "krb5_context context"
+.Fa "int version"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_fcache_version
+.Fa "krb5_context context"
+.Fa "int *version"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_config_files
+.Fa "krb5_context context"
+.Fa "char **filenames"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_prepend_config_files
+.Fa "const char *filelist"
+.Fa "char **pq"
+.Fa "char ***ret_pp"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_prepend_config_files_default
+.Fa "const char *filelist"
+.Fa "char ***pfilenames"
+.Fc
+.Ft krb5_error_code 
+.Fo krb5_get_default_config_files
+.Fa "char ***pfilenames"
+.Fc
+.Ft void
+.Fo krb5_free_config_files
+.Fa "char **filenames"
+.Fc
+.Ft void
+.Fo krb5_set_use_admin_kdc
+.Fa "krb5_context context"
+.Fa "krb5_boolean flag"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_get_use_admin_kdc
+.Fa "krb5_context context"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn krb5_init_context
+function initializes the
+.Fa context
+structure and reads the configuration file
+.Pa /etc/kerberosV/krb5.conf .
+.Pp
+The structure should be freed by calling
+.Fn krb5_free_context
+when it is no longer being used.
+.Pp
+.Fn krb5_init_context
+returns 0 to indicate success.
+Otherwise an errno code is returned.
+Failure means either that something bad happened during initialization
+(typically
+.Bq ENOMEM )
+or that Kerberos should not be used
+.Bq ENXIO .
+.Pp
+.Fn krb5_init_ets
+adds all
+.Xr com_err 3
+libs to
+.Fa context .
+This is done by
+.Fn krb5_init_context .
+.Pp
+.Fn krb5_add_et_list 
+adds a
+.Xr com_err 3
+error-code handler
+.Fa func
+to the specified
+.Fa context .
+The error handler must generated by the the re-rentrant version of the
+.Xr compile_et 3
+program.
+.Fn krb5_add_extra_addresses
+add a list of addresses that should be added when requesting tickets.
+.Pp
+.Fn krb5_add_ignore_addresses
+add a list of addresses that should be ignored when requesting tickets.
+.Pp
+.Fn krb5_get_extra_addresses
+get the list of addresses that should be added when requesting tickets.
+.Pp
+.Fn krb5_get_ignore_addresses
+get the list of addresses that should be ignored when requesting tickets.
+.Pp
+.Fn krb5_set_ignore_addresses
+set the list of addresses that should be ignored when requesting tickets.
+.Pp
+.Fn krb5_set_extra_addresses
+set the list of addresses that should be added when requesting tickets.
+.Pp
+.Fn krb5_set_fcache_version
+sets the version of file credentials caches that should be used.
+.Pp
+.Fn krb5_get_fcache_version
+gets the version of file credentials caches that should be used.
+.Pp
+.Fn krb5_set_config_files
+set the list of configuration files to use and re-initialize the
+configuration from the files.
+.Pp
+.Fn krb5_prepend_config_files
+parse the 
+.Fa filelist
+and prepend the result to the already existing list
+.Fa pq
+The result is returned in
+.Fa ret_pp
+and should be freed with
+.Fn krb5_free_config_files .
+.Pp
+.Fn krb5_prepend_config_files_default
+parse the 
+.Fa filelist
+and append that to the default
+list of configuration files.
+.Pp
+.Fn krb5_get_default_config_files
+get a list of default configuration files.
+.Pp
+.Fn krb5_free_config_files
+free a list of configuration files returned by
+.Fn krb5_get_default_config_files ,
+.Fn krb5_prepend_config_files_default ,
+or
+.Fn krb5_prepend_config_files .
+.Pp
+.Fn krb5_set_use_admin_kdc
+sets if all KDC requests should go admin KDC.
+.Pp
+.Fn krb5_get_use_admin_kdc
+gets if all KDC requests should go admin KDC.
+.Sh SEE ALSO
+.Xr errno 2 ,
+.Xr krb5 3 ,
+.Xr krb5_config 3 ,
+.Xr krb5_context 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_is_thread_safe.3 b/src/kerberosV/src/lib/krb5/krb5_is_thread_safe.3
new file mode 100644 (file)
index 0000000..c07e719
--- /dev/null
@@ -0,0 +1,58 @@
+.\" Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_is_thread_safe.3,v 1.1 2005/01/05 09:47:02 lha Exp $
+.\"
+.Dd January  5, 2005
+.Dt KRB5_IS_THREAD_SAFE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_is_thread_safe
+.Nd "is the Kerberos library compiled with multithread support"
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_boolean
+.Fn krb5_is_thread_safe "void"
+.Sh DESCRIPTION
+.Nm
+returns
+.Dv TRUE
+if the library was compiled with with multithread support.
+If the library isn't compiled, the consumer have to use a global lock
+to make sure Kerboros functions are not called at the same time by
+diffrent threads.
+.\" .Sh EXAMPLE
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr krb5_create_checksum 3 ,
+.Xr krb5_encrypt 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_keyblock.3 b/src/kerberosV/src/lib/krb5/krb5_keyblock.3
new file mode 100644 (file)
index 0000000..9f4e3b9
--- /dev/null
@@ -0,0 +1,218 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_keyblock.3,v 1.9 2005/04/15 16:39:54 lha Exp $
+.\"
+.Dd Apr 14, 2005
+.Dt KRB5_KEYBLOCK 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_keyblock ,
+.Nm krb5_keyblock_get_enctype ,
+.Nm krb5_copy_keyblock ,
+.Nm krb5_copy_keyblock_contents ,
+.Nm krb5_free_keyblock ,
+.Nm krb5_free_keyblock_contents ,
+.Nm krb5_generate_random_keyblock ,
+.Nm krb5_generate_subkey ,
+.Nm krb5_generate_subkey_extended ,
+.Nm krb5_keyblock_init ,
+.Nm krb5_keyblock_zero ,
+.Nm krb5_random_to_key
+.Nd Kerberos 5 key handling functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li krb5_keyblock ;
+.Ft krb5_enctype
+.Fo krb5_keyblock_get_enctype
+.Fa "const krb5_keyblock *block"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_keyblock
+.Fa "krb5_context context"
+.Fa "krb5_keyblock **to"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_keyblock_contents
+.Fa "krb5_context context"
+.Fa "const krb5_keyblock *inblock"
+.Fa "krb5_keyblock *to"
+.Fc
+.Ft void
+.Fo krb5_free_keyblock
+.Fa "krb5_context context"
+.Fa "krb5_keyblock *keyblock"
+.Fc
+.Ft void
+.Fo krb5_free_keyblock_contents
+.Fa "krb5_context context"
+.Fa "krb5_keyblock *keyblock"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_generate_random_keyblock
+.Fa "krb5_context context"
+.Fa "krb5_enctype type"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_generate_subkey
+.Fa "krb5_context context"
+.Fa "const krb5_keyblock *key"
+.Fa "krb5_keyblock **subkey"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_generate_subkey_extended
+.Fa "krb5_context context"
+.Fa "const krb5_keyblock *key"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_keyblock **subkey"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_keyblock_init
+.Fa "krb5_context context"
+.Fa "krb5_enctype type"
+.Fa "const void *data"
+.Fa "size_t size"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft void
+.Fo krb5_keyblock_zero
+.Fa "krb5_keyblock *keyblock"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_random_to_key
+.Fa "krb5_context context"
+.Fa "krb5_enctype type"
+.Fa "const void *data"
+.Fa "size_t size"
+.Fa "krb5_keyblock *key"
+.Fc
+.Sh DESCRIPTION
+.Li krb5_keyblock
+holds the encryption key for a specific encryption type.
+There is no component inside
+.Li krb5_keyblock
+that is directly referable.
+.Pp
+.Fn krb5_keyblock_get_enctype
+returns the encryption type of the keyblock.
+.Pp
+.Fn krb5_copy_keyblock
+makes a copy the keyblock
+.Fa inblock
+to the
+output
+.Fa out .
+.Fa out
+should be freed by the caller with
+.Fa krb5_free_keyblock .
+.Pp
+.Fn krb5_copy_keyblock_contents
+copies the contents of
+.Fa inblock
+to the
+.Fa to
+keyblock.
+The destination keyblock is overritten.
+.Pp
+.Fn krb5_free_keyblock
+zeros out and frees the content and the keyblock itself.
+.Pp
+.Fn krb5_free_keyblock_contents
+zeros out and frees the content of the keyblock.
+.Pp
+.Fn krb5_generate_random_keyblock
+creates a new content of the keyblock
+.Fa key
+of type encrytion type
+.Fa type .
+The content of
+.Fa key
+is overwritten and not freed, so the caller should be sure it is
+freed before calling the function.
+.Pp
+.Fn krb5_generate_subkey
+generates a
+.Fa subkey
+of the same type as
+.Fa key .
+The caller must free the subkey with
+.Fa krb5_free_keyblock .
+.Pp
+.Fn krb5_generate_subkey_extended
+generates a
+.Fa subkey
+of the specified encryption type
+.Fa type .
+If
+.Fa type
+is
+.Dv ETYPE_NULL ,
+of the same type as
+.Fa key .
+The caller must free the subkey with
+.Fa krb5_free_keyblock .
+.Pp
+.Fn krb5_keyblock_init
+Fill in
+.Fa key
+with key data of type
+.Fa enctype
+from 
+.Fa data
+of length
+.Fa size .
+Key should be freed using
+.Fn krb5_free_keyblock_contents .
+.Pp
+.Fn krb5_keyblock_zero
+zeros out the keyblock to to make sure no keymaterial is in
+memory.
+Note that
+.Fn krb5_free_keyblock_contents
+also zeros out the memory.
+.Pp
+.Fn krb5_random_to_key
+converts the random bytestring to a protocol key according to Kerberos
+crypto frame work.
+It the resulting key will be of type
+.Fa enctype .
+It may be assumed that all the bits of the input string are equally
+random, even though the entropy present in the random source may be
+limited
+.\" .Sh EXAMPLES
+.Sh SEE ALSO
+.Xr krb5_crypto_init 3 ,
+.Xr krb5 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_keytab.3 b/src/kerberosV/src/lib/krb5/krb5_keytab.3
new file mode 100644 (file)
index 0000000..9f0f51a
--- /dev/null
@@ -0,0 +1,472 @@
+.\" Copyright (c) 2001 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_keytab.3,v 1.16 2005/05/23 14:07:32 lha Exp $
+.\"
+.Dd March 28, 2005
+.Dt KRB5_KEYTAB 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_kt_ops ,
+.Nm krb5_keytab_entry ,
+.Nm krb5_kt_cursor ,
+.Nm krb5_kt_add_entry ,
+.Nm krb5_kt_close ,
+.Nm krb5_kt_compare ,
+.Nm krb5_kt_copy_entry_contents ,
+.Nm krb5_kt_default ,
+.Nm krb5_kt_default_modify_name ,
+.Nm krb5_kt_default_name ,
+.Nm krb5_kt_end_seq_get ,
+.Nm krb5_kt_free_entry ,
+.Nm krb5_kt_get_entry ,
+.Nm krb5_kt_get_name ,
+.Nm krb5_kt_get_type ,
+.Nm krb5_kt_next_entry ,
+.Nm krb5_kt_read_service_key ,
+.Nm krb5_kt_register ,
+.Nm krb5_kt_remove_entry ,
+.Nm krb5_kt_resolve ,
+.Nm krb5_kt_start_seq_get
+.Nd manage keytab (key storage) files
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fo krb5_kt_add_entry
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fa "krb5_keytab_entry *entry"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_close
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fc
+.Ft krb5_boolean
+.Fo krb5_kt_compare
+.Fa "krb5_context context"
+.Fa "krb5_keytab_entry *entry"
+.Fa "krb5_const_principal principal"
+.Fa "krb5_kvno vno"
+.Fa "krb5_enctype enctype"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_copy_entry_contents
+.Fa "krb5_context context"
+.Fa "const krb5_keytab_entry *in"
+.Fa "krb5_keytab_entry *out"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_default
+.Fa "krb5_context context"
+.Fa "krb5_keytab *id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_default_modify_name
+.Fa "krb5_context context"
+.Fa "char *name"
+.Fa "size_t namesize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_default_name
+.Fa "krb5_context context"
+.Fa "char *name"
+.Fa "size_t namesize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_end_seq_get
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fa "krb5_kt_cursor *cursor"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_free_entry
+.Fa "krb5_context context"
+.Fa "krb5_keytab_entry *entry"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_get_entry
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fa "krb5_const_principal principal"
+.Fa "krb5_kvno kvno"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_keytab_entry *entry"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_get_name
+.Fa "krb5_context context"
+.Fa "krb5_keytab keytab"
+.Fa "char *name"
+.Fa "size_t namesize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_get_type
+.Fa "krb5_context context"
+.Fa "krb5_keytab keytab"
+.Fa "char *prefix"
+.Fa "size_t prefixsize"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_next_entry
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fa "krb5_keytab_entry *entry"
+.Fa "krb5_kt_cursor *cursor"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_read_service_key
+.Fa "krb5_context context"
+.Fa "krb5_pointer keyprocarg"
+.Fa "krb5_principal principal"
+.Fa "krb5_kvno vno"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_keyblock **key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_register
+.Fa "krb5_context context"
+.Fa "const krb5_kt_ops *ops"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_remove_entry
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fa "krb5_keytab_entry *entry"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_resolve
+.Fa "krb5_context context"
+.Fa "const char *name"
+.Fa "krb5_keytab *id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_kt_start_seq_get
+.Fa "krb5_context context"
+.Fa "krb5_keytab id"
+.Fa "krb5_kt_cursor *cursor"
+.Fc
+.Sh DESCRIPTION
+A keytab name is on the form
+.Li type:residual .
+The
+.Li residual
+part is specific to each keytab-type.
+.Pp
+When a keytab-name is resolved, the type is matched with an internal
+list of keytab types. If there is no matching keytab type,
+the default keytab is used. The current default type is
+.Nm file .
+The default value can be changed in the configuration file
+.Pa /etc/kerberosV/krb5.conf
+by setting the variable 
+.Li [defaults]default_keytab_name .
+.Pp
+The keytab types that are implemented in Heimdal
+are:
+.Bl -tag -width Ds
+.It Nm file
+store the keytab in a file, the type's name is
+.Li FILE .
+The residual part is a filename.
+For compatibility with other Kerberos implemtation
+.Li WRFILE
+and
+.LI JAVA14
+is also accepted.
+.Li WRFILE
+has the same format as
+.Li FILE .
+.Li JAVA14
+have a format that is compatible with older versions of MIT kerberos
+and SUN's Java based installation.  They store a truncted kvno, so
+when the knvo excess 255, they are truncted in this format.
+.It Nm keyfile
+store the keytab in a
+.Li AFS
+keyfile (usually
+.Pa /usr/afs/etc/KeyFile ) ,
+the type's name is
+.Li AFSKEYFILE .
+The residual part is a filename.
+.It Nm krb4
+the keytab is a Kerberos 4
+.Pa srvtab
+that is on-the-fly converted to a keytab. The type's name is
+.Li krb4 .
+The residual part is a filename.
+.It Nm memory
+The keytab is stored in a memory segment. This allows sensitive and/or
+temporary data not to be stored on disk. The type's name is
+.Li MEMORY .
+There are no residual part, the only pointer back to the keytab is the
+.Fa id
+returned by
+.Fn krb5_kt_resolve .
+.El
+.Pp
+.Nm krb5_keytab_entry
+holds all data for an entry in a keytab file, like principal name,
+key-type, key, key-version number, etc.
+.Nm krb5_kt_cursor
+holds the current position that is used when iterating through a
+keytab entry with
+.Fn krb5_kt_start_seq_get ,
+.Fn krb5_kt_next_entry ,
+and
+.Fn krb5_kt_end_seq_get .
+.Pp
+.Nm krb5_kt_ops
+contains the different operations that can be done to a keytab. This
+structure is normally only used when doing a new keytab-type
+implementation.
+.Pp
+.Fn krb5_kt_resolve
+is the equivalent of an
+.Xr open 2
+on keytab. Resolve the keytab name in
+.Fa name
+into a keytab in
+.Fa id .
+Returns 0 or an error. The opposite of
+.Fn krb5_kt_resolve
+is
+.Fn krb5_kt_close .
+.Pp
+.Fn krb5_kt_close
+frees all resources allocated to the keytab.
+.Pp
+.Fn krb5_kt_default
+sets the argument
+.Fa id
+to the default keytab.
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_default_modify_name
+copies the name of the default modify keytab into
+.Fa name .
+Return 0 or KRB5_CONFIG_NOTENUFSPACE if
+.Fa namesize
+is too short.
+.Pp
+.Fn krb5_kt_default_name
+copies the name of the default keytab into
+.Fa name .
+Return 0 or KRB5_CONFIG_NOTENUFSPACE if
+.Fa namesize
+is too short.
+.Pp
+.Fn krb5_kt_add_entry
+adds a new
+.Fa entry
+to the keytab
+.Fa id .
+.Li KRB5_KT_NOWRITE
+is returned if the keytab is a readonly keytab.
+.Pp
+.Fn krb5_kt_compare
+compares the passed in
+.Fa entry
+against
+.Fa principal ,
+.Fa vno ,
+and
+.Fa enctype .
+Any of
+.Fa principal ,
+.Fa vno
+or
+.Fa enctype
+might be 0 which acts as a wildcard. Return TRUE if they compare the
+same, FALSE otherwise.
+.Pp
+.Fn krb5_kt_copy_entry_contents
+copies the contents of
+.Fa in
+into
+.Fa out .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_get_name
+retrieves the name of the keytab
+.Fa keytab
+into
+.Fa name ,
+.Fa namesize .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_get_type
+retrieves the type of the keytab
+.Fa keytab
+and store the prefix/name for type of the keytab into
+.Fa prefix ,
+.Fa prefixsize .
+The prefix will have the maximum length of
+.Dv KRB5_KT_PREFIX_MAX_LEN
+(including terminating
+.Dv NUL ) .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_free_entry
+frees the contents of
+.Fa entry .
+.Pp
+.Fn krb5_kt_start_seq_get
+sets
+.Fa cursor
+to point at the beginning of
+.Fa id .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_next_entry
+gets the next entry from
+.Fa id
+pointed to by
+.Fa cursor
+and advance the
+.Fa cursor .
+On success the returne entry must be freed with
+.Fn krb5_kt_free_entry .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_end_seq_get
+releases all resources associated with
+.Fa cursor .
+.Pp
+.Fn krb5_kt_get_entry
+retrieves the keytab entry for
+.Fa principal ,
+.Fa kvno ,
+.Fa enctype
+into
+.Fa entry
+from the keytab
+.Fa id .
+When comparing an entry in the keytab to determine a match, the
+function
+.Fn krb5_kt_compare
+is used, so the wildcard rules applies to the argument of
+.F krb5_kt_get_entry
+too.
+On success the returne entry must be freed with
+.Fn krb5_kt_free_entry .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_read_service_key
+reads the key identified by
+.Fa ( principal ,
+.Fa vno ,
+.Fa enctype )
+from the keytab in
+.Fa keyprocarg
+(the system default keytab if 
+.Dv NULL
+is used) into
+.Fa *key .
+.Fa keyprocarg
+is the same argument as to
+.Fa name
+argument to
+.Fn krb5_kt_resolve .
+Internal
+.Fn krb5_kt_compare
+will be used, so the same wildcard rules applies
+to
+.Fn krb5_kt_read_service_key .
+On success the returned key must be freed with
+.Fa krb5_free_keyblock .
+Returns 0 or an error.
+.Pp
+.Fn krb5_kt_remove_entry
+removes the entry
+.Fa entry
+from the keytab
+.Fa id .
+When comparing an entry in the keytab to determine a match, the
+function
+.Fn krb5_kt_compare
+is use, so the wildcard rules applies to the argument of
+.Fn krb5_kt_remove_entry .
+Returns 0, 
+.Dv KRB5_KT_NOTFOUND
+if not entry matched or another error.
+.Pp
+.Fn krb5_kt_register
+registers a new keytab type
+.Fa ops .
+Returns 0 or an error.
+.Sh EXAMPLES
+This is a minimalistic version of
+.Nm ktutil .
+.Pp
+.Bd -literal
+int
+main (int argc, char **argv)
+{
+    krb5_context context;
+    krb5_keytab keytab;
+    krb5_kt_cursor cursor;
+    krb5_keytab_entry entry;
+    krb5_error_code ret;
+    char *principal;
+
+    if (krb5_init_context (&context) != 0)
+       errx(1, "krb5_context");
+
+    ret = krb5_kt_default (context, &keytab);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_kt_default");
+
+    ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
+    while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
+       krb5_unparse_name_short(context, entry.principal, &principal);
+       printf("principal: %s\\n", principal);
+       free(principal);
+       krb5_kt_free_entry(context, &entry);
+    }
+    ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
+    ret = krb5_kt_close(context, keytab);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_kt_close");
+    krb5_free_context(context);
+    return 0;
+}
+.Ed
+.Sh SEE ALSO
+.Xr krb5.conf 5 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_krbhst_init.3 b/src/kerberosV/src/lib/krb5/krb5_krbhst_init.3
new file mode 100644 (file)
index 0000000..0e87719
--- /dev/null
@@ -0,0 +1,174 @@
+.\" Copyright (c) 2001-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_krbhst_init.3,v 1.12 2005/05/10 09:21:02 lha Exp $
+.\"
+.Dd May 10, 2005
+.Dt KRB5_KRBHST_INIT 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_krbhst_init ,
+.Nm krb5_krbhst_init_flags ,
+.Nm krb5_krbhst_next ,
+.Nm krb5_krbhst_next_as_string ,
+.Nm krb5_krbhst_reset ,
+.Nm krb5_krbhst_free ,
+.Nm krb5_krbhst_format_string ,
+.Nm krb5_krbhst_get_addrinfo
+.Nd lookup Kerberos KDC hosts
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_krbhst_init "krb5_context context" "const char *realm" "unsigned int type" "krb5_krbhst_handle *handle"
+.Ft krb5_error_code
+.Fn krb5_krbhst_init_flags "krb5_context context" "const char *realm" "unsigned int type" "int flags" "krb5_krbhst_handle *handle"
+.Ft krb5_error_code
+.Fn "krb5_krbhst_next" "krb5_context context" "krb5_krbhst_handle handle" "krb5_krbhst_info **host"
+.Ft krb5_error_code
+.Fn krb5_krbhst_next_as_string "krb5_context context" "krb5_krbhst_handle handle" "char *hostname" "size_t hostlen"
+.Ft void
+.Fn krb5_krbhst_reset "krb5_context context" "krb5_krbhst_handle handle"
+.Ft void
+.Fn krb5_krbhst_free "krb5_context context" "krb5_krbhst_handle handle"
+.Ft krb5_error_code
+.Fn krb5_krbhst_format_string "krb5_context context" "const krb5_krbhst_info *host" "char *hostname" "size_t hostlen"
+.Ft krb5_error_code
+.Fn krb5_krbhst_get_addrinfo "krb5_context context" "krb5_krbhst_info *host" "struct addrinfo **ai"
+.Sh DESCRIPTION
+These functions are used to sequence through all Kerberos hosts of a
+particular realm and service. The service type can be the KDCs, the
+administrative servers, the password changing servers, or the servers
+for Kerberos 4 ticket conversion.
+.Pp
+First a handle to a particular service is obtained by calling
+.Fn krb5_krbhst_init
+(or
+.Fn krb5_krbhst_init_flags )
+with the
+.Fa realm
+of interest and the type of service to lookup. The
+.Fa type
+can be one of:
+.Pp
+.Bl -tag -width Ds -compact -offset indent
+.It KRB5_KRBHST_KDC
+.It KRB5_KRBHST_ADMIN
+.It KRB5_KRBHST_CHANGEPW
+.It KRB5_KRBHST_KRB524
+.El
+.Pp
+The
+.Fa handle
+is returned to the caller, and should be passed to the other
+functions.
+.Pp
+The
+.Fa flag
+argument to
+.Nm krb5_krbhst_init_flags
+is the same flags as
+.Fn krb5_send_to_kdc_flags
+uses.
+Possible values are:
+.Pp
+.Bl -tag -width KRB5_KRBHST_FLAGS_LARGE_MSG -compact -offset indent
+.It KRB5_KRBHST_FLAGS_MASTER
+only talk to master (readwrite) KDC
+.It KRB5_KRBHST_FLAGS_LARGE_MSG
+this is a large message, so use transport that can handle that.
+.El
+.Pp
+For each call to
+.Fn krb5_krbhst_next
+information on a new host is returned. The former function returns in
+.Fa host
+a pointer to a structure containing information about the host, such
+as protocol, hostname, and port:
+.Bd -literal -offset indent
+typedef struct krb5_krbhst_info {
+    enum { KRB5_KRBHST_UDP,
+          KRB5_KRBHST_TCP,
+          KRB5_KRBHST_HTTP } proto;
+    unsigned short port;
+    struct addrinfo *ai;
+    struct krb5_krbhst_info *next;
+    char hostname[1];
+} krb5_krbhst_info;
+.Ed
+.Pp
+The related function,
+.Fn krb5_krbhst_next_as_string ,
+return the same information as a URL-like string.
+.Pp
+When there are no more hosts, these functions return
+.Dv KRB5_KDC_UNREACH .
+.Pp
+To re-iterate over all hosts, call
+.Fn krb5_krbhst_reset
+and the next call to
+.Fn krb5_krbhst_next
+will return the first host.
+.Pp
+When done with the handle,
+.Fn krb5_krbhst_free
+should be called.
+.Pp
+To use a
+.Va krb5_krbhst_info ,
+there are two functions:
+.Fn krb5_krbhst_format_string
+that will return a printable representation of that struct
+and
+.Fn krb5_krbhst_get_addrinfo
+that will return a
+.Va struct addrinfo
+that can then be used for communicating with the server mentioned.
+.Sh EXAMPLES
+The following code will print the KDCs of the realm
+.Dq MY.REALM :
+.Bd -literal -offset indent
+krb5_krbhst_handle handle;
+char host[MAXHOSTNAMELEN];
+krb5_krbhst_init(context, "MY.REALM", KRB5_KRBHST_KDC, &handle);
+while(krb5_krbhst_next_as_string(context, handle,
+                                host, sizeof(host)) == 0)
+    printf("%s\\n", host);
+krb5_krbhst_free(context, handle);
+.Ed
+.\" .Sh BUGS
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr krb5_get_krbhst 3 ,
+.Xr krb5_send_to_kdc_flags 3
+.Sh HISTORY
+These functions first appeared in Heimdal 0.3g.
diff --git a/src/kerberosV/src/lib/krb5/krb5_kuserok.3 b/src/kerberosV/src/lib/krb5/krb5_kuserok.3
new file mode 100644 (file)
index 0000000..2f9ac18
--- /dev/null
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2003-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_kuserok.3,v 1.9 2005/05/04 12:11:22 joda Exp $
+.\"
+.Dd May 4, 2005
+.Dt KRB5_KUSEROK 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_kuserok
+.Nd "checks if a principal is permitted to login as a user"
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_boolean
+.Fo krb5_kuserok
+.Fa "krb5_context context"
+.Fa "krb5_principal principal"
+.Fa "const char *user"
+.Fc
+.Sh DESCRIPTION
+This function takes the name of a local
+.Fa user
+and checks if
+.Fa principal
+is allowed to log in as that user.
+.Pp
+The
+.Fa user
+may have a
+.Pa ~/.k5login
+file listing principals that are allowed to login as that user. If
+that file does not exist, all principals with a first component
+identical to the username, and a realm considered local, are allowed
+access.
+.Pp
+The
+.Pa .k5login
+file must contain one principal per line, be owned by
+.Fa user ,
+and not be writable by group or other (but must be readable by
+anyone).
+.Pp
+Note that if the file exists, no implicit access rights are given to
+.Fa user Ns @ Ns Aq localrealm .
+.Pp
+Optionally, a set of files may be put in 
+.Pa ~/.k5login.d ( Ns
+a directory), in which case they will all be checked in the same
+manner as
+.Pa .k5login .
+The files may be called anything, but files starting with a hash
+.Dq ( # ) ,
+or ending with a tilde
+.Dq ( ~ )
+are ignored. Subdirectories are not traversed. Note that this
+directory may not be checked by other implementations.
+.Sh RETURN VALUES
+.Nm
+returns
+.Dv TRUE
+if access should be granted,
+.Dv FALSE
+otherwise.
+.Sh HISTORY
+The
+.Pa ~/.k5login.d
+feature appeared in Heimdal 0.7.
+.Sh SEE ALSO
+.Xr krb5_get_default_realms 3 ,
+.Xr krb5_verify_user 3 ,
+.Xr krb5_verify_user_lrealm 3 ,
+.Xr krb5_verify_user_opt 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_locl.h b/src/kerberosV/src/lib/krb5/krb5_locl.h
new file mode 100644 (file)
index 0000000..95d4ceb
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: krb5_locl.h,v 1.81 2005/05/29 14:28:39 lha Exp $ */
+
+#ifndef __KRB5_LOCL_H__
+#define __KRB5_LOCL_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_PWD_H
+#undef _POSIX_PTHREAD_SEMANTICS
+/* This gets us the 5-arg getpwnam_r on Solaris 9.  */
+#define _POSIX_PTHREAD_SEMANTICS
+#include <pwd.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef _AIX
+struct ether_addr;
+struct mbuf;
+struct sockaddr_dl;
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_SYS_FILIO_H
+#include <sys/filio.h>
+#endif
+#ifdef HAVE_SYS_FILE_H
+#include <sys/file.h>
+#endif
+
+#ifdef HAVE_CRYPT_H
+#undef des_encrypt
+#define des_encrypt wingless_pigs_mostly_fail_to_fly
+#include <crypt.h>
+#undef des_encrypt
+#endif
+
+#ifdef HAVE_DOOR_CREATE
+#include <door.h>
+#endif
+
+#include <roken.h>
+#include <parse_time.h>
+#include <base64.h>
+
+#include "crypto-headers.h"
+
+
+#include <krb5_asn1.h>
+
+/* XXX glue for pkinit */
+struct krb5_pk_identity;
+struct krb5_pk_cert;
+struct ContentInfo;
+typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx;
+
+/* v4 glue */
+struct _krb5_krb_auth_data;
+
+#include <der.h>
+
+#include <krb5.h>
+#include <krb5_err.h>
+#include <asn1_err.h>
+#include <krb5-private.h>
+
+#include "heim_threads.h"
+
+#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
+#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
+
+/* should this be public? */
+
+#define KEYTAB_DEFAULT "ANY:FILE:/etc/kerberosV/krb5.keytab"
+#define KEYTAB_DEFAULT_MODIFY "FILE:/etc/kerberosV/krb5.keytab"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#define KRB5_BUFSIZ 1024
+
+typedef enum {
+    KRB5_PA_PAC_DONT_CARE = 0, 
+    KRB5_PA_PAC_REQ_TRUE,
+    KRB5_PA_PAC_REQ_FALSE
+} krb5_get_init_creds_req_pac;
+
+struct _krb5_get_init_creds_opt_private {
+    int refcount;
+    /* ENC_TIMESTAMP */
+    const char *password;
+    krb5_s2k_proc key_proc;
+    /* PA_PAC_REQUEST */
+    krb5_get_init_creds_req_pac req_pac;
+    /* PKINIT */
+    krb5_pk_init_ctx pk_init_ctx;
+    int canonicalize;
+};
+
+#endif /* __KRB5_LOCL_H__ */
diff --git a/src/kerberosV/src/lib/krb5/krb5_mk_safe.3 b/src/kerberosV/src/lib/krb5/krb5_mk_safe.3
new file mode 100644 (file)
index 0000000..1e74c5b
--- /dev/null
@@ -0,0 +1,82 @@
+.\" Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_mk_safe.3,v 1.2 2003/05/26 14:08:59 lha Exp $
+.\"
+.Dd April 25, 2003
+.Dt KRB5_MK_SAFE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_mk_safe ,
+.Nm krb5_mk_priv
+.Nd generates integrity protected and/or encrypted messages
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fn krb5_mk_priv "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *userdata" "krb5_data *outbuf" "krb5_replay_data *outdata"
+.Ft krb5_error_code
+.Fn krb5_mk_safe "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *userdata" "krb5_data *outbuf" "krb5_replay_data *outdata"
+.Sh DESCRIPTION
+.Fn krb5_mk_safe
+and
+.Fn krb5_mk_priv
+formats
+.Li KRB-SAFE
+(integrity protected)
+and
+.Li KRB-PRIV
+(also encrypted)
+messages into
+.Fa outbuf .
+The actual message data is taken from
+.Fa userdata .
+If the
+.Dv KRB5_AUTH_CONTEXT_DO_SEQUENCE
+or
+.Dv KRB5_AUTH_CONTEXT_DO_TIME
+flags are set in the
+.Fa auth_context ,
+sequence numbers and time stamps are generated.
+If the
+.Dv KRB5_AUTH_CONTEXT_RET_SEQUENCE
+or
+.Dv KRB5_AUTH_CONTEXT_RET_TIME
+flags are set
+they are also returned in the
+.Fa outdata
+parameter.
+.Sh SEE ALSO
+.Xr krb5_auth_con_init 3 ,
+.Xr krb5_rd_priv 3 ,
+.Xr krb5_rd_safe 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_openlog.3 b/src/kerberosV/src/lib/krb5/krb5_openlog.3
new file mode 100644 (file)
index 0000000..59126f2
--- /dev/null
@@ -0,0 +1,242 @@
+.\" Copyright (c) 1997, 1999, 2001 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_openlog.3,v 1.11 2003/05/26 14:09:00 lha Exp $
+.Dd August 6, 1997
+.Dt KRB5_OPENLOG 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_initlog ,
+.Nm krb5_openlog ,
+.Nm krb5_closelog ,
+.Nm krb5_addlog_dest ,
+.Nm krb5_addlog_func ,
+.Nm krb5_log ,
+.Nm krb5_vlog ,
+.Nm krb5_log_msg ,
+.Nm krb5_vlog_msg
+.Nd Heimdal logging functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft "typedef void"
+.Fn "\*(lp*krb5_log_log_func_t\*(rp" "const char *time" "const char *message" "void *data"
+.Ft "typedef void"
+.Fn "\*(lp*krb5_log_close_func_t\*(rp" "void *data"
+.Ft krb5_error_code
+.Fn krb5_addlog_dest "krb5_context context" "krb5_log_facility *facility" "const char *destination"
+.Ft krb5_error_code
+.Fn krb5_addlog_func "krb5_context context" "krb5_log_facility *facility" "int min" "int max" "krb5_log_log_func_t log" "krb5_log_close_func_t close" "void *data"
+.Ft krb5_error_code
+.Fn krb5_closelog "krb5_context context" "krb5_log_facility *facility"
+.Ft krb5_error_code
+.Fn krb5_initlog "krb5_context context" "const char *program" "krb5_log_facility **facility"
+.Ft krb5_error_code
+.Fn krb5_log "krb5_context context" "krb5_log_facility *facility" "int level" "const char *format" "..."
+.Ft krb5_error_code
+.Fn krb5_log_msg "krb5_context context" "krb5_log_facility *facility" "char **reply" "int level" "const char *format" "..."
+.Ft krb5_error_code
+.Fn krb5_openlog "krb5_context context" "const char *program" "krb5_log_facility **facility"
+.Ft krb5_error_code
+.Fn krb5_vlog "krb5_context context" "krb5_log_facility *facility" "int level" "const char *format" "va_list arglist"
+.Ft krb5_error_code
+.Fn krb5_vlog_msg "krb5_context context" "krb5_log_facility *facility" "char **reply" "int level" "const char *format" "va_list arglist"
+.Sh DESCRIPTION
+These functions logs messages to one or more destinations.
+.Pp
+The
+.Fn krb5_openlog
+function creates a logging
+.Fa facility ,
+that is used to log messages. A facility consists of one or more
+destinations (which can be files or syslog or some other device). The
+.Fa program
+parameter should be the generic name of the program that is doing the
+logging. This name is used to lookup which destinations to use. This
+information is contained in the
+.Li logging
+section of the
+.Pa krb5.conf
+configuration file.  If no entry is found for
+.Fa program ,
+the entry for
+.Li default
+is used, or if that is missing too,
+.Li SYSLOG
+will be used as destination.
+.Pp
+To close a logging facility, use the
+.Fn krb5_closelog
+function.
+.Pp
+To log a message to a facility use one of the functions
+.Fn krb5_log ,
+.Fn krb5_log_msg ,
+.Fn krb5_vlog ,
+or
+.Fn krb5_vlog_msg .
+The functions ending in
+.Li _msg
+return in
+.Fa reply
+a pointer to the message that just got logged. This string is allocated,
+and should be freed with
+.Fn free .
+The
+.Fa format
+is a standard
+.Fn printf
+style format string (but see the BUGS section).
+.Pp
+If you want better control of where things gets logged, you can instead of using
+.Fn krb5_openlog
+call
+.Fn krb5_initlog ,
+which just initializes a facility, but doesn't define any actual logging
+destinations. You can then add destinations with the
+.Fn krb5_addlog_dest
+and
+.Fn krb5_addlog_func
+functions.  The first of these takes a string specifying a logging
+destination, and adds this to the facility. If you want to do some
+non-standard logging you can use the
+.Fn krb5_addlog_func
+function, which takes a function to use when logging.
+The
+.Fa log
+function is called for each message with
+.Fa time
+being a string specifying the current time, and
+.Fa message
+the message to log.
+.Fa close
+is called when the facility is closed. You can pass application specific data in the
+.Fa data
+parameter. The
+.Fa min
+and
+.Fa max
+parameter are the same as in a destination (defined below). To specify a
+max of infinity, pass -1.
+.Pp
+.Fn krb5_openlog
+calls
+.Fn krb5_initlog
+and then calls
+.Fn krb5_addlog_dest
+for each destination found.
+.Ss Destinations
+The defined destinations (as specified in
+.Pa krb5.conf )
+follows:
+.Bl -tag -width "xxx" -offset indent
+.It Li STDERR
+This logs to the program's stderr.
+.It Li FILE: Ns Pa /file
+.It Li FILE= Ns Pa /file
+Log to the specified file. The form using a colon appends to the file, the
+form with an equal truncates the file. The truncating form keeps the file
+open, while the appending form closes it after each log message (which
+makes it possible to rotate logs). The truncating form is mainly for
+compatibility with the MIT libkrb5.
+.It Li DEVICE= Ns Pa /device
+This logs to the specified device, at present this is the same as
+.Li FILE:/device .
+.It Li CONSOLE
+Log to the console, this is the same as
+.Li DEVICE=/dev/console .
+.It Li SYSLOG Ns Op :priority Ns Op :facility
+Send messages to the syslog system, using priority, and facility. To
+get the name for one of these, you take the name of the macro passed
+to
+.Xr syslog 3 ,
+and remove the leading
+.Li LOG_
+.No ( Li LOG_NOTICE
+becomes
+.Li NOTICE ) .
+The default values (as well as the values used for unrecognised
+values), are
+.Li ERR ,
+and
+.Li AUTH ,
+respectively.  See
+.Xr syslog 3
+for a list of priorities and facilities.
+.El
+.Pp
+Each destination may optionally be prepended with a range of logging
+levels, specified as
+.Li min-max/ .
+If the
+.Fa level
+parameter to
+.Fn krb5_log
+is within this range (inclusive) the message gets logged to this
+destination, otherwise not. Either of the min and max valued may be
+omitted, in this case min is assumed to be zero, and max is assumed to be
+infinity.  If you don't include a dash, both min and max gets set to the
+specified value. If no range is specified, all messages gets logged.
+.Sh EXAMPLES
+.Bd -literal -offset indent
+[logging]
+       kdc = 0/FILE:/var/log/kdc.log
+       kdc = 1-/SYSLOG:INFO:USER
+       default = STDERR
+.Ed
+.Pp
+This will log all messages from the
+.Nm kdc
+program with level 0 to
+.Pa /var/log/kdc.log ,
+other messages will be logged to syslog with priority
+.Li LOG_INFO ,
+and facility
+.Li LOG_USER .
+All other programs will log all messages to their stderr.
+.Sh SEE ALSO
+.Xr syslog 3 ,
+.Xr krb5.conf 5
+.Sh BUGS
+These functions use
+.Fn asprintf
+to format the message. If your operating system does not have a working
+.Fn asprintf ,
+a replacement will be used. At present this replacement does not handle
+some correct conversion specifications (like floating point numbers). Until
+this is fixed, the use of these conversions should be avoided.
+.Pp
+If logging is done to the syslog facility, these functions might not be
+thread-safe, depending on the implementation of
+.Fn openlog ,
+and
+.Fn syslog .
diff --git a/src/kerberosV/src/lib/krb5/krb5_parse_name.3 b/src/kerberosV/src/lib/krb5/krb5_parse_name.3
new file mode 100644 (file)
index 0000000..c48365f
--- /dev/null
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_parse_name.3,v 1.9 2003/05/26 14:09:00 lha Exp $
+.\"
+.Dd August 8, 1997
+.Dt KRB5_PARSE_NAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_parse_name
+.Nd string to principal conversion
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_parse_name "krb5_context context" "const char *name" "krb5_principal *principal"
+.Sh DESCRIPTION
+.Fn krb5_parse_name
+converts a string representation of a principal name to
+.Nm krb5_principal .
+The
+.Fa principal
+will point to allocated data that should be freed with
+.Fn krb5_free_principal .
+.Pp
+The string should consist of one or more name components separated with slashes
+.Pq Dq / ,
+optionally followed with an
+.Dq @
+and a realm name. A slash or @ may be contained in a name component by
+quoting it with a backslash
+.Pq Dq \e .
+A realm should not contain slashes or colons.
+.Sh SEE ALSO
+.Xr krb5_425_conv_principal 3 ,
+.Xr krb5_build_principal 3 ,
+.Xr krb5_free_principal 3 ,
+.Xr krb5_sname_to_principal 3 ,
+.Xr krb5_unparse_name 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_principal.3 b/src/kerberosV/src/lib/krb5/krb5_principal.3
new file mode 100644 (file)
index 0000000..5bc522f
--- /dev/null
@@ -0,0 +1,332 @@
+.\" Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_principal.3,v 1.7 2005/05/29 21:58:36 lha Exp $
+.\"
+.Dd May 29, 2005
+.Dt KRB5_PRINCIPAL 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_get_default_principal ,
+.Nm krb5_principal ,
+.Nm krb5_build_principal ,
+.Nm krb5_build_principal_ext ,
+.Nm krb5_build_principal_va ,
+.Nm krb5_build_principal_va_ext ,
+.Nm krb5_copy_principal ,
+.Nm krb5_free_principal ,
+.Nm krb5_make_principal ,
+.Nm krb5_parse_name ,
+.Nm krb5_princ_realm ,
+.Nm krb5_princ_set_realm ,
+.Nm krb5_principal_compare ,
+.Nm krb5_principal_compare_any_realm ,
+.Nm krb5_principal_get_comp_string ,
+.Nm krb5_principal_get_realm ,
+.Nm krb5_principal_get_type ,
+.Nm krb5_principal_match ,
+.Nm krb5_principal_set_type ,
+.Nm krb5_realm_compare ,
+.Nm krb5_sname_to_principal ,
+.Nm krb5_sock_to_principal ,
+.Nm krb5_unparse_name ,
+.Nm krb5_unparse_name_fixed ,
+.Nm krb5_unparse_name_fixed_short ,
+.Nm krb5_unparse_name_short
+.Nd Kerberos 5 principal handling functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li krb5_principal ;
+.Ft void
+.Fn krb5_free_principal "krb5_context context" "krb5_principal principal"
+.Ft krb5_error_code
+.Fn krb5_parse_name "krb5_context context" "const char *name" "krb5_principal *principal"
+.Ft krb5_error_code
+.Fn "krb5_unparse_name" "krb5_context context" "krb5_const_principal principal" "char **name"
+.Ft krb5_error_code
+.Fn krb5_unparse_name_fixed "krb5_context context" "krb5_const_principal principal" "char *name" "size_t len"
+.Ft krb5_error_code
+.Fn "krb5_unparse_name_short" "krb5_context context" "krb5_const_principal principal" "char **name"
+.Ft krb5_error_code
+.Fn krb5_unparse_name_fixed_short "krb5_context context" "krb5_const_principal principal" "char *name" "size_t len"
+.Ft krb5_realm *
+.Fn krb5_princ_realm "krb5_context context" "krb5_principal principal"
+.Ft void
+.Fn krb5_princ_set_realm "krb5_context context" "krb5_principal principal" "krb5_realm *realm"
+.Ft krb5_error_code
+.Fn krb5_build_principal "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "..."
+.Ft krb5_error_code
+.Fn krb5_build_principal_va "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "va_list ap"
+.Ft krb5_error_code
+.Fn "krb5_build_principal_ext" "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "..."
+.Ft krb5_error_code
+.Fn krb5_build_principal_va_ext "krb5_context context" "krb5_principal *principal" "int rlen" "krb5_const_realm realm" "va_list ap"
+.Ft krb5_error_code
+.Fn krb5_make_principal "krb5_context context" "krb5_principal *principal" "krb5_const_realm realm" "..."
+.Ft krb5_error_code
+.Fn krb5_copy_principal "krb5_context context" "krb5_const_principal inprinc" "krb5_principal *outprinc"
+.Ft krb5_boolean
+.Fn krb5_principal_compare "krb5_context context" "krb5_const_principal princ1" "krb5_const_principal princ2"
+.Ft krb5_boolean
+.Fn krb5_principal_compare_any_realm "krb5_context context" "krb5_const_principal princ1 "krb5_const_principal princ2"
+.Ft "const char *"
+.Fn krb5_principal_get_comp_string "krb5_context context" "krb5_principal principal" "unsigned int component"
+.Ft "const char *"
+.Fn krb5_principal_get_realm "krb5_context context" "krb5_principal principal"
+.Ft int
+.Fn krb5_principal_get_type "krb5_context context" "krb5_principal principal"
+.Ft krb5_boolean
+.Fn krb5_principal_match "krb5_context context" "krb5_const_principal principal" "krb5_const_principal pattern"
+.Ft void
+.Fn krb5_principal_set_type "krb5_context context" "krb5_principal principal" "int type"
+.Ft krb5_boolean
+.Fn krb5_realm_compare "krb5_context context" "krb5_const_principal princ1" "krb5_const_principal princ2"
+.Ft krb5_error_code
+.Fn krb5_sname_to_principal  "krb5_context context" "const char *hostname" "const char *sname" "int32_t type" "krb5_principal *ret_princ"
+.Ft krb5_error_code
+.Fn krb5_sock_to_principal "krb5_context context" "int socket" "const char *sname" "int32_t type" "krb5_principal *principal"
+.Ft krb5_error_code
+.Fn krb5_get_default_principal "krb5_context context" "krb5_principal *princ"
+.Sh DESCRIPTION
+.Li krb5_principal
+holds the name of a user or service in Kerberos.
+.Pp
+A principal has two parts, a
+.Li PrincipalName
+and a
+.Li realm .
+The PrincipalName consists of one or more components. In printed form,
+the components are separated by /.
+The PrincipalName also has a name-type.
+.Pp
+Examples of a principal are
+.Li nisse/root@EXAMPLE.COM
+and
+.Li host/datan.kth.se@KTH.SE .
+.Fn krb5_parse_name
+passes a principal name in
+.Fa name
+to the kerberos principal structure.
+.Pp
+.Fn krb5_unparse_name
+prints the principal
+.Fa princ
+to the string
+.Fa name .
+.Fa name
+should be freed with
+.Xr free 3 .
+.Fn krb5_unparse_name_fixed
+behaves just like
+.Fn krb5_unparse ,
+but instead unparses the principal into a fixed size buffer.
+.Pp
+.Fn krb5_unparse_name_short
+just returns the principal without the realm if the principal is
+in the default realm. If the principal isn't, the full name is
+returned.
+.Fn krb5_unparse_name_fixed_short
+works just like
+.Fn krb5_unparse_name_short
+but on a fixed size buffer.
+.Pp
+.Fn krb5_build_principal
+builds a principal from the realm
+.Fa realm
+that has the length
+.Fa rlen .
+The following arguments form the components of the principal.
+The list of components is terminated with
+.Dv NULL .
+.Pp
+.Fn krb5_build_principal_va
+works like
+.Fn krb5_build_principal
+using vargs.
+.Pp
+.Fn krb5_build_principal_ext
+and
+.Fn krb5_build_principal_va_ext
+take a list of length-value pairs, the list is terminated with a zero
+length.
+.Pp
+.Fn krb5_make_principal
+works the same way as
+.Fn krb5_build_principal ,
+except it figures out the length of the realm itself.
+.Pp
+.Fn krb5_copy_principal
+makes a copy of a principal.
+The copy needs to be freed with
+.Fn krb5_free_principal .
+.Pp
+.Fn krb5_principal_compare
+compares the two principals, including realm of the principals and returns
+.Dv TRUE
+if they are the same and
+.Dv FALSE
+if not.
+.Pp
+.Fn krb5_principal_compare_any_realm
+works the same way as
+.Fn krb5_principal_compare
+but doesn't compare the realm component of the principal.
+.Pp
+.Fn krb5_realm_compare
+compares the realms of the two principals and returns
+.Dv TRUE
+is they are the same, and
+.Dv FALSE
+if not.
+.Pp
+.Fn krb5_principal_match
+matches a
+.Fa principal
+against a
+.Fa pattern .
+The pattern is a globbing expression, where each component (separated
+by /) is matched against the corresponding component of the principal.
+.Pp
+The
+.Fn krb5_principal_get_realm
+and
+.Fn krb5_principal_get_comp_string
+functions return parts of the
+.Fa principal ,
+either the realm or a specific component.
+Both functions return string pointers to data inside the principal, so
+they are valid only as long as the principal exists.
+.Pp
+The
+.Fa component
+argument to
+.Fn krb5_principal_get_comp_string
+is the index of the component to return, from zero to the total number of
+components minus one. If the index is out of range
+.Dv NULL
+is returned.
+.Pp
+.Fn krb5_principal_get_realm
+and
+.Fn krb5_principal_get_comp_string
+are replacements for
+.Fn krb5_princ_realm ,
+.Fn krb5_princ_component
+and related macros, described as internal in the MIT API
+specification.
+Unlike the macros, these functions return strings, not
+.Dv krb5_data .
+A reason to return
+.Dv krb5_data
+was that it was believed that principal components could contain
+binary data, but this belief was unfounded, and it has been decided
+that principal components are infact UTF8, so it's safe to use zero
+terminated strings.
+.Pp
+It's generally not necessary to look at the components of a principal.
+.Pp
+.Fn krb5_principal_get_type
+and
+.Fn krb5_principal_set_type
+get and sets the name type for a principal.
+Name type handling is tricky and not often needed,
+don't use this unless you know what you do.
+.Pp
+.Fn krb5_princ_realm
+returns the realm component of the principal.
+The caller must not free realm unless
+.Fn krb5_princ_set_realm
+is called to set a new realm after freeing the realm.
+.Fn krb5_princ_set_realm
+sets the realm component of a principal. The old realm is not freed.
+.Pp
+.Fn krb5_sname_to_principal
+and
+.Fn krb5_sock_to_principal
+are for easy creation of
+.Dq service
+principals that can, for instance, be used to lookup a key in a keytab.
+For both functions the
+.Fa sname
+parameter will be used for the first component of the created principal.
+If
+.Fa sname
+is
+.Dv NULL ,
+.Dq host
+will be used instead.
+.Pp
+.Fn krb5_sname_to_principal
+will use the passed
+.Fa hostname
+for the second component.
+If
+.Fa type
+is
+.Dv KRB5_NT_SRV_HST
+this name will be looked up with
+.Fn gethostbyname .
+If
+.Fa hostname
+is
+.Dv NULL ,
+the local hostname will be used.
+.Pp
+.Fn krb5_sock_to_principal
+will use the
+.Dq sockname
+of the passed
+.Fa socket ,
+which should be a bound
+.Dv AF_INET
+or
+.Dv AF_INET6
+socket.
+There must be a mapping between the address and
+.Dq sockname .
+The function may try to resolve the name in DNS.
+.Pp
+.Fn krb5_get_default_principal
+tries to find out what's a reasonable default principal by looking at
+the environment it is running in.
+.\" .Sh EXAMPLES
+.Sh SEE ALSO
+.Xr krb5_425_conv_principal 3 ,
+.Xr krb5_config 3 ,
+.Xr krb5.conf 5
+.Sh BUGS
+You can not have a NUL in a component in some of the variable argument
+functions above.
+Until someone can give a good example of where it would be a good idea
+to have NUL's in a component, this will not be fixed.
diff --git a/src/kerberosV/src/lib/krb5/krb5_rcache.3 b/src/kerberosV/src/lib/krb5/krb5_rcache.3
new file mode 100644 (file)
index 0000000..a854c54
--- /dev/null
@@ -0,0 +1,163 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_rcache.3,v 1.2 2004/03/21 18:14:33 lha Exp $
+.\"
+.Dd March 21, 2004
+.Dt KRB5_RCACHE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_rcache ,
+.Nm krb5_rc_close ,
+.Nm krb5_rc_default ,
+.Nm krb5_rc_default_name ,
+.Nm krb5_rc_default_type ,
+.Nm krb5_rc_destroy ,
+.Nm krb5_rc_expunge ,
+.Nm krb5_rc_get_lifespan ,
+.Nm krb5_rc_get_name ,
+.Nm krb5_rc_get_type ,
+.Nm krb5_rc_initialize ,
+.Nm krb5_rc_recover ,
+.Nm krb5_rc_resolve ,
+.Nm krb5_rc_resolve_full ,
+.Nm krb5_rc_resolve_type ,
+.Nm krb5_rc_store ,
+.Nm krb5_get_server_rcache
+.Nd Kerberos 5 replay cache
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "struct krb5_rcache;"
+.Pp
+.Ft krb5_error_code
+.Fo krb5_rc_close
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_default
+.Fa "krb5_context context"
+.Fa "krb5_rcache *id"
+.Fc
+.Ft "const char *"
+.Fo krb5_rc_default_name
+.Fa "krb5_context context"
+.Fc
+.Ft "const char *"
+.Fo krb5_rc_default_type
+.Fa "krb5_context context"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_destroy
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_expunge
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_get_lifespan
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fa "krb5_deltat *auth_lifespan"
+.Fc
+.Ft "const char*"
+.Fo krb5_rc_get_name
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fc
+.Ft "const char*"
+.Fo "krb5_rc_get_type"
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_initialize
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fa "krb5_deltat auth_lifespan"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_recover
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_resolve
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fa "const char *name"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_resolve_full
+.Fa "krb5_context context"
+.Fa "krb5_rcache *id"
+.Fa "const char *string_name"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_resolve_type
+.Fa "krb5_context context"
+.Fa "krb5_rcache *id"
+.Fa "const char *type"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_rc_store
+.Fa "krb5_context context"
+.Fa "krb5_rcache id"
+.Fa "krb5_donot_replay *rep"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_server_rcache
+.Fa "krb5_context context"
+.Fa "const krb5_data *piece"
+.Fa "krb5_rcache *id"
+.Fc
+.Sh DESCRIPTION
+The
+.Li krb5_rcache
+structure holds a storage element that is used for data manipulation.
+The structure contains no public accessible elements.
+.Pp
+.Fn krb5_rc_initialize
+Creates the reply cache
+.Fa id
+and sets it lifespan to
+.Fa auth_lifespan .
+If the cache already exists, the content is destroyed.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_data 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_rd_error.3 b/src/kerberosV/src/lib/krb5/krb5_rd_error.3
new file mode 100644 (file)
index 0000000..12e2b58
--- /dev/null
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_rd_error.3,v 1.1 2004/07/26 14:29:03 lha Exp $
+.\"
+.Dd July 26, 2004
+.Dt KRB5_RD_ERROR 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_rd_error ,
+.Nm krb5_free_error ,
+.Nm krb5_free_error_contents ,
+.Nm krb5_error_from_rd_error
+.Nd parse, free and read error from KRB-ERROR message
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_rd_error
+.Fa "krb5_context context"
+.Fa "krb5_data *msg"
+.Fa "KRB_ERROR *result"
+.Fc
+.Ft void
+.Fo krb5_free_error
+.Fa "krb5_context context"
+.Fa "krb5_error *error"
+.Fc
+.Ft void
+.Fo krb5_free_error_contents
+.Fa "krb5_context context"
+.Fa "krb5_error *error"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_error_from_rd_error
+.Fa "krb5_context context"
+.Fa "const krb5_error *error"
+.Fa "const krb5_creds *creds"
+.Fc
+.Sh DESCRIPTION
+Usually applications never needs to parse and understand Kerberos
+error messages since higher level functions will parse and push up the
+error in the krb5_context.
+These functions are described for completeness.
+.Pp
+.Fn krb5_rd_error
+parses and returns the kerboeros error message, the structure should be freed with
+.Fn krb5_free_error_contents
+when the caller is done with the structure.
+.Pp
+.Fn krb5_free_error
+frees the content and the memory region holding the structure iself.
+.Pp
+.Fn krb5_free_error_contents
+free the content of the KRB-ERROR message.
+.Pp
+.Fn krb5_error_from_rd_error
+will parse the error message and set the error buffer in krb5_context
+to the error string passed back or the matching error code in the
+KRB-ERROR message.
+Caller should pick up the message with
+.Fn krb5_get_error_string 3
+(don't forget to free the returned string with
+.Fn krb5_free_error_string ) .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_set_error_string 3 ,
+.Xr krb5_get_error_string 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_rd_safe.3 b/src/kerberosV/src/lib/krb5/krb5_rd_safe.3
new file mode 100644 (file)
index 0000000..5d2d4af
--- /dev/null
@@ -0,0 +1,81 @@
+.\" Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_rd_safe.3,v 1.2 2003/05/26 14:09:01 lha Exp $
+.\"
+.Dd April 25, 2003
+.Dt KRB5_RD_SAFE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_rd_safe ,
+.Nm krb5_rd_priv
+.Nd verifies authenticity of messages
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Ft krb5_error_code
+.Fn krb5_rd_priv "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *inbuf" "krb5_data *outbuf" "krb5_replay_data *outdata"
+.Ft krb5_error_code
+.Fn krb5_rd_safe "krb5_context context" "krb5_auth_context auth_context" "const krb5_data *inbuf" "krb5_data *outbuf" "krb5_replay_data *outdata"
+.Sh DESCRIPTION
+.Fn krb5_rd_safe
+and
+.Fn krb5_rd_priv
+parses
+.Li KRB-SAFE
+and
+.Li KRB-PRIV
+messages (as generated by
+.Xr krb5_mk_safe 3
+and
+.Xr krb5_mk_priv 3 )
+from
+.Fa inbuf
+and verifies its integrity. The user data part of the message in put
+in
+.Fa outbuf .
+The encryption state, including keyblocks and addresses, is taken from
+.Fa auth_context .
+If the
+.Dv KRB5_AUTH_CONTEXT_RET_SEQUENCE
+or
+.Dv KRB5_AUTH_CONTEXT_RET_TIME
+flags are set in the
+.Fa auth_context
+the sequence number and time are returned in the
+.Fa outdata
+parameter.
+.Sh SEE ALSO
+.Xr krb5_auth_con_init 3 ,
+.Xr krb5_mk_priv 3 ,
+.Xr krb5_mk_safe 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_set_default_realm.3 b/src/kerberosV/src/lib/krb5/krb5_set_default_realm.3
new file mode 100644 (file)
index 0000000..532feb2
--- /dev/null
@@ -0,0 +1,164 @@
+.\" Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_set_default_realm.3,v 1.8 2005/04/24 07:49:34 lha Exp $
+.\"
+.Dd April 24, 2005
+.Dt KRB5_SET_DEFAULT_REALM 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_copy_host_realm ,
+.Nm krb5_free_host_realm ,
+.Nm krb5_get_default_realm ,
+.Nm krb5_get_default_realms ,
+.Nm krb5_get_host_realm ,
+.Nm krb5_set_default_realm
+.Nd default and host realm read and manipulation routines
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_copy_host_realm
+.Fa "krb5_context context"
+.Fa "const krb5_realm *from"
+.Fa "krb5_realm **to"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_host_realm
+.Fa "krb5_context context"
+.Fa "krb5_realm *realmlist"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_default_realm
+.Fa "krb5_context context"
+.Fa "krb5_realm *realm"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_default_realms
+.Fa "krb5_context context"
+.Fa "krb5_realm **realm"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_host_realm
+.Fa "krb5_context context"
+.Fa "const char *host"
+.Fa "krb5_realm **realms"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_default_realm
+.Fa "krb5_context context"
+.Fa "const char *realm"
+.Fc
+.Sh DESCRIPTION
+.Fn krb5_copy_host_realm
+copies the list of realms from
+.Fa from
+to
+.Fa to .
+.Fa to
+should be freed by the caller using
+.Fa krb5_free_host_realm .
+.Pp
+.Fn krb5_free_host_realm
+frees all memory allocated by
+.Fa realmlist .
+.Pp
+.Fn krb5_get_default_realm
+returns the first default realm for this host.
+The realm returned should be freed with
+.Fn free .
+.Pp
+.Fn krb5_get_default_realms
+returns a
+.Dv NULL
+terminated list of default realms for this context.
+Realms returned by
+.Fn krb5_get_default_realms
+should be freed with
+.Fn krb5_free_host_realm .
+.Pp
+.Fn krb5_get_host_realm
+returns a
+.Dv NULL
+terminated list of realms for
+.Fa host
+by looking up the information in the
+.Li [domain_realm]
+in
+.Pa krb5.conf
+or in
+.Li DNS .
+If the mapping in
+.Li [domain_realm]
+results in the string
+.Li dns_locate ,
+DNS is used to lookup the realm.
+.Pp
+When using
+.Li DNS
+to a resolve the domain for the host a.b.c,
+.Fn krb5_get_host_realm
+looks for a
+.Dv TXT
+resource record named
+.Li _kerberos.a.b.c ,
+and if not found, it strips off the first component and tries a again
+(_kerberos.b.c) until it reaches the root.
+.Pp
+If there is no configuration or DNS information found,
+.Fn krb5_get_host_realm
+assumes it can use the domain part of the
+.Fa host
+to form a realm.
+Caller must free
+.Fa realmlist
+with
+.Fn krb5_free_host_realm .
+.Pp
+.Fn krb5_set_default_realm
+sets the default realm for the
+.Fa context .
+If
+.Dv NULL
+is used as a
+.Fa realm ,
+the
+.Li [libdefaults]default_realm
+stanza in
+.Pa krb5.conf
+is used.
+If there is no such stanza in the configuration file, the
+.Fn krb5_get_host_realm
+function is used to form a default realm.
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_set_password.3 b/src/kerberosV/src/lib/krb5/krb5_set_password.3
new file mode 100644 (file)
index 0000000..420da69
--- /dev/null
@@ -0,0 +1,143 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_set_password.3,v 1.7 2004/07/15 14:39:06 lha Exp $
+.\"
+.Dd July 15, 2004
+.Dt KRB5_SET_PASSWORD 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_change_password ,
+.Nm krb5_set_password ,
+.Nm krb5_set_password_using_ccache ,
+.Nm krb5_passwd_result_to_string
+.Nd change password functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_change_password
+.Fa "krb5_context context"
+.Fa "krb5_creds *creds"
+.Fa "char *newpw"
+.Fa "int *result_code"
+.Fa "krb5_data *result_code_string"
+.Fa "krb5_data *result_string"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_password
+.Fa "krb5_context context"
+.Fa "krb5_creds *creds"
+.Fa "char *newpw"
+.Fa "krb5_principal targprinc"
+.Fa "int *result_code"
+.Fa "krb5_data *result_code_string"
+.Fa "krb5_data *result_string"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_set_password_using_ccache
+.Fa "krb5_context context"
+.Fa "krb5_ccache ccache"
+.Fa "char *newpw"
+.Fa "krb5_principal targprinc"
+.Fa "int *result_code"
+.Fa "krb5_data *result_code_string"
+.Fa "krb5_data *result_string"
+.Fc
+.Ft "const char *"
+.Fo krb5_passwd_result_to_string
+.Fa "krb5_context context"
+.Fa "int result"
+.Fc
+.Sh DESCRIPTION
+These functions change the password for a given principal.
+.Pp
+.Fn krb5_set_password
+and
+.Fn krb5_set_password_using_ccache
+are the newer of the three functions, and use a newer version of the
+protocol (and also fall back to the older set-password protocol if the
+newer protocol doesn't work).
+.Pp
+.Fn krb5_change_password
+sets the password
+.Fa newpasswd
+for the client principal in
+.Fa creds .
+The server principal of creds must be
+.Li kadmin/changepw .
+.Pp
+.Fn krb5_set_password
+and
+.Fn krb5_set_password_using_ccache
+change the password for the principal
+.Fa targprinc .
+.Pp
+.Fn krb5_set_password
+requires that the credential for
+.Li kadmin/changepw@REALM
+is in
+.Fa creds .
+If the user caller isn't an administrator, this credential
+needs to be an initial credential, see
+.Xr krb5_get_init_creds 3
+how to get such credentials.
+.Pp
+.Fn krb5_set_password_using_ccache
+will get the credential from
+.Fa ccache .
+.Pp
+If
+.Fa targprinc
+is
+.Dv NULL ,
+.Fn krb5_set_password_using_ccache
+uses the the default principal in
+.Fa ccache
+and
+.Fn krb5_set_password
+uses the global the default principal.
+.Pp
+All three functions return an error in
+.Fa result_code
+and maybe an error string to print in
+.Fa result_string .
+.Pp
+.Fn krb5_passwd_result_to_string
+returns an human readable string describing the error code in
+.Fa result_code
+from the
+.Fn krb5_set_password
+functions.
+.Sh SEE ALSO
+.Xr krb5_ccache 3 ,
+.Xr krb5_init_context 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_storage.3 b/src/kerberosV/src/lib/krb5/krb5_storage.3
new file mode 100644 (file)
index 0000000..0ce2ccc
--- /dev/null
@@ -0,0 +1,391 @@
+.\" Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_storage.3,v 1.4 2005/05/10 10:46:46 lha Exp $
+.\"
+.Dd May 10, 2005
+.Dt KRB5_STORAGE 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_storage ,
+.Nm krb5_storage_emem ,
+.Nm krb5_storage_from_data ,
+.Nm krb5_storage_from_fd ,
+.Nm krb5_storage_from_mem ,
+.Nm krb5_storage_set_flags ,
+.Nm krb5_storage_clear_flags ,
+.Nm krb5_storage_is_flags ,
+.Nm krb5_storage_set_byteorder ,
+.Nm krb5_storage_get_byteorder ,
+.Nm krb5_storage_set_eof_code ,
+.Nm krb5_storage_seek ,
+.Nm krb5_storage_read ,
+.Nm krb5_storage_write ,
+.Nm krb5_storage_free ,
+.Nm krb5_storage_to_data ,
+.Nm krb5_store_int32 ,
+.Nm krb5_ret_int32 ,
+.Nm krb5_store_int16 ,
+.Nm krb5_ret_int16 ,
+.Nm krb5_store_int8 ,
+.Nm krb5_ret_int8 ,
+.Nm krb5_store_data ,
+.Nm krb5_ret_data ,
+.Nm krb5_store_string ,
+.Nm krb5_ret_string ,
+.Nm krb5_store_stringz ,
+.Nm krb5_ret_stringz ,
+.Nm krb5_store_principal ,
+.Nm krb5_ret_principal ,
+.Nm krb5_store_keyblock ,
+.Nm krb5_ret_keyblock ,
+.Nm krb5_store_times ,
+.Nm krb5_ret_times ,
+.Nm krb5_store_address ,
+.Nm krb5_ret_address ,
+.Nm krb5_store_addrs ,
+.Nm krb5_ret_addrs ,
+.Nm krb5_store_authdata ,
+.Nm krb5_ret_authdata ,
+.Nm krb5_store_creds ,
+.Nm krb5_ret_creds
+.Nd operates on the Kerberos datatype krb5_storage
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "struct krb5_storage;"
+.Pp
+.Ft "krb5_storage *"
+.Fn krb5_storage_from_fd "int fd"
+.Ft "krb5_storage *"
+.Fn krb5_storage_emem "void"
+.Ft "krb5_storage *"
+.Fn krb5_storage_from_mem "void *buf" "size_t len"
+.Ft "krb5_storage *"
+.Fn krb5_storage_from_data "krb5_data *data"
+.Ft void
+.Fn krb5_storage_set_flags "krb5_storage *sp" "krb5_flags flags"
+.Ft void
+.Fn krb5_storage_clear_flags "krb5_storage *sp" "krb5_flags flags"
+.Ft krb5_boolean
+.Fn krb5_storage_is_flags "krb5_storage *sp" "krb5_flags flags"
+.Ft void
+.Fn krb5_storage_set_byteorder "krb5_storage *sp" "krb5_flags byteorder"
+.Ft krb5_flags
+.Fn krb5_storage_get_byteorder "krb5_storage *sp" "krb5_flags byteorder"
+.Ft void
+.Fn krb5_storage_set_eof_code "krb5_storage *sp" "int code"
+.Ft off_t
+.Fn krb5_storage_seek "krb5_storage *sp" "off_t offset" "int whence"
+.Ft krb5_ssize_t
+.Fn krb5_storage_read "krb5_storage *sp" "void *buf" "size_t len"
+.Ft krb5_ssize_t
+.Fn krb5_storage_write "krb5_storage *sp" "const void *buf" "size_t len"
+.Ft krb5_error_code
+.Fn krb5_storage_free "krb5_storage *sp"
+.Ft krb5_error_code
+.Fn krb5_storage_to_data "krb5_storage *sp" "krb5_data *data"
+.Ft krb5_error_code
+.Fn krb5_store_int32 "krb5_storage *sp" "int32_t value"
+.Ft krb5_error_code
+.Fn krb5_ret_int32 "krb5_storage *sp" "int32_t *value"
+.Ft krb5_error_code
+.Fn krb5_store_int16 "krb5_storage *sp" "int16_t value"
+.Ft krb5_error_code
+.Fn krb5_ret_int16 "krb5_storage *sp" "int16_t *value"
+.Ft krb5_error_code
+.Fn krb5_store_int8 "krb5_storage *sp" "int8_t value"
+.Ft krb5_error_code
+.Fn krb5_ret_int8 "krb5_storage *sp" "int8_t *value"
+.Ft krb5_error_code
+.Fn krb5_store_data "krb5_storage *sp" "krb5_data data"
+.Ft krb5_error_code
+.Fn krb5_ret_data "krb5_storage *sp" "krb5_data *data"
+.Ft krb5_error_code
+.Fn krb5_store_string "krb5_storage *sp" "const char *s"
+.Ft krb5_error_code
+.Fn krb5_ret_string "krb5_storage *sp" "char **string"
+.Ft krb5_error_code
+.Fn krb5_store_stringz "krb5_storage *sp" "const char *s"
+.Ft krb5_error_code
+.Fn krb5_ret_stringz "krb5_storage *sp" "char **string"
+.Ft krb5_error_code
+.Fn krb5_store_principal "krb5_storage *sp" "krb5_principal p"
+.Ft krb5_error_code
+.Fn krb5_ret_principal "krb5_storage *sp" "krb5_principal *princ"
+.Ft krb5_error_code
+.Fn krb5_store_keyblock "krb5_storage *sp" "krb5_keyblock p"
+.Ft krb5_error_code
+.Fn krb5_ret_keyblock "krb5_storage *sp" "krb5_keyblock *p"
+.Ft krb5_error_code
+.Fn krb5_store_times "krb5_storage *sp" "krb5_times times"
+.Ft krb5_error_code
+.Fn krb5_ret_times "krb5_storage *sp" "krb5_times *times"
+.Ft krb5_error_code
+.Fn krb5_store_address "krb5_storage *sp" "krb5_address p"
+.Ft krb5_error_code
+.Fn krb5_ret_address "krb5_storage *sp" "krb5_address *adr"
+.Ft krb5_error_code
+.Fn krb5_store_addrs "krb5_storage *sp" "krb5_addresses p"
+.Ft krb5_error_code
+.Fn krb5_ret_addrs "krb5_storage *sp" "krb5_addresses *adr"
+.Ft krb5_error_code
+.Fn krb5_store_authdata "krb5_storage *sp" "krb5_authdata auth"
+.Ft krb5_error_code
+.Fn krb5_ret_authdata "krb5_storage *sp" "krb5_authdata *auth"
+.Ft krb5_error_code
+.Fn krb5_store_creds "krb5_storage *sp" "krb5_creds *creds"
+.Ft krb5_error_code
+.Fn krb5_ret_creds "krb5_storage *sp" "krb5_creds *creds"
+.Sh DESCRIPTION
+The
+.Li krb5_storage
+structure holds a storage element that is used for data manipulation.
+The structure contains no public accessible elements.
+.Pp
+.Fn krb5_storage_emem
+create a memory based krb5 storage unit that dynamicly resized to the
+ammount of data stored in.
+The storage never returns errors, on memory allocation errors
+.Xr exit 3
+will be called.
+.Pp
+.Fn krb5_storage_from_data
+create a krb5 storage unit that will read is data from a
+.Li krb5_data .
+There is no copy made of the
+.Fa data ,
+so the caller must not free
+.Fa data
+until the storage is freed.
+.Pp
+.Fn krb5_storage_from_fd
+create a krb5 storage unit that will read is data from a
+file descriptor.
+The descriptor must be seekable if
+.Fn krb5_storage_seek
+is used.
+Caller must not free the file descriptor before the storage is freed.
+.Pp
+.Fn krb5_storage_from_mem
+create a krb5 storage unit that will read is data from a
+memory region.
+There is no copy made of the
+.Fa data ,
+so the caller must not free
+.Fa data
+until the storage is freed.
+.Pp
+.Fn krb5_storage_set_flags
+and
+.Fn krb5_storage_clear_flags
+modifies the behavior of the storage functions.
+.Fn krb5_storage_is_flags
+tests if the
+.Fa flags
+are set on the
+.Li krb5_storage .
+Valid flags to set, is and clear is are:
+.Pp
+.Bl -tag -width "Fan vet..." -compact -offset indent
+.It KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS
+Stores the number of principal componets one too many when storing
+principal namees, used for compatibility with version 1 of file
+keytabs and version 1 of file credential caches.
+.It KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE
+Doesn't store the name type in when storing a principal name, used for
+compatibility with version 1 of file keytabs and version 1 of file
+credential caches.
+.It KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE
+Stores the keyblock type twice storing a keyblock, used for
+compatibility version 3 of file credential caches.
+.It KRB5_STORAGE_BYTEORDER_MASK
+bitmask that can be used to and out what type of byte order order is used.
+.It KRB5_STORAGE_BYTEORDER_BE
+Store integers in in big endian byte order, this is the default mode.
+.It KRB5_STORAGE_BYTEORDER_LE
+Store integers in in little endian byte order.
+.It KRB5_STORAGE_BYTEORDER_HOST
+Stores the integers in host byte order, used for compatibility with
+version 1 of file keytabs and version 1 and 2 of file credential
+caches.
+.It KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER
+Store the credential flags in a krb5_creds in the reverse bit order.
+.El
+.Pp
+.Fn krb5_storage_set_byteorder
+and
+.Fn krb5_storage_get_byteorder
+modifies the byte order used in the storage for integers.
+The flags used is same as above.
+The valid flags are
+.Dv KRB5_STORAGE_BYTEORDER_BE ,
+.Dv KRB5_STORAGE_BYTEORDER_LE
+and
+.Dv KRB5_STORAGE_BYTEORDER_HOST .
+.Pp
+.Fn krb5_storage_set_eof_code
+sets the error code that will be returned on end of file condition to
+.Fa code .
+.Pp
+.Fn krb5_storage_seek
+seeks
+.Fa offset
+bytes in the storage
+.Fa sp .
+The
+.Fa whence
+argument is one of
+.Bl -tag -width SEEK_SET -compact -offset indent
+.It SEEK_SET
+offset is from begining of storage.
+.It SEEK_CUR
+offset is relative from current offset.
+.It SEEK_END
+offset is from end of storage.
+.El
+.Pp
+.Fn krb5_storage_read
+reads
+.Fa len
+(or less bytes in case of end of file) into
+.Fa buf
+from the current offset in the storage
+.Fa sp .
+.Pp
+.Fn krb5_storage_write
+writes
+.Fa len
+or (less bytes in case of end of file) from
+.Fa buf
+from the current offset in the storage
+.Fa sp .
+.Pp
+.Fn krb5_storage_free
+frees the storage
+.Fa sp .
+.Pp
+.Fn krb5_storage_to_data
+converts the data in storage
+.Fa sp
+into a
+.Li krb5_data
+structure.
+.Fa data
+must be freed with
+.Fn krb5_data_free
+by the caller when done with the
+.Fa data .
+.Pp
+All
+.Li krb5_store
+and
+.Li krb5_ret
+functions move the current offset forward when the functions returns.
+.Pp
+.Fn krb5_store_int32 ,
+.Fn krb5_ret_int32 ,
+.Fn krb5_store_int16 ,
+.Fn krb5_ret_int16 ,
+.Fn krb5_store_int8 ,
+and
+.Fn krb5_ret_int8 
+stores and reads an integer from
+.Fa sp
+in the byte order specified by the flags set on the
+.Fa sp .
+.Pp
+.Fn krb5_store_data
+and
+.Fn krb5_ret_data
+store and reads a krb5_data.
+The length of the data is stored with
+.Fn krb5_store_int32 .
+.Pp
+.Fn krb5_store_string
+and
+.Fn krb5_ret_string
+store and reads a string by storing the length of the string with
+.Fn krb5_store_int32
+followed by the string itself.
+.Pp
+.Fn krb5_store_stringz
+and 
+.Fn krb5_ret_stringz
+store and reads a string by storing string followed by a
+.Dv NUL .
+.Pp
+.Fn krb5_store_principal
+and
+.Fn krb5_ret_principal
+store and reads a principal.
+.Pp
+.Fn krb5_store_keyblock
+and
+.Fn krb5_ret_keyblock
+store and reads a
+.Li krb5_keyblock .
+.Pp
+.Fn krb5_store_times
+.Fn krb5_ret_times
+store and reads
+.Li krb5_times 
+structure .
+.Pp
+.Fn krb5_store_address
+and
+.Fn krb5_ret_address
+store and reads a 
+.Li krb5_address .
+.Pp
+.Fn krb5_store_addrs
+and
+.Fn krb5_ret_addrs
+store and reads a 
+.Li krb5_addresses .
+.Pp
+.Fn krb5_store_authdata
+and
+.Fn krb5_ret_authdata
+store and reads a
+.Li krb5_authdata .
+.Pp
+.Fn krb5_store_creds
+and
+.Fn krb5_ret_creds
+store and reads a
+.Li krb5_creds .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_data 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_string_to_key.3 b/src/kerberosV/src/lib/krb5/krb5_string_to_key.3
new file mode 100644 (file)
index 0000000..289ed79
--- /dev/null
@@ -0,0 +1,165 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_string_to_key.3,v 1.3 2004/08/13 13:23:57 lha Exp $
+.\"
+.Dd August 13, 2004
+.Dt KRB5_STRING_TO_KEY 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_string_to_key ,
+.Nm krb5_string_to_key_data ,
+.Nm krb5_string_to_key_data_salt ,
+.Nm krb5_string_to_key_data_salt_opaque ,
+.Nm krb5_string_to_key_derived ,
+.Nm krb5_string_to_key_salt ,
+.Nm krb5_string_to_key_salt_opaque ,
+.Nm krb5_get_pw_salt ,
+.Nm krb5_free_salt
+.Nd turns a string to a Kerberos key
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fo krb5_string_to_key
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "const char *password"
+.Fa "krb5_principal principal"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_key_data
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_data password"
+.Fa "krb5_principal principal"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_key_data_salt
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_data password"
+.Fa "krb5_salt salt"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_key_data_salt_opaque
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "krb5_data password"
+.Fa "krb5_salt salt"
+.Fa "krb5_data opaque"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_key_salt
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "const char *password"
+.Fa "krb5_salt salt"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_key_salt_opaque
+.Fa "krb5_context context"
+.Fa "krb5_enctype enctype"
+.Fa "const char *password"
+.Fa "krb5_salt salt"
+.Fa "krb5_data opaque"
+.Fa "krb5_keyblock *key"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_get_pw_salt
+.Fa "krb5_context context"
+.Fa "krb5_const_principal principal"
+.Fa "krb5_salt *salt"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_free_salt
+.Fa "krb5_context context"
+.Fa "krb5_salt salt"
+.Fc
+.Sh DESCRIPTION
+The string to key functions convert a string to a kerberos key.
+.Pp
+.Fn krb5_string_to_key_data_salt_opaque
+is the function that does all the work, the rest of the functions are
+just wrapers around
+.Fn krb5_string_to_key_data_salt_opaque
+that calls it with default values.
+.Pp
+.Fn krb5_string_to_key_data_salt_opaque
+transforms the
+.Fa password
+with the given salt-string
+.Fa salt
+and the opaque, encryption type specific parameter
+.Fa opaque
+to a encryption key
+.Fa key
+according to the string to key function associated with
+.Fa enctype .
+.Pp
+The
+.Fa key
+should be freed with
+.Fn krb5_free_keyblock_contents .
+.Pp
+If one of the functions that doesn't take a
+.Li krb5_salt
+as it argument
+.Fn krb5_get_pw_salt
+is used to get the salt value.
+.Pp
+.Fn krb5_get_pw_salt
+get the default password salt for a principal, use
+.Fn krb5_free_salt
+to free the salt when done.
+.Pp
+.Fn krb5_free_salt
+frees the content of
+.Fa salt .
+.Pp
+.Fn krb5_string_to_key_derived
+is deprecated, see the BUGS section below.
+.Sh BUGS
+.Fn krb5_string_to_key_derived
+only works for
+.Dv ETYPE_DES3_CBC_SHA1 ,
+if you use on on some other enctypes, it will produce the wrong result.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_data 3 ,
+.Xr krb5_keyblock 3 ,
+.Xr kerberos 8
diff --git a/src/kerberosV/src/lib/krb5/krb5_ticket.3 b/src/kerberosV/src/lib/krb5/krb5_ticket.3
new file mode 100644 (file)
index 0000000..e536e01
--- /dev/null
@@ -0,0 +1,128 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_ticket.3,v 1.4 2004/08/12 10:22:04 lha Exp $
+.\"
+.Dd August 12, 2004
+.Dt KRB5_TICKET 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_ticket ,
+.Nm krb5_free_ticket ,
+.Nm krb5_copy_ticket ,
+.Nm krb5_ticket_get_authorization_data_type ,
+.Nm krb5_ticket_get_client ,
+.Nm krb5_ticket_get_server
+.Nd Kerberos 5 ticket access and handling functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li krb5_ticket ;
+.Pp
+.Ft krb5_error_code
+.Fo krb5_free_ticket
+.Fa "krb5_context context"
+.Fa "krb5_ticket *ticket"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_copy_ticket
+.Fa "krb5_context context"
+.Fa "const krb5_ticket *from"
+.Fa "krb5_ticket **to"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_ticket_get_authorization_data_type
+.Fa "krb5_context context"
+.Fa "krb5_ticket *ticket"
+.Fa "int type"
+.Fa "krb5_data *data"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_ticket_get_client
+.Fa "krb5_context context"
+.Fa "const krb5_ticket *ticket"
+.Fa "krb5_principal *client"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_ticket_get_server
+.Fa "krb5_context context"
+.Fa "const krb5_ticket *ticket"
+.Fa "krb5_principal *server"
+.Fc
+.Sh DESCRIPTION
+.Li krb5_ticket
+holds a kerberos ticket.
+The internals of the structure should never be accessed directly,
+functions exist for extracting information.
+.Pp
+.Fn krb5_free_ticket
+frees the
+.Fa ticket
+and its content.
+Used to free the result of
+.Fn krb5_copy_ticket
+and
+.Fn krb5_recvauth .
+.Pp
+.Fn krb5_copy_ticket
+copies the content of the ticket
+.Fa from
+to the ticket
+.Fa to .
+The result
+.Fa to
+should be freed with
+.Fn krb5_free_ticket .
+.Pp
+.Fn krb5_ticket_get_authorization_data_type
+fetches the authorization data of the type
+.Fa type
+from the
+.Fa ticket .
+If there isn't any authorization data of type
+.Fa type ,
+.Dv ENOENT
+is returned.
+.Fa data
+needs to be freed with
+.Fn krb5_data_free
+on success.
+.Pp
+.Fn krb5_ticket_get_client
+and
+.Fn krb5_ticket_get_server
+returns a copy of the client/server principal from the ticket.
+The principal returned should be free using
+.Xr krb5_free_principal 3 .
+.Sh SEE ALSO
+.Xr krb5 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_timeofday.3 b/src/kerberosV/src/lib/krb5/krb5_timeofday.3
new file mode 100644 (file)
index 0000000..f566cd6
--- /dev/null
@@ -0,0 +1,118 @@
+.\" $KTH: krb5_timeofday.3,v 1.8 2003/06/24 05:12:43 lha Exp $
+.\"
+.\" Copyright (c) 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_timeofday.3,v 1.8 2003/06/24 05:12:43 lha Exp $
+.\"
+.Dd June 17, 2003
+.Dt KRB5_TIMEOFDAY 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_timeofday ,
+.Nm krb5_set_real_time ,
+.Nm krb5_us_timeofday ,
+.Nm krb5_format_time ,
+.Nm krb5_string_to_deltat
+.Nd Kerberos 5 time handling functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li krb5_timestamp ;
+.Pp
+.Li krb5_deltat ;
+.Ft krb5_error_code
+.Fo krb5_set_real_time
+.Fa "krb5_context context"
+.Fa "krb5_timestamp sec"
+.Fa "int32_t usec"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_timeofday
+.Fa "krb5_context context"
+.Fa "krb5_timestamp *timeret"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_us_timeofday
+.Fa "krb5_context context"
+.Fa "krb5_timestamp *sec"
+.Fa "int32_t *usec"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_format_time
+.Fa "krb5_context context"
+.Fa "time_t t"
+.Fa "char *s"
+.Fa "size_t len"
+.Fa "krb5_boolean include_time"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_string_to_deltat
+.Fa "const char *string"
+.Fa "krb5_deltat *deltat"
+.Fc
+.Sh DESCRIPTION
+.Nm krb5_set_real_time
+sets the absolute time that the caller knows the KDC has.
+With this the Kerberos library can calculate the relative
+difference between the KDC time and the local system time and store it
+in the
+.Fa context .
+With this information the Kerberos library can adjust all time stamps
+in Kerberos packages.
+.Pp
+.Fn krb5_timeofday
+returns the current time, but adjusted with the time difference
+between the local host and the KDC.
+.Fn krb5_us_timeofday
+also returns microseconds.
+.Pp
+.Nm krb5_format_time
+formats the time
+.Fa t
+into the string
+.Fa s
+of length
+.Fa len .
+If
+.Fa include_time
+is set, the time is set include_time.
+.Pp
+.Nm krb5_string_to_deltat
+parses delta time
+.Fa string
+into
+.Fa deltat .
+.Sh SEE ALSO
+.Xr gettimeofday 2 ,
+.Xr krb5 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_unparse_name.3 b/src/kerberosV/src/lib/krb5/krb5_unparse_name.3
new file mode 100644 (file)
index 0000000..7d01e20
--- /dev/null
@@ -0,0 +1,62 @@
+.\" Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_unparse_name.3,v 1.9 2003/05/26 14:09:03 lha Exp $
+.\"
+.Dd August 8, 1997
+.Dt KRB5_UNPARSE_NAME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_unparse_name
+.\" .Nm krb5_unparse_name_ext
+.Nd principal to string conversion
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_unparse_name "krb5_context context" "krb5_principal principal" "char **name"
+.\" .Ft krb5_error_code
+.\" .Fn krb5_unparse_name_ext "krb5_context context" "krb5_const_principal principal" "char **name" "size_t *size"
+.Sh DESCRIPTION
+This function takes a
+.Fa principal ,
+and will convert in to a printable representation with the same syntax
+as described in
+.Xr krb5_parse_name 3 .
+.Fa *name
+will point to allocated data and should be freed by the caller.
+.Sh SEE ALSO
+.Xr krb5_425_conv_principal 3 ,
+.Xr krb5_build_principal 3 ,
+.Xr krb5_free_principal 3 ,
+.Xr krb5_parse_name 3 ,
+.Xr krb5_sname_to_principal 3
diff --git a/src/kerberosV/src/lib/krb5/krb5_verify_init_creds.3 b/src/kerberosV/src/lib/krb5/krb5_verify_init_creds.3
new file mode 100644 (file)
index 0000000..05d125f
--- /dev/null
@@ -0,0 +1,103 @@
+.\" Copyright (c) 2003 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_verify_init_creds.3,v 1.1 2004/07/18 15:23:44 lha Exp $
+.\"
+.Dd July 18, 2004
+.Dt KRB5_VERIFY_INIT_CREDS 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_verify_init_creds_opt_init ,
+.Nm krb5_verify_init_creds_opt_set_ap_req_nofail ,
+.Nm krb5_verify_init_creds
+.Nd "verifies a credential cache is correct by using a local keytab"
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Pp
+.Li "struct krb5_verify_init_creds_opt;"
+.Ft void
+.Fo krb5_verify_init_creds_opt_init
+.Fa "krb5_verify_init_creds_opt *options"
+.Fc
+.Ft void
+.Fo krb5_verify_init_creds_opt_set_ap_req_nofail
+.Fa "krb5_verify_init_creds_opt *options"
+.Fa "int ap_req_nofail"
+.Fc
+.Ft krb5_error_code
+.Fo krb5_verify_init_creds
+.Fa "krb5_context context"
+.Fa "krb5_creds *creds"
+.Fa "krb5_principal ap_req_server"
+.Fa "krb5_ccache *ccache"
+.Fa "krb5_verify_init_creds_opt *options"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm krb5_verify_init_creds
+function verifies the initial tickets with the local keytab to make
+sure the response of the KDC was spoof-ed.
+.Pp
+.Nm krb5_verify_init_creds
+will use principal
+.Fa ap_req_server
+from the local keytab, if
+.Dv NULL
+is passed in, the code will guess the local hostname and use that to
+form host/hostname/GUESSED-REALM-FOR-HOSTNAME.
+.Fa creds
+is the credential that
+.Nm krb5_verify_init_creds
+should verify.
+If
+.Fa ccache
+is given
+.Fn krb5_verify_init_creds
+stores all credentials it fetched from the KDC there, otherwise it
+will use a memory credential cache that is destroyed when done.
+.Pp
+.Fn krb5_verify_init_creds_opt_init
+cleans the the structure, must be used before trying to pass it in to
+.Fn krb5_verify_init_creds .
+.Pp
+.Fn krb5_verify_init_creds_opt_set_ap_req_nofail
+controls controls the behavior if
+.Fa ap_req_server
+doesn't exists in the local keytab or in the KDC's database, if its
+true, the error will be ignored.  Note that this use is possible
+insecure.
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_get_init_creds 3 ,
+.Xr krb5_verify_user 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_verify_user.3 b/src/kerberosV/src/lib/krb5/krb5_verify_user.3
new file mode 100644 (file)
index 0000000..1b046ab
--- /dev/null
@@ -0,0 +1,226 @@
+.\" Copyright (c) 2001 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_verify_user.3,v 1.13 2004/03/20 18:36:51 lha Exp $
+.\"
+.Dd March 25, 2003
+.Dt KRB5_VERIFY_USER 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_verify_user ,
+.Nm krb5_verify_user_lrealm ,
+.Nm krb5_verify_user_opt ,
+.Nm krb5_verify_opt_init
+.Nm krb5_verify_opt_set_ccache ,
+.Nm krb5_verify_opt_set_flags ,
+.Nm krb5_verify_opt_set_service ,
+.Nm krb5_verify_opt_set_secure ,
+.Nm krb5_verify_opt_set_keytab
+.Nd Heimdal password verifying functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn "krb5_verify_user" "krb5_context context" " krb5_principal principal" "krb5_ccache ccache" "const char *password" "krb5_boolean secure" "const char *service"
+.Ft krb5_error_code
+.Fn "krb5_verify_user_lrealm" "krb5_context context" "krb5_principal principal" "krb5_ccache ccache" "const char *password" "krb5_boolean secure" "const char *service"
+.Ft void
+.Fn krb5_verify_opt_init "krb5_verify_opt *opt"
+.Ft void
+.Fn krb5_verify_opt_set_ccache "krb5_verify_opt *opt" "krb5_ccache ccache"
+.Ft void
+.Fn krb5_verify_opt_set_keytab "krb5_verify_opt *opt" "krb5_keytab keytab"
+.Ft void
+.Fn krb5_verify_opt_set_secure "krb5_verify_opt *opt" "krb5_boolean secure"
+.Ft void
+.Fn krb5_verify_opt_set_service "krb5_verify_opt *opt" "const char *service"
+.Ft void
+.Fn krb5_verify_opt_set_flags "krb5_verify_opt *opt" "unsigned int flags"
+.Ft krb5_error_code
+.Fo krb5_verify_user_opt
+.Fa "krb5_context context"
+.Fa "krb5_principal principal"
+.Fa "const char *password"
+.Fa "krb5_verify_opt *opt"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm krb5_verify_user
+function verifies the password supplied by a user.
+The principal whose password will be verified is specified in
+.Fa principal .
+New tickets will be obtained as a side-effect and stored in
+.Fa ccache
+(if
+.Dv NULL ,
+the default ccache is used).
+.Fn krb5_verify_user
+will call
+.Fn krb5_cc_initialize
+on the given
+.Fa ccache ,
+so
+.Fa ccache
+must only initialized with
+.Fn krb5_cc_resolve
+or
+.Fn krb5_cc_gen_new .
+If the password is not supplied in
+.Fa password
+(and is given as
+.Dv NULL )
+the user will be prompted for it.
+If
+.Fa secure
+the ticket will be verified against the locally stored service key
+.Fa service
+(by default
+.Ql host
+if given as
+.Dv NULL
+).
+.Pp
+The
+.Nm krb5_verify_user_lrealm
+function does the same, except that it ignores the realm in
+.Fa principal
+and tries all the local realms (see
+.Xr krb5.conf 5 ) .
+After a successful return, the principal is set to the authenticated
+realm. If the call fails, the principal will not be meaningful, and
+should only be freed with
+.Xr krb5_free_principal 3 .
+.Pp
+.Fn krb5_verify_opt_init
+resets all opt to default values.
+.Pp
+None of the krb5_verify_opt_set function makes a copy of the data
+structure that they are called with. Its up the caller to free them
+after the
+.Fn krb5_verify_user_opt
+is called.
+.Pp
+.Fn krb5_verify_opt_set_ccache
+sets the
+.Fa ccache
+that user of
+.Fa opt
+will use. If not set, the default credential cache will be used.
+.Pp
+.Fn krb5_verify_opt_set_keytab
+sets the
+.Fa keytab
+that user of
+.Fa opt
+will use. If not set, the default keytab will be used.
+.Pp
+.Fn krb5_verify_opt_set_secure
+if
+.Fa secure
+if true, the password verification will require that the ticket will
+be verified against the locally stored service key. If not set,
+default value is true.
+.Pp
+.Fn krb5_verify_opt_set_service
+sets the
+.Fa service
+principal that user of
+.Fa opt
+will use. If not set, the
+.Ql host
+service will be used.
+.Pp
+.Fn krb5_verify_opt_set_flags
+sets
+.Fa flags
+that user of
+.Fa opt
+will use.
+If the flag
+.Dv KRB5_VERIFY_LREALMS
+is used, the
+.Fa principal
+will be modified like
+.Fn krb5_verify_user_lrealm
+modifies it.
+.Pp
+.Fn krb5_verify_user_opt
+function verifies the
+.Fa password
+supplied by a user.
+The principal whose password will be verified is specified in
+.Fa principal .
+Options the to the verification process is pass in in
+.Fa opt .
+.Sh EXAMPLES
+Here is a example program that verifies a password. it uses the
+.Ql host/`hostname`
+service principal in
+.Pa krb5.keytab .
+.Bd -literal
+#include <krb5.h>
+
+int
+main(int argc, char **argv)
+{
+    char *user;
+    krb5_error_code error;
+    krb5_principal princ;
+    krb5_context context;
+
+    if (argc != 2)
+       errx(1, "usage: verify_passwd <principal-name>");
+
+    user = argv[1];
+
+    if (krb5_init_context(&context) < 0)
+       errx(1, "krb5_init_context");
+
+    if ((error = krb5_parse_name(context, user, &princ)) != 0)
+       krb5_err(context, 1, error, "krb5_parse_name");
+
+    error = krb5_verify_user(context, princ, NULL, NULL, TRUE, NULL);
+    if (error)
+        krb5_err(context, 1, error, "krb5_verify_user");
+
+    return 0;
+}
+.Ed
+.Sh SEE ALSO
+.Xr krb5_cc_gen_new 3 ,
+.Xr krb5_cc_initialize 3 ,
+.Xr krb5_cc_resolve 3 ,
+.Xr krb5_err 3 ,
+.Xr krb5_free_principal 3 ,
+.Xr krb5_init_context 3 ,
+.Xr krb5_kt_default 3 ,
+.Xr krb5.conf 5
diff --git a/src/kerberosV/src/lib/krb5/krb5_warn.3 b/src/kerberosV/src/lib/krb5/krb5_warn.3
new file mode 100644 (file)
index 0000000..d43e271
--- /dev/null
@@ -0,0 +1,173 @@
+.\" Copyright (c) 1997, 2001 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: krb5_warn.3,v 1.12 2005/03/26 10:04:33 lha Exp $
+.\"
+.Dd March 20, 2004
+.Dt KRB5_WARN 3
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5_abort ,
+.Nm krb5_abortx ,
+.Nm krb5_clear_error_string ,
+.Nm krb5_err ,
+.Nm krb5_errx ,
+.Nm krb5_free_error_string ,
+.Nm krb5_get_err_text ,
+.Nm krb5_get_error_string ,
+.Nm krb5_have_error_string ,
+.Nm krb5_set_error_string ,
+.Nm krb5_set_warn_dest ,
+.Nm krb5_vabort ,
+.Nm krb5_vabortx ,
+.Nm krb5_verr ,
+.Nm krb5_verrx ,
+.Nm krb5_vset_error_string ,
+.Nm krb5_vwarn ,
+.Nm krb5_vwarnx ,
+.Nm krb5_warn ,
+.Nm krb5_warnx
+.Nd Heimdal warning and error functions
+.Sh LIBRARY
+Kerberos 5 Library (libkrb5, -lkrb5)
+.Sh SYNOPSIS
+.In krb5.h
+.Ft krb5_error_code
+.Fn krb5_abort "krb5_context context" "krb5_error_code code" "const char *fmt"  "..."
+.Ft krb5_error_code
+.Fn krb5_abortx "krb5_context context" "krb5_error_code code" "const char *fmt"  "..."
+.Ft void
+.Fn krb5_clear_error_string "krb5_context context"
+.Ft krb5_error_code
+.Fn krb5_err "krb5_context context" "int eval" "krb5_error_code code" "const char *format" "..."
+.Ft krb5_error_code
+.Fn krb5_errx "krb5_context context" "int eval" "const char *format" "..."
+.Ft void
+.Fn krb5_free_error_string "krb5_context context" "char *str"
+.Ft krb5_error_code
+.Fn krb5_verr "krb5_context context" "int eval" "krb5_error_code code" "const char *format" "va_list ap"
+.Ft krb5_error_code
+.Fn krb5_verrx "krb5_context context" "int eval" "const char *format" "va_list ap"
+.Ft krb5_error_code
+.Fn krb5_vset_error_string "krb5_context context" "const char *fmt" "va_list args"
+.Ft krb5_error_code
+.Fn krb5_vwarn "krb5_context context" "krb5_error_code code" "const char *format" "va_list ap"
+.Ft krb5_error_code
+.Fn krb5_vwarnx "krb5_context context" "const char *format" "va_list ap"
+.Ft krb5_error_code
+.Fn krb5_warn "krb5_context context" "krb5_error_code code" "const char *format" "..."
+.Ft krb5_error_code
+.Fn krb5_warnx "krb5_context context" "const char *format" "..."
+.Ft krb5_error_code
+.Fn krb5_set_error_string "krb5_context context" "const char *fmt" "..."
+.Ft krb5_error_code
+.Fn krb5_set_warn_dest "krb5_context context" "krb5_log_facility *facility"
+.Ft "char *"
+.Fn krb5_get_err_text "krb5_context context" "krb5_error_code code"
+.Ft char*
+.Fn krb5_get_error_string "krb5_context context"
+.Ft krb5_boolean
+.Fn krb5_have_error_string "krb5_context context"
+.Ft krb5_error_code
+.Fn krb5_vabortx "krb5_context context" "const char *fmt" "va_list ap"
+.Ft krb5_error_code
+.Fn krb5_vabort "krb5_context context" "const char *fmt" "va_list ap"
+.Sh DESCRIPTION
+These functions print a warning message to some destination.
+.Fa format
+is a printf style format specifying the message to print. The forms not ending in an
+.Dq x
+print the error string associated with
+.Fa code
+along with the message.
+The
+.Dq err
+functions exit with exit status
+.Fa eval
+after printing the message.
+.Pp
+The
+.Fn krb5_set_warn_func
+function sets the destination for warning messages to the specified
+.Fa facility .
+Messages logged with the
+.Dq warn
+functions have a log level of 1, while the
+.Dq err
+functions log with level 0.
+.Pp
+.Fn krb5_get_err_text
+fetches the human readable strings describing the error-code.
+.Pp
+.Fn krb5_abort
+and 
+.Nm krb5_abortx
+behaves like
+.Nm krb5_err
+and
+.Nm krb5_errx
+but instead of exiting using the
+.Xr exit 3
+call,
+.Xr abort 3
+is used.
+.Pp
+.Fn krb5_free_error_string
+frees the error string
+.Fa str
+returned by
+.Fn krb5_get_error_string .
+.Pp
+.Fn krb5_clear_error_string
+clears the error string from the
+.Fa context .
+.Pp
+.Fn krb5_set_error_string
+and
+.Fn krb5_vset_error_string
+sets an verbose error string in
+.Fa context .
+.Pp
+.Fn krb5_get_error_string
+fetches the error string from
+.Fa context .
+The error message in the context is consumed and must be freed using
+.Fn krb5_free_error_string
+by the caller.
+.Pp
+.Fn krb5_have_error_string
+returns
+.Dv TRUE
+if there is a verbose error message in the
+.Fa context .
+.Sh SEE ALSO
+.Xr krb5 3 ,
+.Xr krb5_openlog 3
diff --git a/src/kerberosV/src/lib/krb5/krbhst-test.c b/src/kerberosV/src/lib/krb5/krbhst-test.c
new file mode 100644 (file)
index 0000000..df252d1
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2001 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+#include <err.h>
+#include <getarg.h>
+
+RCSID("$KTH: krbhst-test.c,v 1.3 2002/08/23 03:43:18 assar Exp $");
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "[realms ...]");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    int i, j;
+    krb5_context context;
+    int types[] = {KRB5_KRBHST_KDC, KRB5_KRBHST_ADMIN, KRB5_KRBHST_CHANGEPW,
+                  KRB5_KRBHST_KRB524};
+    const char *type_str[] = {"kdc", "admin", "changepw", "krb524"};
+    int optind = 0;
+    
+    setprogname (argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    krb5_init_context (&context);
+    for(i = 0; i < argc; i++) {
+       krb5_krbhst_handle handle;
+       char host[MAXHOSTNAMELEN];
+
+       for (j = 0; j < sizeof(types)/sizeof(*types); ++j) {
+           printf ("%s for %s:\n", type_str[j], argv[i]);
+
+           krb5_krbhst_init(context, argv[i], types[j], &handle);
+           while(krb5_krbhst_next_as_string(context, handle,
+                                            host, sizeof(host)) == 0)
+               printf("%s\n", host);
+           krb5_krbhst_reset(context, handle);
+           printf ("\n");
+       }
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/krbhst.c b/src/kerberosV/src/lib/krb5/krbhst.c
new file mode 100644 (file)
index 0000000..b563b3e
--- /dev/null
@@ -0,0 +1,861 @@
+/*
+ * Copyright (c) 2001 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <resolve.h>
+
+RCSID("$KTH: krbhst.c,v 1.51 2005/05/20 09:09:42 lha Exp $");
+
+static int
+string_to_proto(const char *string)
+{
+    if(strcasecmp(string, "udp") == 0)
+       return KRB5_KRBHST_UDP;
+    else if(strcasecmp(string, "tcp") == 0) 
+       return KRB5_KRBHST_TCP;
+    else if(strcasecmp(string, "http") == 0) 
+       return KRB5_KRBHST_HTTP;
+    return -1;
+}
+
+/*
+ * set `res' and `count' to the result of looking up SRV RR in DNS for
+ * `proto', `proto', `realm' using `dns_type'.
+ * if `port' != 0, force that port number
+ */
+
+static krb5_error_code
+srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, 
+              const char *realm, const char *dns_type,
+              const char *proto, const char *service, int port)
+{
+    char domain[1024];
+    struct dns_reply *r;
+    struct resource_record *rr;
+    int num_srv;
+    int proto_num;
+    int def_port;
+
+    *res = NULL;
+    *count = 0;
+
+    proto_num = string_to_proto(proto);
+    if(proto_num < 0) {
+       krb5_set_error_string(context, "unknown protocol `%s'", proto);
+       return EINVAL;
+    }
+
+    if(proto_num == KRB5_KRBHST_HTTP)
+       def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));
+    else if(port == 0)
+       def_port = ntohs(krb5_getportbyname (context, service, proto, 88));
+    else
+       def_port = port;
+
+    snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm);
+
+    r = dns_lookup(domain, dns_type);
+    if(r == NULL)
+       return KRB5_KDC_UNREACH;
+
+    for(num_srv = 0, rr = r->head; rr; rr = rr->next) 
+       if(rr->type == T_SRV)
+           num_srv++;
+
+    *res = malloc(num_srv * sizeof(**res));
+    if(*res == NULL) {
+       dns_free_data(r);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    dns_srv_order(r);
+
+    for(num_srv = 0, rr = r->head; rr; rr = rr->next) 
+       if(rr->type == T_SRV) {
+           krb5_krbhst_info *hi;
+           size_t len = strlen(rr->u.srv->target);
+
+           hi = calloc(1, sizeof(*hi) + len);
+           if(hi == NULL) {
+               dns_free_data(r);
+               while(--num_srv >= 0)
+                   free((*res)[num_srv]);
+               free(*res);
+               *res = NULL;
+               return ENOMEM;
+           }
+           (*res)[num_srv++] = hi;
+
+           hi->proto = proto_num;
+           
+           hi->def_port = def_port;
+           if (port != 0)
+               hi->port = port;
+           else
+               hi->port = rr->u.srv->port;
+
+           strlcpy(hi->hostname, rr->u.srv->target, len + 1);
+       }
+
+    *count = num_srv;
+           
+    dns_free_data(r);
+    return 0;
+}
+
+
+struct krb5_krbhst_data {
+    char *realm;
+    unsigned int flags;
+    int def_port;
+    int port;                  /* hardwired port number if != 0 */
+#define KD_CONFIG               1
+#define KD_SRV_UDP              2
+#define KD_SRV_TCP              4
+#define KD_SRV_HTTP             8
+#define KD_FALLBACK            16
+#define KD_CONFIG_EXISTS       32
+#define KD_LARGE_MSG           64
+    krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, 
+                               krb5_krbhst_info**);
+
+    unsigned int fallback_count;
+
+    struct krb5_krbhst_info *hosts, **index, **end;
+};
+
+static krb5_boolean
+krbhst_empty(const struct krb5_krbhst_data *kd)
+{
+    return kd->index == &kd->hosts;
+}
+
+/*
+ * Return the default protocol for the `kd' (either TCP or UDP)
+ */
+
+static int
+krbhst_get_default_proto(struct krb5_krbhst_data *kd)
+{
+    if (kd->flags & KD_LARGE_MSG)
+       return KRB5_KRBHST_TCP;
+    return KRB5_KRBHST_UDP;
+}
+
+
+/*
+ * parse `spec' into a krb5_krbhst_info, defaulting the port to `def_port'
+ * and forcing it to `port' if port != 0
+ */
+
+static struct krb5_krbhst_info*
+parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd,
+              const char *spec, int def_port, int port)
+{
+    const char *p = spec;
+    struct krb5_krbhst_info *hi;
+    
+    hi = calloc(1, sizeof(*hi) + strlen(spec));
+    if(hi == NULL)
+       return NULL;
+       
+    hi->proto = krbhst_get_default_proto(kd);
+
+    if(strncmp(p, "http://", 7) == 0){
+       hi->proto = KRB5_KRBHST_HTTP;
+       p += 7;
+    } else if(strncmp(p, "http/", 5) == 0) {
+       hi->proto = KRB5_KRBHST_HTTP;
+       p += 5;
+       def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80));
+    }else if(strncmp(p, "tcp/", 4) == 0){
+       hi->proto = KRB5_KRBHST_TCP;
+       p += 4;
+    } else if(strncmp(p, "udp/", 4) == 0) {
+       p += 4;
+    }
+
+    if(strsep_copy(&p, ":", hi->hostname, strlen(spec) + 1) < 0) {
+       free(hi);
+       return NULL;
+    }
+    /* get rid of trailing /, and convert to lower case */
+    hi->hostname[strcspn(hi->hostname, "/")] = '\0';
+    strlwr(hi->hostname);
+
+    hi->port = hi->def_port = def_port;
+    if(p != NULL) {
+       char *end;
+       hi->port = strtol(p, &end, 0);
+       if(end == p) {
+           free(hi);
+           return NULL;
+       }
+    }
+    if (port)
+       hi->port = port;
+    return hi;
+}
+
+static void
+free_krbhst_info(krb5_krbhst_info *hi)
+{
+    if (hi->ai != NULL)
+       freeaddrinfo(hi->ai);
+    free(hi);
+}
+
+static void
+append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host)
+{
+    struct krb5_krbhst_info *h;
+
+    for(h = kd->hosts; h; h = h->next)
+       if(h->proto == host->proto && 
+          h->port == host->port && 
+          strcmp(h->hostname, host->hostname) == 0) {
+           free_krbhst_info(host);
+           return;
+       }
+    *kd->end = host;
+    kd->end = &host->next;
+}
+
+static krb5_error_code
+append_host_string(krb5_context context, struct krb5_krbhst_data *kd,
+                  const char *host, int def_port, int port)
+{
+    struct krb5_krbhst_info *hi;
+
+    hi = parse_hostspec(context, kd, host, def_port, port);
+    if(hi == NULL)
+       return ENOMEM;
+    
+    append_host_hostinfo(kd, hi);
+    return 0;
+}
+
+/*
+ * return a readable representation of `host' in `hostname, hostlen'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_format_string(krb5_context context, const krb5_krbhst_info *host, 
+                         char *hostname, size_t hostlen)
+{
+    const char *proto = "";
+    char portstr[7] = "";
+    if(host->proto == KRB5_KRBHST_TCP)
+       proto = "tcp/";
+    else if(host->proto == KRB5_KRBHST_HTTP)
+       proto = "http://";
+    if(host->port != host->def_port)
+       snprintf(portstr, sizeof(portstr), ":%d", host->port);
+    snprintf(hostname, hostlen, "%s%s%s", proto, host->hostname, portstr);
+    return 0;
+}
+
+/*
+ * create a getaddrinfo `hints' based on `proto'
+ */
+
+static void
+make_hints(struct addrinfo *hints, int proto)
+{
+    memset(hints, 0, sizeof(*hints));
+    hints->ai_family = AF_UNSPEC;
+    switch(proto) {
+    case KRB5_KRBHST_UDP :
+       hints->ai_socktype = SOCK_DGRAM;
+       break;
+    case KRB5_KRBHST_HTTP :
+    case KRB5_KRBHST_TCP :
+       hints->ai_socktype = SOCK_STREAM;
+       break;
+    }
+}
+
+/*
+ * return an `struct addrinfo *' in `ai' corresponding to the information
+ * in `host'.  free:ing is handled by krb5_krbhst_free.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host,
+                        struct addrinfo **ai)
+{
+    struct addrinfo hints;
+    char portstr[NI_MAXSERV];
+    int ret;
+
+    if (host->ai == NULL) {
+       make_hints(&hints, host->proto);
+       snprintf (portstr, sizeof(portstr), "%d", host->port);
+       ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai);
+       if (ret)
+           return krb5_eai_to_heim_errno(ret, errno);
+    }
+    *ai = host->ai;
+    return 0;
+}
+
+static krb5_boolean
+get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host)
+{
+    struct krb5_krbhst_info *hi = *kd->index;
+    if(hi != NULL) {
+       *host = hi;
+       kd->index = &(*kd->index)->next;
+       return TRUE;
+    }
+    return FALSE;
+}
+
+static void
+srv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 
+             const char *proto, const char *service)
+{
+    krb5_krbhst_info **res;
+    int count, i;
+
+    if (srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service,
+                      kd->port))
+       return;
+    for(i = 0; i < count; i++)
+       append_host_hostinfo(kd, res[i]);
+    free(res);
+}
+
+/*
+ * read the configuration for `conf_string', defaulting to kd->def_port and
+ * forcing it to `kd->port' if kd->port != 0
+ */
+
+static void
+config_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 
+                const char *conf_string)
+{
+    int i;
+       
+    char **hostlist;
+    hostlist = krb5_config_get_strings(context, NULL, 
+                                      "realms", kd->realm, conf_string, NULL);
+
+    if(hostlist == NULL)
+       return;
+    kd->flags |= KD_CONFIG_EXISTS;
+    for(i = 0; hostlist && hostlist[i] != NULL; i++)
+       append_host_string(context, kd, hostlist[i], kd->def_port, kd->port);
+
+    krb5_config_free_strings(hostlist);
+}
+
+/*
+ * as a fallback, look for `serv_string.kd->realm' (typically
+ * kerberos.REALM, kerberos-1.REALM, ...
+ * `port' is the default port for the service, and `proto' the 
+ * protocol
+ */
+
+static krb5_error_code
+fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, 
+                  const char *serv_string, int port, int proto)
+{
+    char *host;
+    int ret;
+    struct addrinfo *ai;
+    struct addrinfo hints;
+    char portstr[NI_MAXSERV];
+
+    if(kd->fallback_count == 0)
+       asprintf(&host, "%s.%s.", serv_string, kd->realm);
+    else
+       asprintf(&host, "%s-%d.%s.", 
+                serv_string, kd->fallback_count, kd->realm);       
+
+    if (host == NULL)
+       return ENOMEM;
+    
+    make_hints(&hints, proto);
+    snprintf(portstr, sizeof(portstr), "%d", port);
+    ret = getaddrinfo(host, portstr, &hints, &ai);
+    if (ret) {
+       /* no more hosts, so we're done here */
+       free(host);
+       kd->flags |= KD_FALLBACK;
+    } else {
+       struct krb5_krbhst_info *hi;
+       size_t hostlen = strlen(host);
+
+       hi = calloc(1, sizeof(*hi) + hostlen);
+       if(hi == NULL) {
+           free(host);
+           return ENOMEM;
+       }
+
+       hi->proto = proto;
+       hi->port  = hi->def_port = port;
+       hi->ai    = ai;
+       memmove(hi->hostname, host, hostlen - 1);
+       hi->hostname[hostlen - 1] = '\0';
+       free(host);
+       append_host_hostinfo(kd, hi);
+       kd->fallback_count++;
+    }
+    return 0;
+}
+
+static krb5_error_code
+kdc_get_next(krb5_context context,
+            struct krb5_krbhst_data *kd,
+            krb5_krbhst_info **host)
+{
+    krb5_error_code ret;
+
+    if((kd->flags & KD_CONFIG) == 0) {
+       config_get_hosts(context, kd, "kdc");
+       kd->flags |= KD_CONFIG;
+       if(get_next(kd, host))
+           return 0;
+    }
+
+    if (kd->flags & KD_CONFIG_EXISTS)
+       return KRB5_KDC_UNREACH; /* XXX */
+
+    if(context->srv_lookup) {
+       if((kd->flags & KD_SRV_UDP) == 0 && (kd->flags & KD_LARGE_MSG) == 0) {
+           srv_get_hosts(context, kd, "udp", "kerberos");
+           kd->flags |= KD_SRV_UDP;
+           if(get_next(kd, host))
+               return 0;
+       }
+
+       if((kd->flags & KD_SRV_TCP) == 0) {
+           srv_get_hosts(context, kd, "tcp", "kerberos");
+           kd->flags |= KD_SRV_TCP;
+           if(get_next(kd, host))
+               return 0;
+       }
+       if((kd->flags & KD_SRV_HTTP) == 0) {
+           srv_get_hosts(context, kd, "http", "kerberos");
+           kd->flags |= KD_SRV_HTTP;
+           if(get_next(kd, host))
+               return 0;
+       }
+    }
+
+    while((kd->flags & KD_FALLBACK) == 0) {
+       ret = fallback_get_hosts(context, kd, "kerberos",
+                                kd->def_port, 
+                                krbhst_get_default_proto(kd));
+       if(ret)
+           return ret;
+       if(get_next(kd, host))
+           return 0;
+    }
+
+    return KRB5_KDC_UNREACH; /* XXX */
+}
+
+static krb5_error_code
+admin_get_next(krb5_context context,
+              struct krb5_krbhst_data *kd,
+              krb5_krbhst_info **host)
+{
+    krb5_error_code ret;
+
+    if((kd->flags & KD_CONFIG) == 0) {
+       config_get_hosts(context, kd, "admin_server");
+       kd->flags |= KD_CONFIG;
+       if(get_next(kd, host))
+           return 0;
+    }
+
+    if (kd->flags & KD_CONFIG_EXISTS)
+       return KRB5_KDC_UNREACH; /* XXX */
+
+    if(context->srv_lookup) {
+       if((kd->flags & KD_SRV_TCP) == 0) {
+           srv_get_hosts(context, kd, "tcp", "kerberos-adm");
+           kd->flags |= KD_SRV_TCP;
+           if(get_next(kd, host))
+               return 0;
+       }
+    }
+
+    if (krbhst_empty(kd)
+       && (kd->flags & KD_FALLBACK) == 0) {
+       ret = fallback_get_hosts(context, kd, "kerberos",
+                                kd->def_port,
+                                krbhst_get_default_proto(kd));
+       if(ret)
+           return ret;
+       kd->flags |= KD_FALLBACK;
+       if(get_next(kd, host))
+           return 0;
+    }
+
+    return KRB5_KDC_UNREACH;   /* XXX */
+}
+
+static krb5_error_code
+kpasswd_get_next(krb5_context context,
+                struct krb5_krbhst_data *kd,
+                krb5_krbhst_info **host)
+{
+    krb5_error_code ret;
+
+    if((kd->flags & KD_CONFIG) == 0) {
+       config_get_hosts(context, kd, "kpasswd_server");
+       kd->flags |= KD_CONFIG;
+       if(get_next(kd, host))
+           return 0;
+    }
+
+    if (kd->flags & KD_CONFIG_EXISTS)
+       return KRB5_KDC_UNREACH; /* XXX */
+
+    if(context->srv_lookup) {
+       if((kd->flags & KD_SRV_UDP) == 0) {
+           srv_get_hosts(context, kd, "udp", "kpasswd");
+           kd->flags |= KD_SRV_UDP;
+           if(get_next(kd, host))
+               return 0;
+       }
+       if((kd->flags & KD_SRV_TCP) == 0) {
+           srv_get_hosts(context, kd, "tcp", "kpasswd");
+           kd->flags |= KD_SRV_TCP;
+           if(get_next(kd, host))
+               return 0;
+       }
+    }
+
+    /* no matches -> try admin */
+
+    if (krbhst_empty(kd)) {
+       kd->flags = 0;
+       kd->port  = kd->def_port;
+       kd->get_next = admin_get_next;
+       ret = (*kd->get_next)(context, kd, host);
+       if (ret == 0)
+           (*host)->proto = krbhst_get_default_proto(kd);
+       return ret;
+    }
+
+    return KRB5_KDC_UNREACH; /* XXX */
+}
+
+static krb5_error_code
+krb524_get_next(krb5_context context,
+               struct krb5_krbhst_data *kd,
+               krb5_krbhst_info **host)
+{
+    if((kd->flags & KD_CONFIG) == 0) {
+       config_get_hosts(context, kd, "krb524_server");
+       if(get_next(kd, host))
+           return 0;
+       kd->flags |= KD_CONFIG;
+    }
+
+    if (kd->flags & KD_CONFIG_EXISTS)
+       return KRB5_KDC_UNREACH; /* XXX */
+
+    if(context->srv_lookup) {
+       if((kd->flags & KD_SRV_UDP) == 0) {
+           srv_get_hosts(context, kd, "udp", "krb524");
+           kd->flags |= KD_SRV_UDP;
+           if(get_next(kd, host))
+               return 0;
+       }
+
+       if((kd->flags & KD_SRV_TCP) == 0) {
+           srv_get_hosts(context, kd, "tcp", "krb524");
+           kd->flags |= KD_SRV_TCP;
+           if(get_next(kd, host))
+               return 0;
+       }
+    }
+
+    /* no matches -> try kdc */
+
+    if (krbhst_empty(kd)) {
+       kd->flags = 0;
+       kd->port  = kd->def_port;
+       kd->get_next = kdc_get_next;
+       return (*kd->get_next)(context, kd, host);
+    }
+
+    return KRB5_KDC_UNREACH; /* XXX */
+}
+
+static struct krb5_krbhst_data*
+common_init(krb5_context context,
+           const char *realm,
+           int flags)
+{
+    struct krb5_krbhst_data *kd;
+
+    if((kd = calloc(1, sizeof(*kd))) == NULL)
+       return NULL;
+
+    if((kd->realm = strdup(realm)) == NULL) {
+       free(kd);
+       return NULL;
+    }
+
+    if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG)
+       kd->flags |= KD_LARGE_MSG;
+    kd->end = kd->index = &kd->hosts;
+    return kd;
+}
+
+/*
+ * initialize `handle' to look for hosts of type `type' in realm `realm'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_init(krb5_context context,
+                const char *realm,
+                unsigned int type,
+                krb5_krbhst_handle *handle)
+{
+    return krb5_krbhst_init_flags(context, realm, type, 0, handle);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_init_flags(krb5_context context,
+                      const char *realm,
+                      unsigned int type,
+                      int flags,
+                      krb5_krbhst_handle *handle)
+{
+    struct krb5_krbhst_data *kd;
+    krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, 
+                               krb5_krbhst_info **);
+    int def_port;
+
+    switch(type) {
+    case KRB5_KRBHST_KDC:
+       get_next = kdc_get_next;
+       def_port = ntohs(krb5_getportbyname (context, "kerberos", "udp", 88));
+       break;
+    case KRB5_KRBHST_ADMIN:
+       get_next = admin_get_next;
+       def_port = ntohs(krb5_getportbyname (context, "kerberos-adm",
+                                            "tcp", 749));
+       break;
+    case KRB5_KRBHST_CHANGEPW:
+       get_next = kpasswd_get_next;
+       def_port = ntohs(krb5_getportbyname (context, "kpasswd", "udp",
+                                            KPASSWD_PORT));
+       break;
+    case KRB5_KRBHST_KRB524:
+       get_next = krb524_get_next;
+       def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444));
+       break;
+    default:
+       krb5_set_error_string(context, "unknown krbhst type (%u)", type);
+       return ENOTTY;
+    }
+    if((kd = common_init(context, realm, flags)) == NULL)
+       return ENOMEM;
+    kd->get_next = get_next;
+    kd->def_port = def_port;
+    *handle = kd;
+    return 0;
+}
+
+/*
+ * return the next host information from `handle' in `host'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_next(krb5_context context,
+                krb5_krbhst_handle handle,
+                krb5_krbhst_info **host)
+{
+    if(get_next(handle, host))
+       return 0;
+
+    return (*handle->get_next)(context, handle, host);
+}
+
+/*
+ * return the next host information from `handle' as a host name
+ * in `hostname' (or length `hostlen)
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_krbhst_next_as_string(krb5_context context,
+                          krb5_krbhst_handle handle,
+                          char *hostname,
+                          size_t hostlen)
+{
+    krb5_error_code ret;
+    krb5_krbhst_info *host;
+    ret = krb5_krbhst_next(context, handle, &host);
+    if(ret)
+       return ret;
+    return krb5_krbhst_format_string(context, host, hostname, hostlen);
+}
+
+
+void KRB5_LIB_FUNCTION
+krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle)
+{
+    handle->index = &handle->hosts;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle)
+{
+    krb5_krbhst_info *h, *next;
+
+    if (handle == NULL)
+       return;
+
+    for (h = handle->hosts; h != NULL; h = next) {
+       next = h->next;
+       free_krbhst_info(h);
+    }
+
+    free(handle->realm);
+    free(handle);
+}
+
+/* backwards compatibility ahead */
+
+static krb5_error_code
+gethostlist(krb5_context context, const char *realm, 
+           unsigned int type, char ***hostlist)
+{
+    krb5_error_code ret;
+    int nhost = 0;
+    krb5_krbhst_handle handle;
+    char host[MAXHOSTNAMELEN];
+    krb5_krbhst_info *hostinfo;
+
+    ret = krb5_krbhst_init(context, realm, type, &handle);
+    if (ret)
+       return ret;
+
+    while(krb5_krbhst_next(context, handle, &hostinfo) == 0)
+       nhost++;
+    if(nhost == 0)
+       return KRB5_KDC_UNREACH;
+    *hostlist = calloc(nhost + 1, sizeof(**hostlist));
+    if(*hostlist == NULL) {
+       krb5_krbhst_free(context, handle);
+       return ENOMEM;
+    }
+
+    krb5_krbhst_reset(context, handle);
+    nhost = 0;
+    while(krb5_krbhst_next_as_string(context, handle, 
+                                    host, sizeof(host)) == 0) {
+       if(((*hostlist)[nhost++] = strdup(host)) == NULL) {
+           krb5_free_krbhst(context, *hostlist);
+           krb5_krbhst_free(context, handle);
+           return ENOMEM;
+       }
+    }
+    (*hostlist)[nhost++] = NULL;
+    krb5_krbhst_free(context, handle);
+    return 0;
+}
+
+/*
+ * return an malloced list of kadmin-hosts for `realm' in `hostlist'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krb_admin_hst (krb5_context context,
+                       const krb5_realm *realm,
+                       char ***hostlist)
+{
+    return gethostlist(context, *realm, KRB5_KRBHST_ADMIN, hostlist);
+}
+
+/*
+ * return an malloced list of changepw-hosts for `realm' in `hostlist'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krb_changepw_hst (krb5_context context,
+                          const krb5_realm *realm,
+                          char ***hostlist)
+{
+    return gethostlist(context, *realm, KRB5_KRBHST_CHANGEPW, hostlist);
+}
+
+/*
+ * return an malloced list of 524-hosts for `realm' in `hostlist'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krb524hst (krb5_context context,
+                   const krb5_realm *realm,
+                   char ***hostlist)
+{
+    return gethostlist(context, *realm, KRB5_KRBHST_KRB524, hostlist);
+}
+
+
+/*
+ * return an malloced list of KDC's for `realm' in `hostlist'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_krbhst (krb5_context context,
+                const krb5_realm *realm,
+                char ***hostlist)
+{
+    return gethostlist(context, *realm, KRB5_KRBHST_KDC, hostlist);
+}
+
+/*
+ * free all the memory allocated in `hostlist'
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_krbhst (krb5_context context,
+                 char **hostlist)
+{
+    char **p;
+
+    for (p = hostlist; *p; ++p)
+       free (*p);
+    free (hostlist);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/kuserok.c b/src/kerberosV/src/lib/krb5/kuserok.c
new file mode 100644 (file)
index 0000000..684d5bd
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <dirent.h>
+
+RCSID("$KTH: kuserok.c,v 1.13.2.1 2005/09/09 10:47:46 lha Exp $");
+
+/* see if principal is mentioned in the filename access file, return
+   TRUE (in result) if so, FALSE otherwise */
+
+static krb5_error_code
+check_one_file(krb5_context context, 
+              const char *filename, 
+              struct passwd *pwd,
+              krb5_principal principal, 
+              krb5_boolean *result)
+{
+    FILE *f;
+    char buf[BUFSIZ];
+    krb5_error_code ret;
+    struct stat st;
+    
+    *result = FALSE;
+
+    f = fopen (filename, "r");
+    if (f == NULL)
+       return errno;
+    
+    /* check type and mode of file */
+    if (fstat(fileno(f), &st) != 0) {
+       fclose (f);
+       return errno;
+    }
+    if (S_ISDIR(st.st_mode)) {
+       fclose (f);
+       return EISDIR;
+    }
+    if (st.st_uid != pwd->pw_uid && st.st_uid != 0) {
+       fclose (f);
+       return EACCES;
+    }
+    if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0) {
+       fclose (f);
+       return EACCES;
+    }
+
+    while (fgets (buf, sizeof(buf), f) != NULL) {
+       krb5_principal tmp;
+       char *newline = buf + strcspn(buf, "\n");
+
+       if(*newline != '\n') {
+           int c;
+           c = fgetc(f);
+           if(c != EOF) {
+               while(c != EOF && c != '\n')
+                   c = fgetc(f);
+               /* line was too long, so ignore it */
+               continue;
+           }
+       }
+       *newline = '\0';
+       ret = krb5_parse_name (context, buf, &tmp);
+       if (ret)
+           continue;
+       *result = krb5_principal_compare (context, principal, tmp);
+       krb5_free_principal (context, tmp);
+       if (*result) {
+           fclose (f);
+           return 0;
+       }
+    }
+    fclose (f);
+    return 0;
+}
+
+static krb5_error_code
+check_directory(krb5_context context, 
+               const char *dirname, 
+               struct passwd *pwd,
+               krb5_principal principal, 
+               krb5_boolean *result)
+{
+    DIR *d;
+    struct dirent *dent;
+    char filename[MAXPATHLEN];
+    krb5_error_code ret = 0;
+    struct stat st;
+
+    *result = FALSE;
+
+    if(lstat(dirname, &st) < 0)
+       return errno;
+
+    if (!S_ISDIR(st.st_mode))
+       return ENOTDIR;
+    
+    if (st.st_uid != pwd->pw_uid && st.st_uid != 0)
+       return EACCES;
+    if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
+       return EACCES;
+
+    if((d = opendir(dirname)) == NULL) 
+       return errno;
+
+#ifdef HAVE_DIRFD
+    {
+       int fd;
+       struct stat st2;
+
+       fd = dirfd(d);
+       if(fstat(fd, &st2) < 0) {
+           closedir(d);
+           return errno;
+       }
+       if(st.st_dev != st2.st_dev || st.st_ino != st2.st_ino) {
+           closedir(d);
+           return EACCES;
+       }
+    }
+#endif
+
+    while((dent = readdir(d)) != NULL) {
+       if(strcmp(dent->d_name, ".") == 0 ||
+          strcmp(dent->d_name, "..") == 0 ||
+          dent->d_name[0] == '#' ||                      /* emacs autosave */
+          dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */
+           continue;
+       snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name);
+       ret = check_one_file(context, filename, pwd, principal, result);
+       if(ret == 0 && *result == TRUE)
+           break;
+       ret = 0; /* don't propagate errors upstream */
+    }
+    closedir(d);
+    return ret;
+}
+
+static krb5_boolean
+match_local_principals(krb5_context context,
+                      krb5_principal principal,
+                      const char *luser)
+{
+    krb5_error_code ret;
+    krb5_realm *realms, *r;
+    krb5_boolean result = FALSE;
+    
+    /* multi-component principals can never match */
+    if(krb5_principal_get_comp_string(context, principal, 1) != NULL)
+       return FALSE;
+
+    ret = krb5_get_default_realms (context, &realms);
+    if (ret)
+       return FALSE;
+       
+    for (r = realms; *r != NULL; ++r) {
+       if(strcmp(krb5_principal_get_realm(context, principal),
+                 *r) != 0)
+           continue;
+       if(strcmp(krb5_principal_get_comp_string(context, principal, 0),
+                 luser) == 0) {
+           result = TRUE;
+           break;
+       }
+    }
+    krb5_free_host_realm (context, realms);
+    return result;
+}
+
+/**
+ * Return TRUE iff `principal' is allowed to login as `luser'.
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_kuserok (krb5_context context,
+             krb5_principal principal,
+             const char *luser)
+{
+    char *buf;
+    size_t buflen;
+    struct passwd *pwd;
+    krb5_error_code ret;
+    krb5_boolean result = FALSE;
+
+    krb5_boolean found_file = FALSE;
+
+#ifdef POSIX_GETPWNAM_R
+    char pwbuf[2048];
+    struct passwd pw;
+
+    if(getpwnam_r(luser, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
+       return FALSE;
+#else
+    pwd = getpwnam (luser);
+#endif
+    if (pwd == NULL)
+       return FALSE;
+
+#define KLOGIN "/.k5login"
+    buflen = strlen(pwd->pw_dir) + sizeof(KLOGIN) + 2; /* 2 for .d */
+    buf = malloc(buflen);
+    if(buf == NULL)
+       return FALSE;
+    /* check user's ~/.k5login */
+    strlcpy(buf, pwd->pw_dir, buflen);
+    strlcat(buf, KLOGIN, buflen);
+    ret = check_one_file(context, buf, pwd, principal, &result);
+
+    if(ret == 0 && result == TRUE) {
+       free(buf);
+       return TRUE;
+    }
+
+    if(ret != ENOENT) 
+       found_file = TRUE;
+
+    strlcat(buf, ".d", buflen);
+    ret = check_directory(context, buf, pwd, principal, &result);
+    free(buf);
+    if(ret == 0 && result == TRUE)
+       return TRUE;
+
+    if(ret != ENOENT && ret != ENOTDIR) 
+       found_file = TRUE;
+
+    /* finally if no files exist, allow all principals matching
+       <localuser>@<LOCALREALM> */
+    if(found_file == FALSE)
+       return match_local_principals(context, principal, luser);
+
+    return FALSE;
+}
diff --git a/src/kerberosV/src/lib/krb5/log.c b/src/kerberosV/src/lib/krb5/log.c
new file mode 100644 (file)
index 0000000..2ab8af9
--- /dev/null
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: log.c,v 1.34 2005/06/11 00:14:28 lha Exp $");
+
+struct facility {
+    int min;
+    int max;
+    krb5_log_log_func_t log;
+    krb5_log_close_func_t close;
+    void *data;
+};
+
+static struct facility*
+log_realloc(krb5_log_facility *f)
+{
+    struct facility *fp;
+    fp = realloc(f->val, (f->len + 1) * sizeof(*f->val));
+    if(fp == NULL)
+       return NULL;
+    f->len++;
+    f->val = fp;
+    fp += f->len - 1;
+    return fp;
+}
+
+struct s2i {
+    const char *s;
+    int val;
+};
+
+#define L(X) { #X, LOG_ ## X }
+
+static struct s2i syslogvals[] = {
+    L(EMERG),
+    L(ALERT),
+    L(CRIT),
+    L(ERR),
+    L(WARNING),
+    L(NOTICE),
+    L(INFO),
+    L(DEBUG),
+
+    L(AUTH),
+#ifdef LOG_AUTHPRIV
+    L(AUTHPRIV),
+#endif
+#ifdef LOG_CRON
+    L(CRON),
+#endif
+    L(DAEMON),
+#ifdef LOG_FTP
+    L(FTP),
+#endif
+    L(KERN),
+    L(LPR),
+    L(MAIL),
+#ifdef LOG_NEWS
+    L(NEWS),
+#endif
+    L(SYSLOG),
+    L(USER),
+#ifdef LOG_UUCP
+    L(UUCP),
+#endif
+    L(LOCAL0),
+    L(LOCAL1),
+    L(LOCAL2),
+    L(LOCAL3),
+    L(LOCAL4),
+    L(LOCAL5),
+    L(LOCAL6),
+    L(LOCAL7),
+    { NULL, -1 }
+};
+
+static int
+find_value(const char *s, struct s2i *table)
+{
+    while(table->s && strcasecmp(table->s, s))
+       table++;
+    return table->val;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_initlog(krb5_context context,
+            const char *program,
+            krb5_log_facility **fac)
+{
+    krb5_log_facility *f = calloc(1, sizeof(*f));
+    if(f == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    f->program = strdup(program);
+    if(f->program == NULL){
+       free(f);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    *fac = f;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_addlog_func(krb5_context context,
+                krb5_log_facility *fac,
+                int min,
+                int max,
+                krb5_log_log_func_t log,
+                krb5_log_close_func_t close,
+                void *data)
+{
+    struct facility *fp = log_realloc(fac);
+    if(fp == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    fp->min = min;
+    fp->max = max;
+    fp->log = log;
+    fp->close = close;
+    fp->data = data;
+    return 0;
+}
+
+/* Avoid conflict with syslog_data in syslog.h, rename to syslog_d */
+
+struct _heimdal_syslog_data{
+    int priority;
+};
+
+static void
+log_syslog(const char *time,
+          const char *msg,
+          void *data)
+     
+{
+    struct _heimdal_syslog_data *s = data;
+    syslog(s->priority, "%s", msg);
+}
+
+static void
+close_syslog(void *data)
+{
+    free(data);
+    closelog();
+}
+
+static krb5_error_code
+open_syslog(krb5_context context,
+           krb5_log_facility *facility, int min, int max,
+           const char *sev, const char *fac)
+{
+    struct _heimdal_syslog_data *sd = malloc(sizeof(*sd));
+    int i;
+
+    if(sd == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    i = find_value(sev, syslogvals);
+    if(i == -1)
+       i = LOG_ERR;
+    sd->priority = i;
+    i = find_value(fac, syslogvals);
+    if(i == -1)
+       i = LOG_AUTH;
+    sd->priority |= i;
+    roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i);
+    return krb5_addlog_func(context, facility, min, max,
+                           log_syslog, close_syslog, sd);
+}
+
+struct file_data{
+    const char *filename;
+    const char *mode;
+    FILE *fd;
+    int keep_open;
+};
+
+static void
+log_file(const char *time,
+        const char *msg,
+        void *data)
+{
+    struct file_data *f = data;
+    if(f->keep_open == 0)
+       f->fd = fopen(f->filename, f->mode);
+    if(f->fd == NULL)
+       return;
+    fprintf(f->fd, "%s %s\n", time, msg);
+    if(f->keep_open == 0)
+       fclose(f->fd);
+}
+
+static void
+close_file(void *data)
+{
+    struct file_data *f = data;
+    if(f->keep_open && f->filename)
+       fclose(f->fd);
+    free(data);
+}
+
+static krb5_error_code
+open_file(krb5_context context, krb5_log_facility *fac, int min, int max,
+         const char *filename, const char *mode, FILE *f, int keep_open)
+{
+    struct file_data *fd = malloc(sizeof(*fd));
+    if(fd == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    fd->filename = filename;
+    fd->mode = mode;
+    fd->fd = f;
+    fd->keep_open = keep_open;
+
+    return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd);
+}
+
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig)
+{
+    krb5_error_code ret = 0;
+    int min = 0, max = -1, n;
+    char c;
+    const char *p = orig;
+
+    n = sscanf(p, "%d%c%d/", &min, &c, &max);
+    if(n == 2){
+       if(c == '/') {
+           if(min < 0){
+               max = -min;
+               min = 0;
+           }else{
+               max = min;
+           }
+       }
+    }
+    if(n){
+       p = strchr(p, '/');
+       if(p == NULL) {
+           krb5_set_error_string (context, "failed to parse \"%s\"", orig);
+           return HEIM_ERR_LOG_PARSE;
+       }
+       p++;
+    }
+    if(strcmp(p, "STDERR") == 0){
+       ret = open_file(context, f, min, max, NULL, NULL, stderr, 1);
+    }else if(strcmp(p, "CONSOLE") == 0){
+       ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0);
+    }else if(strncmp(p, "FILE:", 4) == 0 && (p[4] == ':' || p[4] == '=')){
+       char *fn;
+       FILE *file = NULL;
+       int keep_open = 0;
+       fn = strdup(p + 5);
+       if(fn == NULL) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           return ENOMEM;
+       }
+       if(p[4] == '='){
+           int i = open(fn, O_WRONLY | O_CREAT | 
+                        O_TRUNC | O_APPEND, 0666);
+           if(i < 0) {
+               ret = errno;
+               krb5_set_error_string (context, "open(%s): %s", fn,
+                                      strerror(ret));
+               free(fn);
+               return ret;
+           }
+           file = fdopen(i, "a");
+           if(file == NULL){
+               ret = errno;
+               close(i);
+               krb5_set_error_string (context, "fdopen(%s): %s", fn,
+                                      strerror(ret));
+               free(fn);
+               return ret;
+           }
+           keep_open = 1;
+       }
+       ret = open_file(context, f, min, max, fn, "a", file, keep_open);
+    }else if(strncmp(p, "DEVICE=", 6) == 0){
+       ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0);
+    }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){
+       char severity[128] = "";
+       char facility[128] = "";
+       p += 6;
+       if(*p != '\0')
+           p++;
+       if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
+           strsep_copy(&p, ":", facility, sizeof(facility));
+       if(*severity == '\0')
+           strlcpy(severity, "ERR", sizeof(severity));
+       if(*facility == '\0')
+           strlcpy(facility, "AUTH", sizeof(facility));
+       ret = open_syslog(context, f, min, max, severity, facility);
+    }else{
+       krb5_set_error_string (context, "unknown log type: %s", p);
+       ret = HEIM_ERR_LOG_PARSE; /* XXX */
+    }
+    return ret;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_openlog(krb5_context context,
+            const char *program,
+            krb5_log_facility **fac)
+{
+    krb5_error_code ret;
+    char **p, **q;
+
+    ret = krb5_initlog(context, program, fac);
+    if(ret)
+       return ret;
+
+    p = krb5_config_get_strings(context, NULL, "logging", program, NULL);
+    if(p == NULL)
+       p = krb5_config_get_strings(context, NULL, "logging", "default", NULL);
+    if(p){
+       for(q = p; *q; q++)
+           ret = krb5_addlog_dest(context, *fac, *q);
+       krb5_config_free_strings(p);
+    }else
+       ret = krb5_addlog_dest(context, *fac, "SYSLOG");
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_closelog(krb5_context context,
+             krb5_log_facility *fac)
+{
+    int i;
+    for(i = 0; i < fac->len; i++)
+       (*fac->val[i].close)(fac->val[i].data);
+    free(fac->val);
+    free(fac->program);
+    fac->val = NULL;
+    fac->len = 0;
+    fac->program = NULL;
+    free(fac);
+    return 0;
+}
+
+#undef __attribute__
+#define __attribute__(X)
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vlog_msg(krb5_context context,
+             krb5_log_facility *fac,
+             char **reply,
+             int level,
+             const char *fmt,
+             va_list ap)
+     __attribute__((format (printf, 5, 0)))
+{
+    
+    char *msg = NULL;
+    const char *actual = NULL;
+    char buf[64];
+    time_t t = 0;
+    int i;
+
+    for(i = 0; fac && i < fac->len; i++)
+       if(fac->val[i].min <= level && 
+          (fac->val[i].max < 0 || fac->val[i].max >= level)) {
+           if(t == 0) {
+               t = time(NULL);
+               krb5_format_time(context, t, buf, sizeof(buf), TRUE);
+           }
+           if(actual == NULL) {
+               vasprintf(&msg, fmt, ap);
+               if(msg == NULL)
+                   actual = fmt;
+               else
+                   actual = msg;
+           }
+           (*fac->val[i].log)(buf, actual, fac->val[i].data);
+       }
+    if(reply == NULL)
+       free(msg);
+    else
+       *reply = msg;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vlog(krb5_context context,
+         krb5_log_facility *fac,
+         int level,
+         const char *fmt,
+         va_list ap)
+     __attribute__((format (printf, 4, 0)))
+{
+    return krb5_vlog_msg(context, fac, NULL, level, fmt, ap);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_log_msg(krb5_context context,
+            krb5_log_facility *fac,
+            int level,
+            char **reply,
+            const char *fmt,
+            ...)
+     __attribute__((format (printf, 5, 6)))
+{
+    va_list ap;
+    krb5_error_code ret;
+
+    va_start(ap, fmt);
+    ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_log(krb5_context context,
+        krb5_log_facility *fac,
+        int level,
+        const char *fmt,
+        ...)
+     __attribute__((format (printf, 4, 5)))
+{
+    va_list ap;
+    krb5_error_code ret;
+
+    va_start(ap, fmt);
+    ret = krb5_vlog(context, fac, level, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+
diff --git a/src/kerberosV/src/lib/krb5/mcache.c b/src/kerberosV/src/lib/krb5/mcache.c
new file mode 100644 (file)
index 0000000..59c3d5b
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: mcache.c,v 1.19 2004/04/25 19:25:35 joda Exp $");
+
+typedef struct krb5_mcache {
+    char *name;
+    unsigned int refcnt;
+    int dead;
+    krb5_principal primary_principal;
+    struct link {
+       krb5_creds cred;
+       struct link *next;
+    } *creds;
+    struct krb5_mcache *next;
+} krb5_mcache;
+
+static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static struct krb5_mcache *mcc_head;
+
+#define        MCACHE(X)       ((krb5_mcache *)(X)->data.data)
+
+#define MISDEAD(X)     ((X)->dead)
+
+#define MCC_CURSOR(C) ((struct link*)(C))
+
+static const char*
+mcc_get_name(krb5_context context,
+            krb5_ccache id)
+{
+    return MCACHE(id)->name;
+}
+
+static krb5_mcache *
+mcc_alloc(const char *name)
+{
+    krb5_mcache *m, *m_c;
+
+    ALLOC(m, 1);
+    if(m == NULL)
+       return NULL;
+    if(name == NULL)
+       asprintf(&m->name, "%p", m);
+    else
+       m->name = strdup(name);
+    if(m->name == NULL) {
+       free(m);
+       return NULL;
+    }
+    /* check for dups first */
+    HEIMDAL_MUTEX_lock(&mcc_mutex);
+    for (m_c = mcc_head; m_c != NULL; m_c = m_c->next)
+       if (strcmp(m->name, m_c->name) == 0)
+           break;
+    if (m_c) {
+       free(m->name);
+       free(m);
+       HEIMDAL_MUTEX_unlock(&mcc_mutex);
+       return NULL;
+    }
+
+    m->dead = 0;
+    m->refcnt = 1;
+    m->primary_principal = NULL;
+    m->creds = NULL;
+    m->next = mcc_head;
+    mcc_head = m;
+    HEIMDAL_MUTEX_unlock(&mcc_mutex);
+    return m;
+}
+
+static krb5_error_code
+mcc_resolve(krb5_context context, krb5_ccache *id, const char *res)
+{
+    krb5_mcache *m;
+
+    HEIMDAL_MUTEX_lock(&mcc_mutex);
+    for (m = mcc_head; m != NULL; m = m->next)
+       if (strcmp(m->name, res) == 0)
+           break;
+    HEIMDAL_MUTEX_unlock(&mcc_mutex);
+
+    if (m != NULL) {
+       m->refcnt++;
+       (*id)->data.data = m;
+       (*id)->data.length = sizeof(*m);
+       return 0;
+    }
+
+    m = mcc_alloc(res);
+    if (m == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    
+    (*id)->data.data = m;
+    (*id)->data.length = sizeof(*m);
+
+    return 0;
+}
+
+
+static krb5_error_code
+mcc_gen_new(krb5_context context, krb5_ccache *id)
+{
+    krb5_mcache *m;
+
+    m = mcc_alloc(NULL);
+
+    if (m == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+
+    (*id)->data.data = m;
+    (*id)->data.length = sizeof(*m);
+
+    return 0;
+}
+
+static krb5_error_code
+mcc_initialize(krb5_context context,
+              krb5_ccache id,
+              krb5_principal primary_principal)
+{
+    krb5_mcache *m = MCACHE(id);
+    m->dead = 0;
+    return krb5_copy_principal (context,
+                               primary_principal,
+                               &m->primary_principal);
+}
+
+static krb5_error_code
+mcc_close(krb5_context context,
+         krb5_ccache id)
+{
+    krb5_mcache *m = MCACHE(id);
+
+    if (--m->refcnt != 0)
+       return 0;
+
+    if (MISDEAD(m)) {
+       free (m->name);
+       krb5_data_free(&id->data);
+    }
+
+    return 0;
+}
+
+static krb5_error_code
+mcc_destroy(krb5_context context,
+           krb5_ccache id)
+{
+    krb5_mcache **n, *m = MCACHE(id);
+    struct link *l;
+
+    if (m->refcnt == 0)
+       krb5_abortx(context, "mcc_destroy: refcnt already 0");
+
+    if (!MISDEAD(m)) {
+       /* if this is an active mcache, remove it from the linked
+           list, and free all data */
+       HEIMDAL_MUTEX_lock(&mcc_mutex);
+       for(n = &mcc_head; n && *n; n = &(*n)->next) {
+           if(m == *n) {
+               *n = m->next;
+               break;
+           }
+       }
+       HEIMDAL_MUTEX_unlock(&mcc_mutex);
+       if (m->primary_principal != NULL) {
+           krb5_free_principal (context, m->primary_principal);
+           m->primary_principal = NULL;
+       }
+       m->dead = 1;
+
+       l = m->creds;
+       while (l != NULL) {
+           struct link *old;
+           
+           krb5_free_cred_contents (context, &l->cred);
+           old = l;
+           l = l->next;
+           free (old);
+       }
+       m->creds = NULL;
+    }
+    return 0;
+}
+
+static krb5_error_code
+mcc_store_cred(krb5_context context,
+              krb5_ccache id,
+              krb5_creds *creds)
+{
+    krb5_mcache *m = MCACHE(id);
+    krb5_error_code ret;
+    struct link *l;
+
+    if (MISDEAD(m))
+       return ENOENT;
+
+    l = malloc (sizeof(*l));
+    if (l == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return KRB5_CC_NOMEM;
+    }
+    l->next = m->creds;
+    m->creds = l;
+    memset (&l->cred, 0, sizeof(l->cred));
+    ret = krb5_copy_creds_contents (context, creds, &l->cred);
+    if (ret) {
+       m->creds = l->next;
+       free (l);
+       return ret;
+    }
+    return 0;
+}
+
+static krb5_error_code
+mcc_get_principal(krb5_context context,
+                 krb5_ccache id,
+                 krb5_principal *principal)
+{
+    krb5_mcache *m = MCACHE(id);
+
+    if (MISDEAD(m) || m->primary_principal == NULL)
+       return ENOENT;
+    return krb5_copy_principal (context,
+                               m->primary_principal,
+                               principal);
+}
+
+static krb5_error_code
+mcc_get_first (krb5_context context,
+              krb5_ccache id,
+              krb5_cc_cursor *cursor)
+{
+    krb5_mcache *m = MCACHE(id);
+
+    if (MISDEAD(m))
+       return ENOENT;
+
+    *cursor = m->creds;
+    return 0;
+}
+
+static krb5_error_code
+mcc_get_next (krb5_context context,
+             krb5_ccache id,
+             krb5_cc_cursor *cursor,
+             krb5_creds *creds)
+{
+    krb5_mcache *m = MCACHE(id);
+    struct link *l;
+
+    if (MISDEAD(m))
+       return ENOENT;
+
+    l = *cursor;
+    if (l != NULL) {
+       *cursor = l->next;
+       return krb5_copy_creds_contents (context,
+                                        &l->cred,
+                                        creds);
+    } else
+       return KRB5_CC_END;
+}
+
+static krb5_error_code
+mcc_end_get (krb5_context context,
+            krb5_ccache id,
+            krb5_cc_cursor *cursor)
+{
+    return 0;
+}
+
+static krb5_error_code
+mcc_remove_cred(krb5_context context,
+                krb5_ccache id,
+                krb5_flags which,
+                krb5_creds *mcreds)
+{
+    krb5_mcache *m = MCACHE(id);
+    struct link **q, *p;
+    for(q = &m->creds, p = *q; p; p = *q) {
+       if(krb5_compare_creds(context, which, mcreds, &p->cred)) {
+           *q = p->next;
+           krb5_free_cred_contents(context, &p->cred);
+           free(p);
+       } else
+           q = &p->next;
+    }
+    return 0;
+}
+
+static krb5_error_code
+mcc_set_flags(krb5_context context,
+             krb5_ccache id,
+             krb5_flags flags)
+{
+    return 0; /* XXX */
+}
+                   
+const krb5_cc_ops krb5_mcc_ops = {
+    "MEMORY",
+    mcc_get_name,
+    mcc_resolve,
+    mcc_gen_new,
+    mcc_initialize,
+    mcc_destroy,
+    mcc_close,
+    mcc_store_cred,
+    NULL, /* mcc_retrieve */
+    mcc_get_principal,
+    mcc_get_first,
+    mcc_get_next,
+    mcc_end_get,
+    mcc_remove_cred,
+    mcc_set_flags
+};
diff --git a/src/kerberosV/src/lib/krb5/misc.c b/src/kerberosV/src/lib/krb5/misc.c
new file mode 100644 (file)
index 0000000..f6b4c58
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: misc.c,v 1.5 1999/12/02 17:05:11 joda Exp $");
diff --git a/src/kerberosV/src/lib/krb5/mit_glue.c b/src/kerberosV/src/lib/krb5/mit_glue.c
new file mode 100644 (file)
index 0000000..7c4a975
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+RCSID("$KTH: mit_glue.c,v 1.7 2005/05/18 04:21:44 lha Exp $");
+
+/*
+ * Glue for MIT API
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       return ret;
+
+    ret = krb5_create_checksum(context, crypto,  usage, cksumtype,
+                              input->data, input->length, cksum);
+    krb5_crypto_destroy(context, crypto);
+
+    return ret ;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    krb5_checksum data_cksum;
+
+    *valid = 0;
+
+    ret = krb5_c_make_checksum(context, cksum->cksumtype,
+                              key, usage, data, &data_cksum);
+    if (ret)
+       return ret;
+
+    if (data_cksum.cksumtype == cksum->cksumtype
+       && data_cksum.checksum.length == cksum->checksum.length
+       && memcmp(data_cksum.checksum.data, cksum->checksum.data, cksum->checksum.length) == 0)
+       *valid = 1;
+
+    krb5_free_checksum_contents(context, &data_cksum);
+
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_get_checksum(krb5_context context, const krb5_checksum *cksum,
+                   krb5_cksumtype *type, krb5_data **data)
+{
+    krb5_error_code ret;
+
+    if (type)
+       *type = cksum->cksumtype;
+    if (data) {
+       *data = malloc(sizeof(**data));
+       if (*data == NULL)
+           return ENOMEM;
+
+       ret = copy_octet_string(&cksum->checksum, *data);
+       if (ret) {
+           free(*data);
+           *data = NULL;
+           return ret;
+       }
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_set_checksum(krb5_context context, krb5_checksum *cksum,
+                   krb5_cksumtype type, const krb5_data *data)
+{
+    cksum->cksumtype = type;
+    return copy_octet_string(data, &cksum->checksum);
+}
+
+void KRB5_LIB_FUNCTION 
+krb5_free_checksum (krb5_context context, krb5_checksum *cksum)
+{
+    krb5_checksum_free(context, cksum);
+    free(cksum);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_checksum_contents(krb5_context context, krb5_checksum *cksum)
+{
+    krb5_checksum_free(context, cksum);
+    memset(cksum, 0, sizeof(*cksum));
+}
+
+void KRB5_LIB_FUNCTION
+krb5_checksum_free(krb5_context context, krb5_checksum *cksum)
+{
+    free_Checksum(cksum);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_valid_enctype (krb5_enctype etype)
+{
+    return krb5_enctype_valid(NULL, etype);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_valid_cksumtype(krb5_cksumtype ctype)
+{
+    return krb5_cksumtype_valid(NULL, ctype);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
+{
+    return krb5_checksum_is_collision_proof(NULL, ctype);
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_c_is_keyed_cksum(krb5_cksumtype ctype)
+{
+    return krb5_checksum_is_keyed(NULL, ctype);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_checksum (krb5_context context,
+                   const krb5_checksum *old,
+                   krb5_checksum **new)
+{
+    *new = malloc(sizeof(**new));
+    if (*new == NULL)
+       return ENOMEM;
+    return copy_Checksum(old, *new);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_checksum_length (krb5_context context, krb5_cksumtype cksumtype,
+                       size_t *length)
+{
+    return krb5_checksumsize(context, cksumtype, length);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_block_size(krb5_context context, 
+                 krb5_enctype enctype, 
+                 size_t *blocksize)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    krb5_keyblock key;
+
+    ret = krb5_generate_random_keyblock(context, enctype, &key);
+    if (ret)
+       return ret;
+
+    ret = krb5_crypto_init(context, &key, 0, &crypto);
+    krb5_free_keyblock_contents(context, &key);
+    if (ret)
+       return ret;
+    ret = krb5_crypto_getblocksize(context, crypto, blocksize);
+    krb5_crypto_destroy(context, crypto);
+
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_decrypt(krb5_context context, 
+              const krb5_keyblock key, 
+              krb5_keyusage usage, 
+              const krb5_data *ivec, 
+              krb5_enc_data *input, 
+              krb5_data *output)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, &key, input->enctype, &crypto);
+    if (ret)
+       return ret;
+
+    if (ivec) {
+       size_t blocksize;
+
+       ret = krb5_crypto_getblocksize(context, crypto, &blocksize);
+       if (ret) {
+       krb5_crypto_destroy(context, crypto);
+       return ret;
+       }
+       
+       if (blocksize > ivec->length) {
+           krb5_crypto_destroy(context, crypto);
+           return KRB5_BAD_MSIZE;
+       }
+    }
+
+    ret = krb5_decrypt_ivec(context, crypto, usage, 
+                           input->ciphertext.data, input->ciphertext.length, 
+                           output, 
+                           ivec ? ivec->data : NULL);
+
+    krb5_crypto_destroy(context, crypto);
+
+    return ret ;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+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)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       return ret;
+
+    if (ivec) {
+       size_t blocksize;
+
+       ret = krb5_crypto_getblocksize(context, crypto, &blocksize);
+       if (ret) {
+           krb5_crypto_destroy(context, crypto);
+           return ret;
+       }
+
+       if (blocksize > ivec->length) {
+           krb5_crypto_destroy(context, crypto);
+           return KRB5_BAD_MSIZE;
+       }
+    }
+
+    ret = krb5_encrypt_ivec(context, crypto, usage, 
+                           input->data, input->length, 
+                           &output->ciphertext, 
+                           ivec ? ivec->data : NULL);
+    output->kvno = 0;
+    krb5_crypto_getenctype(context, crypto, &output->enctype);
+
+    krb5_crypto_destroy(context, crypto);
+
+    return ret ;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_encrypt_length(krb5_context context, 
+                     krb5_enctype enctype, 
+                     size_t inputlen,
+                     size_t *length)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    krb5_keyblock key;
+
+    ret = krb5_generate_random_keyblock(context, enctype, &key);
+    if (ret)
+       return ret;
+
+    ret = krb5_crypto_init(context, &key, 0, &crypto);
+    krb5_free_keyblock_contents(context, &key);
+    if (ret)
+       return ret;
+
+    *length = krb5_get_wrapped_length(context, crypto, inputlen);
+    krb5_crypto_destroy(context, crypto);
+
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_enctype_compare(krb5_context context, 
+                      krb5_enctype e1,
+                      krb5_enctype e2, 
+                      krb5_boolean *similar)
+{
+    *similar = krb5_enctypes_compatible_keys(context, e1, e2);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_c_make_random_key(krb5_context context,
+                      krb5_enctype enctype, 
+                      krb5_keyblock *random_key)
+{
+    return krb5_generate_random_keyblock(context, enctype, random_key);
+}
diff --git a/src/kerberosV/src/lib/krb5/mk_error.c b/src/kerberosV/src/lib/krb5/mk_error.c
new file mode 100644 (file)
index 0000000..b4f58a4
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: mk_error.c,v 1.21 2004/05/25 21:33:10 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_error(krb5_context context,
+             krb5_error_code error_code,
+             const char *e_text,
+             const krb5_data *e_data,
+             const krb5_principal client,
+             const krb5_principal server,
+             time_t *client_time,
+             int *client_usec,
+             krb5_data *reply)
+{
+    KRB_ERROR msg;
+    krb5_timestamp sec;
+    int32_t usec;
+    size_t len;
+    krb5_error_code ret = 0;
+
+    krb5_us_timeofday (context, &sec, &usec);
+
+    memset(&msg, 0, sizeof(msg));
+    msg.pvno     = 5;
+    msg.msg_type = krb_error;
+    msg.stime    = sec;
+    msg.susec    = usec;
+    msg.ctime    = client_time;
+    msg.cusec    = client_usec;
+    /* Make sure we only send `protocol' error codes */
+    if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) {
+       if(e_text == NULL)
+           e_text = krb5_get_err_text(context, error_code);
+       error_code = KRB5KRB_ERR_GENERIC;
+    }
+    msg.error_code = error_code - KRB5KDC_ERR_NONE;
+    if (e_text)
+       msg.e_text = (heim_general_string*)&e_text;
+    if (e_data)
+       msg.e_data = (heim_octet_string*)e_data;
+    if(server){
+       msg.realm = server->realm;
+       msg.sname = server->name;
+    }else{
+       msg.realm = "<unspecified realm>";
+    }
+    if(client){
+       msg.crealm = &client->realm;
+       msg.cname = &client->name;
+    }
+
+    ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret);
+    if (ret)
+       return ret;
+    if(reply->length != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/mk_priv.c b/src/kerberosV/src/lib/krb5/mk_priv.c
new file mode 100644 (file)
index 0000000..1879f5f
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: mk_priv.c,v 1.34 2004/05/25 21:33:32 lha Exp $");
+
+      
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    KRB_PRIV s;
+    EncKrbPrivPart part;
+    u_char *buf = NULL;
+    size_t buf_size;
+    size_t len;
+    krb5_crypto crypto;
+    krb5_keyblock *key;
+    krb5_replay_data rdata;
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+       outdata == NULL)
+       return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
+
+    if (auth_context->local_subkey)
+       key = auth_context->local_subkey;
+    else if (auth_context->remote_subkey)
+       key = auth_context->remote_subkey;
+    else
+       key = auth_context->keyblock;
+
+    memset(&rdata, 0, sizeof(rdata));
+
+    part.user_data = *userdata;
+
+    krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec);
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+       part.timestamp = &rdata.timestamp;
+       part.usec      = &rdata.usec;
+    } else {
+       part.timestamp = NULL;
+       part.usec      = NULL;
+    }
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) {
+       outdata->timestamp = rdata.timestamp;
+       outdata->usec = rdata.usec;
+    }
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+       rdata.seq = auth_context->local_seqnumber;
+       part.seq_number = &rdata.seq;
+    } else
+       part.seq_number = NULL;
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
+       outdata->seq = auth_context->local_seqnumber;
+    
+    part.s_address = auth_context->local_address;
+    part.r_address = auth_context->remote_address;
+
+    krb5_data_zero (&s.enc_part.cipher);
+
+    ASN1_MALLOC_ENCODE(EncKrbPrivPart, buf, buf_size, &part, &len, ret);
+    if (ret)
+       goto fail;
+    if (buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    s.pvno = 5;
+    s.msg_type = krb_priv;
+    s.enc_part.etype = key->keytype;
+    s.enc_part.kvno = NULL;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret) {
+       free (buf);
+       return ret;
+    }
+    ret = krb5_encrypt (context, 
+                       crypto,
+                       KRB5_KU_KRB_PRIV,
+                       buf + buf_size - len, 
+                       len,
+                       &s.enc_part.cipher);
+    krb5_crypto_destroy(context, crypto);
+    if (ret) {
+       free(buf);
+       return ret;
+    }
+    free(buf);
+
+
+    ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret);
+
+    if(ret)
+       goto fail;
+    krb5_data_free (&s.enc_part.cipher);
+
+    ret = krb5_data_copy(outbuf, buf + buf_size - len, len);
+    if (ret) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       free(buf);
+       return ENOMEM;
+    }
+    free (buf);
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
+       auth_context->local_seqnumber =
+           (auth_context->local_seqnumber + 1) & 0xFFFFFFFF;
+    return 0;
+
+  fail:
+    free (buf);
+    krb5_data_free (&s.enc_part.cipher);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/mk_rep.c b/src/kerberosV/src/lib/krb5/mk_rep.c
new file mode 100644 (file)
index 0000000..c68ca06
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: mk_rep.c,v 1.26 2004/05/25 21:33:51 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_rep(krb5_context context,
+           krb5_auth_context auth_context,
+           krb5_data *outbuf)
+{
+    krb5_error_code ret;
+    AP_REP ap;
+    EncAPRepPart body;
+    u_char *buf = NULL;
+    size_t buf_size;
+    size_t len;
+    krb5_crypto crypto;
+
+    ap.pvno = 5;
+    ap.msg_type = krb_ap_rep;
+
+    memset (&body, 0, sizeof(body));
+
+    body.ctime = auth_context->authenticator->ctime;
+    body.cusec = auth_context->authenticator->cusec;
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) {
+       if (auth_context->local_subkey == NULL) {
+           ret = krb5_auth_con_generatelocalsubkey(context,
+                                                   auth_context,
+                                                   auth_context->keyblock);
+           if(ret) {
+               krb5_set_error_string (context,
+                                      "krb5_mk_rep: generating subkey");
+               free_EncAPRepPart(&body);
+               return ret;
+           }
+       }
+       ret = krb5_copy_keyblock(context, auth_context->local_subkey,
+                                &body.subkey);
+       if (ret) {
+           krb5_set_error_string (context,
+                                  "krb5_copy_keyblock: out of memory");
+           free_EncAPRepPart(&body);
+           return ENOMEM;
+       }
+    } else
+       body.subkey = NULL;
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+       if(auth_context->local_seqnumber == 0) 
+           krb5_generate_seq_number (context,
+                                     auth_context->keyblock,
+                                     &auth_context->local_seqnumber);
+       ALLOC(body.seq_number, 1);
+       if (body.seq_number == NULL) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           free_EncAPRepPart(&body);
+           return ENOMEM;
+       }
+       *(body.seq_number) = auth_context->local_seqnumber;
+    } else
+       body.seq_number = NULL;
+
+    ap.enc_part.etype = auth_context->keyblock->keytype;
+    ap.enc_part.kvno  = NULL;
+
+    ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret);
+    free_EncAPRepPart (&body);
+    if(ret)
+       return ret;
+    if (buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    ret = krb5_crypto_init(context, auth_context->keyblock, 
+                          0 /* ap.enc_part.etype */, &crypto);
+    if (ret) {
+       free (buf);
+       return ret;
+    }
+    ret = krb5_encrypt (context,
+                       crypto,
+                       KRB5_KU_AP_REQ_ENC_PART,
+                       buf + buf_size - len, 
+                       len,
+                       &ap.enc_part.cipher);
+    krb5_crypto_destroy(context, crypto);
+    free(buf);
+    if (ret)
+       return ret;
+
+    ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret);
+    if (ret == 0 && outbuf->length != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    free_AP_REP (&ap);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/mk_req.c b/src/kerberosV/src/lib/krb5/mk_req.c
new file mode 100644 (file)
index 0000000..d6f6506
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: mk_req.c,v 1.26 2004/05/25 21:34:11 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_req_exact(krb5_context context,
+                 krb5_auth_context *auth_context,
+                 const krb5_flags ap_req_options,
+                 const krb5_principal server,
+                 krb5_data *in_data,
+                 krb5_ccache ccache,
+                 krb5_data *outbuf)
+{
+    krb5_error_code ret;
+    krb5_creds this_cred, *cred;
+
+    memset(&this_cred, 0, sizeof(this_cred));
+
+    ret = krb5_cc_get_principal(context, ccache, &this_cred.client);
+  
+    if(ret)
+       return ret;
+
+    ret = krb5_copy_principal (context, server, &this_cred.server);
+    if (ret) {
+       krb5_free_cred_contents (context, &this_cred);
+       return ret;
+    }
+
+    this_cred.times.endtime = 0;
+    if (auth_context && *auth_context && (*auth_context)->keytype)
+       this_cred.session.keytype = (*auth_context)->keytype;
+
+    ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred);
+    krb5_free_cred_contents(context, &this_cred);
+    if (ret)
+       return ret;
+
+    ret = krb5_mk_req_extended (context,
+                               auth_context,
+                               ap_req_options,
+                               in_data,
+                               cred,
+                               outbuf);
+    krb5_free_creds(context, cred);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_req(krb5_context context,
+           krb5_auth_context *auth_context,
+           const krb5_flags ap_req_options,
+           const char *service,
+           const char *hostname,
+           krb5_data *in_data,
+           krb5_ccache ccache,
+           krb5_data *outbuf)
+{
+    krb5_error_code ret;
+    char **realms;
+    char *real_hostname;
+    krb5_principal server;
+
+    ret = krb5_expand_hostname_realms (context, hostname,
+                                      &real_hostname, &realms);
+    if (ret)
+       return ret;
+
+    ret = krb5_build_principal (context, &server,
+                               strlen(*realms),
+                               *realms,
+                               service,
+                               real_hostname,
+                               NULL);
+    free (real_hostname);
+    krb5_free_host_realm (context, realms);
+    if (ret)
+       return ret;
+    ret = krb5_mk_req_exact (context, auth_context, ap_req_options,
+                            server, in_data, ccache, outbuf);
+    krb5_free_principal (context, server);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/mk_req_ext.c b/src/kerberosV/src/lib/krb5/mk_req_ext.c
new file mode 100644 (file)
index 0000000..3ad4bbf
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: mk_req_ext.c,v 1.30 2005/01/05 06:31:01 lukeh Exp $");
+
+krb5_error_code
+_krb5_mk_req_internal(krb5_context context,
+                     krb5_auth_context *auth_context,
+                     const krb5_flags ap_req_options,
+                     krb5_data *in_data,
+                     krb5_creds *in_creds,
+                     krb5_data *outbuf,
+                     krb5_key_usage checksum_usage,
+                     krb5_key_usage encrypt_usage)
+{
+  krb5_error_code ret;
+  krb5_data authenticator;
+  Checksum c;
+  Checksum *c_opt;
+  krb5_auth_context ac;
+
+  if(auth_context) {
+      if(*auth_context == NULL)
+         ret = krb5_auth_con_init(context, auth_context);
+      else
+         ret = 0;
+      ac = *auth_context;
+  } else
+      ret = krb5_auth_con_init(context, &ac);
+  if(ret)
+      return ret;
+      
+  if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) {
+      ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session);
+      if(ret)
+         goto out;
+  }
+
+#if 0
+  {
+      /* This is somewhat bogus since we're possibly overwriting a
+         value specified by the user, but it's the easiest way to make
+         the code use a compatible enctype */
+      Ticket ticket;
+      krb5_keytype ticket_keytype;
+
+      ret = decode_Ticket(in_creds->ticket.data, 
+                         in_creds->ticket.length, 
+                         &ticket, 
+                         NULL);
+      krb5_enctype_to_keytype (context,
+                              ticket.enc_part.etype,
+                              &ticket_keytype);
+
+      if (ticket_keytype == in_creds->session.keytype)
+         krb5_auth_setenctype(context, 
+                              ac,
+                              ticket.enc_part.etype);
+      free_Ticket(&ticket);
+  }
+#endif
+
+  krb5_free_keyblock(context, ac->keyblock);
+  ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock);
+  if (ret)
+      goto out;
+  
+  /* it's unclear what type of checksum we can use.  try the best one, except:
+   * a) if it's configured differently for the current realm, or
+   * b) if the session key is des-cbc-crc
+   */
+
+  if (in_data) {
+      if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) {
+         /* this is to make DCE secd (and older MIT kdcs?) happy */
+         ret = krb5_create_checksum(context, 
+                                    NULL,
+                                    0,
+                                    CKSUMTYPE_RSA_MD4,
+                                    in_data->data,
+                                    in_data->length,
+                                    &c);
+      } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 ||
+               ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) {
+         /* this is to make MS kdc happy */ 
+         ret = krb5_create_checksum(context, 
+                                    NULL,
+                                    0,
+                                    CKSUMTYPE_RSA_MD5,
+                                    in_data->data,
+                                    in_data->length,
+                                    &c);
+      } else {
+         krb5_crypto crypto;
+
+         ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto);
+         if (ret)
+             goto out;
+         ret = krb5_create_checksum(context, 
+                                    crypto,
+                                    checksum_usage,
+                                    0,
+                                    in_data->data,
+                                    in_data->length,
+                                    &c);
+         krb5_crypto_destroy(context, crypto);
+      }
+      c_opt = &c;
+  } else {
+      c_opt = NULL;
+  }
+
+  if (ret)
+      goto out;
+  
+  ret = krb5_build_authenticator (context,
+                                 ac,
+                                 ac->keyblock->keytype,
+                                 in_creds,
+                                 c_opt,
+                                 NULL,
+                                 &authenticator,
+                                 encrypt_usage);
+  if (c_opt)
+      free_Checksum (c_opt);
+  if (ret)
+    goto out;
+
+  ret = krb5_build_ap_req (context, ac->keyblock->keytype, 
+                          in_creds, ap_req_options, authenticator, outbuf);
+out:
+  if(auth_context == NULL)
+      krb5_auth_con_free(context, ac);
+  return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_mk_req_extended(krb5_context context,
+                    krb5_auth_context *auth_context,
+                    const krb5_flags ap_req_options,
+                    krb5_data *in_data,
+                    krb5_creds *in_creds,
+                    krb5_data *outbuf)
+{
+    return _krb5_mk_req_internal (context,
+                                auth_context,
+                                ap_req_options,
+                                in_data,
+                                in_creds,
+                                outbuf,
+                                KRB5_KU_AP_REQ_AUTH_CKSUM,
+                                KRB5_KU_AP_REQ_AUTH);
+}
diff --git a/src/kerberosV/src/lib/krb5/mk_safe.c b/src/kerberosV/src/lib/krb5/mk_safe.c
new file mode 100644 (file)
index 0000000..8059310
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: mk_safe.c,v 1.30 2004/05/25 21:34:52 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    KRB_SAFE s;
+    u_char *buf = NULL;
+    size_t buf_size;
+    size_t len;
+    krb5_crypto crypto;
+    krb5_keyblock *key;
+    krb5_replay_data rdata;
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+       outdata == NULL)
+       return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
+
+    if (auth_context->local_subkey)
+       key = auth_context->local_subkey;
+    else if (auth_context->remote_subkey)
+       key = auth_context->remote_subkey;
+    else
+       key = auth_context->keyblock;
+
+    s.pvno = 5;
+    s.msg_type = krb_safe;
+
+    memset(&rdata, 0, sizeof(rdata));
+
+    s.safe_body.user_data = *userdata;
+
+    krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec);
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+       s.safe_body.timestamp  = &rdata.timestamp;
+       s.safe_body.usec       = &rdata.usec;
+    } else {
+       s.safe_body.timestamp  = NULL;
+       s.safe_body.usec       = NULL;
+    }
+    
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) {
+       outdata->timestamp = rdata.timestamp;
+       outdata->usec = rdata.usec;
+    }
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+       rdata.seq = auth_context->local_seqnumber;
+       s.safe_body.seq_number = &rdata.seq;
+    } else 
+       s.safe_body.seq_number = NULL;
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
+       outdata->seq = auth_context->local_seqnumber;
+    
+    s.safe_body.s_address = auth_context->local_address;
+    s.safe_body.r_address = auth_context->remote_address;
+
+    s.cksum.cksumtype       = 0;
+    s.cksum.checksum.data   = NULL;
+    s.cksum.checksum.length = 0;
+
+    ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, &s, &len, ret);
+    if (ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret) {
+       free (buf);
+       return ret;
+    }
+    ret = krb5_create_checksum(context, 
+                              crypto,
+                              KRB5_KU_KRB_SAFE_CKSUM,
+                              0,
+                              buf,
+                              len,
+                              &s.cksum);
+    krb5_crypto_destroy(context, crypto);
+    if (ret) {
+       free (buf);
+       return ret;
+    }
+
+    free(buf);
+    ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, &s, &len, ret);
+    free_Checksum (&s.cksum);
+    if(ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    outbuf->length = len;
+    outbuf->data   = buf;
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
+       auth_context->local_seqnumber =
+           (auth_context->local_seqnumber + 1) & 0xFFFFFFFF;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/n-fold-test.c b/src/kerberosV/src/lib/krb5/n-fold-test.c
new file mode 100644 (file)
index 0000000..4d68efb
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1999 - 2001 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. */
+
+#include "krb5_locl.h"
+
+RCSID("$KTH: n-fold-test.c,v 1.5 2004/05/25 21:35:12 lha Exp $");
+
+enum { MAXSIZE = 24 };
+
+static struct testcase {
+    const char *str;
+    unsigned n;
+    unsigned char res[MAXSIZE];
+} tests[] = {
+    {"012345",         8,
+     {0xbe, 0x07, 0x26, 0x31, 0x27, 0x6b, 0x19, 0x55}
+    },
+    {"basch",          24,
+     {0x1a, 0xab, 0x6b, 0x42, 0x96, 0x4b, 0x98, 0xb2, 0x1f, 0x8c, 0xde,
+      0x2d, 0x24, 0x48, 0xba, 0x34, 0x55, 0xd7, 0x86, 0x2c, 0x97, 0x31,
+      0x64, 0x3f}
+    },
+    {"eichin",         24,
+     {0x65, 0x69, 0x63, 0x68, 0x69, 0x6e, 0x4b, 0x73, 0x2b, 0x4b,
+      0x1b, 0x43, 0xda, 0x1a, 0x5b, 0x99, 0x5a, 0x58, 0xd2, 0xc6, 0xd0,
+      0xd2, 0xdc, 0xca}
+    },
+    {"sommerfeld",     24,
+     {0x2f, 0x7a, 0x98, 0x55, 0x7c, 0x6e, 0xe4, 0xab, 0xad, 0xf4,
+      0xe7, 0x11, 0x92, 0xdd, 0x44, 0x2b, 0xd4, 0xff, 0x53, 0x25, 0xa5,
+      0xde, 0xf7, 0x5c}
+    },
+    {"MASSACHVSETTS INSTITVTE OF TECHNOLOGY", 24,
+     {0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60, 0x32, 0x82,
+      0xb3, 0x08, 0xa5, 0x08, 0x41, 0x22, 0x9a, 0xd7, 0x98, 0xfa, 0xb9,
+      0x54, 0x0c, 0x1b}
+    },
+    {"assar@NADA.KTH.SE", 24,
+     {0x5c, 0x06, 0xc3, 0x4d, 0x2c, 0x89, 0x05, 0xbe, 0x7a, 0x51,
+      0x83, 0x6c, 0xd6, 0xf8, 0x1c, 0x4b, 0x7a, 0x93, 0x49, 0x16, 0x5a,
+      0xb3, 0xfa, 0xa9}
+    },
+    {"testKRBTEST.MIT.EDUtestkey", 24,
+     {0x50, 0x2c, 0xf8, 0x29, 0x78, 0xe5, 0xfb, 0x1a, 0x29, 0x06,
+      0xbd, 0x22, 0x28, 0x91, 0x56, 0xc0, 0x06, 0xa0, 0xdc, 0xf5, 0xb6,
+      0xc2, 0xda, 0x6c}
+    },
+    {"password", 7,
+     {0x78, 0xa0, 0x7b, 0x6c, 0xaf, 0x85, 0xfa}
+    },
+    {"Rough Consensus, and Running Code", 8,
+     {0xbb, 0x6e, 0xd3, 0x08, 0x70, 0xb7, 0xf0, 0xe0},
+    },
+    {"password", 21,
+     {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", 24,
+     {0xdb, 0x3b, 0x0d, 0x8f, 0x0b, 0x06, 0x1e, 0x60, 0x32, 0x82, 0xb3,
+      0x08, 0xa5, 0x08, 0x41, 0x22, 0x9a, 0xd7, 0x98, 0xfa, 0xb9, 0x54,
+      0x0c, 0x1b}
+    },
+    {NULL, 0}
+};
+
+int KRB5_LIB_FUNCTION
+main(int argc, char **argv)
+{
+    unsigned char data[MAXSIZE];
+    struct testcase *t;
+    int ret = 0;
+
+    for (t = tests; t->str; ++t) {
+       int i;
+
+       _krb5_n_fold (t->str, strlen(t->str), data, t->n);
+       if (memcmp (data, t->res, t->n) != 0) {
+           printf ("n-fold(\"%s\", %d) failed\n", t->str, t->n);
+           printf ("should be: ");
+           for (i = 0; i < t->n; ++i)
+               printf ("%02x", t->res[i]);
+           printf ("\nresult was: ");
+           for (i = 0; i < t->n; ++i)
+               printf ("%02x", data[i]);
+           printf ("\n");
+           ret = 1;
+       }
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/n-fold.c b/src/kerberosV/src/lib/krb5/n-fold.c
new file mode 100644 (file)
index 0000000..42e4e71
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#include "krb5_locl.h"
+
+RCSID("$KTH: n-fold.c,v 1.7 2004/05/25 21:35:31 lha Exp $");
+
+static void
+rr13(unsigned char *buf, size_t len)
+{
+    unsigned char *tmp;
+    int bytes = (len + 7) / 8;
+    int i;
+    if(len == 0)
+       return;
+    {
+       const int bits = 13 % len;
+       const int lbit = len % 8;
+    
+       tmp = malloc(bytes);
+       memcpy(tmp, buf, bytes);
+       if(lbit) {
+           /* pad final byte with inital bits */
+           tmp[bytes - 1] &= 0xff << (8 - lbit);
+           for(i = lbit; i < 8; i += len)
+               tmp[bytes - 1] |= buf[0] >> i;
+       }
+       for(i = 0; i < bytes; i++) {
+           int bb;
+           int b1, s1, b2, s2;
+           /* calculate first bit position of this byte */
+           bb = 8 * i - bits;
+           while(bb < 0)
+               bb += len;
+           /* byte offset and shift count */
+           b1 = bb / 8;
+           s1 = bb % 8;
+       
+           if(bb + 8 > bytes * 8) 
+               /* watch for wraparound */
+               s2 = (len + 8 - s1) % 8;
+           else 
+               s2 = 8 - s1;
+           b2 = (b1 + 1) % bytes;
+           buf[i] = (tmp[b1] << s1) | (tmp[b2] >> s2);
+       }
+       free(tmp);
+    }
+}
+
+/* Add `b' to `a', both beeing one's complement numbers. */
+static void
+add1(unsigned char *a, unsigned char *b, size_t len)
+{
+    int i;
+    int carry = 0;
+    for(i = len - 1; i >= 0; i--){
+       int x = a[i] + b[i] + carry;
+       carry = x > 0xff;
+       a[i] = x & 0xff;
+    }
+    for(i = len - 1; carry && i >= 0; i--){
+       int x = a[i] + carry;
+       carry = x > 0xff;
+       a[i] = x & 0xff;
+    }
+}
+
+void KRB5_LIB_FUNCTION
+_krb5_n_fold(const void *str, size_t len, void *key, size_t size)
+{
+    /* if len < size we need at most N * len bytes, ie < 2 * size;
+       if len > size we need at most 2 * len */
+    size_t maxlen = 2 * max(size, len);
+    size_t l = 0;
+    unsigned char *tmp = malloc(maxlen);
+    unsigned char *buf = malloc(len);
+    
+    memcpy(buf, str, len);
+    memset(key, 0, size);
+    do {
+       memcpy(tmp + l, buf, len);
+       l += len;
+       rr13(buf, len * 8);
+       while(l >= size) {
+           add1(key, tmp, size);
+           l -= size;
+           if(l == 0)
+               break;
+           memmove(tmp, tmp + size, l);
+       }
+    } while(l != 0);
+    memset(buf, 0, len);
+    free(buf);
+    memset(tmp, 0, maxlen);
+    free(tmp);
+}
diff --git a/src/kerberosV/src/lib/krb5/name-45-test.c b/src/kerberosV/src/lib/krb5/name-45-test.c
new file mode 100644 (file)
index 0000000..04941cb
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2002 - 2003 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: name-45-test.c,v 1.7 2005/05/29 18:22:59 lha Exp $");
+
+enum { MAX_COMPONENTS = 3 };
+
+static struct testcase {
+    const char *v4_name;
+    const char *v4_inst;
+    const char *v4_realm;
+
+    krb5_realm v5_realm;
+    unsigned ncomponents;
+    char *comp_val[MAX_COMPONENTS];
+
+    const char *config_file;
+    krb5_error_code ret;       /* expected error code from 524 */
+
+    krb5_error_code ret2;      /* expected error code from 425 */
+} tests[] = {
+    {"", "", "", "", 1, {""}, NULL, 0, 0},
+    {"a", "", "", "", 1, {"a"}, NULL, 0, 0},
+    {"a", "b", "", "", 2, {"a", "b"}, NULL, 0, 0},
+    {"a", "b", "c", "c", 2, {"a", "b"}, NULL, 0, 0},
+
+    {"krbtgt", "FOO.SE", "FOO.SE", "FOO.SE", 2,
+     {"krbtgt", "FOO.SE"}, NULL, 0, 0},
+
+    {"foo", "bar", "BAZ", "BAZ", 2,
+     {"foo", "bar"}, NULL, 0, 0},
+    {"foo", "bar", "BAZ", "BAZ", 2,
+     {"foo", "bar"},
+     "[libdefaults]\n"
+     " v4_name_convert = {\n"
+     "         host = {\n"
+     "                 foo = foo5\n"
+     "         }\n"
+     "}\n",
+    HEIM_ERR_V4_PRINC_NO_CONV, 0},
+    {"foo", "bar", "BAZ", "BAZ", 2,
+     {"foo5", "bar.baz"},
+     "[realms]\n"
+     "  BAZ = {\n"
+     "         v4_name_convert = {\n"
+     "                 host = {\n"
+     "                         foo = foo5\n"
+     "                 }\n"
+     "         }\n"
+     "         v4_instance_convert = {\n"
+     "                 bar = bar.baz\n"
+     "         }\n"
+     "  }\n",
+     0, 0},
+
+    {"rcmd", "foo", "realm", "realm", 2, {"host", "foo"}, NULL,
+     HEIM_ERR_V4_PRINC_NO_CONV, 0},
+    {"rcmd", "foo", "realm", "realm", 2, {"host", "foo.realm"},
+     "[realms]\n"
+     " realm = {\n"
+     "         v4_instance_convert = {\n"
+     "                 foo = foo.realm\n"
+     "         }\n"
+     " }\n",
+     0, 0},
+
+    {"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2,
+     {"pop", "mail0.nada.kth.se"}, "", HEIM_ERR_V4_PRINC_NO_CONV, 0},
+    {"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2,
+     {"pop", "mail0.nada.kth.se"},
+     "[realms]\n"
+     " NADA.KTH.SE = {\n"
+     "         default_domain = nada.kth.se\n"
+     " }\n",
+     0, 0},
+    {"pop", "mail0", "NADA.KTH.SE", "NADA.KTH.SE", 2,
+     {"pop", "mail0.nada.kth.se"},
+     "[libdefaults]\n"
+     " v4_instance_resolve = true\n",
+     HEIM_ERR_V4_PRINC_NO_CONV, 0},
+
+    {"rcmd", "hokkigai", "NADA.KTH.SE", "NADA.KTH.SE", 2,
+     {"host", "hokkigai.pdc.kth.se"}, "", HEIM_ERR_V4_PRINC_NO_CONV, 0},
+    {"rcmd", "hokkigai", "NADA.KTH.SE", "NADA.KTH.SE", 2,
+     {"host", "hokkigai.pdc.kth.se"},
+     "[libdefaults]\n"
+     " v4_instance_resolve = true\n"
+     "[realms]\n"
+     " NADA.KTH.SE = {\n"
+     "         v4_name_convert = {\n"
+     "                 host = {\n"
+     "                         rcmd = host\n"
+     "                 }\n"
+     "         }\n"
+     "         default_domain = pdc.kth.se\n"
+     " }\n",
+     0, 0},
+
+    {"0123456789012345678901234567890123456789",
+     "0123456789012345678901234567890123456789",
+     "0123456789012345678901234567890123456789",
+     "0123456789012345678901234567890123456789",
+     2, {"0123456789012345678901234567890123456789",
+        "0123456789012345678901234567890123456789"}, NULL,
+     0, KRB5_PARSE_MALFORMED},
+
+    {"012345678901234567890123456789012345678",
+     "012345678901234567890123456789012345678",
+     "012345678901234567890123456789012345678",
+     "012345678901234567890123456789012345678",
+     2, {"012345678901234567890123456789012345678",
+        "012345678901234567890123456789012345678"}, NULL,
+     0, 0},
+
+    {NULL, NULL, NULL, NULL, 0, {NULL}, NULL, 0}
+};
+
+int
+main(int argc, char **argv)
+{
+    struct testcase *t;
+    krb5_context context;
+    krb5_error_code ret;
+    char hostname[1024];
+    int val = 0;
+
+    setprogname(argv[0]);
+
+    gethostname(hostname, sizeof(hostname));
+    if (!(strstr(hostname, "kth.se") != NULL || strstr(hostname, "su.se") != NULL))
+       return 0;
+
+    for (t = tests; t->v4_name; ++t) {
+       krb5_principal princ;
+       int i;
+       char name[40], inst[40], realm[40];
+       char printable_princ[256];
+
+       ret = krb5_init_context (&context);
+       if (ret)
+           errx (1, "krb5_init_context failed: %d", ret);
+
+       if (t->config_file != NULL) {
+           char template[] = "/tmp/krb5-conf-XXXXXXXXXX";
+           int fd = mkstemp(template);
+           char *files[2];
+
+           if (fd < 0)
+               krb5_err (context, 1, errno, "mkstemp %s", template);
+
+           if (write (fd, t->config_file, strlen(t->config_file))
+               != strlen(t->config_file))
+               krb5_err (context, 1, errno, "write %s", template);
+           close (fd);
+           files[0] = template;
+           files[1] = NULL;
+
+           ret = krb5_set_config_files (context, files);
+           unlink (template);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_set_config_files");
+       }
+
+       ret = krb5_425_conv_principal (context,
+                                      t->v4_name,
+                                      t->v4_inst,
+                                      t->v4_realm,
+                                      &princ);
+       if (ret) {
+           if (ret != t->ret) {
+               krb5_warn (context, ret,
+                          "krb5_425_conv_principal %s.%s@%s",
+                          t->v4_name, t->v4_inst, t->v4_realm);
+               val = 1;
+           }
+       } else {
+           if (t->ret) {
+               char *s;
+               krb5_unparse_name(context, princ, &s);
+               krb5_warnx (context,
+                           "krb5_425_conv_principal %s.%s@%s "
+                           "passed unexpected: %s",
+                           t->v4_name, t->v4_inst, t->v4_realm, s);
+               free(s);
+               val = 1;
+               continue;
+           }
+       }
+
+       if (ret)
+           continue;
+
+       if (strcmp (t->v5_realm, princ->realm) != 0) {
+           printf ("wrong realm (\"%s\" should be \"%s\")"
+                   " for \"%s.%s@%s\"\n",
+                   princ->realm, t->v5_realm,
+                   t->v4_name,
+                   t->v4_inst,
+                   t->v4_realm);
+           val = 1;
+       }
+
+       if (t->ncomponents != princ->name.name_string.len) {
+           printf ("wrong number of components (%u should be %u)"
+                   " for \"%s.%s@%s\"\n",
+                   princ->name.name_string.len, t->ncomponents,
+                   t->v4_name,
+                   t->v4_inst,
+                   t->v4_realm);
+           val = 1;
+       } else {
+           for (i = 0; i < t->ncomponents; ++i) {
+               if (strcmp(t->comp_val[i],
+                          princ->name.name_string.val[i]) != 0) {
+                   printf ("bad component %d (\"%s\" should be \"%s\")"
+                           " for \"%s.%s@%s\"\n",
+                           i,
+                           princ->name.name_string.val[i],
+                           t->comp_val[i],
+                           t->v4_name,
+                           t->v4_inst,
+                           t->v4_realm);
+                   val = 1;
+               }
+           }
+       }
+       ret = krb5_524_conv_principal (context, princ,
+                                      name, inst, realm);
+       if (krb5_unparse_name_fixed(context, princ,
+                                   printable_princ, sizeof(printable_princ)))
+           strlcpy(printable_princ, "unknown principal",
+                   sizeof(printable_princ));
+       if (ret) {
+           if (ret != t->ret2) {
+               krb5_warn (context, ret,
+                          "krb5_524_conv_principal %s", printable_princ);
+               val = 1;
+           }
+       } else {
+           if (t->ret2) {
+               krb5_warnx (context,
+                           "krb5_524_conv_principal %s "
+                           "passed unexpected", printable_princ);
+               val = 1;
+               continue;
+           }
+       }
+       if (ret) {
+           krb5_free_principal (context, princ);
+           continue;
+       }
+
+       krb5_free_principal (context, princ);
+    }
+    return val;
+}
diff --git a/src/kerberosV/src/lib/krb5/net_read.c b/src/kerberosV/src/lib/krb5/net_read.c
new file mode 100644 (file)
index 0000000..297c620
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1997, 1998, 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: net_read.c,v 1.7 2004/05/25 21:35:50 lha Exp $");
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_net_read (krb5_context context,
+              void *p_fd,
+              void *buf,
+              size_t len)
+{
+  int fd = *((int *)p_fd);
+
+  return net_read (fd, buf, len);
+}
diff --git a/src/kerberosV/src/lib/krb5/net_write.c b/src/kerberosV/src/lib/krb5/net_write.c
new file mode 100644 (file)
index 0000000..e116987
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: net_write.c,v 1.9 2004/05/25 21:36:09 lha Exp $");
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_net_write (krb5_context context,
+               void *p_fd,
+               const void *buf,
+               size_t len)
+{
+  int fd = *((int *)p_fd);
+
+  return net_write (fd, buf, len);
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_net_write_block(krb5_context context,
+                    void *p_fd,
+                    const void *buf,
+                    size_t len,
+                    time_t timeout)
+{
+  int fd = *((int *)p_fd);
+  int ret;
+  struct timeval tv, *tvp;
+  const char *cbuf = (const char *)buf;
+  size_t rem = len;
+  ssize_t count;
+  fd_set wfds;
+
+  do {
+      FD_ZERO(&wfds);
+      FD_SET(fd, &wfds);
+      
+      if (timeout != 0) {
+         tv.tv_sec = timeout;
+         tv.tv_usec = 0;
+         tvp = &tv;
+      } else
+         tvp = NULL;
+
+      ret = select(fd + 1, NULL, &wfds, NULL, tvp);
+      if (ret < 0) {
+         if (errno == EINTR)
+             continue;
+         return -1;
+      } else if (ret == 0)
+         return 0;
+      
+      if (!FD_ISSET(fd, &wfds)) {
+         errno = ETIMEDOUT;
+         return -1;
+      }
+
+#ifdef WIN32
+      count = send (fd, cbuf, rem, 0);
+#else
+      count = write (fd, cbuf, rem);
+#endif
+      if (count < 0) {
+         if (errno == EINTR)
+             continue;
+         else
+             return count;
+      }
+      cbuf += count;
+      rem -= count;
+
+  } while (rem > 0);
+
+  return len;
+}
diff --git a/src/kerberosV/src/lib/krb5/padata.c b/src/kerberosV/src/lib/krb5/padata.c
new file mode 100644 (file)
index 0000000..7313c04
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: padata.c,v 1.4 2004/05/25 21:36:29 lha Exp $");
+
+PA_DATA *
+krb5_find_padata(PA_DATA *val, unsigned len, int type, int *index)
+{
+    for(; *index < len; (*index)++)
+       if(val[*index].padata_type == type)
+           return val + *index;
+    return NULL;    
+}
+
+int KRB5_LIB_FUNCTION
+krb5_padata_add(krb5_context context, METHOD_DATA *md,
+               int type, void *buf, size_t len)
+{
+    PA_DATA *pa;
+
+    pa = realloc (md->val, (md->len + 1) * sizeof(*md->val));
+    if (pa == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    md->val = pa;
+
+    pa[md->len].padata_type = type;
+    pa[md->len].padata_value.length = len;
+    pa[md->len].padata_value.data = buf;
+    md->len++;    
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/parse-name-test.c b/src/kerberosV/src/lib/krb5/parse-name-test.c
new file mode 100644 (file)
index 0000000..3e1f3f4
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2002 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: parse-name-test.c,v 1.6 2005/04/30 15:18:15 lha Exp $");
+
+enum { MAX_COMPONENTS = 3 };
+
+static struct testcase {
+    const char *input_string;
+    const char *output_string;
+    krb5_realm realm;
+    unsigned ncomponents;
+    char *comp_val[MAX_COMPONENTS];
+    int realmp;
+} tests[] = {
+    {"", "@", "", 1, {""}, FALSE},
+    {"a", "a@", "", 1, {"a"}, FALSE},
+    {"\\n", "\\n@", "", 1, {"\n"}, FALSE},
+    {"\\ ", "\\ @", "", 1, {" "}, FALSE},
+    {"\\t", "\\t@", "", 1, {"\t"}, FALSE},
+    {"\\b", "\\b@", "", 1, {"\b"}, FALSE},
+    {"\\\\", "\\\\@", "", 1, {"\\"}, FALSE},
+    {"\\/", "\\/@", "", 1, {"/"}, FALSE},
+    {"\\@", "\\@@", "", 1, {"@"}, FALSE},
+    {"@", "@", "", 1, {""}, TRUE},
+    {"a/b", "a/b@", "", 2, {"a", "b"}, FALSE},
+    {"a/", "a/@", "", 2, {"a", ""}, FALSE},
+    {"a\\//\\/", "a\\//\\/@", "", 2, {"a/", "/"}, FALSE},
+    {"/a", "/a@", "", 2, {"", "a"}, FALSE},
+    {"\\@@\\@", "\\@@\\@", "@", 1, {"@"}, TRUE},
+    {"a/b/c", "a/b/c@", "", 3, {"a", "b", "c"}, FALSE},
+    {NULL, NULL, "", 0, { NULL }, FALSE}};
+
+int KRB5_LIB_FUNCTION
+main(int argc, char **argv)
+{
+    struct testcase *t;
+    krb5_context context;
+    krb5_error_code ret;
+    int val = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    /* to enable realm-less principal name above */
+
+    krb5_set_default_realm(context, "");
+
+    for (t = tests; t->input_string; ++t) {
+       krb5_principal princ;
+       int i, j;
+       char name_buf[1024];
+       char *s;
+
+       ret = krb5_parse_name(context, t->input_string, &princ);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_parse_name %s",
+                     t->input_string);
+       if (strcmp (t->realm, princ->realm) != 0) {
+           printf ("wrong realm (\"%s\" should be \"%s\")"
+                   " for \"%s\"\n",
+                   princ->realm, t->realm,
+                   t->input_string);
+           val = 1;
+       }
+
+       if (t->ncomponents != princ->name.name_string.len) {
+           printf ("wrong number of components (%u should be %u)"
+                   " for \"%s\"\n",
+                   princ->name.name_string.len, t->ncomponents,
+                   t->input_string);
+           val = 1;
+       } else {
+           for (i = 0; i < t->ncomponents; ++i) {
+               if (strcmp(t->comp_val[i],
+                          princ->name.name_string.val[i]) != 0) {
+                   printf ("bad component %d (\"%s\" should be \"%s\")"
+                           " for \"%s\"\n",
+                           i,
+                           princ->name.name_string.val[i],
+                           t->comp_val[i],
+                           t->input_string);
+                   val = 1;
+               }
+           }
+       }
+       for (j = 0; j < strlen(t->output_string); ++j) {
+           ret = krb5_unparse_name_fixed(context, princ,
+                                         name_buf, j);
+           if (ret != ERANGE) {
+               printf ("unparse_name %s with length %d should have failed\n",
+                       t->input_string, j);
+               val = 1;
+               break;
+           }
+       }
+       ret = krb5_unparse_name_fixed(context, princ,
+                                     name_buf, sizeof(name_buf));
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_unparse_name_fixed");
+
+       if (strcmp (t->output_string, name_buf) != 0) {
+           printf ("failed comparing the re-parsed"
+                   " (\"%s\" should be \"%s\")\n",
+                   name_buf, t->output_string);
+           val = 1;
+       }
+
+       ret = krb5_unparse_name(context, princ, &s);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_unparse_name");
+
+       if (strcmp (t->output_string, s) != 0) {
+           printf ("failed comparing the re-parsed"
+                   " (\"%s\" should be \"%s\"\n",
+                   s, t->output_string);
+           val = 1;
+       }
+       free(s);
+
+       if (!t->realmp) {
+           for (j = 0; j < strlen(t->input_string); ++j) {
+               ret = krb5_unparse_name_fixed_short(context, princ,
+                                                   name_buf, j);
+               if (ret != ERANGE) {
+                   printf ("unparse_name_short %s with length %d"
+                           " should have failed\n",
+                           t->input_string, j);
+                   val = 1;
+                   break;
+               }
+           }
+           ret = krb5_unparse_name_fixed_short(context, princ,
+                                               name_buf, sizeof(name_buf));
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_unparse_name_fixed");
+
+           if (strcmp (t->input_string, name_buf) != 0) {
+               printf ("failed comparing the re-parsed"
+                       " (\"%s\" should be \"%s\")\n",
+                       name_buf, t->input_string);
+               val = 1;
+           }
+
+           ret = krb5_unparse_name_short(context, princ, &s);
+           if (ret)
+               krb5_err (context, 1, ret, "krb5_unparse_name_short");
+
+           if (strcmp (t->input_string, s) != 0) {
+               printf ("failed comparing the re-parsed"
+                       " (\"%s\" should be \"%s\"\n",
+                       s, t->input_string);
+               val = 1;
+           }
+           free(s);
+       }
+       krb5_free_principal (context, princ);
+    }
+    return val;
+}
diff --git a/src/kerberosV/src/lib/krb5/pkinit.c b/src/kerberosV/src/lib/krb5/pkinit.c
new file mode 100644 (file)
index 0000000..4fd75bc
--- /dev/null
@@ -0,0 +1,2585 @@
+/*
+ * Copyright (c) 2003 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: pkinit.c,v 1.55.2.1 2005/10/12 12:44:38 lha Exp $");
+
+#ifdef PKINIT
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#include <openssl/engine.h>
+#include <openssl/ui.h>
+
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
+#include "heim_asn1.h"
+#include "rfc2459_asn1.h"
+#include "cms_asn1.h"
+#include "pkinit_asn1.h"
+
+enum {
+    COMPAT_WIN2K = 1,
+    COMPAT_19 = 2,
+    COMPAT_25 = 3
+};
+
+
+
+#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R)                     \
+{                                                                      \
+  unsigned char *p;                                                    \
+  (BL) = i2d_##T((S), NULL);                                           \
+  if ((BL) <= 0) {                                                     \
+     (R) = EINVAL;                                                     \
+  } else {                                                             \
+    (B) = malloc((BL));                                                        \
+    if ((B) == NULL) {                                                 \
+       (R) = ENOMEM;                                                   \
+    } else {                                                           \
+        p = (B);                                                       \
+        (R) = 0;                                                       \
+        (BL) = i2d_##T((S), &p);                                       \
+        if ((BL) <= 0) {                                               \
+           free((B));                                                          \
+           (R) = ASN1_OVERRUN;                                         \
+        }                                                              \
+    }                                                                  \
+  }                                                                    \
+}
+
+/* ENGING_load_private_key requires a UI_METHOD and data  
+ * if to be usable from PAM 
+ */
+
+struct krb5_ui_data {
+    krb5_context context;
+    krb5_prompter_fct prompter;
+    void * prompter_data;
+};
+
+struct krb5_pk_identity {
+    EVP_PKEY *private_key;
+    STACK_OF(X509) *cert;
+    STACK_OF(X509) *trusted_certs;
+    STACK_OF(X509_CRL) *crls;
+    ENGINE *engine;
+};
+
+struct krb5_pk_cert {
+    X509 *cert;
+};
+
+struct krb5_pk_init_ctx_data {
+    struct krb5_pk_identity *id;
+    DH *dh;
+};
+
+
+void KRB5_LIB_FUNCTION
+_krb5_pk_cert_free(struct krb5_pk_cert *cert)
+{
+    if (cert->cert)
+       X509_free(cert->cert);
+    free(cert);
+}
+
+static krb5_error_code
+BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
+{
+    integer->length = BN_num_bytes(bn);
+    integer->data = malloc(integer->length);
+    if (integer->data == NULL) {
+       krb5_clear_error_string(context);
+       return ENOMEM;
+    }
+    BN_bn2bin(bn, integer->data);
+    integer->negative = bn->neg;
+    return 0;
+}
+
+/*
+ * UI ex_data has the callback_data as passed to Engine. This is far
+ * from being complete, we will only process one prompt
+ */
+
+static int
+krb5_ui_method_read_string(UI *ui, UI_STRING *uis)
+{
+    char *buffer;
+    size_t length;
+    krb5_error_code ret;
+    krb5_prompt prompt;
+    krb5_data password_data;
+    struct krb5_ui_data *ui_data;
+  
+    ui_data = (struct krb5_ui_data *)UI_get_app_data(ui);
+
+    switch (UI_get_string_type(uis)) {
+    case UIT_INFO:
+    case UIT_ERROR:
+       /* looks like the RedHat pam_prompter might handle 
+        * INFO and ERROR, Will see what happens */
+    case UIT_VERIFY:
+    case UIT_PROMPT:
+       length = UI_get_result_maxsize(uis);
+       buffer = malloc(length);
+       if (buffer == NULL) {
+           krb5_set_error_string(ui_data->context, "malloc: out of memory");
+           return 0;
+       }
+       password_data.data = buffer;
+       password_data.length = length;
+
+       prompt.prompt = UI_get0_output_string(uis);
+       prompt.hidden = !(UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO);
+       prompt.reply  = &password_data;
+       prompt.type   = KRB5_PROMPT_TYPE_PASSWORD;
+  
+       ret = (*ui_data->prompter)(ui_data->context, 
+                                  ui_data->prompter_data, 
+                                  NULL, NULL, 1, &prompt);
+       if (ret == 0) {
+           buffer[length - 1] = '\0';
+           UI_set_result(ui, uis, password_data.data);
+
+           /*
+            * RedHat pam_krb5 pam_prompter does a strdup but others
+            * may copy into buffer. XXX should we just leak the
+            * memory instead ?
+            */
+
+           if (buffer != password_data.data)
+               free(password_data.data);
+           memset (buffer, 0, length);
+           free(buffer);
+           return 1;
+       }
+       memset (buffer, 0, length);
+       free(buffer);
+       break;
+    case UIT_NONE:
+    case UIT_BOOLEAN:
+       /* XXX for now do not handle */
+       break;
+
+    }
+    return 0;
+}
+
+
+static krb5_error_code
+set_digest_alg(DigestAlgorithmIdentifier *id,
+              const heim_oid *oid,
+              void *param, size_t length)
+{
+    krb5_error_code ret;
+    if (param) {
+       id->parameters = malloc(sizeof(*id->parameters));
+       if (id->parameters == NULL)
+           return ENOMEM;
+       id->parameters->data = malloc(length);
+       if (id->parameters->data == NULL) {
+           free(id->parameters);
+           id->parameters = NULL;
+           return ENOMEM;
+       }
+       memcpy(id->parameters->data, param, length);
+       id->parameters->length = length;
+    } else
+       id->parameters = NULL;
+    ret = copy_oid(oid, &id->algorithm);
+    if (ret) {
+       if (id->parameters) {
+           free(id->parameters->data);
+           free(id->parameters);
+           id->parameters = NULL;
+       }
+       return ret;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_create_sign(krb5_context context,
+                    const heim_oid *eContentType,
+                    krb5_data *eContent,
+                    struct krb5_pk_identity *id,
+                    krb5_data *sd_data)
+{
+    SignerInfo *signer_info;
+    X509 *user_cert;
+    heim_integer *serial;
+    krb5_error_code ret;
+    krb5_data buf;
+    SignedData sd;
+    EVP_MD_CTX md;
+    int len, i;
+    size_t size;
+    
+    X509_NAME *issuer_name;
+
+    memset(&sd, 0, sizeof(sd));
+
+    if (id == NULL)
+       return HEIM_PKINIT_NO_CERTIFICATE;
+    if (id->cert == NULL)
+       return HEIM_PKINIT_NO_CERTIFICATE;
+    if (id->private_key == NULL)
+       return HEIM_PKINIT_NO_PRIVATE_KEY;
+
+    if (sk_X509_num(id->cert) == 0)
+       return HEIM_PKINIT_NO_CERTIFICATE;
+
+    sd.version = 3;
+
+    sd.digestAlgorithms.len = 0;
+    sd.digestAlgorithms.val = NULL;
+    copy_oid(eContentType, &sd.encapContentInfo.eContentType);
+    ALLOC(sd.encapContentInfo.eContent, 1);
+    if (sd.encapContentInfo.eContent == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ret = krb5_data_copy(&buf, eContent->data, eContent->length);
+    if (ret) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+
+    sd.encapContentInfo.eContent->data = buf.data;
+    sd.encapContentInfo.eContent->length = buf.length;
+
+    ALLOC_SEQ(&sd.signerInfos, 1);
+    if (sd.signerInfos.val == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    signer_info = &sd.signerInfos.val[0];
+
+    user_cert = sk_X509_value(id->cert, 0);
+    if (user_cert == NULL) {
+       krb5_set_error_string(context, "pkinit: no user certificate");
+       ret = HEIM_PKINIT_NO_CERTIFICATE;
+       goto out;
+    }
+
+    signer_info->version = 1;
+
+    issuer_name = X509_get_issuer_name(user_cert);
+
+    OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, 
+                              buf.data,
+                              buf.length,
+                              issuer_name,
+                              ret);
+    if (ret) {
+       krb5_set_error_string(context, "pkinit: failed encoding name");
+       goto out;
+    }
+    ret = decode_Name(buf.data, buf.length,
+                     &signer_info->sid.u.issuerAndSerialNumber.issuer,
+                     NULL);
+    free(buf.data);
+    if (ret) {
+       krb5_set_error_string(context, "pkinit: failed to parse Name");
+       goto out;
+    }
+    signer_info->sid.element = choice_CMSIdentifier_issuerAndSerialNumber;
+
+    serial = &signer_info->sid.u.issuerAndSerialNumber.serialNumber;
+    {
+       ASN1_INTEGER *isn = X509_get_serialNumber(user_cert);
+       BIGNUM *bn = ASN1_INTEGER_to_BN(isn, NULL);
+       if (bn == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string(context, "pkinit: failed allocating "
+                                 "serial number");
+           goto out;
+       }
+       ret = BN_to_integer(context, bn, serial);
+       BN_free(bn);
+       if (ret) {
+           krb5_set_error_string(context, "pkinit: failed encoding "
+                                 "serial number");
+           goto out;
+       }
+    }
+
+    ret = set_digest_alg(&signer_info->digestAlgorithm,
+                        oid_id_secsig_sha_1(), "\x05\x00", 2);
+    if (ret) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto out;
+    }
+
+    signer_info->signedAttrs = NULL;
+    signer_info->unsignedAttrs = NULL;
+
+    copy_oid(oid_id_pkcs1_rsaEncryption(),
+            &signer_info->signatureAlgorithm.algorithm);
+    signer_info->signatureAlgorithm.parameters = NULL;
+
+    buf.data = malloc(EVP_PKEY_size(id->private_key));
+    if (buf.data == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    EVP_SignInit(&md, EVP_sha1());
+    EVP_SignUpdate(&md,
+                  sd.encapContentInfo.eContent->data,
+                  sd.encapContentInfo.eContent->length);
+    ret = EVP_SignFinal(&md, buf.data, &len, id->private_key);
+    if (ret != 1) {
+       free(buf.data);
+       krb5_set_error_string(context, "PKINIT: failed to sign with "
+                             "private key: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = EINVAL;
+       goto out;
+    }
+
+    signer_info->signature.data = buf.data;
+    signer_info->signature.length = len;
+
+    ALLOC_SEQ(&sd.digestAlgorithms, 1);
+    if (sd.digestAlgorithms.val == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ret = set_digest_alg(&sd.digestAlgorithms.val[0],
+                        oid_id_secsig_sha_1(), "\x05\x00", 2);
+    if (ret) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       goto out;
+    }
+
+    ALLOC(sd.certificates, 1);
+    if (sd.certificates == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+
+    sd.certificates->data = NULL;
+    sd.certificates->length = 0;
+
+    for (i = 0; i < sk_X509_num(id->cert); i++) {
+       void *data;
+
+       OPENSSL_ASN1_MALLOC_ENCODE(X509, 
+                                  buf.data,
+                                  buf.length,
+                                  sk_X509_value(id->cert, i),
+                                  ret);
+       if (ret) {
+           krb5_clear_error_string(context);
+           goto out;
+       }
+       data = realloc(sd.certificates->data, 
+                      sd.certificates->length + buf.length);
+       if (data == NULL) {
+           free(buf.data);
+           krb5_clear_error_string(context);
+           ret = ENOMEM;
+           goto out;
+       }
+       memcpy(((char *)data) + sd.certificates->length,
+              buf.data, buf.length);
+       sd.certificates->length += buf.length;
+       sd.certificates->data = data;
+       free(buf.data);
+    }
+
+    ASN1_MALLOC_ENCODE(SignedData, sd_data->data, sd_data->length, 
+                      &sd, &size, ret);
+    if (ret) {
+       krb5_set_error_string(context, "SignedData failed %d", ret);
+       goto out;
+    }
+    if (sd_data->length != size)
+       krb5_abortx(context, "internal ASN1 encoder error");
+
+ out:
+    free_SignedData(&sd);
+
+    return ret;
+}
+
+static krb5_error_code
+build_auth_pack_win2k(krb5_context context,
+                      unsigned nonce,
+                      const KDC_REQ_BODY *body,
+                      AuthPack_Win2k *a)
+{
+    krb5_error_code ret;
+    krb5_timestamp sec;
+    int32_t usec;
+
+    /* fill in PKAuthenticator */
+    ret = copy_PrincipalName(body->sname, &a->pkAuthenticator.kdcName);
+    if (ret)
+       return ret;
+    ret = copy_Realm(&body->realm, &a->pkAuthenticator.kdcRealm);
+    if (ret)
+       return ret;
+
+    krb5_us_timeofday(context, &sec, &usec);
+    a->pkAuthenticator.ctime = sec;
+    a->pkAuthenticator.cusec = usec;
+    a->pkAuthenticator.nonce = nonce;
+
+    return 0;
+}
+
+static krb5_error_code
+build_auth_pack_19(krb5_context context,
+                  unsigned nonce,
+                  const KDC_REQ_BODY *body,
+                  AuthPack_19 *a)
+{
+    size_t buf_size, len;
+    krb5_cksumtype cksum;
+    krb5_error_code ret;
+    void *buf;
+    krb5_timestamp sec;
+    int32_t usec;
+
+    krb5_clear_error_string(context);
+
+    /* XXX some PACKETCABLE needs implemetations need md5 */
+    cksum = CKSUMTYPE_RSA_MD5;
+
+    krb5_us_timeofday(context, &sec, &usec);
+    a->pkAuthenticator.ctime = sec;
+    a->pkAuthenticator.nonce = nonce;
+
+    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
+    if (ret)
+       return ret;
+    if (buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_create_checksum(context,
+                              NULL,
+                              0,
+                              cksum,
+                              buf,
+                              len,
+                              &a->pkAuthenticator.paChecksum);
+    free(buf);
+
+    return ret;
+}
+
+static krb5_error_code
+build_auth_pack(krb5_context context,
+               unsigned nonce,
+               DH *dh,
+               const KDC_REQ_BODY *body,
+               AuthPack *a)
+{
+    size_t buf_size, len;
+    krb5_error_code ret;
+    void *buf;
+    krb5_timestamp sec;
+    int32_t usec;
+    Checksum checksum;
+
+    krb5_clear_error_string(context);
+
+    memset(&checksum, 0, sizeof(checksum));
+
+    krb5_us_timeofday(context, &sec, &usec);
+    a->pkAuthenticator.ctime = sec;
+    a->pkAuthenticator.nonce = nonce;
+
+    ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret);
+    if (ret)
+       return ret;
+    if (buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    ret = krb5_create_checksum(context,
+                              NULL,
+                              0,
+                              CKSUMTYPE_SHA1,
+                              buf,
+                              len,
+                              &checksum);
+    free(buf);
+    if (ret == 0) {
+       ret = krb5_data_copy(&a->pkAuthenticator.paChecksum,
+                            checksum.checksum.data, checksum.checksum.length);
+       free_Checksum(&checksum);
+    }
+
+    if (ret == 0 && dh) {
+       DomainParameters dp;
+       heim_integer dh_pub_key;
+       krb5_data buf;
+       size_t size;
+
+       ALLOC(a->clientPublicValue, 1);
+       if (a->clientPublicValue == NULL)
+           return ENOMEM;
+       ret = copy_oid(oid_id_dhpublicnumber(),
+                      &a->clientPublicValue->algorithm.algorithm);
+       if (ret)
+           return ret;
+       
+       memset(&dp, 0, sizeof(dp));
+
+       ret = BN_to_integer(context, dh->p, &dp.p);
+       if (ret) {
+           free_DomainParameters(&dp);
+           return ret;
+       }
+       ret = BN_to_integer(context, dh->g, &dp.g);
+       if (ret) {
+           free_DomainParameters(&dp);
+           return ret;
+       }
+       ret = BN_to_integer(context, dh->q, &dp.q);
+       if (ret) {
+           free_DomainParameters(&dp);
+           return ret;
+       }
+       dp.j = NULL;
+       dp.validationParms = NULL;
+
+       a->clientPublicValue->algorithm.parameters = 
+           malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
+       if (a->clientPublicValue->algorithm.parameters == NULL) {
+           free_DomainParameters(&dp);
+           return ret;
+       }
+
+       ASN1_MALLOC_ENCODE(DomainParameters,
+                          a->clientPublicValue->algorithm.parameters->data,
+                          a->clientPublicValue->algorithm.parameters->length,
+                          &dp, &size, ret);
+       free_DomainParameters(&dp);
+       if (ret)
+           return ret;
+       if (size != a->clientPublicValue->algorithm.parameters->length)
+           krb5_abortx(context, "Internal ASN1 encoder error");
+
+       ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
+       if (ret)
+           return ret;
+
+       buf.length = length_heim_integer(&dh_pub_key);
+       buf.data = malloc(buf.length);
+       if (buf.data == NULL) {
+           free_heim_integer(&dh_pub_key);
+           krb5_set_error_string(context, "malloc: out of memory");
+           return ret;
+       }
+       ret = der_put_heim_integer((char *)buf.data + buf.length - 1,
+                                  buf.length, &dh_pub_key, &size);
+       free_heim_integer(&dh_pub_key);
+       if (ret) {
+           free(buf.data);
+           return ret;
+       }
+       if (size != buf.length)
+           krb5_abortx(context, "asn1 internal error");
+
+       a->clientPublicValue->subjectPublicKey.length = buf.length * 8;
+       a->clientPublicValue->subjectPublicKey.data = buf.data;
+    }
+
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_mk_ContentInfo(krb5_context context,
+                       const krb5_data *buf, 
+                       const heim_oid *oid,
+                       struct ContentInfo *content_info)
+{
+    krb5_error_code ret;
+
+    ret = copy_oid(oid, &content_info->contentType);
+    if (ret)
+       return ret;
+    ALLOC(content_info->content, 1);
+    if (content_info->content == NULL)
+       return ENOMEM;
+    content_info->content->data = malloc(buf->length);
+    if (content_info->content->data == NULL)
+       return ENOMEM;
+    memcpy(content_info->content->data, buf->data, buf->length);
+    content_info->content->length = buf->length;
+    return 0;
+}
+
+static krb5_error_code
+pk_mk_padata(krb5_context context,
+            int compat,
+            krb5_pk_init_ctx ctx,
+            const KDC_REQ_BODY *req_body,
+            unsigned nonce,
+            METHOD_DATA *md)
+{
+    struct ContentInfo content_info;
+    krb5_error_code ret;
+    const heim_oid *oid;
+    PA_PK_AS_REQ req;
+    size_t size;
+    krb5_data buf, sd_buf;
+    int pa_type;
+
+    krb5_data_zero(&buf);
+    krb5_data_zero(&sd_buf);
+    memset(&req, 0, sizeof(req));
+    memset(&content_info, 0, sizeof(content_info));
+
+    if (compat == COMPAT_WIN2K) {
+       AuthPack_Win2k ap;
+
+       memset(&ap, 0, sizeof(ap));
+
+       ret = build_auth_pack_win2k(context, nonce, req_body, &ap);
+       if (ret) {
+           free_AuthPack_Win2k(&ap);
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length,
+                          &ap, &size, ret);
+       free_AuthPack_Win2k(&ap);
+       if (ret) {
+           krb5_set_error_string(context, "AuthPack_Win2k: %d", ret);
+           goto out;
+       }
+       if (buf.length != size)
+           krb5_abortx(context, "internal ASN1 encoder error");
+
+       oid = oid_id_pkcs7_data();
+    } else if (compat == COMPAT_19) {
+       AuthPack_19 ap;
+       
+       memset(&ap, 0, sizeof(ap));
+
+       ret = build_auth_pack_19(context, nonce, req_body, &ap);
+       if (ret) {
+           free_AuthPack_19(&ap);
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(AuthPack_19, buf.data, buf.length, &ap, &size, ret);
+       free_AuthPack_19(&ap);
+       if (ret) {
+           krb5_set_error_string(context, "AuthPack_19: %d", ret);
+           goto out;
+       }
+       if (buf.length != size)
+           krb5_abortx(context, "internal ASN1 encoder error");
+
+       oid = oid_id_pkauthdata();
+    } else if (compat == COMPAT_25) {
+       AuthPack ap;
+       
+       memset(&ap, 0, sizeof(ap));
+
+       ret = build_auth_pack(context, nonce, ctx->dh, req_body, &ap);
+       if (ret) {
+           free_AuthPack(&ap);
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret);
+       free_AuthPack(&ap);
+       if (ret) {
+           krb5_set_error_string(context, "AuthPack: %d", ret);
+           goto out;
+       }
+       if (buf.length != size)
+           krb5_abortx(context, "internal ASN1 encoder error");
+
+       oid = oid_id_pkauthdata();
+    } else
+       krb5_abortx(context, "internal pkinit error");
+
+    ret = _krb5_pk_create_sign(context,
+                              oid,
+                              &buf,
+                              ctx->id, 
+                              &sd_buf);
+    krb5_data_free(&buf);
+    if (ret)
+       goto out;
+
+    ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(), 
+                                 &content_info);
+    krb5_data_free(&sd_buf);
+    if (ret)
+       goto out;
+
+    /* XXX tell the kdc what CAs the client is willing to accept */
+    req.trustedCertifiers = NULL;
+    req.kdcPkId = NULL;
+
+    if (compat == COMPAT_WIN2K) {
+       PA_PK_AS_REQ_Win2k winreq;
+
+       pa_type = KRB5_PADATA_PK_AS_REQ_WIN;
+
+       memset(&winreq, 0, sizeof(winreq));
+
+       ASN1_MALLOC_ENCODE(ContentInfo,
+                          winreq.signed_auth_pack.data,
+                          winreq.signed_auth_pack.length,
+                          &content_info,
+                          &size,
+                          ret);
+       if (ret)
+           goto out;
+       if (winreq.signed_auth_pack.length != size)
+           krb5_abortx(context, "Internal ASN1 encoder error");
+
+       ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length,
+                          &winreq, &size, ret);
+       free_PA_PK_AS_REQ_Win2k(&winreq);
+
+    } else if (compat == COMPAT_19) {
+       PA_PK_AS_REQ_19 req_19;
+
+       pa_type = KRB5_PADATA_PK_AS_REQ_19;
+
+       memset(&req_19, 0, sizeof(req_19));
+
+       ret = copy_ContentInfo(&content_info, &req_19.signedAuthPack);
+       if (ret) {
+           krb5_clear_error_string(context);
+           goto out;
+       }
+       req_19.kdcCert = NULL;
+       req_19.trustedCertifiers = NULL;
+       req_19.encryptionCert = NULL;
+
+       ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_19, buf.data, buf.length,
+                          &req_19, &size, ret);
+
+       free_PA_PK_AS_REQ_19(&req_19);
+
+    } else if (compat == COMPAT_25) {
+
+       pa_type = KRB5_PADATA_PK_AS_REQ;
+
+       ASN1_MALLOC_ENCODE(ContentInfo,
+                          req.signedAuthPack.data,
+                          req.signedAuthPack.length,
+                          &content_info,
+                          &size,
+                          ret);
+       if (ret)
+           goto out;
+       if (req.signedAuthPack.length != size)
+           krb5_abortx(context, "Internal ASN1 encoder error");
+
+       ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length,
+                          &req, &size, ret);
+
+    } else
+       krb5_abortx(context, "internal pkinit error");
+    if (ret) {
+       krb5_set_error_string(context, "PA-PK-AS-REQ %d", ret);
+       goto out;
+    }
+    if (buf.length != size)
+       krb5_abortx(context, "Internal ASN1 encoder error");
+
+    ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length);
+    if (ret)
+       free(buf.data);
+ out:
+    free_ContentInfo(&content_info);
+
+    return ret;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION 
+_krb5_pk_mk_padata(krb5_context context,
+                  void *c,
+                  const KDC_REQ_BODY *req_body,
+                  unsigned nonce,
+                  METHOD_DATA *md)
+{
+    krb5_pk_init_ctx ctx = c;
+    krb5_error_code ret;
+    size_t size;
+    krb5_data buf;
+    const char *provisioning_server;
+    int win2k_compat;
+
+    win2k_compat = krb5_config_get_bool_default(context, NULL,
+                                               FALSE,
+                                               "realms",
+                                               req_body->realm,
+                                               "win2k_pkinit",
+                                               NULL);
+    if (context->pkinit_flags & KRB5_PKINIT_WIN2K)
+       win2k_compat = 1;
+
+    if (win2k_compat) {
+       ret = pk_mk_padata(context, COMPAT_WIN2K, ctx, req_body, nonce, md);
+       if (ret)
+           goto out;
+    } else {
+       ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md);
+       if (ret)
+           goto out;
+
+       ret = pk_mk_padata(context, COMPAT_25, ctx, req_body, nonce, md);
+       if (ret)
+           goto out;
+    }
+
+    provisioning_server =
+       krb5_config_get_string(context, NULL,
+                              "realms",
+                              req_body->realm,
+                              "packet-cable-provisioning-server",
+                              NULL);
+
+    if (provisioning_server) {
+       /* PacketCable requires the PROV-SRV-LOCATION authenticator */
+       const PROV_SRV_LOCATION prov_server = (char *)provisioning_server;
+
+       ASN1_MALLOC_ENCODE(PROV_SRV_LOCATION, buf.data, buf.length,
+                          &prov_server, &size, ret);
+       if (ret)
+           goto out;
+       if (buf.length != size)
+           krb5_abortx(context, "Internal ASN1 encoder error");
+
+       /* PacketCable uses -1 (application specific) as the auth data type */
+       ret = krb5_padata_add(context, md, -1, buf.data, buf.length);
+       if (ret)
+           free(buf.data);
+    }
+ out:
+    return ret;
+}
+
+static krb5_boolean
+pk_peer_compare(krb5_context context,
+               const SignerIdentifier *peer1, 
+               X509 *peer2)
+{
+    switch (peer1->element) {
+    case choice_CMSIdentifier_issuerAndSerialNumber: {
+       ASN1_INTEGER *i;
+       const heim_integer *serial;
+       X509_NAME *name;
+       unsigned char *p;
+       size_t len;
+
+       i = X509_get_serialNumber(peer2);
+       serial = &peer1->u.issuerAndSerialNumber.serialNumber;
+
+       if (i->length != serial->length ||
+           memcmp(i->data, serial->data, i->length) != 0)
+           return FALSE;
+
+       p = peer1->u.issuerAndSerialNumber.issuer._save.data;
+       len = peer1->u.issuerAndSerialNumber.issuer._save.length;
+       name = d2i_X509_NAME(NULL, &p, len);
+       if (name == NULL)
+           return FALSE;
+       
+       if (X509_NAME_cmp(name, X509_get_issuer_name(peer2)) != 0) {
+           X509_NAME_free(name);
+           return FALSE;
+       }
+       X509_NAME_free(name);
+       break;
+    }
+    case choice_CMSIdentifier_subjectKeyIdentifier:
+       return FALSE;
+    default:
+       return FALSE;
+    }
+    return TRUE;
+}
+
+static krb5_error_code
+pk_decrypt_key(krb5_context context,
+              heim_octet_string *encrypted_key,
+              EVP_PKEY *priv_key,
+              krb5_keyblock *key)
+{
+    int ret;
+    unsigned char *buf;
+
+    buf = malloc(EVP_PKEY_size(priv_key));
+    if (buf == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = EVP_PKEY_decrypt(buf,
+                          encrypted_key->data,
+                          encrypted_key->length,
+                          priv_key);
+    if (ret <= 0) {
+       free(buf);
+       krb5_set_error_string(context, "Can't decrypt key: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       return ENOMEM;
+    }
+
+    key->keytype = 0;
+    key->keyvalue.length = ret;
+    key->keyvalue.data = malloc(ret);
+    if (key->keyvalue.data == NULL) {
+       free(buf);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy(key->keyvalue.data, buf, ret);
+    free(buf);
+    return 0;
+}
+
+
+static krb5_error_code 
+pk_verify_chain_standard(krb5_context context,
+                        struct krb5_pk_identity *id,
+                        const SignerIdentifier *client,
+                        STACK_OF(X509) *chain,
+                        X509 **client_cert)
+{
+    X509_STORE *cert_store = NULL;
+    X509_STORE_CTX *store_ctx = NULL;
+    X509 *cert = NULL;
+    int i;
+    int ret;
+
+    ret = KRB5_KDC_ERROR_CLIENT_NAME_MISMATCH;
+    for (i = 0; i < sk_X509_num(chain); i++) {
+       cert = sk_X509_value(chain, i);
+       if (pk_peer_compare(context, client, cert) == TRUE) {
+           ret = 0;
+           break;
+       }
+    }
+    if (ret) {
+       krb5_set_error_string(context, "PKINIT: verify chain failed "
+                             "to find client in chain");
+       return ret;
+    }
+
+    cert_store = X509_STORE_new();
+    if (cert_store == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context, "PKINIT: can't create X509 store: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+    }
+
+    store_ctx = X509_STORE_CTX_new();
+    if (store_ctx == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string(context,
+                             "PKINIT: can't create X509 store ctx: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       goto end;
+    }
+   
+    X509_STORE_CTX_init(store_ctx, cert_store, cert, chain);
+    X509_STORE_CTX_trusted_stack(store_ctx, id->trusted_certs);
+    if (X509_verify_cert(store_ctx) < 0) {
+       store_ctx->error = X509_V_ERR_CERT_REJECTED;    /* XXX better value? */
+    }
+    /* the last checked certificate is in store_ctx->current_cert */
+    krb5_clear_error_string(context);
+    switch(store_ctx->error) {
+    case X509_V_OK:
+       ret = 0;
+       break;
+    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+       ret = KRB5_KDC_ERROR_CANT_VERIFY_CERTIFICATE;
+       krb5_set_error_string(context, "PKINIT: failed to verify "
+                             "certificate: %s ",
+                             X509_verify_cert_error_string(store_ctx->error));
+       break;
+    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+    case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+    case X509_V_ERR_CERT_NOT_YET_VALID:
+    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+    case X509_V_ERR_CERT_HAS_EXPIRED:
+       ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE;
+       krb5_set_error_string(context, "PKINIT: invalid certificate: %s ",
+                             X509_verify_cert_error_string(store_ctx->error));
+       break;
+    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+    case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+    case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+    case X509_V_ERR_INVALID_CA:
+       ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE;
+       krb5_set_error_string(context, "PKINIT: unknown CA or can't "
+                             "verify certificate: %s",
+                             X509_verify_cert_error_string(store_ctx->error));
+       break;
+    default:
+       ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; /* XXX */
+       krb5_set_error_string(context, "PKINIT: failed to verify "
+                             "certificate: %s (%ld) ",
+                             X509_verify_cert_error_string(store_ctx->error),
+                             (long)store_ctx->error);
+       break;
+    }
+    if (ret)
+       goto end;
+
+    /* 
+     * Since X509_verify_cert() doesn't do CRL checking at all, we have to
+     * perform own verification against CRLs
+     */
+#if 0
+    ret = pk_verify_crl(context, store_ctx, id->crls);
+    if (ret)
+       goto end;
+#endif
+
+    if (client_cert && cert)
+       *client_cert = X509_dup(cert);
+
+ end:
+    if (cert_store)
+       X509_STORE_free(cert_store);
+    if (store_ctx)
+       X509_STORE_CTX_free(store_ctx);
+    return ret;
+}
+
+static int
+cert_to_X509(krb5_context context, CertificateSetReal *set,
+            STACK_OF(X509_CRL) **certs)
+{
+    krb5_error_code ret;
+    int i;
+
+    *certs = sk_X509_new_null();
+
+    ret = 0;
+    for (i = 0; i < set->len; i++) {
+       unsigned char *p;
+       X509 *cert;
+
+       p = set->val[i].data;
+       cert = d2i_X509(NULL, &p, set->val[i].length);
+       if (cert == NULL) {
+           ret = ASN1_BAD_FORMAT;
+           break;
+       }
+       sk_X509_insert(*certs, cert, i);
+    }
+    if (ret) {
+       krb5_set_error_string(context,
+                             "PKINIT: Failed to decode certificate chain");
+       sk_X509_free(*certs);
+       *certs = NULL;
+    }
+    return ret;
+}
+
+static krb5_error_code
+any_to_CertificateSet(krb5_context context, heim_any *cert, 
+                     CertificateSetReal *set)
+{
+    size_t size, len, length;
+    heim_any *val;
+    int ret;
+    char *p;
+    
+    set->len = 0;
+    set->val = NULL;
+
+    len = 0;
+    p = cert->data;
+    length = cert->length;
+    while (len < cert->length) {
+       val = realloc(set->val, (set->len + 1) * sizeof(set->val[0]));
+       if (val == NULL) {
+           ret = ENOMEM;
+           goto out;
+       }
+       set->val = val;
+       ret = decode_heim_any(p, length, &set->val[set->len], &size);
+       if (ret)
+           goto out;
+       set->len++;
+
+       p += size;
+       len += size;
+       length -= size;
+    }
+    return 0;
+ out:
+    krb5_clear_error_string(context);
+    free_CertificateSetReal(set);
+    set->val = NULL;
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_verify_sign(krb5_context context,
+                    const char *data,
+                    size_t length,
+                    struct krb5_pk_identity *id,
+                    heim_oid *contentType,
+                    krb5_data *content,
+                    struct krb5_pk_cert **signer)
+{
+    STACK_OF(X509) *certificates;
+    SignerInfo *signer_info;
+    const EVP_MD *evp_type;
+    EVP_PKEY *public_key;
+    krb5_error_code ret;
+    CertificateSetReal set;
+    EVP_MD_CTX md;
+    X509 *cert;
+    SignedData sd;
+    size_t size;
+    
+    *signer = NULL;
+    krb5_data_zero(content);
+    contentType->length = 0;
+    contentType->components = NULL;
+
+    memset(&sd, 0, sizeof(sd));
+
+    ret = decode_SignedData(data, length, &sd, &size);
+    if (ret) {
+       krb5_set_error_string(context, 
+                             "PKINIT: decoding failed SignedData: %d",
+                             ret);
+       goto out;
+    }
+
+    if (sd.encapContentInfo.eContent == NULL) {
+       krb5_set_error_string(context, 
+                             "PKINIT: signature missing encapContent");
+       ret = KRB5KRB_AP_ERR_MSG_TYPE;
+       goto out;
+    }
+
+    /* XXX Check CMS version */
+
+    if (sd.signerInfos.len < 1) {
+       krb5_set_error_string(context,
+                             "PKINIT: signature information missing from "
+                             "pkinit response");
+       ret = KRB5_KDC_ERR_INVALID_SIG;
+       goto out;
+    }
+
+    signer_info = &sd.signerInfos.val[0];
+  
+    ret = any_to_CertificateSet(context, sd.certificates, &set);
+    if (ret) {
+       krb5_set_error_string(context,
+                             "PKINIT: failed to decode CertificateSet");
+       goto out;
+    }
+
+    ret = cert_to_X509(context, &set, &certificates);
+    free_CertificateSetReal(&set);
+    if (ret) {
+       krb5_set_error_string(context,
+                             "PKINIT: failed to decode Certificates");
+       goto out;
+    }
+
+    ret = pk_verify_chain_standard(context, id,
+                                  &signer_info->sid,
+                                  certificates,
+                                  &cert);
+    sk_X509_free(certificates);
+    if (ret)
+       goto out;
+  
+    if (signer_info->signature.length == 0) {
+       free_SignedData(&sd);
+       X509_free(cert);
+       krb5_set_error_string(context, "PKINIT: signature missing from"
+                             "pkinit response");
+       return KRB5_KDC_ERR_INVALID_SIG; 
+    }
+
+    public_key = X509_get_pubkey(cert);
+
+    /* verify signature */
+    if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm,
+               oid_id_pkcs1_sha1WithRSAEncryption()) == 0)
+       evp_type = EVP_sha1();
+    else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm,
+                         oid_id_pkcs1_md5WithRSAEncryption()) == 0) 
+       evp_type = EVP_md5();
+    else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, 
+                         oid_id_secsig_sha_1()) == 0)
+       evp_type = EVP_sha1();
+    else {
+       X509_free(cert);
+       krb5_set_error_string(context, "PKINIT: The requested digest "
+                             "algorithm is not supported");
+       ret = KRB5_KDC_ERR_INVALID_SIG;
+       goto out;
+    }
+
+    EVP_VerifyInit(&md, evp_type);
+    EVP_VerifyUpdate(&md,
+                    sd.encapContentInfo.eContent->data,
+                    sd.encapContentInfo.eContent->length);
+    ret = EVP_VerifyFinal(&md,
+                         signer_info->signature.data,
+                         signer_info->signature.length,
+                         public_key);
+    if (ret != 1) {
+       X509_free(cert);
+       krb5_set_error_string(context, "PKINIT: signature didn't verify: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = KRB5_KDC_ERR_INVALID_SIG;
+       goto out;
+    }
+
+    ret = copy_oid(&sd.encapContentInfo.eContentType, contentType);
+    if (ret) {
+       krb5_clear_error_string(context);
+       goto out;
+    }
+
+    content->data = malloc(sd.encapContentInfo.eContent->length);
+    if (content->data == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+    content->length = sd.encapContentInfo.eContent->length;
+    memcpy(content->data,sd.encapContentInfo.eContent->data,content->length);
+
+    *signer = malloc(sizeof(**signer));
+    if (*signer == NULL) {
+       krb5_clear_error_string(context);
+       ret = ENOMEM;
+       goto out;
+    }
+    (*signer)->cert = cert;
+
+ out:
+    free_SignedData(&sd);
+    if (ret) {
+       free_oid(contentType);
+       krb5_data_free(content);
+    }
+    return ret;
+}
+
+static krb5_error_code
+get_reply_key(krb5_context context,
+             const krb5_data *content,
+             unsigned nonce,
+             krb5_keyblock **key)
+{
+    ReplyKeyPack_19 key_pack;
+    krb5_error_code ret;
+    size_t size;
+
+    ret = decode_ReplyKeyPack_19(content->data,
+                                content->length,
+                                &key_pack,
+                                &size);
+    if (ret) {
+       krb5_set_error_string(context, "PKINIT decoding reply key failed");
+       free_ReplyKeyPack_19(&key_pack);
+       return ret;
+    }
+     
+    if (key_pack.nonce != nonce) {
+       krb5_set_error_string(context, "PKINIT enckey nonce is wrong");
+       free_ReplyKeyPack_19(&key_pack);
+       return KRB5KRB_AP_ERR_MODIFIED;
+    }
+
+    *key = malloc (sizeof (**key));
+    if (*key == NULL) {
+       krb5_set_error_string(context, "PKINIT failed allocating reply key");
+       free_ReplyKeyPack_19(&key_pack);
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ret = copy_EncryptionKey(&key_pack.replyKey, *key);
+    free_ReplyKeyPack_19(&key_pack);
+    if (ret) {
+       krb5_set_error_string(context, "PKINIT failed copying reply key");
+       free(*key);
+    }
+
+    return ret;
+}
+
+static krb5_error_code
+pk_verify_host(krb5_context context, struct krb5_pk_cert *host)
+{
+    /* XXX */
+    return 0;
+}
+
+static krb5_error_code
+pk_rd_pa_reply_enckey(krb5_context context,
+                     int win2k_compat,
+                      ContentInfo *rep,
+                     krb5_pk_init_ctx ctx,
+                     krb5_enctype etype,
+                     unsigned nonce,
+                     PA_DATA *pa,
+                     krb5_keyblock **key) 
+{
+    krb5_error_code ret;
+    EnvelopedData ed;
+    krb5_keyblock tmp_key;
+    krb5_crypto crypto;
+    krb5_data plain;
+    KeyTransRecipientInfo *ri;
+    int length;
+    size_t size;
+    X509 *user_cert;
+    char *p;
+    krb5_boolean bret;
+    krb5_data content;
+    heim_oid contentType = { 0, NULL };
+    struct krb5_pk_cert *host = NULL;
+    heim_octet_string encryptedContent;
+    heim_octet_string *any;
+    krb5_data ivec;
+    krb5_data params;
+
+
+    memset(&tmp_key, 0, sizeof(tmp_key));
+    memset(&ed, 0, sizeof(ed));
+    krb5_data_zero(&plain);
+    krb5_data_zero(&content);
+    krb5_data_zero(&encryptedContent);
+    krb5_data_zero(&ivec);
+
+    user_cert = sk_X509_value(ctx->id->cert, 0);
+
+    if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) {
+       krb5_set_error_string(context, "PKINIT: Invalid content type");
+       return EINVAL;
+    }
+
+    if (rep->content == NULL) {
+       krb5_set_error_string(context, "PKINIT: No content in reply");
+       return EINVAL;
+    }
+
+    ret = decode_EnvelopedData(rep->content->data,
+                              rep->content->length,
+                              &ed,
+                              &size);
+    if (ret) {
+       free_EnvelopedData(&ed);
+       return ret;
+    }
+
+    if (ed.recipientInfos.len != 1) {
+       free_EnvelopedData(&ed);
+       krb5_set_error_string(context, "pkinit: Number of recipient infos "
+                             "not one (%d)",
+                             ed.recipientInfos.len);
+       return EINVAL; /* XXX */
+    }
+
+    ri = &ed.recipientInfos.val[0];
+
+    /* XXX make SignerIdentifier and RecipientIdentifier the same */
+    bret = pk_peer_compare(context, (SignerIdentifier *)&ri->rid, user_cert);
+    if (bret == FALSE) {
+       ret = KRB5KRB_AP_ERR_BADMATCH; /* XXX */
+       goto out;
+    }
+
+    if (heim_oid_cmp(oid_id_pkcs1_rsaEncryption(),
+                    &ri->keyEncryptionAlgorithm.algorithm)) {
+       krb5_set_error_string(context, "PKINIT: invalid content type");
+       return EINVAL;
+    }
+    
+    ret = pk_decrypt_key(context, &ri->encryptedKey,
+                        ctx->id->private_key, &tmp_key);
+    if (ret)
+       goto out;
+
+  
+    /* verify content type */
+    if (win2k_compat) {
+       if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_data())) {
+           ret = KRB5KRB_AP_ERR_MSG_TYPE;
+           goto out;
+       }
+    } else {
+       if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_signedData())) {
+           ret = KRB5KRB_AP_ERR_MSG_TYPE;
+           goto out;
+       }
+    }
+
+    if (ed.encryptedContentInfo.encryptedContent == NULL) {
+       krb5_set_error_string(context, "PKINIT: OPTIONAL encryptedContent "
+                             "field not filled in in KDC reply");
+       ret = KRB5_BADMSGTYPE;
+       goto out;
+    }
+
+    any = ed.encryptedContentInfo.encryptedContent;
+    ret = der_get_octet_string(any->data, any->length,
+                              &encryptedContent, NULL);
+    if (ret) {
+       krb5_set_error_string(context,
+                             "PKINIT: encryptedContent content invalid");
+       goto out;
+    }
+
+    if (ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters == NULL){
+       krb5_set_error_string(context,
+                             "PKINIT: encryptedContent parameter missing");
+       ret = KRB5_BADMSGTYPE;
+       goto out;
+    }
+
+    params.data = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->data;
+    params.length = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->length;
+
+    ret = _krb5_oid_to_enctype(context,
+                              &ed.encryptedContentInfo.contentEncryptionAlgorithm.algorithm,
+                              &tmp_key.keytype);
+    if (ret)
+       goto out;
+
+    ret = krb5_crypto_init(context, &tmp_key, 0, &crypto);
+    if (ret)
+       goto out;
+
+    ret = krb5_crypto_get_params(context, crypto, &params, &ivec);
+    if (ret)
+       goto out;
+
+    ret = krb5_decrypt_ivec(context, crypto,
+                           0,
+                           encryptedContent.data,
+                           encryptedContent.length,
+                           &plain,
+                           ivec.data);
+
+    p = plain.data;
+    length = plain.length;
+
+    /* win2k uses ContentInfo */
+    if (win2k_compat) {
+       ContentInfo ci;
+       size_t size;
+
+       ret = decode_ContentInfo(p, length, &ci, &size);
+       if (ret) {
+           krb5_set_error_string(context,
+                                 "PKINIT: failed decoding ContentInfo: %d",
+                                 ret);
+           goto out;
+       }
+
+       if (heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) {
+           ret = EINVAL; /* XXX */
+           krb5_set_error_string(context, "PKINIT: Invalid content type");
+           goto out;
+       }
+       p = ci.content->data;
+       length = ci.content->length;
+    } 
+
+    ret = _krb5_pk_verify_sign(context, 
+                              p,
+                              length,
+                              ctx->id,
+                              &contentType,
+                              &content,
+                              &host);
+    if (ret)
+       goto out;
+
+    /* make sure that it is the kdc's certificate */
+    ret = pk_verify_host(context, host);
+    if (ret) {
+       krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret);
+       goto out;
+    }
+
+    if (win2k_compat) {
+       if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
+           krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
+           ret = KRB5KRB_AP_ERR_MSG_TYPE;
+           goto out;
+       }
+    } else {
+       if (heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) {
+           krb5_set_error_string(context, "PKINIT: reply key, wrong oid");
+           ret = KRB5KRB_AP_ERR_MSG_TYPE;
+           goto out;
+       }
+    }
+
+    ret = get_reply_key(context, &content, nonce, key);
+    if (ret)
+       goto out;
+
+    /* XXX compare given etype with key->etype */
+
+ out:
+    if (host)
+       _krb5_pk_cert_free(host);
+    free_oid(&contentType);
+    free_octet_string(&encryptedContent);
+    krb5_data_free(&content);
+    krb5_free_keyblock_contents(context, &tmp_key);
+    krb5_data_free(&plain);
+    krb5_data_free(&ivec);
+
+    return ret;
+}
+
+static krb5_error_code
+pk_rd_pa_reply_dh(krb5_context context,
+                  ContentInfo *rep,
+                 krb5_pk_init_ctx ctx,
+                 krb5_enctype etype,
+                  unsigned nonce,
+                  PA_DATA *pa,
+                  krb5_keyblock **key)
+{
+    unsigned char *p, *dh_gen_key = NULL;
+    ASN1_INTEGER *dh_pub_key = NULL;
+    struct krb5_pk_cert *host = NULL;
+    BIGNUM *kdc_dh_pubkey = NULL;
+    KDCDHKeyInfo kdc_dh_info;
+    heim_oid contentType = { 0, NULL };
+    krb5_data content;
+    krb5_error_code ret;
+    int dh_gen_keylen;
+    size_t size;
+
+    krb5_data_zero(&content);
+    memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
+
+    if (heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) {
+       krb5_set_error_string(context, "PKINIT: Invalid content type");
+       return EINVAL;
+    }
+
+    if (rep->content == NULL) {
+       krb5_set_error_string(context, "PKINIT: No content in reply");
+       return EINVAL;
+    }
+
+    ret = _krb5_pk_verify_sign(context, 
+                              rep->content->data,
+                              rep->content->length,
+                              ctx->id,
+                              &contentType,
+                              &content,
+                              &host);
+    if (ret)
+       goto out;
+
+    /* make sure that it is the kdc's certificate */
+    ret = pk_verify_host(context, host);
+    if (ret)
+       goto out;
+
+    if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
+       ret = KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */
+       goto out;
+    }
+
+    ret = decode_KDCDHKeyInfo(content.data,
+                             content.length,
+                             &kdc_dh_info,
+                             &size);
+
+    if (ret)
+       goto out;
+
+    if (kdc_dh_info.nonce != nonce) {
+       krb5_set_error_string(context, "PKINIT: DH nonce is wrong");
+       ret = KRB5KRB_AP_ERR_MODIFIED;
+       goto out;
+    }
+
+    p = kdc_dh_info.subjectPublicKey.data;
+    size = (kdc_dh_info.subjectPublicKey.length + 7) / 8;
+    dh_pub_key = d2i_ASN1_INTEGER(NULL, &p, size);
+    if (dh_pub_key == NULL) {
+       krb5_set_error_string(context,
+                             "PKINIT: Can't parse KDC's DH public key");
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+
+    kdc_dh_pubkey = ASN1_INTEGER_to_BN(dh_pub_key, NULL);
+    if (kdc_dh_pubkey == NULL) {
+       krb5_set_error_string(context,
+                             "PKINIT: Can't convert KDC's DH public key");
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+
+    dh_gen_key = malloc(DH_size(ctx->dh));
+    if (dh_gen_key == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    dh_gen_keylen = DH_compute_key(dh_gen_key, kdc_dh_pubkey, ctx->dh);
+    if (dh_gen_keylen == -1) {
+       krb5_set_error_string(context, 
+                             "PKINIT: Can't compute Diffie-Hellman key (%s)",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = KRB5KRB_ERR_GENERIC;
+       goto out;
+    }
+
+    *key = malloc (sizeof (**key));
+    if (*key == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    ret = krb5_random_to_key(context, etype, dh_gen_key, dh_gen_keylen, *key);
+    if (ret) {
+       krb5_set_error_string(context,
+                             "PKINIT: can't create key from DH key");
+       free(*key);
+       *key = NULL;
+       goto out;
+    }
+
+ out:
+    if (kdc_dh_pubkey)
+       BN_free(kdc_dh_pubkey);
+    if (dh_gen_key) {
+       memset(dh_gen_key, 0, DH_size(ctx->dh));
+       free(dh_gen_key);
+    }
+    if (dh_pub_key)
+       ASN1_INTEGER_free(dh_pub_key);
+    if (host)
+       _krb5_pk_cert_free(host);
+    if (content.data)
+       krb5_data_free(&content);
+    free_KDCDHKeyInfo(&kdc_dh_info);
+
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_rd_pa_reply(krb5_context context,
+                    void *c,
+                    krb5_enctype etype,
+                    unsigned nonce,
+                    PA_DATA *pa,
+                    krb5_keyblock **key)
+{
+    krb5_pk_init_ctx ctx = c;
+    krb5_error_code ret;
+    ContentInfo ci;
+    size_t size;
+
+    /* Check for PK-INIT -25 */
+    if (pa->padata_type == KRB5_PADATA_PK_AS_REP) {
+       PA_PK_AS_REP rep;
+
+       memset(&rep, 0, sizeof(rep));
+
+       ret = decode_PA_PK_AS_REP(pa->padata_value.data,
+                                 pa->padata_value.length,
+                                 &rep,
+                                 &size);
+       if (ret)
+           return ret;
+
+       switch (rep.element) {
+       case choice_PA_PK_AS_REP_encKeyPack:
+           ret = decode_ContentInfo(rep.u.encKeyPack.data,
+                                    rep.u.encKeyPack.length,
+                                    &ci,
+                                    &size);
+           free_PA_PK_AS_REP(&rep);
+           if (ret) {
+               krb5_set_error_string(context,
+                                     "PKINIT: -25 decoding failed "
+                                     "ContentInfo: %d", ret);
+               break;
+           }
+           ret = pk_rd_pa_reply_enckey(context, 0, &ci, ctx,
+                                       etype, nonce, pa, key);
+           free_ContentInfo(&ci);
+           return ret;
+       default:
+           free_PA_PK_AS_REP(&rep);
+           krb5_set_error_string(context, "PKINIT: -25 reply "
+                                 "invalid content type");
+           break;
+       }
+    }
+
+    /* Check for PK-INIT -19 */
+    {
+       PA_PK_AS_REP_19 rep19;
+
+       memset(&rep19, 0, sizeof(rep19));
+
+       ret = decode_PA_PK_AS_REP_19(pa->padata_value.data,
+                                    pa->padata_value.length,
+                                    &rep19,
+                                    &size);
+       if (ret == 0) {
+           switch(rep19.element) {
+           case choice_PA_PK_AS_REP_19_dhSignedData:
+               ret = pk_rd_pa_reply_dh(context, &rep19.u.dhSignedData, ctx,
+                                       etype, nonce, pa, key);
+               break;
+           case choice_PA_PK_AS_REP_19_encKeyPack:
+               ret = pk_rd_pa_reply_enckey(context, 0,
+                                           &rep19.u.encKeyPack, ctx,
+                                           etype, nonce, pa, key);
+               break;
+           default:
+               krb5_set_error_string(context, "PKINIT: -19 reply invalid "
+                                     "content type");
+               ret = EINVAL;
+               break;
+           }
+           free_PA_PK_AS_REP_19(&rep19);
+           if (ret == 0)
+               return 0;
+       }
+    }
+
+    /* Check for Windows encoding of the AS-REP pa data */ 
+    {
+       PA_PK_AS_REP_Win2k w2krep;
+
+       memset(&w2krep, 0, sizeof(w2krep));
+       
+       ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data,
+                                       pa->padata_value.length,
+                                       &w2krep,
+                                       &size);
+       if (ret) {
+           krb5_set_error_string(context, "PKINIT: Failed decoding windows"
+                                 "pkinit reply %d", ret);
+           return ret;
+       }
+       
+       switch (w2krep.element) {
+       case choice_PA_PK_AS_REP_Win2k_encKeyPack:
+           ret = decode_ContentInfo(w2krep.u.encKeyPack.data,
+                                    w2krep.u.encKeyPack.length,
+                                    &ci,
+                                    &size);
+           free_PA_PK_AS_REP_Win2k(&w2krep);
+           if (ret) {
+               krb5_set_error_string(context,
+                                     "PKINIT: decoding failed "
+                                     "ContentInfo: %d",
+                                     ret);
+               return ret;
+           }
+           ret = pk_rd_pa_reply_enckey(context, 1, &ci, ctx,
+                                       etype, nonce, pa, key);
+           free_ContentInfo(&ci);
+           break;
+       default:
+           free_PA_PK_AS_REP_Win2k(&w2krep);
+           krb5_set_error_string(context, "PKINIT: win2k reply invalid "
+                                 "content type");
+           ret = EINVAL;
+           break;
+       }
+    
+    }
+
+    return ret;
+}
+
+static int
+ssl_pass_cb(char *buf, int size, int rwflag, void *u)
+{
+    krb5_error_code ret;
+    krb5_prompt prompt;
+    krb5_data password_data;
+    krb5_prompter_fct prompter = u;
+   
+    password_data.data   = buf;
+    password_data.length = size;
+    prompt.prompt = "Enter your private key passphrase: ";
+    prompt.hidden = 1;
+    prompt.reply  = &password_data;
+    prompt.type   = KRB5_PROMPT_TYPE_PASSWORD;
+   
+    ret = (*prompter)(NULL, NULL, NULL, NULL, 1, &prompt);
+    if (ret) {
+       memset (buf, 0, size);
+       return 0;
+    }
+    return strlen(buf);
+}
+
+static krb5_error_code
+load_openssl_cert(krb5_context context,
+                 const char *file,
+                 STACK_OF(X509) **c)
+{
+    STACK_OF(X509) *certificate;
+    krb5_error_code ret;
+    FILE *f;
+
+    f = fopen(file, "r");
+    if (f == NULL) {
+       ret = errno;
+       krb5_set_error_string(context, "PKINIT: open failed %s: %s", 
+                             file, strerror(ret));
+       return ret;
+    }
+
+    certificate = sk_X509_new_null();
+    while (1) {
+       /* see http://www.openssl.org/docs/crypto/pem.html section BUGS */
+       X509 *cert;
+       cert = PEM_read_X509(f, NULL, NULL, NULL);
+       if (cert == NULL) {
+           if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) {
+               /* End of file reached. no error */
+               ERR_clear_error();
+               break;
+           }
+           krb5_set_error_string(context, "PKINIT: Can't read certificate");
+           fclose(f);
+           return HEIM_PKINIT_CERTIFICATE_INVALID;
+       }
+       sk_X509_insert(certificate, cert, sk_X509_num(certificate));
+    }
+    fclose(f);
+    if (sk_X509_num(certificate) == 0) {
+       krb5_set_error_string(context, "PKINIT: No certificate found");
+       return HEIM_PKINIT_NO_CERTIFICATE;
+    }
+    *c = certificate;
+    return 0;
+}
+
+static krb5_error_code
+load_openssl_file(krb5_context context,
+                 char *password,
+                 krb5_prompter_fct prompter,
+                 void *prompter_data,
+                 const char *user_id,
+                 struct krb5_pk_identity *id)
+{
+    krb5_error_code ret;
+    STACK_OF(X509) *certificate = NULL;
+    char *cert_file = NULL, *key_file;
+    EVP_PKEY *private_key = NULL;
+    FILE *f;
+
+    cert_file = strdup(user_id);
+    if (cert_file == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    key_file = strchr(cert_file, ',');
+    if (key_file == NULL) {
+       krb5_set_error_string(context, "PKINIT: key file missing");
+       ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+       goto out;
+    }
+    *key_file++ = '\0';
+
+    ret = load_openssl_cert(context, cert_file, &certificate);
+    if (ret)
+       goto out;
+
+    /* load private key */
+    f = fopen(key_file, "r");
+    if (f == NULL) {
+       ret = errno;
+       krb5_set_error_string(context, "PKINIT: open %s: %s",
+                             key_file, strerror(ret));
+       goto out;
+    }
+    if (password == NULL || password[0] == '\0') {
+       if (prompter == NULL)
+           prompter = krb5_prompter_posix;
+       private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, prompter);
+    } else
+       private_key = PEM_read_PrivateKey(f, NULL, NULL, password);
+    fclose(f);
+    if (private_key == NULL) {
+       krb5_set_error_string(context, "PKINIT: Can't read private key");
+       ret = HEIM_PKINIT_PRIVATE_KEY_INVALID;
+       goto out;
+    }
+    ret = X509_check_private_key(sk_X509_value(certificate, 0), private_key);
+    if (ret != 1) {
+       ret = HEIM_PKINIT_PRIVATE_KEY_INVALID;
+       krb5_set_error_string(context,
+                             "PKINIT: The private key doesn't match "
+                             "the public key certificate");
+       goto out;
+    }
+
+    id->private_key = private_key;
+    id->cert = certificate;
+
+    return 0;
+ out:
+    if (cert_file)
+       free(cert_file);
+    if (certificate)
+       sk_X509_pop_free(certificate, X509_free);
+    if (private_key)
+       EVP_PKEY_free(private_key);
+
+    return ret;
+}
+
+static int
+add_pair(krb5_context context, char *str, char ***cmds, int *num)
+{
+    char **c;
+    char *p;
+    int i;
+
+    p = strchr(str, ':');
+    if (p) {
+       *p = '\0';
+       p++;
+    }
+
+    /* filter out dup keys */
+    for (i = 0; i < *num; i++)
+       if (strcmp((*cmds)[i * 2], str) == 0)
+           return 0;
+
+    c = realloc(*cmds, sizeof(*c) * ((*num + 1) * 2));
+    if (c == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    c[(*num * 2)] = str;
+    c[(*num * 2) + 1] = p;
+    *num += 1;
+    *cmds = c;
+    return 0;
+}
+
+static krb5_error_code
+eval_pairs(krb5_context context, ENGINE *e, const char *name,
+          const char *type, char **cmds, int num)
+{
+    int i;
+
+    for (i = 0; i < num; i++) {
+       char *a1 = cmds[i * 2], *a2 = cmds[(i * 2) + 1];
+       if(!ENGINE_ctrl_cmd_string(e, a1, a2, 0)) {
+           krb5_set_error_string(context,
+                                 "PKINIT: Failed %scommand (%s - %s:%s): %s", 
+                                 type, name, a1, a2 ? a2 : "(NULL)",
+                                 ERR_error_string(ERR_get_error(), NULL));
+           return HEIM_PKINIT_NO_PRIVATE_KEY;
+       }
+    }
+    return 0;
+}
+
+struct engine_context {
+    char **pre_cmds;
+    char **post_cmds;
+    int num_pre;
+    int num_post;
+    char *engine_name;
+    char *cert_file;
+    char *key_id;
+};
+
+static krb5_error_code
+parse_openssl_engine_conf(krb5_context context, 
+                         struct engine_context *ctx,
+                         char *line)
+{
+    krb5_error_code ret;
+    char *last, *p, *q;
+
+    for (p = strtok_r(line, ",", &last);
+        p != NULL;
+        p = strtok_r(NULL, ",", &last)) {
+
+       q = strchr(p, '=');
+       if (q == NULL) {
+           krb5_set_error_string(context, 
+                                 "PKINIT: openssl engine configuration "
+                                 "key %s missing = and thus value", p);
+           return HEIM_PKINIT_NO_PRIVATE_KEY;
+       }
+       *q = '\0';
+       q++;
+       if (strcasecmp("PRE", p) == 0) {
+           ret = add_pair(context, q, &ctx->pre_cmds, &ctx->num_pre);
+           if (ret)
+               return ret;
+       } else if (strcasecmp("POST", p) == 0) {
+           ret = add_pair(context, q, &ctx->post_cmds, &ctx->num_post);
+           if (ret)
+               return ret;
+       } else if (strcasecmp("KEY", p) == 0) {
+           ctx->key_id = q;
+       } else if (strcasecmp("CERT", p) == 0) {
+           ctx->cert_file = q;
+       } else if (strcasecmp("ENGINE", p) == 0) {
+           ctx->engine_name = q;
+       } else {
+           krb5_set_error_string(context, 
+                                 "PKINIT: openssl engine configuration "
+                                 "key %s is unknown", p);
+           return HEIM_PKINIT_NO_PRIVATE_KEY;
+       }
+    }
+    return 0;
+}
+
+
+static krb5_error_code
+load_openssl_engine(krb5_context context,
+                   char *password,
+                   krb5_prompter_fct prompter,
+                   void *prompter_data,
+                   const char *string,
+                   struct krb5_pk_identity *id)
+{
+    struct engine_context ctx;
+    krb5_error_code ret;
+    const char *f;
+    char *file_conf = NULL, *user_conf = NULL;
+    ENGINE *e = NULL;
+
+    memset(&ctx, 0, sizeof(ctx));
+
+    ENGINE_load_builtin_engines();
+
+    user_conf = strdup(string);
+    if (user_conf == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ret = parse_openssl_engine_conf(context, &ctx, user_conf);
+    if (ret)
+       goto out;
+
+    f = krb5_config_get_string_default(context, NULL, NULL,
+                                      "libdefaults", 
+                                      "pkinit-openssl-engine", 
+                                      NULL);
+    if (f) {
+       file_conf = strdup(f);
+       if (file_conf) {
+           ret = parse_openssl_engine_conf(context, &ctx, file_conf);
+           if (ret)
+               goto out;
+       }
+    }
+
+    if (ctx.cert_file == NULL) {
+       krb5_set_error_string(context, 
+                             "PKINIT: openssl engine missing certificate");
+       ret = HEIM_PKINIT_NO_CERTIFICATE;
+       goto out;
+    }
+    if (ctx.key_id == NULL) {
+       krb5_set_error_string(context,
+                             "PKINIT: openssl engine missing key id");
+       ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+       goto out;
+    }
+    if (ctx.engine_name == NULL) {
+       krb5_set_error_string(context,
+                             "PKINIT: openssl engine missing engine name");
+       ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+       goto out;
+    }
+
+    e = ENGINE_by_id(ctx.engine_name);
+    if (e == NULL) {
+       krb5_set_error_string(context, 
+                             "PKINIT: failed getting openssl engine %s: %s", 
+                             ctx.engine_name,
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+       goto out;
+    }
+
+    ret = eval_pairs(context, e, ctx.engine_name, "pre", 
+                    ctx.pre_cmds, ctx.num_pre);
+    if (ret)
+       goto out;
+
+    if(!ENGINE_init(e)) {
+       ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+       krb5_set_error_string(context,
+                             "PKINIT: openssl engine init %s failed: %s", 
+                             ctx.engine_name,
+                             ERR_error_string(ERR_get_error(), NULL));
+       ENGINE_free(e);
+       goto out;
+    }
+
+    ret = eval_pairs(context, e, ctx.engine_name, "post", 
+                    ctx.post_cmds, ctx.num_post);
+    if (ret)
+       goto out;
+
+    /*
+     * If the engine supports a LOAD_CERT_CTRL function, lets try
+     * it. OpenSC support this function. Eventially this should be
+     * a ENGINE_load_cert function if it failes, treat it like a
+     * non fatal error.
+     */
+    {
+       struct {
+           const char * cert_id;
+           X509 * cert;
+       } parms;
+
+       parms.cert_id = ctx.cert_file;
+       parms.cert = NULL;
+       ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); 
+       if (parms.cert) {
+           id->cert = sk_X509_new_null();
+           sk_X509_insert(id->cert, parms.cert, 0);    
+       }  
+    }
+
+    if (id->cert == NULL) {
+       ret = load_openssl_cert(context, ctx.cert_file, &id->cert);
+       if (ret)
+           goto out;
+    }
+
+    {
+       UI_METHOD * krb5_ui_method = NULL;
+       struct krb5_ui_data ui_data;
+
+       krb5_ui_method = UI_create_method("Krb5 ui method");
+       if (krb5_ui_method == NULL) {
+           krb5_set_error_string(context,
+                                 "PKINIT: failed to setup prompter "
+                                 "function: %s",
+                                 ERR_error_string(ERR_get_error(), NULL));
+           ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+           goto out;
+       }
+       UI_method_set_reader(krb5_ui_method, krb5_ui_method_read_string);
+
+       ui_data.context = context;
+       ui_data.prompter = prompter;
+       if (prompter == NULL)
+           ui_data.prompter = krb5_prompter_posix;
+       ui_data.prompter_data = prompter_data;
+
+       id->private_key = ENGINE_load_private_key(e,
+                                                 ctx.key_id, 
+                                                 krb5_ui_method,
+                                                 (void*) &ui_data);
+       UI_destroy_method(krb5_ui_method);
+    }
+       
+    if (id->private_key == NULL) {
+       krb5_set_error_string(context,
+                             "PKINIT: failed to load private key: %s",
+                             ERR_error_string(ERR_get_error(), NULL));
+       ret = HEIM_PKINIT_NO_PRIVATE_KEY;
+       goto out;
+    }
+
+    ret = X509_check_private_key(sk_X509_value(id->cert, 0), id->private_key);
+    if (ret != 1) {
+       ret = HEIM_PKINIT_PRIVATE_KEY_INVALID;
+       krb5_set_error_string(context,
+                             "PKINIT: The private key doesn't match "
+                             "the public key certificate");
+       goto out;
+    }
+
+    if (user_conf)
+       free(user_conf);
+    if (file_conf)
+       free(file_conf);
+
+    id->engine = e;
+
+    return 0;
+
+ out:
+    if (user_conf)
+       free(user_conf);
+    if (file_conf)
+       free(file_conf);
+    if (e) {
+       ENGINE_finish(e); /* make sure all shared libs are unloaded */
+       ENGINE_free(e);
+    }
+       
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_load_openssl_id(krb5_context context,
+                        struct krb5_pk_identity **ret_id,
+                        const char *user_id,
+                        const char *x509_anchors,
+                        krb5_prompter_fct prompter,
+                        void *prompter_data,
+                        char *password)
+{
+    STACK_OF(X509) *trusted_certs = NULL;
+    struct krb5_pk_identity *id = NULL;
+    krb5_error_code ret;
+    struct dirent *file;
+    char *dirname = NULL;
+    DIR *dir;
+    FILE *f;
+    krb5_error_code (*load_pair)(krb5_context, 
+                                char *, 
+                                krb5_prompter_fct prompter,
+                                void * prompter_data,
+                                const char *,
+                                struct krb5_pk_identity *) = NULL;
+
+
+    *ret_id = NULL;
+
+    if (x509_anchors == NULL) {
+       krb5_set_error_string(context, "PKINIT: No root ca directory given");
+       return HEIM_PKINIT_NO_VALID_CA;
+    }
+
+    if (user_id == NULL) {
+       krb5_set_error_string(context,
+                             "PKINIT: No user X509 source given given");
+       return HEIM_PKINIT_NO_PRIVATE_KEY;
+    }
+
+    /* 
+     *
+     */
+
+    if (strncasecmp(user_id, "FILE:", 5) == 0) {
+       load_pair = load_openssl_file;
+       user_id += 5;
+    } else if (strncasecmp(user_id, "ENGINE:", 7) == 0) {
+       load_pair = load_openssl_engine;
+       user_id += 7;
+    } else {
+       krb5_set_error_string(context, "PKINIT: user identity not FILE");
+       return HEIM_PKINIT_NO_CERTIFICATE;
+    }
+    if (strncasecmp(x509_anchors, "OPENSSL-ANCHOR-DIR:", 19) != 0) {
+       krb5_set_error_string(context, "PKINIT: anchor OPENSSL-ANCHOR-DIR");
+       return HEIM_PKINIT_NO_VALID_CA;
+    }
+    x509_anchors += 19;
+
+    id = malloc(sizeof(*id));
+    if (id == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }  
+    memset(id, 0, sizeof(*id));
+
+    OpenSSL_add_all_algorithms();
+    ERR_load_crypto_strings();
+
+    
+    ret = (*load_pair)(context, password, prompter, prompter_data, user_id, id);
+    if (ret)
+       goto out;
+
+    /* load anchors */
+
+    dirname = strdup(x509_anchors);
+    if (dirname == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto out;
+    }
+
+    {
+       size_t len;
+       len = strlen(dirname);
+       if (dirname[len - 1] == '/')
+           dirname[len - 1] = '\0';
+    }
+
+    /* read ca certificates */
+    dir = opendir(dirname);
+    if (dir == NULL) {
+       ret = errno;
+       krb5_set_error_string(context, "PKINIT: open directory %s: %s",
+                             dirname, strerror(ret));
+       goto out;
+    }
+
+    trusted_certs = sk_X509_new_null();
+    while ((file = readdir(dir)) != NULL) {
+       X509 *cert;
+       char *filename;
+
+       /*
+        * Assume the certificate filenames constist of hashed subject
+        * name followed by suffix ".0"
+        */
+
+       if (strlen(file->d_name) == 10 && strcmp(&file->d_name[8],".0") == 0) {
+           asprintf(&filename, "%s/%s", dirname, file->d_name);
+           if (filename == NULL) {
+               ret = ENOMEM;
+               krb5_set_error_string(context, "malloc: out or memory");
+               goto out;
+           }
+           f = fopen(filename, "r");
+           if (f == NULL) {
+               ret = errno;
+               krb5_set_error_string(context, "PKINIT: open %s: %s",
+                                     filename, strerror(ret));
+               free(filename);
+               closedir(dir);
+               goto out;
+           }
+           cert = PEM_read_X509(f, NULL, NULL, NULL);
+           fclose(f);
+           if (cert != NULL) {
+               /* order of the certs is not important */
+               sk_X509_push(trusted_certs, cert);
+           }
+           free(filename);
+       }
+    }
+    closedir(dir);
+
+    if (sk_X509_num(trusted_certs) == 0) {
+       krb5_set_error_string(context,
+                             "PKINIT: No CA certificate(s) found in %s",
+                             dirname);
+       ret = HEIM_PKINIT_NO_VALID_CA;
+       goto out;
+    }
+
+    id->trusted_certs = trusted_certs;
+
+    *ret_id = id;
+
+    return 0;
+
+ out:
+    if (dirname)
+       free(dirname);
+    if (trusted_certs)
+       sk_X509_pop_free(trusted_certs, X509_free);
+    if (id) {
+       if (id->cert)
+           sk_X509_pop_free(id->cert, X509_free);
+       if (id->private_key)
+           EVP_PKEY_free(id->private_key);
+       free(id);
+    }
+
+    return ret;
+}
+
+#endif /* PKINIT */
+
+void KRB5_LIB_FUNCTION
+_krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
+{
+#ifdef PKINIT
+    krb5_pk_init_ctx ctx;
+
+    if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL)
+       return;
+    ctx = opt->opt_private->pk_init_ctx;
+    if (ctx->dh)
+       DH_free(ctx->dh);
+       ctx->dh = NULL;
+    if (ctx->id) {
+       if (ctx->id->cert)
+           sk_X509_pop_free(ctx->id->cert, X509_free);
+       if (ctx->id->trusted_certs)
+           sk_X509_pop_free(ctx->id->trusted_certs, X509_free);
+       if (ctx->id->private_key)
+           EVP_PKEY_free(ctx->id->private_key);
+       if (ctx->id->engine) {
+               ENGINE_finish(ctx->id->engine); /* unload shared libs etc */
+           ENGINE_free(ctx->id->engine);
+               ctx->id->engine = NULL;
+       }
+       free(ctx->id);
+       ctx->id = NULL;
+    }
+    opt->opt_private->pk_init_ctx = NULL;
+#endif
+}
+    
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_pkinit(krb5_context context,
+                                  krb5_get_init_creds_opt *opt,
+                                  krb5_principal principal,
+                                  const char *user_id,
+                                  const char *x509_anchors,
+                                  int flags,
+                                  krb5_prompter_fct prompter,
+                                  void *prompter_data,
+                                  char *password)
+{
+#ifdef PKINIT
+    krb5_error_code ret;
+
+    if (opt->opt_private == NULL) {
+       krb5_set_error_string(context, "PKINIT: on non extendable opt");
+       return EINVAL;
+    }
+
+    opt->opt_private->pk_init_ctx = malloc(sizeof(*opt->opt_private->pk_init_ctx));
+    if (opt->opt_private->pk_init_ctx == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    opt->opt_private->pk_init_ctx->dh = NULL;
+    opt->opt_private->pk_init_ctx->id = NULL;
+    ret = _krb5_pk_load_openssl_id(context,
+                                  &opt->opt_private->pk_init_ctx->id,
+                                  user_id,
+                                  x509_anchors,
+                                  prompter,
+                                  prompter_data,
+                                  password);
+    if (ret) {
+       free(opt->opt_private->pk_init_ctx);
+       opt->opt_private->pk_init_ctx = NULL;
+    }
+
+    /* XXX */
+    if (ret == 0 && (flags & 1) && !(flags & 2)) { 
+       DH *dh;
+       const char *P =
+            "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1"
+            "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD"
+            "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245"
+            "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED"
+            "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381"
+            "FFFFFFFF" "FFFFFFFF";
+       const char *G = "2";
+       const char *Q =
+           "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68"
+           "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E"
+           "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122"
+           "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6"
+           "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0"
+           "FFFFFFFF" "FFFFFFFF";
+
+       dh = DH_new();
+       if (dh == NULL) {
+           _krb5_get_init_creds_opt_free_pkinit(opt);
+           return ENOMEM;
+       }
+       opt->opt_private->pk_init_ctx->dh = dh;
+       if (!BN_hex2bn(&dh->p, P)) {
+           _krb5_get_init_creds_opt_free_pkinit(opt);
+           return ENOMEM;
+       }
+       if (!BN_hex2bn(&dh->g, G)) {
+           _krb5_get_init_creds_opt_free_pkinit(opt);
+           return ENOMEM;
+       }
+       if (!BN_hex2bn(&dh->q, Q)) {
+           _krb5_get_init_creds_opt_free_pkinit(opt);
+           return ENOMEM;
+       }
+       /* XXX generate a new key for each request ? */
+       if (DH_generate_key(dh) != 1) {
+           _krb5_get_init_creds_opt_free_pkinit(opt);
+           return ENOMEM;
+       }
+    }
+    return ret;
+#else
+    krb5_set_error_string(context, "no support for PKINIT compiled in");
+    return EINVAL;
+#endif
+}
diff --git a/src/kerberosV/src/lib/krb5/principal.c b/src/kerberosV/src/lib/krb5/principal.c
new file mode 100644 (file)
index 0000000..e5e7ccc
--- /dev/null
@@ -0,0 +1,1096 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#ifdef HAVE_RES_SEARCH
+#define USE_RESOLVER
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#include <fnmatch.h>
+#include "resolve.h"
+
+RCSID("$KTH: principal.c,v 1.88 2004/12/29 01:54:54 lha Exp $");
+
+#define princ_num_comp(P) ((P)->name.name_string.len)
+#define princ_type(P) ((P)->name.name_type)
+#define princ_comp(P) ((P)->name.name_string.val)
+#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)])
+#define princ_realm(P) ((P)->realm)
+
+void KRB5_LIB_FUNCTION
+krb5_free_principal(krb5_context context,
+                   krb5_principal p)
+{
+    if(p){
+       free_Principal(p);
+       free(p);
+    }
+}
+
+void KRB5_LIB_FUNCTION
+krb5_principal_set_type(krb5_context context,
+                       krb5_principal principal,
+                       int type)
+{
+    princ_type(principal) = type;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_principal_get_type(krb5_context context,
+                       krb5_principal principal)
+{
+    return princ_type(principal);
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_principal_get_realm(krb5_context context,
+                        krb5_principal principal)
+{
+    return princ_realm(principal);
+}                       
+
+const char* KRB5_LIB_FUNCTION
+krb5_principal_get_comp_string(krb5_context context,
+                              krb5_principal principal,
+                              unsigned int component)
+{
+    if(component >= princ_num_comp(principal))
+       return NULL;
+    return princ_ncomp(principal, component);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_parse_name(krb5_context context,
+               const char *name,
+               krb5_principal *principal)
+{
+    krb5_error_code ret;
+    heim_general_string *comp;
+    heim_general_string realm = NULL;
+    int ncomp;
+
+    const char *p;
+    char *q;
+    char *s;
+    char *start;
+
+    int n;
+    char c;
+    int got_realm = 0;
+  
+    /* count number of component */
+    ncomp = 1;
+    for(p = name; *p; p++){
+       if(*p=='\\'){
+           if(!p[1]) {
+               krb5_set_error_string (context,
+                                      "trailing \\ in principal name");
+               return KRB5_PARSE_MALFORMED;
+           }
+           p++;
+       } else if(*p == '/')
+           ncomp++;
+    }
+    comp = calloc(ncomp, sizeof(*comp));
+    if (comp == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+  
+    n = 0;
+    p = start = q = s = strdup(name);
+    if (start == NULL) {
+       free (comp);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    while(*p){
+       c = *p++;
+       if(c == '\\'){
+           c = *p++;
+           if(c == 'n')
+               c = '\n';
+           else if(c == 't')
+               c = '\t';
+           else if(c == 'b')
+               c = '\b';
+           else if(c == '0')
+               c = '\0';
+           else if(c == '\0') {
+               krb5_set_error_string (context,
+                                      "trailing \\ in principal name");
+               ret = KRB5_PARSE_MALFORMED;
+               goto exit;
+           }
+       }else if(c == '/' || c == '@'){
+           if(got_realm){
+               krb5_set_error_string (context,
+                                      "part after realm in principal name");
+               ret = KRB5_PARSE_MALFORMED;
+               goto exit;
+           }else{
+               comp[n] = malloc(q - start + 1);
+               if (comp[n] == NULL) {
+                   krb5_set_error_string (context, "malloc: out of memory");
+                   ret = ENOMEM;
+                   goto exit;
+               }
+               memcpy(comp[n], start, q - start);
+               comp[n][q - start] = 0;
+               n++;
+           }
+           if(c == '@')
+               got_realm = 1;
+           start = q;
+           continue;
+       }
+       if(got_realm && (c == ':' || c == '/' || c == '\0')) {
+           krb5_set_error_string (context,
+                                  "part after realm in principal name");
+           ret = KRB5_PARSE_MALFORMED;
+           goto exit;
+       }
+       *q++ = c;
+    }
+    if(got_realm){
+       realm = malloc(q - start + 1);
+       if (realm == NULL) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           ret = ENOMEM;
+           goto exit;
+       }
+       memcpy(realm, start, q - start);
+       realm[q - start] = 0;
+    }else{
+       ret = krb5_get_default_realm (context, &realm);
+       if (ret)
+           goto exit;
+
+       comp[n] = malloc(q - start + 1);
+       if (comp[n] == NULL) {
+           krb5_set_error_string (context, "malloc: out of memory");
+           ret = ENOMEM;
+           goto exit;
+       }
+       memcpy(comp[n], start, q - start);
+       comp[n][q - start] = 0;
+       n++;
+    }
+    *principal = malloc(sizeof(**principal));
+    if (*principal == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       ret = ENOMEM;
+       goto exit;
+    }
+    (*principal)->name.name_type = KRB5_NT_PRINCIPAL;
+    (*principal)->name.name_string.val = comp;
+    princ_num_comp(*principal) = n;
+    (*principal)->realm = realm;
+    free(s);
+    return 0;
+exit:
+    while(n>0){
+       free(comp[--n]);
+    }
+    free(comp);
+    free(realm);
+    free(s);
+    return ret;
+}
+
+static const char quotable_chars[] = " \n\t\b\\/@";
+static const char replace_chars[] = " ntb\\/@";
+
+#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
+
+static size_t
+quote_string(const char *s, char *out, size_t index, size_t len)
+{
+    const char *p, *q;
+    for(p = s; *p && index < len; p++){
+       if((q = strchr(quotable_chars, *p))){
+           add_char(out, index, len, '\\');
+           add_char(out, index, len, replace_chars[q - quotable_chars]);
+       }else
+           add_char(out, index, len, *p);
+    }
+    if(index < len)
+       out[index] = '\0';
+    return index;
+}
+
+
+static krb5_error_code
+unparse_name_fixed(krb5_context context,
+                  krb5_const_principal principal,
+                  char *name,
+                  size_t len,
+                  krb5_boolean short_form)
+{
+    size_t index = 0;
+    int i;
+    for(i = 0; i < princ_num_comp(principal); i++){
+       if(i)
+           add_char(name, index, len, '/');
+       index = quote_string(princ_ncomp(principal, i), name, index, len);
+       if(index == len)
+           return ERANGE;
+    } 
+    /* add realm if different from default realm */
+    if(short_form) {
+       krb5_realm r;
+       krb5_error_code ret;
+       ret = krb5_get_default_realm(context, &r);
+       if(ret)
+           return ret;
+       if(strcmp(princ_realm(principal), r) != 0)
+           short_form = 0;
+       free(r);
+    }
+    if(!short_form) {
+       add_char(name, index, len, '@');
+       index = quote_string(princ_realm(principal), name, index, len);
+       if(index == len)
+           return ERANGE;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_fixed(krb5_context context,
+                       krb5_const_principal principal,
+                       char *name,
+                       size_t len)
+{
+    return unparse_name_fixed(context, principal, name, len, FALSE);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_fixed_short(krb5_context context,
+                             krb5_const_principal principal,
+                             char *name,
+                             size_t len)
+{
+    return unparse_name_fixed(context, principal, name, len, TRUE);
+}
+
+static krb5_error_code
+unparse_name(krb5_context context,
+            krb5_const_principal principal,
+            char **name,
+            krb5_boolean short_flag)
+{
+    size_t len = 0, plen;
+    int i;
+    krb5_error_code ret;
+    /* count length */
+    plen = strlen(princ_realm(principal));
+    if(strcspn(princ_realm(principal), quotable_chars) == plen)
+       len += plen;
+    else
+       len += 2*plen;
+    len++;
+    for(i = 0; i < princ_num_comp(principal); i++){
+       plen = strlen(princ_ncomp(principal, i));
+       if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen)
+           len += plen;
+       else
+           len += 2*plen;
+       len++;
+    }
+    len++;
+    *name = malloc(len);
+    if(*name == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    ret = unparse_name_fixed(context, principal, *name, len, short_flag);
+    if(ret) {
+       free(*name);
+       *name = NULL;
+    }
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name(krb5_context context,
+                 krb5_const_principal principal,
+                 char **name)
+{
+    return unparse_name(context, principal, name, FALSE);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_short(krb5_context context,
+                       krb5_const_principal principal,
+                       char **name)
+{
+    return unparse_name(context, principal, name, TRUE);
+}
+
+#if 0 /* not implemented */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_unparse_name_ext(krb5_context context,
+                     krb5_const_principal principal,
+                     char **name,
+                     size_t *size)
+{
+    krb5_abortx(context, "unimplemented krb5_unparse_name_ext called");
+}
+
+#endif
+
+krb5_realm*
+krb5_princ_realm(krb5_context context,
+                krb5_principal principal)
+{
+    return &princ_realm(principal);
+}
+
+
+void KRB5_LIB_FUNCTION
+krb5_princ_set_realm(krb5_context context,
+                    krb5_principal principal,
+                    krb5_realm *realm)
+{
+    princ_realm(principal) = *realm;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal(krb5_context context,
+                    krb5_principal *principal,
+                    int rlen,
+                    krb5_const_realm realm,
+                    ...)
+{
+    krb5_error_code ret;
+    va_list ap;
+    va_start(ap, realm);
+    ret = krb5_build_principal_va(context, principal, rlen, realm, ap);
+    va_end(ap);
+    return ret;
+}
+
+static krb5_error_code
+append_component(krb5_context context, krb5_principal p, 
+                const char *comp,
+                size_t comp_len)
+{
+    heim_general_string *tmp;
+    size_t len = princ_num_comp(p);
+
+    tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp));
+    if(tmp == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    princ_comp(p) = tmp;
+    princ_ncomp(p, len) = malloc(comp_len + 1);
+    if (princ_ncomp(p, len) == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    memcpy (princ_ncomp(p, len), comp, comp_len);
+    princ_ncomp(p, len)[comp_len] = '\0';
+    princ_num_comp(p)++;
+    return 0;
+}
+
+static void
+va_ext_princ(krb5_context context, krb5_principal p, va_list ap)
+{
+    while(1){
+       const char *s;
+       int len;
+       len = va_arg(ap, int);
+       if(len == 0)
+           break;
+       s = va_arg(ap, const char*);
+       append_component(context, p, s, len);
+    }
+}
+
+static void
+va_princ(krb5_context context, krb5_principal p, va_list ap)
+{
+    while(1){
+       const char *s;
+       s = va_arg(ap, const char*);
+       if(s == NULL)
+           break;
+       append_component(context, p, s, strlen(s));
+    }
+}
+
+
+static krb5_error_code
+build_principal(krb5_context context,
+               krb5_principal *principal,
+               int rlen,
+               krb5_const_realm realm,
+               void (*func)(krb5_context, krb5_principal, va_list),
+               va_list ap)
+{
+    krb5_principal p;
+  
+    p = calloc(1, sizeof(*p));
+    if (p == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    princ_type(p) = KRB5_NT_PRINCIPAL;
+
+    princ_realm(p) = strdup(realm);
+    if(p->realm == NULL){
+       free(p);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+  
+    (*func)(context, p, ap);
+    *principal = p;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_make_principal(krb5_context context,
+                   krb5_principal *principal,
+                   krb5_const_realm realm,
+                   ...)
+{
+    krb5_error_code ret;
+    krb5_realm r = NULL;
+    va_list ap;
+    if(realm == NULL) {
+       ret = krb5_get_default_realm(context, &r);
+       if(ret)
+           return ret;
+       realm = r;
+    }
+    va_start(ap, realm);
+    ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap);
+    va_end(ap);
+    if(r)
+       free(r);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal_va(krb5_context context, 
+                       krb5_principal *principal, 
+                       int rlen,
+                       krb5_const_realm realm,
+                       va_list ap)
+{
+    return build_principal(context, principal, rlen, realm, va_princ, ap);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal_va_ext(krb5_context context, 
+                           krb5_principal *principal, 
+                           int rlen,
+                           krb5_const_realm realm,
+                           va_list ap)
+{
+    return build_principal(context, principal, rlen, realm, va_ext_princ, ap);
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_build_principal_ext(krb5_context context,
+                        krb5_principal *principal,
+                        int rlen,
+                        krb5_const_realm realm,
+                        ...)
+{
+    krb5_error_code ret;
+    va_list ap;
+    va_start(ap, realm);
+    ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap);
+    va_end(ap);
+    return ret;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_principal(krb5_context context,
+                   krb5_const_principal inprinc,
+                   krb5_principal *outprinc)
+{
+    krb5_principal p = malloc(sizeof(*p));
+    if (p == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    if(copy_Principal(inprinc, p)) {
+       free(p);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    *outprinc = p;
+    return 0;
+}
+
+/*
+ * return TRUE iff princ1 == princ2 (without considering the realm)
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_principal_compare_any_realm(krb5_context context,
+                                krb5_const_principal princ1,
+                                krb5_const_principal princ2)
+{
+    int i;
+    if(princ_num_comp(princ1) != princ_num_comp(princ2))
+       return FALSE;
+    for(i = 0; i < princ_num_comp(princ1); i++){
+       if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0)
+           return FALSE;
+    }
+    return TRUE;
+}
+
+/*
+ * return TRUE iff princ1 == princ2
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_principal_compare(krb5_context context,
+                      krb5_const_principal princ1,
+                      krb5_const_principal princ2)
+{
+    if(!krb5_realm_compare(context, princ1, princ2))
+       return FALSE;
+    return krb5_principal_compare_any_realm(context, princ1, princ2);
+}
+
+/*
+ * return TRUE iff realm(princ1) == realm(princ2)
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_realm_compare(krb5_context context,
+                  krb5_const_principal princ1,
+                  krb5_const_principal princ2)
+{
+    return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0;
+}
+
+/*
+ * return TRUE iff princ matches pattern
+ */
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_principal_match(krb5_context context,
+                    krb5_const_principal princ,
+                    krb5_const_principal pattern)
+{
+    int i;
+    if(princ_num_comp(princ) != princ_num_comp(pattern))
+       return FALSE;
+    if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0)
+       return FALSE;
+    for(i = 0; i < princ_num_comp(princ); i++){
+       if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0)
+           return FALSE;
+    }
+    return TRUE;
+}
+
+
+static struct v4_name_convert {
+    const char *from;
+    const char *to; 
+} default_v4_name_convert[] = {
+    { "ftp",   "ftp" },
+    { "hprop", "hprop" },
+    { "pop",   "pop" },
+    { "imap",  "imap" },
+    { "rcmd",  "host" },
+    { "smtp",  "smtp" },
+    { NULL, NULL }
+};
+
+/*
+ * return the converted instance name of `name' in `realm'.
+ * look in the configuration file and then in the default set above.
+ * return NULL if no conversion is appropriate.
+ */
+
+static const char*
+get_name_conversion(krb5_context context, const char *realm, const char *name)
+{
+    struct v4_name_convert *q;
+    const char *p;
+
+    p = krb5_config_get_string(context, NULL, "realms", realm,
+                              "v4_name_convert", "host", name, NULL);
+    if(p == NULL)
+       p = krb5_config_get_string(context, NULL, "libdefaults", 
+                                  "v4_name_convert", "host", name, NULL);
+    if(p)
+       return p;
+
+    /* XXX should be possible to override default list */
+    p = krb5_config_get_string(context, NULL,
+                              "realms",
+                              realm,
+                              "v4_name_convert",
+                              "plain",
+                              name,
+                              NULL);
+    if(p)
+       return NULL;
+    p = krb5_config_get_string(context, NULL,
+                              "libdefaults",
+                              "v4_name_convert",
+                              "plain",
+                              name,
+                              NULL);
+    if(p)
+       return NULL;
+    for(q = default_v4_name_convert; q->from; q++)
+       if(strcmp(q->from, name) == 0)
+           return q->to;
+    return NULL;
+}
+
+/*
+ * convert the v4 principal `name.instance@realm' to a v5 principal in `princ'.
+ * if `resolve', use DNS.
+ * if `func', use that function for validating the conversion
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_425_conv_principal_ext(krb5_context context,
+                           const char *name,
+                           const char *instance,
+                           const char *realm,
+                           krb5_boolean (*func)(krb5_context, krb5_principal),
+                           krb5_boolean resolve,
+                           krb5_principal *princ)
+{
+    const char *p;
+    krb5_error_code ret;
+    krb5_principal pr;
+    char host[MAXHOSTNAMELEN];
+    char local_hostname[MAXHOSTNAMELEN];
+
+    /* do the following: if the name is found in the
+       `v4_name_convert:host' part, is is assumed to be a `host' type
+       principal, and the instance is looked up in the
+       `v4_instance_convert' part. if not found there the name is
+       (optionally) looked up as a hostname, and if that doesn't yield
+       anything, the `default_domain' is appended to the instance
+       */
+
+    if(instance == NULL)
+       goto no_host;
+    if(instance[0] == 0){
+       instance = NULL;
+       goto no_host;
+    }
+    p = get_name_conversion(context, realm, name);
+    if(p == NULL)
+       goto no_host;
+    name = p;
+    p = krb5_config_get_string(context, NULL, "realms", realm, 
+                              "v4_instance_convert", instance, NULL);
+    if(p){
+       instance = p;
+       ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
+       if(func == NULL || (*func)(context, pr)){
+           *princ = pr;
+           return 0;
+       }
+       krb5_free_principal(context, pr);
+       *princ = NULL;
+       krb5_clear_error_string (context);
+       return HEIM_ERR_V4_PRINC_NO_CONV;
+    }
+    if(resolve){
+       krb5_boolean passed = FALSE;
+       char *inst = NULL;
+#ifdef USE_RESOLVER
+       struct dns_reply *r;
+
+       r = dns_lookup(instance, "aaaa");
+       if (r && r->head && r->head->type == T_AAAA) {
+           inst = strdup(r->head->domain);
+           dns_free_data(r);
+           passed = TRUE;
+       } else {
+           r = dns_lookup(instance, "a");
+           if(r && r->head && r->head->type == T_A) {
+               inst = strdup(r->head->domain);
+               dns_free_data(r);
+               passed = TRUE;
+           }
+       }
+#else
+       struct addrinfo hints, *ai;
+       int ret;
+       
+       memset (&hints, 0, sizeof(hints));
+       hints.ai_flags = AI_CANONNAME;
+       ret = getaddrinfo(instance, NULL, &hints, &ai);
+       if (ret == 0) {
+           const struct addrinfo *a;
+           for (a = ai; a != NULL; a = a->ai_next) {
+               if (a->ai_canonname != NULL) {
+                   inst = strdup (a->ai_canonname);
+                   passed = TRUE;
+                   break;
+               }
+           }
+           freeaddrinfo (ai);
+       }
+#endif
+       if (passed) {
+           if (inst == NULL) {
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           strlwr(inst);
+           ret = krb5_make_principal(context, &pr, realm, name, inst,
+                                     NULL);
+           free (inst);
+           if(ret == 0) {
+               if(func == NULL || (*func)(context, pr)){
+                   *princ = pr;
+                   return 0;
+               }
+               krb5_free_principal(context, pr);
+           }
+       }
+    }
+    if(func != NULL) {
+       snprintf(host, sizeof(host), "%s.%s", instance, realm);
+       strlwr(host);
+       ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+       if((*func)(context, pr)){
+           *princ = pr;
+           return 0;
+       }
+       krb5_free_principal(context, pr);
+    }
+
+    /*
+     * if the instance is the first component of the local hostname,
+     * the converted host should be the long hostname.
+     */
+
+    if (func == NULL && 
+        gethostname (local_hostname, sizeof(local_hostname)) == 0 &&
+        strncmp(instance, local_hostname, strlen(instance)) == 0 && 
+       local_hostname[strlen(instance)] == '.') {
+       strlcpy(host, local_hostname, sizeof(host));
+       goto local_host;
+    }
+
+    {
+       char **domains, **d;
+       domains = krb5_config_get_strings(context, NULL, "realms", realm,
+                                         "v4_domains", NULL);
+       for(d = domains; d && *d; d++){
+           snprintf(host, sizeof(host), "%s.%s", instance, *d);
+           ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+           if(func == NULL || (*func)(context, pr)){
+               *princ = pr;
+               krb5_config_free_strings(domains);
+               return 0;
+           }
+           krb5_free_principal(context, pr);
+       }
+       krb5_config_free_strings(domains);
+    }
+
+    
+    p = krb5_config_get_string(context, NULL, "realms", realm, 
+                              "default_domain", NULL);
+    if(p == NULL){
+       /* this should be an error, just faking a name is not good */
+       krb5_clear_error_string (context);
+       return HEIM_ERR_V4_PRINC_NO_CONV;
+    }
+       
+    if (*p == '.')
+       ++p;
+    snprintf(host, sizeof(host), "%s.%s", instance, p);
+local_host:
+    ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+    if(func == NULL || (*func)(context, pr)){
+       *princ = pr;
+       return 0;
+    }
+    krb5_free_principal(context, pr);
+    krb5_clear_error_string (context);
+    return HEIM_ERR_V4_PRINC_NO_CONV;
+no_host:
+    p = krb5_config_get_string(context, NULL,
+                              "realms",
+                              realm,
+                              "v4_name_convert",
+                              "plain",
+                              name,
+                              NULL);
+    if(p == NULL)
+       p = krb5_config_get_string(context, NULL,
+                                  "libdefaults",
+                                  "v4_name_convert",
+                                  "plain",
+                                  name,
+                                  NULL);
+    if(p)
+       name = p;
+    
+    ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
+    if(func == NULL || (*func)(context, pr)){
+       *princ = pr;
+       return 0;
+    }
+    krb5_free_principal(context, pr);
+    krb5_clear_error_string (context);
+    return HEIM_ERR_V4_PRINC_NO_CONV;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_425_conv_principal(krb5_context context,
+                       const char *name,
+                       const char *instance,
+                       const char *realm,
+                       krb5_principal *princ)
+{
+    krb5_boolean resolve = krb5_config_get_bool(context,
+                                               NULL,
+                                               "libdefaults", 
+                                               "v4_instance_resolve", 
+                                               NULL);
+
+    return krb5_425_conv_principal_ext(context, name, instance, realm, 
+                                      NULL, resolve, princ);
+}
+
+
+static int
+check_list(const krb5_config_binding *l, const char *name, const char **out)
+{
+    while(l){
+       if (l->type != krb5_config_string)
+           continue;
+       if(strcmp(name, l->u.string) == 0) {
+           *out = l->name;
+           return 1;
+       }
+       l = l->next;
+    }
+    return 0;
+}
+
+static int
+name_convert(krb5_context context, const char *name, const char *realm, 
+            const char **out)
+{
+    const krb5_config_binding *l;
+    l = krb5_config_get_list (context,
+                             NULL,
+                             "realms",
+                             realm,
+                             "v4_name_convert",
+                             "host",
+                             NULL);
+    if(l && check_list(l, name, out))
+       return KRB5_NT_SRV_HST;
+    l = krb5_config_get_list (context,
+                             NULL,
+                             "libdefaults",
+                             "v4_name_convert",
+                             "host",
+                             NULL);
+    if(l && check_list(l, name, out))
+       return KRB5_NT_SRV_HST;
+    l = krb5_config_get_list (context,
+                             NULL,
+                             "realms",
+                             realm,
+                             "v4_name_convert",
+                             "plain",
+                             NULL);
+    if(l && check_list(l, name, out))
+       return KRB5_NT_UNKNOWN;
+    l = krb5_config_get_list (context,
+                             NULL,
+                             "libdefaults",
+                             "v4_name_convert",
+                             "host",
+                             NULL);
+    if(l && check_list(l, name, out))
+       return KRB5_NT_UNKNOWN;
+    
+    /* didn't find it in config file, try built-in list */
+    {
+       struct v4_name_convert *q;
+       for(q = default_v4_name_convert; q->from; q++) {
+           if(strcmp(name, q->to) == 0) {
+               *out = q->from;
+               return KRB5_NT_SRV_HST;
+           }
+       }
+    }
+    return -1;
+}
+
+/*
+ * convert the v5 principal in `principal' into a v4 corresponding one
+ * in `name, instance, realm'
+ * this is limited interface since there's no length given for these
+ * three parameters.  They have to be 40 bytes each (ANAME_SZ).
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_524_conv_principal(krb5_context context,
+                       const krb5_principal principal,
+                       char *name, 
+                       char *instance,
+                       char *realm)
+{
+    const char *n, *i, *r;
+    char tmpinst[40];
+    int type = princ_type(principal);
+    const int aname_sz = 40;
+
+    r = principal->realm;
+
+    switch(principal->name.name_string.len){
+    case 1:
+       n = principal->name.name_string.val[0];
+       i = "";
+       break;
+    case 2:
+       n = principal->name.name_string.val[0];
+       i = principal->name.name_string.val[1];
+       break;
+    default:
+       krb5_set_error_string (context,
+                              "cannot convert a %d component principal",
+                              principal->name.name_string.len);
+       return KRB5_PARSE_MALFORMED;
+    }
+
+    {
+       const char *tmp;
+       int t = name_convert(context, n, r, &tmp);
+       if(t >= 0) {
+           type = t;
+           n = tmp;
+       }
+    }
+
+    if(type == KRB5_NT_SRV_HST){
+       char *p;
+
+       strlcpy (tmpinst, i, sizeof(tmpinst));
+       p = strchr(tmpinst, '.');
+       if(p)
+           *p = 0;
+       i = tmpinst;
+    }
+    
+    if (strlcpy (name, n, aname_sz) >= aname_sz) {
+       krb5_set_error_string (context,
+                              "too long name component to convert");
+       return KRB5_PARSE_MALFORMED;
+    }
+    if (strlcpy (instance, i, aname_sz) >= aname_sz) {
+       krb5_set_error_string (context,
+                              "too long instance component to convert");
+       return KRB5_PARSE_MALFORMED;
+    }
+    if (strlcpy (realm, r, aname_sz) >= aname_sz) {
+       krb5_set_error_string (context,
+                              "too long realm component to convert");
+       return KRB5_PARSE_MALFORMED;
+    }
+    return 0;
+}
+
+/*
+ * Create a principal in `ret_princ' for the service `sname' running
+ * on host `hostname'.  */
+                       
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sname_to_principal (krb5_context context,
+                        const char *hostname,
+                        const char *sname,
+                        int32_t type,
+                        krb5_principal *ret_princ)
+{
+    krb5_error_code ret;
+    char localhost[MAXHOSTNAMELEN];
+    char **realms, *host = NULL;
+       
+    if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) {
+       krb5_set_error_string (context, "unsupported name type %d",
+                              type);
+       return KRB5_SNAME_UNSUPP_NAMETYPE;
+    }
+    if(hostname == NULL) {
+       gethostname(localhost, sizeof(localhost));
+       hostname = localhost;
+    }
+    if(sname == NULL)
+       sname = "host";
+    if(type == KRB5_NT_SRV_HST) {
+       ret = krb5_expand_hostname_realms (context, hostname,
+                                          &host, &realms);
+       if (ret)
+           return ret;
+       strlwr(host);
+       hostname = host;
+    } else {
+       ret = krb5_get_host_realm(context, hostname, &realms);
+       if(ret)
+           return ret;
+    }
+
+    ret = krb5_make_principal(context, ret_princ, realms[0], sname,
+                             hostname, NULL);
+    if(host)
+       free(host);
+    krb5_free_host_realm(context, realms);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/prog_setup.c b/src/kerberosV/src/lib/krb5/prog_setup.c
new file mode 100644 (file)
index 0000000..86efa79
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$KTH: prog_setup.c,v 1.10 2004/05/25 21:37:55 lha Exp $");
+
+void KRB5_LIB_FUNCTION
+krb5_std_usage(int code, struct getargs *args, int num_args)
+{
+    arg_printusage(args, num_args, NULL, "");
+    exit(code);
+}
+
+int KRB5_LIB_FUNCTION
+krb5_program_setup(krb5_context *context, int argc, char **argv,
+                  struct getargs *args, int num_args, 
+                  void (*usage)(int, struct getargs*, int))
+{
+    krb5_error_code ret;
+    int optind = 0;
+
+    if(usage == NULL)
+       usage = krb5_std_usage;
+
+    ret = krb5_init_context(context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+    
+    if(getarg(args, num_args, argc, argv, &optind))
+       (*usage)(1, args, num_args);
+    return optind;
+}
diff --git a/src/kerberosV/src/lib/krb5/prompter_posix.c b/src/kerberosV/src/lib/krb5/prompter_posix.c
new file mode 100644 (file)
index 0000000..638e5b0
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: prompter_posix.c,v 1.10 2004/05/25 21:38:14 lha Exp $");
+
+int KRB5_LIB_FUNCTION
+krb5_prompter_posix (krb5_context context,
+                    void *data,
+                    const char *name,
+                    const char *banner,
+                    int num_prompts,
+                    krb5_prompt prompts[])
+{
+    int i;
+
+    if (name)
+       fprintf (stderr, "%s\n", name);
+    if (banner)
+       fprintf (stderr, "%s\n", banner);
+    if (name || banner)
+       fflush(stderr);
+    for (i = 0; i < num_prompts; ++i) {
+       if (prompts[i].hidden) {
+           if(UI_UTIL_read_pw_string(prompts[i].reply->data,
+                                 prompts[i].reply->length,
+                                 prompts[i].prompt,
+                                 0))
+              return 1;
+       } else {
+           char *s = prompts[i].reply->data;
+
+           fputs (prompts[i].prompt, stdout);
+           fflush (stdout);
+           if(fgets(prompts[i].reply->data,
+                    prompts[i].reply->length,
+                    stdin) == NULL)
+               return 1;
+           s[strcspn(s, "\n")] = '\0';
+       }
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/rd_cred.c b/src/kerberosV/src/lib/krb5/rd_cred.c
new file mode 100644 (file)
index 0000000..3b79a2a
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: rd_cred.c,v 1.22.2.2 2005/10/22 02:24:36 lha Exp $");
+
+static krb5_error_code
+compare_addrs(krb5_context context,
+             krb5_address *a,
+             krb5_address *b,
+             const char *message)
+{
+    char a_str[64], b_str[64];
+    size_t len;
+
+    if(krb5_address_compare (context, a, b))
+       return 0;
+
+    krb5_print_address (a, a_str, sizeof(a_str), &len);
+    krb5_print_address (b, b_str, sizeof(b_str), &len);
+    krb5_set_error_string(context, "%s: %s != %s", message, b_str, a_str);
+    return KRB5KRB_AP_ERR_BADADDR;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_cred(krb5_context context,
+            krb5_auth_context auth_context,
+            krb5_data *in_data,
+            krb5_creds ***ret_creds,
+            krb5_replay_data *outdata)
+{
+    krb5_error_code ret;
+    size_t len;
+    KRB_CRED cred;
+    EncKrbCredPart enc_krb_cred_part;
+    krb5_data enc_krb_cred_part_data;
+    krb5_crypto crypto;
+    int i;
+
+    memset(&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part));
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+       outdata == NULL)
+       return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
+
+    *ret_creds = NULL;
+
+    ret = decode_KRB_CRED(in_data->data, in_data->length, 
+                         &cred, &len);
+    if(ret)
+       return ret;
+
+    if (cred.pvno != 5) {
+       ret = KRB5KRB_AP_ERR_BADVERSION;
+       krb5_clear_error_string (context);
+       goto out;
+    }
+
+    if (cred.msg_type != krb_cred) {
+       ret = KRB5KRB_AP_ERR_MSG_TYPE;
+       krb5_clear_error_string (context);
+       goto out;
+    }
+
+    if (cred.enc_part.etype == ETYPE_NULL) {  
+       /* DK: MIT GSS-API Compatibility */
+       enc_krb_cred_part_data.length = cred.enc_part.cipher.length;
+       enc_krb_cred_part_data.data   = cred.enc_part.cipher.data;
+    } else {
+       /* Try both subkey and session key.
+        * 
+        * RFC2140 claims we should use the session key, but Heimdal
+        * before 0.8 used the remote subkey if it was send in the
+        * auth_context.
+        */
+
+       if (auth_context->remote_subkey) {
+           ret = krb5_crypto_init(context, auth_context->remote_subkey,
+                                  0, &crypto);
+           if (ret)
+               goto out;
+
+           ret = krb5_decrypt_EncryptedData(context,
+                                            crypto,
+                                            KRB5_KU_KRB_CRED,
+                                            &cred.enc_part,
+                                            &enc_krb_cred_part_data);
+           
+           krb5_crypto_destroy(context, crypto);
+       }
+
+       /* 
+        * If there was not subkey, or we failed using subkey, 
+        * retry using the session key
+        */
+       if (auth_context->remote_subkey == NULL || ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+       {
+
+           ret = krb5_crypto_init(context, auth_context->keyblock,
+                                  0, &crypto);
+
+           if (ret)
+               goto out;
+           
+           ret = krb5_decrypt_EncryptedData(context,
+                                            crypto,
+                                            KRB5_KU_KRB_CRED,
+                                            &cred.enc_part,
+                                            &enc_krb_cred_part_data);
+           
+           krb5_crypto_destroy(context, crypto);
+       }
+       if (ret)
+           goto out;
+    }
+
+    ret = krb5_decode_EncKrbCredPart (context,
+                                     enc_krb_cred_part_data.data,
+                                     enc_krb_cred_part_data.length,
+                                     &enc_krb_cred_part,
+                                     &len);
+    if (ret)
+       goto out;
+
+    /* check sender address */
+
+    if (enc_krb_cred_part.s_address
+       && auth_context->remote_address
+       && auth_context->remote_port) {
+       krb5_address *a;
+
+       ret = krb5_make_addrport (context, &a,
+                                 auth_context->remote_address,
+                                 auth_context->remote_port);
+       if (ret)
+           goto out;
+
+
+       ret = compare_addrs(context, a, enc_krb_cred_part.s_address, 
+                           "sender address is wrong in received creds");
+       krb5_free_address(context, a);
+       free(a);
+       if(ret)
+           goto out;
+    }
+
+    /* check receiver address */
+
+    if (enc_krb_cred_part.r_address
+       && auth_context->local_address) {
+       if(auth_context->local_port &&
+          enc_krb_cred_part.r_address->addr_type == KRB5_ADDRESS_ADDRPORT) {
+           krb5_address *a;
+           ret = krb5_make_addrport (context, &a,
+                                     auth_context->local_address,
+                                     auth_context->local_port);
+           if (ret)
+               goto out;
+           
+           ret = compare_addrs(context, a, enc_krb_cred_part.r_address, 
+                               "receiver address is wrong in received creds");
+           krb5_free_address(context, a);
+           free(a);
+           if(ret)
+               goto out;
+       } else {
+           ret = compare_addrs(context, auth_context->local_address,
+                               enc_krb_cred_part.r_address,
+                               "receiver address is wrong in received creds");
+           if(ret)
+               goto out;
+       }
+    }
+
+    /* check timestamp */
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+       krb5_timestamp sec;
+
+       krb5_timeofday (context, &sec);
+
+       if (enc_krb_cred_part.timestamp == NULL ||
+           enc_krb_cred_part.usec      == NULL ||
+           abs(*enc_krb_cred_part.timestamp - sec)
+           > context->max_skew) {
+           krb5_clear_error_string (context);
+           ret = KRB5KRB_AP_ERR_SKEW;
+           goto out;
+       }
+    }
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
+       /* if these fields are not present in the cred-part, silently
+           return zero */
+       memset(outdata, 0, sizeof(*outdata));
+       if(enc_krb_cred_part.timestamp)
+           outdata->timestamp = *enc_krb_cred_part.timestamp;
+       if(enc_krb_cred_part.usec)
+           outdata->usec = *enc_krb_cred_part.usec;
+       if(enc_krb_cred_part.nonce)
+           outdata->seq = *enc_krb_cred_part.nonce;
+    }
+    
+    /* Convert to NULL terminated list of creds */
+
+    *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1, 
+                       sizeof(**ret_creds));
+
+    if (*ret_creds == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string (context, "malloc: out of memory");
+       goto out;
+    }
+
+    for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) {
+       KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i];
+       krb5_creds *creds;
+       size_t len;
+
+       creds = calloc(1, sizeof(*creds));
+       if(creds == NULL) {
+           ret = ENOMEM;
+           krb5_set_error_string (context, "malloc: out of memory");
+           goto out;
+       }
+
+       ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, 
+                          &cred.tickets.val[i], &len, ret);
+       if (ret)
+           goto out;
+       if(creds->ticket.length != len)
+           krb5_abortx(context, "internal error in ASN.1 encoder");
+       copy_EncryptionKey (&kci->key, &creds->session);
+       if (kci->prealm && kci->pname)
+           _krb5_principalname2krb5_principal (&creds->client,
+                                               *kci->pname,
+                                               *kci->prealm);
+       if (kci->flags)
+           creds->flags.b = *kci->flags;
+       if (kci->authtime)
+           creds->times.authtime = *kci->authtime;
+       if (kci->starttime)
+           creds->times.starttime = *kci->starttime;
+       if (kci->endtime)
+           creds->times.endtime = *kci->endtime;
+       if (kci->renew_till)
+           creds->times.renew_till = *kci->renew_till;
+       if (kci->srealm && kci->sname)
+           _krb5_principalname2krb5_principal (&creds->server,
+                                               *kci->sname,
+                                               *kci->srealm);
+       if (kci->caddr)
+           krb5_copy_addresses (context,
+                                kci->caddr,
+                                &creds->addresses);
+       
+       (*ret_creds)[i] = creds;
+       
+    }
+    (*ret_creds)[i] = NULL;
+
+    free_KRB_CRED (&cred);
+    free_EncKrbCredPart(&enc_krb_cred_part);
+
+    return 0;
+
+  out:
+    free_EncKrbCredPart(&enc_krb_cred_part);
+    free_KRB_CRED (&cred);
+    if(*ret_creds) {
+       for(i = 0; (*ret_creds)[i]; i++)
+           krb5_free_creds(context, (*ret_creds)[i]);
+       free(*ret_creds);
+    }
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_cred2 (krb5_context      context,
+              krb5_auth_context auth_context,
+              krb5_ccache       ccache,
+              krb5_data         *in_data)
+{
+    krb5_error_code ret;
+    krb5_creds **creds;
+    int i;
+
+    ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL);
+    if(ret)
+       return ret;
+
+    /* Store the creds in the ccache */
+
+    for(i = 0; creds && creds[i]; i++) {
+       krb5_cc_store_cred(context, ccache, creds[i]);
+       krb5_free_creds(context, creds[i]);
+    }
+    free(creds);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/rd_error.c b/src/kerberosV/src/lib/krb5/rd_error.c
new file mode 100644 (file)
index 0000000..56b9a7e
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: rd_error.c,v 1.8 2005/05/18 04:21:57 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_error(krb5_context context,
+             krb5_data *msg,
+             KRB_ERROR *result)
+{
+    
+    size_t len;
+    krb5_error_code ret;
+
+    ret = decode_KRB_ERROR(msg->data, msg->length, result, &len);
+    if(ret)
+       return ret;
+    result->error_code += KRB5KDC_ERR_NONE;
+    return 0;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_error_contents (krb5_context context,
+                         krb5_error *error)
+{
+    free_KRB_ERROR(error);
+    memset(error, 0, sizeof(*error));
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_error (krb5_context context,
+                krb5_error *error)
+{
+    krb5_free_error_contents (context, error);
+    free (error);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_error_from_rd_error(krb5_context context,
+                        const krb5_error *error,
+                        const krb5_creds *creds)
+{
+    krb5_error_code ret;
+
+    ret = error->error_code;
+    if (error->e_text != NULL) {
+       krb5_set_error_string(context, "%s", *error->e_text);
+    } else {
+       char clientname[256], servername[256];
+
+       if (creds != NULL) {
+           krb5_unparse_name_fixed(context, creds->client,
+                                   clientname, sizeof(clientname));
+           krb5_unparse_name_fixed(context, creds->server,
+                                   servername, sizeof(servername));
+       }
+
+       switch (ret) {
+       case KRB5KDC_ERR_NAME_EXP :
+           krb5_set_error_string(context, "Client %s%s%s expired",
+                                 creds ? "(" : "",
+                                 creds ? clientname : "",
+                                 creds ? ")" : "");
+           break;
+       case KRB5KDC_ERR_SERVICE_EXP :
+           krb5_set_error_string(context, "Server %s%s%s expired",
+                                 creds ? "(" : "",
+                                 creds ? servername : "",
+                                 creds ? ")" : "");
+           break;
+       case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN :
+           krb5_set_error_string(context, "Client %s%s%s unknown",
+                                 creds ? "(" : "",
+                                 creds ? clientname : "",
+                                 creds ? ")" : "");
+           break;
+       case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN :
+           krb5_set_error_string(context, "Server %s%s%s unknown",
+                                 creds ? "(" : "",
+                                 creds ? servername : "",
+                                 creds ? ")" : "");
+           break;
+       default :
+           krb5_clear_error_string(context);
+           break;
+       }
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/rd_priv.c b/src/kerberosV/src/lib/krb5/rd_priv.c
new file mode 100644 (file)
index 0000000..266fc4d
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1997-2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: rd_priv.c,v 1.31 2004/05/25 21:39:13 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    KRB_PRIV priv;
+    EncKrbPrivPart part;
+    size_t len;
+    krb5_data plain;
+    krb5_keyblock *key;
+    krb5_crypto crypto;
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+       outdata == NULL)
+       return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
+
+    memset(&priv, 0, sizeof(priv));
+    ret = decode_KRB_PRIV (inbuf->data, inbuf->length, &priv, &len);
+    if (ret) 
+       goto failure;
+    if (priv.pvno != 5) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BADVERSION;
+       goto failure;
+    }
+    if (priv.msg_type != krb_priv) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_MSG_TYPE;
+       goto failure;
+    }
+
+    if (auth_context->remote_subkey)
+       key = auth_context->remote_subkey;
+    else if (auth_context->local_subkey)
+       key = auth_context->local_subkey;
+    else
+       key = auth_context->keyblock;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       goto failure;
+    ret = krb5_decrypt_EncryptedData(context,
+                                    crypto,
+                                    KRB5_KU_KRB_PRIV,
+                                    &priv.enc_part,
+                                    &plain);
+    krb5_crypto_destroy(context, crypto);
+    if (ret) 
+       goto failure;
+
+    ret = decode_EncKrbPrivPart (plain.data, plain.length, &part, &len);
+    krb5_data_free (&plain);
+    if (ret) 
+       goto failure;
+  
+    /* check sender address */
+
+    if (part.s_address
+       && auth_context->remote_address
+       && !krb5_address_compare (context,
+                                 auth_context->remote_address,
+                                 part.s_address)) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BADADDR;
+       goto failure_part;
+    }
+
+    /* check receiver address */
+
+    if (part.r_address
+       && auth_context->local_address
+       && !krb5_address_compare (context,
+                                 auth_context->local_address,
+                                 part.r_address)) {
+       krb5_clear_error_string (context);
+       ret = KRB5KRB_AP_ERR_BADADDR;
+       goto failure_part;
+    }
+
+    /* check timestamp */
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+       krb5_timestamp sec;
+
+       krb5_timeofday (context, &sec);
+       if (part.timestamp == NULL ||
+           part.usec      == NULL ||
+           abs(*part.timestamp - sec) > context->max_skew) {
+           krb5_clear_error_string (context);
+           ret = KRB5KRB_AP_ERR_SKEW;
+           goto failure_part;
+       }
+    }
+
+    /* XXX - check replay cache */
+
+    /* check sequence number. since MIT krb5 cannot generate a sequence
+       number of zero but instead generates no sequence number, we accept that
+    */
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+       if ((part.seq_number == NULL
+            && auth_context->remote_seqnumber != 0)
+           || (part.seq_number != NULL
+               && *part.seq_number != auth_context->remote_seqnumber)) {
+           krb5_clear_error_string (context);
+           ret = KRB5KRB_AP_ERR_BADORDER;
+           goto failure_part;
+       }
+       auth_context->remote_seqnumber++;
+    }
+
+    ret = krb5_data_copy (outbuf, part.user_data.data, part.user_data.length);
+    if (ret)
+       goto failure_part;
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
+       /* if these fields are not present in the priv-part, silently
+           return zero */
+       memset(outdata, 0, sizeof(*outdata));
+       if(part.timestamp)
+           outdata->timestamp = *part.timestamp;
+       if(part.usec)
+           outdata->usec = *part.usec;
+       if(part.seq_number)
+           outdata->seq = *part.seq_number;
+    }
+
+  failure_part:
+    free_EncKrbPrivPart (&part);
+
+  failure:
+    free_KRB_PRIV (&priv);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/rd_rep.c b/src/kerberosV/src/lib/krb5/rd_rep.c
new file mode 100644 (file)
index 0000000..981937f
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: rd_rep.c,v 1.23 2004/05/25 21:39:33 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_rep(krb5_context context,
+           krb5_auth_context auth_context,
+           const krb5_data *inbuf,
+           krb5_ap_rep_enc_part **repl)
+{
+  krb5_error_code ret;
+  AP_REP ap_rep;
+  size_t len;
+  krb5_data data;
+  krb5_crypto crypto;
+
+  krb5_data_zero (&data);
+  ret = 0;
+
+  ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len);
+  if (ret)
+      return ret;
+  if (ap_rep.pvno != 5) {
+    ret = KRB5KRB_AP_ERR_BADVERSION;
+    krb5_clear_error_string (context);
+    goto out;
+  }
+  if (ap_rep.msg_type != krb_ap_rep) {
+    ret = KRB5KRB_AP_ERR_MSG_TYPE;
+    krb5_clear_error_string (context);
+    goto out;
+  }
+
+  ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto);
+  if (ret)
+      goto out;
+  ret = krb5_decrypt_EncryptedData (context, 
+                                   crypto,     
+                                   KRB5_KU_AP_REQ_ENC_PART,
+                                   &ap_rep.enc_part,
+                                   &data);
+  krb5_crypto_destroy(context, crypto);
+  if (ret)
+      goto out;
+
+  *repl = malloc(sizeof(**repl));
+  if (*repl == NULL) {
+    ret = ENOMEM;
+    krb5_set_error_string (context, "malloc: out of memory");
+    goto out;
+  }
+  ret = krb5_decode_EncAPRepPart(context,
+                                data.data,
+                                data.length,
+                                *repl, 
+                                &len);
+  if (ret)
+      return ret;
+  
+  if ((*repl)->ctime != auth_context->authenticator->ctime ||
+      (*repl)->cusec != auth_context->authenticator->cusec) {
+    ret = KRB5KRB_AP_ERR_MUT_FAIL;
+    krb5_clear_error_string (context);
+    goto out;
+  }
+  if ((*repl)->seq_number)
+      krb5_auth_con_setremoteseqnumber(context, auth_context,
+                                      *((*repl)->seq_number));
+  if ((*repl)->subkey)
+    krb5_auth_con_setremotesubkey(context, auth_context, (*repl)->subkey);
+  
+out:
+  krb5_data_free (&data);
+  free_AP_REP (&ap_rep);
+  return ret;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_free_ap_rep_enc_part (krb5_context context,
+                          krb5_ap_rep_enc_part *val)
+{
+    free_EncAPRepPart (val);
+    free (val);
+}
diff --git a/src/kerberosV/src/lib/krb5/rd_req.c b/src/kerberosV/src/lib/krb5/rd_req.c
new file mode 100644 (file)
index 0000000..b37d413
--- /dev/null
@@ -0,0 +1,637 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: rd_req.c,v 1.57.4.1 2006/02/03 14:38:02 lha Exp $");
+
+static krb5_error_code
+decrypt_tkt_enc_part (krb5_context context,
+                     krb5_keyblock *key,
+                     EncryptedData *enc_part,
+                     EncTicketPart *decr_part)
+{
+    krb5_error_code ret;
+    krb5_data plain;
+    size_t len;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       return ret;
+    ret = krb5_decrypt_EncryptedData (context,
+                                     crypto,
+                                     KRB5_KU_TICKET,
+                                     enc_part,
+                                     &plain);
+    krb5_crypto_destroy(context, crypto);
+    if (ret)
+       return ret;
+
+    ret = krb5_decode_EncTicketPart(context, plain.data, plain.length, 
+                                   decr_part, &len);
+    krb5_data_free (&plain);
+    return ret;
+}
+
+static krb5_error_code
+decrypt_authenticator (krb5_context context,
+                      EncryptionKey *key,
+                      EncryptedData *enc_part,
+                      Authenticator *authenticator,
+                      krb5_key_usage usage)
+{
+    krb5_error_code ret;
+    krb5_data plain;
+    size_t len;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       return ret;
+    ret = krb5_decrypt_EncryptedData (context,
+                                     crypto,
+                                     usage /* KRB5_KU_AP_REQ_AUTH */,
+                                     enc_part,
+                                     &plain);
+    /* for backwards compatibility, also try the old usage */
+    if (ret && usage == KRB5_KU_TGS_REQ_AUTH)
+       ret = krb5_decrypt_EncryptedData (context,
+                                         crypto,
+                                         KRB5_KU_AP_REQ_AUTH,
+                                         enc_part,
+                                         &plain);
+    krb5_crypto_destroy(context, crypto);
+    if (ret)
+       return ret;
+
+    ret = krb5_decode_Authenticator(context, plain.data, plain.length, 
+                                   authenticator, &len);
+    krb5_data_free (&plain);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decode_ap_req(krb5_context context,
+                  const krb5_data *inbuf,
+                  krb5_ap_req *ap_req)
+{
+    krb5_error_code ret;
+    size_t len;
+    ret = decode_AP_REQ(inbuf->data, inbuf->length, ap_req, &len);
+    if (ret)
+       return ret;
+    if (ap_req->pvno != 5){
+       free_AP_REQ(ap_req);
+       krb5_clear_error_string (context);
+       return KRB5KRB_AP_ERR_BADVERSION;
+    }
+    if (ap_req->msg_type != krb_ap_req){
+       free_AP_REQ(ap_req);
+       krb5_clear_error_string (context);
+       return KRB5KRB_AP_ERR_MSG_TYPE;
+    }
+    if (ap_req->ticket.tkt_vno != 5){
+       free_AP_REQ(ap_req);
+       krb5_clear_error_string (context);
+       return KRB5KRB_AP_ERR_BADVERSION;
+    }
+    return 0;
+}
+
+static krb5_error_code
+check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc)
+{
+    char **realms;
+    int num_realms;
+    krb5_error_code ret;
+           
+    if(enc->transited.tr_type != DOMAIN_X500_COMPRESS)
+       return KRB5KDC_ERR_TRTYPE_NOSUPP;
+
+    if(enc->transited.contents.length == 0)
+       return 0;
+
+    ret = krb5_domain_x500_decode(context, enc->transited.contents, 
+                                 &realms, &num_realms, 
+                                 enc->crealm,
+                                 ticket->realm);
+    if(ret)
+       return ret;
+    ret = krb5_check_transited(context, enc->crealm, 
+                              ticket->realm, 
+                              realms, num_realms, NULL);
+    free(realms);
+    return ret;
+}
+
+static krb5_error_code
+find_etypelist(krb5_context context,
+              krb5_auth_context auth_context,
+              EtypeList *etypes)
+{
+    krb5_error_code ret;
+    krb5_authdata *ad;
+    krb5_authdata adIfRelevant;
+    unsigned i;
+
+    adIfRelevant.len = 0;
+
+    etypes->len = 0;
+    etypes->val = NULL;
+
+    ad = auth_context->authenticator->authorization_data;
+    if (ad == NULL)
+       return 0;
+
+    for (i = 0; i < ad->len; i++) {
+       if (ad->val[i].ad_type == KRB5_AUTHDATA_IF_RELEVANT) {
+           ret = decode_AD_IF_RELEVANT(ad->val[i].ad_data.data,
+                                       ad->val[i].ad_data.length,
+                                       &adIfRelevant,
+                                       NULL);
+           if (ret)
+               return ret;
+
+           if (adIfRelevant.len == 1 &&
+               adIfRelevant.val[0].ad_type ==
+                       KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION) {
+               break;
+           }
+           free_AD_IF_RELEVANT(&adIfRelevant);
+           adIfRelevant.len = 0;
+       }
+    }
+
+    if (adIfRelevant.len == 0)
+       return 0;
+
+    ret = decode_EtypeList(adIfRelevant.val[0].ad_data.data,
+                          adIfRelevant.val[0].ad_data.length,
+                          etypes,
+                          NULL);
+
+    free_AD_IF_RELEVANT(&adIfRelevant);
+
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_decrypt_ticket(krb5_context context,
+                   Ticket *ticket,
+                   krb5_keyblock *key,
+                   EncTicketPart *out,
+                   krb5_flags flags)
+{
+    EncTicketPart t;
+    krb5_error_code ret;
+    ret = decrypt_tkt_enc_part (context, key, &ticket->enc_part, &t);
+    if (ret)
+       return ret;
+    
+    {
+       krb5_timestamp now;
+       time_t start = t.authtime;
+
+       krb5_timeofday (context, &now);
+       if(t.starttime)
+           start = *t.starttime;
+       if(start - now > context->max_skew
+          || (t.flags.invalid
+              && !(flags & KRB5_VERIFY_AP_REQ_IGNORE_INVALID))) {
+           free_EncTicketPart(&t);
+           krb5_clear_error_string (context);
+           return KRB5KRB_AP_ERR_TKT_NYV;
+       }
+       if(now - t.endtime > context->max_skew) {
+           free_EncTicketPart(&t);
+           krb5_clear_error_string (context);
+           return KRB5KRB_AP_ERR_TKT_EXPIRED;
+       }
+       
+       if(!t.flags.transited_policy_checked) {
+           ret = check_transited(context, ticket, &t);
+           if(ret) {
+               free_EncTicketPart(&t);
+               return ret;
+           }
+       }
+    }
+    
+    if(out)
+       *out = t;
+    else
+       free_EncTicketPart(&t);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_authenticator_checksum(krb5_context context,
+                                  krb5_auth_context ac,
+                                  void *data,
+                                  size_t len)
+{
+    krb5_error_code ret;
+    krb5_keyblock *key;
+    krb5_authenticator authenticator;
+    krb5_crypto crypto;
+    
+    ret = krb5_auth_con_getauthenticator (context,
+                                     ac,
+                                     &authenticator);
+    if(ret)
+       return ret;
+    if(authenticator->cksum == NULL) {
+       krb5_free_authenticator(context, &authenticator);
+       return -17;
+    }
+    ret = krb5_auth_con_getkey(context, ac, &key);
+    if(ret) {
+       krb5_free_authenticator(context, &authenticator);
+       return ret;
+    }
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if(ret)
+       goto out;
+    ret = krb5_verify_checksum (context,
+                               crypto,
+                               KRB5_KU_AP_REQ_AUTH_CKSUM,
+                               data,
+                               len,
+                               authenticator->cksum);
+    krb5_crypto_destroy(context, crypto);
+out:
+    krb5_free_authenticator(context, &authenticator);
+    krb5_free_keyblock(context, key);
+    return ret;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_ap_req(krb5_context context,
+                  krb5_auth_context *auth_context,
+                  krb5_ap_req *ap_req,
+                  krb5_const_principal server,
+                  krb5_keyblock *keyblock,
+                  krb5_flags flags,
+                  krb5_flags *ap_req_options,
+                  krb5_ticket **ticket)
+{
+    return krb5_verify_ap_req2 (context,
+                               auth_context,
+                               ap_req,
+                               server,
+                               keyblock,
+                               flags,
+                               ap_req_options,
+                               ticket,
+                               KRB5_KU_AP_REQ_AUTH);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_ap_req2(krb5_context context,
+                   krb5_auth_context *auth_context,
+                   krb5_ap_req *ap_req,
+                   krb5_const_principal server,
+                   krb5_keyblock *keyblock,
+                   krb5_flags flags,
+                   krb5_flags *ap_req_options,
+                   krb5_ticket **ticket,
+                   krb5_key_usage usage)
+{
+    krb5_ticket *t;
+    krb5_auth_context ac;
+    krb5_error_code ret;
+    EtypeList etypes;
+    
+    if (auth_context && *auth_context) {
+       ac = *auth_context;
+    } else {
+       ret = krb5_auth_con_init (context, &ac);
+       if (ret)
+           return ret;
+    }
+
+    t = malloc(sizeof(*t));
+    if (t == NULL) {
+       ret = ENOMEM;
+       krb5_clear_error_string (context);
+       goto out;
+    }
+    memset(t, 0, sizeof(*t));
+
+    if (ap_req->ap_options.use_session_key && ac->keyblock){
+       ret = krb5_decrypt_ticket(context, &ap_req->ticket, 
+                                 ac->keyblock, 
+                                 &t->ticket,
+                                 flags);
+       krb5_free_keyblock(context, ac->keyblock);
+       ac->keyblock = NULL;
+    }else
+       ret = krb5_decrypt_ticket(context, &ap_req->ticket, 
+                                 keyblock, 
+                                 &t->ticket,
+                                 flags);
+    
+    if(ret)
+       goto out;
+
+    _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, 
+                                      ap_req->ticket.realm);
+    _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, 
+                                      t->ticket.crealm);
+
+    /* save key */
+
+    krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock);
+
+    ret = decrypt_authenticator (context,
+                                &t->ticket.key,
+                                &ap_req->authenticator,
+                                ac->authenticator,
+                                usage);
+    if (ret)
+       goto out;
+
+    {
+       krb5_principal p1, p2;
+       krb5_boolean res;
+       
+       _krb5_principalname2krb5_principal(&p1,
+                                          ac->authenticator->cname,
+                                          ac->authenticator->crealm);
+       _krb5_principalname2krb5_principal(&p2, 
+                                          t->ticket.cname,
+                                          t->ticket.crealm);
+       res = krb5_principal_compare (context, p1, p2);
+       krb5_free_principal (context, p1);
+       krb5_free_principal (context, p2);
+       if (!res) {
+           ret = KRB5KRB_AP_ERR_BADMATCH;
+           krb5_clear_error_string (context);
+           goto out;
+       }
+    }
+
+    /* check addresses */
+
+    if (t->ticket.caddr
+       && ac->remote_address
+       && !krb5_address_search (context,
+                                ac->remote_address,
+                                t->ticket.caddr)) {
+       ret = KRB5KRB_AP_ERR_BADADDR;
+       krb5_clear_error_string (context);
+       goto out;
+    }
+
+    /* check timestamp in authenticator */
+    {
+       krb5_timestamp now;
+
+       krb5_timeofday (context, &now);
+
+       if (abs(ac->authenticator->ctime - now) > context->max_skew) {
+           ret = KRB5KRB_AP_ERR_SKEW;
+           krb5_clear_error_string (context);
+           goto out;
+       }
+    }
+
+    if (ac->authenticator->seq_number)
+       krb5_auth_con_setremoteseqnumber(context, ac,
+                                        *ac->authenticator->seq_number);
+
+    /* XXX - Xor sequence numbers */
+
+    if (ac->authenticator->subkey) {
+       ret = krb5_auth_con_setremotesubkey(context, ac,
+                                           ac->authenticator->subkey);
+       if (ret)
+           goto out;
+    }
+
+    ret = find_etypelist(context, ac, &etypes);
+    if (ret)
+       goto out;
+
+    ac->keytype = ETYPE_NULL;
+
+    if (etypes.val) {
+       int i;
+
+       for (i = 0; i < etypes.len; i++) {
+           if (krb5_enctype_valid(context, etypes.val[i]) == 0) {
+               ac->keytype = etypes.val[i];
+               break;
+           }
+       }
+    }
+
+    if (ap_req_options) {
+       *ap_req_options = 0;
+       if (ac->keytype != ETYPE_NULL)
+           *ap_req_options |= AP_OPTS_USE_SUBKEY;
+       if (ap_req->ap_options.use_session_key)
+           *ap_req_options |= AP_OPTS_USE_SESSION_KEY;
+       if (ap_req->ap_options.mutual_required)
+           *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED;
+    }
+
+    if(ticket)
+       *ticket = t;
+    else
+       krb5_free_ticket (context, t);
+    if (auth_context) {
+       if (*auth_context == NULL)
+           *auth_context = ac;
+    } else
+       krb5_auth_con_free (context, ac);
+    free_EtypeList(&etypes);
+    return 0;
+ out:
+    if (t)
+       krb5_free_ticket (context, t);
+    if (auth_context == NULL || *auth_context == NULL)
+       krb5_auth_con_free (context, ac);
+    return ret;
+}
+                  
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_req_with_keyblock(krb5_context context,
+                         krb5_auth_context *auth_context,
+                         const krb5_data *inbuf,
+                         krb5_const_principal server,
+                         krb5_keyblock *keyblock,
+                         krb5_flags *ap_req_options,
+                         krb5_ticket **ticket)
+{
+    krb5_error_code ret;
+    krb5_ap_req ap_req;
+
+    if (*auth_context == NULL) {
+       ret = krb5_auth_con_init(context, auth_context);
+       if (ret)
+           return ret;
+    }
+
+    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
+    if(ret)
+       return ret;
+
+    ret = krb5_verify_ap_req(context,
+                            auth_context,
+                            &ap_req,
+                            server,
+                            keyblock,
+                            0,
+                            ap_req_options,
+                            ticket);
+
+    free_AP_REQ(&ap_req);
+    return ret;
+}
+
+static krb5_error_code
+get_key_from_keytab(krb5_context context,
+                   krb5_auth_context *auth_context,
+                   krb5_ap_req *ap_req,
+                   krb5_const_principal server,
+                   krb5_keytab keytab,
+                   krb5_keyblock **out_key)
+{
+    krb5_keytab_entry entry;
+    krb5_error_code ret;
+    int kvno;
+    krb5_keytab real_keytab;
+
+    if(keytab == NULL)
+       krb5_kt_default(context, &real_keytab);
+    else
+       real_keytab = keytab;
+    
+    if (ap_req->ticket.enc_part.kvno)
+       kvno = *ap_req->ticket.enc_part.kvno;
+    else
+       kvno = 0;
+
+    ret = krb5_kt_get_entry (context,
+                            real_keytab,
+                            server,
+                            kvno,
+                            ap_req->ticket.enc_part.etype,
+                            &entry);
+    if(ret)
+       goto out;
+    ret = krb5_copy_keyblock(context, &entry.keyblock, out_key);
+    krb5_kt_free_entry (context, &entry);
+out:    
+    if(keytab == NULL)
+       krb5_kt_close(context, real_keytab);
+    
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    krb5_ap_req ap_req;
+    krb5_keyblock *keyblock = NULL;
+    krb5_principal service = NULL;
+
+    if (*auth_context == NULL) {
+       ret = krb5_auth_con_init(context, auth_context);
+       if (ret)
+           return ret;
+    }
+
+    ret = krb5_decode_ap_req(context, inbuf, &ap_req);
+    if(ret)
+       return ret;
+
+    if(server == NULL){
+       _krb5_principalname2krb5_principal(&service,
+                                          ap_req.ticket.sname,
+                                          ap_req.ticket.realm);
+       server = service;
+    }
+    if (ap_req.ap_options.use_session_key &&
+       (*auth_context)->keyblock == NULL) {
+       krb5_set_error_string(context, "krb5_rd_req: user to user auth "
+                             "without session key given");
+       ret = KRB5KRB_AP_ERR_NOKEY;
+       goto out;
+    }
+
+    if((*auth_context)->keyblock == NULL){
+       ret = get_key_from_keytab(context, 
+                                 auth_context, 
+                                 &ap_req,
+                                 server,
+                                 keytab,
+                                 &keyblock);
+       if(ret)
+           goto out;
+    } else {
+       ret = krb5_copy_keyblock(context,
+                                (*auth_context)->keyblock,
+                                &keyblock);
+       if (ret)
+           goto out;
+    }
+
+    ret = krb5_verify_ap_req(context,
+                            auth_context,
+                            &ap_req,
+                            server,
+                            keyblock,
+                            0,
+                            ap_req_options,
+                            ticket);
+
+    krb5_free_keyblock(context, keyblock);
+
+out:
+    free_AP_REQ(&ap_req);
+    if(service)
+       krb5_free_principal(context, service);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/rd_safe.c b/src/kerberosV/src/lib/krb5/rd_safe.c
new file mode 100644 (file)
index 0000000..36c1b3a
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 1997 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 <krb5_locl.h>
+
+RCSID("$KTH: rd_safe.c,v 1.29 2004/05/25 21:40:13 lha Exp $");
+
+static krb5_error_code
+verify_checksum(krb5_context context,
+               krb5_auth_context auth_context,
+               KRB_SAFE *safe)
+{
+    krb5_error_code ret;
+    u_char *buf;
+    size_t buf_size;
+    size_t len;
+    Checksum c;
+    krb5_crypto crypto;
+    krb5_keyblock *key;
+
+    c = safe->cksum;
+    safe->cksum.cksumtype       = 0;
+    safe->cksum.checksum.data   = NULL;
+    safe->cksum.checksum.length = 0;
+
+    ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, safe, &len, ret);
+    if(ret)
+       return ret;
+    if(buf_size != len)
+       krb5_abortx(context, "internal error in ASN.1 encoder");
+
+    if (auth_context->remote_subkey)
+       key = auth_context->remote_subkey;
+    else if (auth_context->local_subkey)
+       key = auth_context->local_subkey;
+    else
+       key = auth_context->keyblock;
+
+    ret = krb5_crypto_init(context, key, 0, &crypto);
+    if (ret)
+       goto out;
+    ret = krb5_verify_checksum (context,
+                               crypto,
+                               KRB5_KU_KRB_SAFE_CKSUM,
+                               buf + buf_size - len,
+                               len,
+                               &c);
+    krb5_crypto_destroy(context, crypto);
+out:
+    safe->cksum = c;
+    free (buf);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 ret;
+    KRB_SAFE safe;
+    size_t len;
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
+       outdata == NULL) {
+       krb5_set_error_string(context, "rd_safe: need outdata to return data");
+       return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
+    }
+
+    ret = decode_KRB_SAFE (inbuf->data, inbuf->length, &safe, &len);
+    if (ret) 
+       return ret;
+    if (safe.pvno != 5) {
+       ret = KRB5KRB_AP_ERR_BADVERSION;
+       krb5_clear_error_string (context);
+       goto failure;
+    }
+    if (safe.msg_type != krb_safe) {
+       ret = KRB5KRB_AP_ERR_MSG_TYPE;
+       krb5_clear_error_string (context);
+       goto failure;
+    }
+    if (!krb5_checksum_is_keyed(context, safe.cksum.cksumtype)
+       || !krb5_checksum_is_collision_proof(context, safe.cksum.cksumtype)) {
+       ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
+       krb5_clear_error_string (context);
+       goto failure;
+    }
+
+    /* check sender address */
+
+    if (safe.safe_body.s_address
+       && auth_context->remote_address
+       && !krb5_address_compare (context,
+                                 auth_context->remote_address,
+                                 safe.safe_body.s_address)) {
+       ret = KRB5KRB_AP_ERR_BADADDR;
+       krb5_clear_error_string (context);
+       goto failure;
+    }
+
+    /* check receiver address */
+
+    if (safe.safe_body.r_address
+       && auth_context->local_address
+       && !krb5_address_compare (context,
+                                 auth_context->local_address,
+                                 safe.safe_body.r_address)) {
+       ret = KRB5KRB_AP_ERR_BADADDR;
+       krb5_clear_error_string (context);
+       goto failure;
+    }
+
+    /* check timestamp */
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
+       krb5_timestamp sec;
+
+       krb5_timeofday (context, &sec);
+
+       if (safe.safe_body.timestamp == NULL ||
+           safe.safe_body.usec      == NULL ||
+           abs(*safe.safe_body.timestamp - sec) > context->max_skew) {
+           ret = KRB5KRB_AP_ERR_SKEW;
+           krb5_clear_error_string (context);
+           goto failure;
+       }
+    }
+    /* XXX - check replay cache */
+
+    /* check sequence number. since MIT krb5 cannot generate a sequence
+       number of zero but instead generates no sequence number, we accept that
+    */
+
+    if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+       if ((safe.safe_body.seq_number == NULL
+            && auth_context->remote_seqnumber != 0)
+           || (safe.safe_body.seq_number != NULL
+               && *safe.safe_body.seq_number !=
+               auth_context->remote_seqnumber)) {
+           ret = KRB5KRB_AP_ERR_BADORDER;
+           krb5_clear_error_string (context);
+           goto failure;
+       }
+       auth_context->remote_seqnumber++;
+    }
+
+    ret = verify_checksum (context, auth_context, &safe);
+    if (ret)
+       goto failure;
+  
+    outbuf->length = safe.safe_body.user_data.length;
+    outbuf->data   = malloc(outbuf->length);
+    if (outbuf->data == NULL) {
+       ret = ENOMEM;
+       krb5_set_error_string (context, "malloc: out of memory");
+       goto failure;
+    }
+    memcpy (outbuf->data, safe.safe_body.user_data.data, outbuf->length);
+
+    if ((auth_context->flags & 
+        (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
+       /* if these fields are not present in the safe-part, silently
+           return zero */
+       memset(outdata, 0, sizeof(*outdata));
+       if(safe.safe_body.timestamp)
+           outdata->timestamp = *safe.safe_body.timestamp;
+       if(safe.safe_body.usec)
+           outdata->usec = *safe.safe_body.usec;
+       if(safe.safe_body.seq_number)
+           outdata->seq = *safe.safe_body.seq_number;
+    }
+
+  failure:
+    free_KRB_SAFE (&safe);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/read_message.c b/src/kerberosV/src/lib/krb5/read_message.c
new file mode 100644 (file)
index 0000000..2a707d3
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: read_message.c,v 1.9 2004/05/25 21:40:33 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_read_message (krb5_context context,
+                  krb5_pointer p_fd,
+                  krb5_data *data)
+{
+    krb5_error_code ret;
+    u_int32_t len;
+    u_int8_t buf[4];
+
+    ret = krb5_net_read (context, p_fd, buf, 4);
+    if(ret == -1) {
+       ret = errno;
+       krb5_clear_error_string (context);
+       return ret;
+    }
+    if(ret < 4) {
+       data->length = 0;
+       return HEIM_ERR_EOF;
+    }
+    len = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+    ret = krb5_data_alloc (data, len);
+    if (ret)
+       return ret;
+    if (krb5_net_read (context, p_fd, data->data, len) != len) {
+       ret = errno;
+       krb5_data_free (data);
+       krb5_clear_error_string (context);
+       return ret;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_read_priv_message(krb5_context context,
+                      krb5_auth_context ac,
+                      krb5_pointer p_fd,
+                      krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_data packet;
+
+    ret = krb5_read_message(context, p_fd, &packet);
+    if(ret)
+       return ret;
+    ret = krb5_rd_priv (context, ac, &packet, data, NULL);
+    krb5_data_free(&packet);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_read_safe_message(krb5_context context,
+                      krb5_auth_context ac,
+                      krb5_pointer p_fd,
+                      krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_data packet;
+
+    ret = krb5_read_message(context, p_fd, &packet);
+    if(ret)
+       return ret;
+    ret = krb5_rd_safe (context, ac, &packet, data, NULL);
+    krb5_data_free(&packet);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/recvauth.c b/src/kerberosV/src/lib/krb5/recvauth.c
new file mode 100644 (file)
index 0000000..f1af7db
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 1997-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: recvauth.c,v 1.17 2004/05/25 21:40:56 lha Exp $");
+
+/*
+ * See `sendauth.c' for the format.
+ */
+
+static krb5_boolean
+match_exact(const void *data, const char *appl_version)
+{
+    return strcmp(data, appl_version) == 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_recvauth(krb5_context context,
+             krb5_auth_context *auth_context,
+             krb5_pointer p_fd,
+             const char *appl_version,
+             krb5_principal server,
+             int32_t flags,
+             krb5_keytab keytab,
+             krb5_ticket **ticket)
+{
+    return krb5_recvauth_match_version(context, auth_context, p_fd,
+                                      match_exact, appl_version,
+                                      server, flags,
+                                      keytab, ticket);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_recvauth_match_version(krb5_context context,
+                           krb5_auth_context *auth_context,
+                           krb5_pointer p_fd,
+                           krb5_boolean (*match_appl_version)(const void *, 
+                                                              const char*),
+                           const void *match_data,
+                           krb5_principal server,
+                           int32_t flags,
+                           krb5_keytab keytab,
+                           krb5_ticket **ticket)
+{
+  krb5_error_code ret;
+  const char *version = KRB5_SENDAUTH_VERSION;
+  char her_version[sizeof(KRB5_SENDAUTH_VERSION)];
+  char *her_appl_version;
+  u_int32_t len;
+  u_char repl;
+  krb5_data data;
+  krb5_flags ap_options;
+  ssize_t n;
+
+  /*
+   * If there are no addresses in auth_context, get them from `fd'.
+   */
+
+  if (*auth_context == NULL) {
+      ret = krb5_auth_con_init (context, auth_context);
+      if (ret)
+         return ret;
+  }
+
+  ret = krb5_auth_con_setaddrs_from_fd (context,
+                                       *auth_context,
+                                       p_fd);
+  if (ret)
+      return ret;
+
+  if(!(flags & KRB5_RECVAUTH_IGNORE_VERSION)) {
+    n = krb5_net_read (context, p_fd, &len, 4);
+    if (n < 0) {
+       ret = errno;
+       krb5_set_error_string (context, "read: %s", strerror(errno));
+       return ret;
+    }
+    if (n == 0) {
+       krb5_clear_error_string (context);
+       return KRB5_SENDAUTH_BADAUTHVERS;
+    }
+    len = ntohl(len);
+    if (len != sizeof(her_version)
+       || krb5_net_read (context, p_fd, her_version, len) != len
+       || strncmp (version, her_version, len)) {
+      repl = 1;
+      krb5_net_write (context, p_fd, &repl, 1);
+       krb5_clear_error_string (context);
+      return KRB5_SENDAUTH_BADAUTHVERS;
+    }
+  }
+
+  n = krb5_net_read (context, p_fd, &len, 4);
+  if (n < 0) {
+      ret = errno;
+      krb5_set_error_string (context, "read: %s", strerror(errno));
+      return ret;
+  }
+  if (n == 0) {
+      krb5_clear_error_string (context);
+      return KRB5_SENDAUTH_BADAPPLVERS;
+  }
+  len = ntohl(len);
+  her_appl_version = malloc (len);
+  if (her_appl_version == NULL) {
+      repl = 2;
+      krb5_net_write (context, p_fd, &repl, 1);
+      krb5_set_error_string (context, "malloc: out of memory");
+      return ENOMEM;
+  }
+  if (krb5_net_read (context, p_fd, her_appl_version, len) != len
+      || !(*match_appl_version)(match_data, her_appl_version)) {
+    repl = 2;
+    krb5_net_write (context, p_fd, &repl, 1);
+    krb5_set_error_string (context, "wrong sendauth version (%s)",
+                          her_appl_version);
+    free (her_appl_version);
+    return KRB5_SENDAUTH_BADAPPLVERS;
+  }
+  free (her_appl_version);
+
+  repl = 0;
+  if (krb5_net_write (context, p_fd, &repl, 1) != 1) {
+    ret = errno;
+    krb5_set_error_string (context, "write: %s", strerror(errno));
+    return ret;
+  }
+
+  krb5_data_zero (&data);
+  ret = krb5_read_message (context, p_fd, &data);
+  if (ret)
+      return ret;
+
+  ret = krb5_rd_req (context,
+                    auth_context,
+                    &data,
+                    server,
+                    keytab,
+                    &ap_options,
+                    ticket);
+  krb5_data_free (&data);
+  if (ret) {
+      krb5_data error_data;
+      krb5_error_code ret2;
+
+      ret2 = krb5_mk_error (context,
+                           ret,
+                           NULL,
+                           NULL,
+                           NULL,
+                           server,
+                           NULL,
+                           NULL,
+                           &error_data);
+      if (ret2 == 0) {
+         krb5_write_message (context, p_fd, &error_data);
+         krb5_data_free (&error_data);
+      }
+      return ret;
+  }      
+
+  len = 0;
+  if (krb5_net_write (context, p_fd, &len, 4) != 4) {
+      ret = errno;
+      krb5_set_error_string (context, "write: %s", strerror(errno));
+      return ret;
+  }
+
+  if (ap_options & AP_OPTS_MUTUAL_REQUIRED) {
+    ret = krb5_mk_rep (context, *auth_context, &data);
+    if (ret)
+      return ret;
+
+    ret = krb5_write_message (context, p_fd, &data);
+    if (ret)
+       return ret;
+    krb5_data_free (&data);
+  }
+  return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/replay.c b/src/kerberosV/src/lib/krb5/replay.c
new file mode 100644 (file)
index 0000000..79b304c
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 1997-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <vis.h>
+
+RCSID("$KTH: replay.c,v 1.10 2004/05/25 21:41:15 lha Exp $");
+
+struct krb5_rcache_data {
+    char *name;
+};
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_resolve(krb5_context context,
+               krb5_rcache id,
+               const char *name)
+{
+    id->name = strdup(name);
+    if(id->name == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return KRB5_RC_MALLOC;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_resolve_type(krb5_context context,
+                    krb5_rcache *id,
+                    const char *type)
+{
+    if(strcmp(type, "FILE")) {
+       krb5_set_error_string (context, "replay cache type %s not supported",
+                              type);
+       return KRB5_RC_TYPE_NOTFOUND;
+    }
+    *id = calloc(1, sizeof(**id));
+    if(*id == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return KRB5_RC_MALLOC;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_resolve_full(krb5_context context,
+                    krb5_rcache *id,
+                    const char *string_name)
+{
+    krb5_error_code ret;
+    if(strncmp(string_name, "FILE:", 5)) {
+       krb5_set_error_string (context, "replay cache type %s not supported",
+                              string_name);
+       return KRB5_RC_TYPE_NOTFOUND;
+    }
+    ret = krb5_rc_resolve_type(context, id, "FILE");
+    if(ret)
+       return ret;
+    ret = krb5_rc_resolve(context, *id, string_name + 5);
+    return ret;
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_default_name(krb5_context context)
+{
+    return "FILE:/var/run/default_rcache";
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_default_type(krb5_context context)
+{
+    return "FILE";
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_default(krb5_context context,
+               krb5_rcache *id)
+{
+    return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context));
+}
+
+struct rc_entry{
+    time_t stamp;
+    unsigned char data[16];
+};
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_initialize(krb5_context context,
+                  krb5_rcache id,
+                  krb5_deltat auth_lifespan)
+{
+    FILE *f = fopen(id->name, "w");
+    struct rc_entry tmp;
+    int ret;
+
+    if(f == NULL) {
+       ret = errno;
+       krb5_set_error_string (context, "open(%s): %s", id->name,
+                              strerror(ret));
+       return ret;
+    }
+    tmp.stamp = auth_lifespan;
+    fwrite(&tmp, 1, sizeof(tmp), f);
+    fclose(f);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_recover(krb5_context context,
+               krb5_rcache id)
+{
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_destroy(krb5_context context,
+               krb5_rcache id)
+{
+    int ret;
+
+    if(remove(id->name) < 0) {
+       ret = errno;
+       krb5_set_error_string (context, "remove(%s): %s", id->name,
+                              strerror(ret));
+       return ret;
+    }
+    return krb5_rc_close(context, id);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_close(krb5_context context,
+             krb5_rcache id)
+{
+    free(id->name);
+    free(id);
+    return 0;
+}
+
+static void
+checksum_authenticator(Authenticator *auth, void *data)
+{
+    MD5_CTX md5;
+    int i;
+
+    MD5_Init (&md5);
+    MD5_Update (&md5, auth->crealm, strlen(auth->crealm));
+    for(i = 0; i < auth->cname.name_string.len; i++)
+       MD5_Update(&md5, auth->cname.name_string.val[i], 
+                  strlen(auth->cname.name_string.val[i]));
+    MD5_Update (&md5, &auth->ctime, sizeof(auth->ctime));
+    MD5_Update (&md5, &auth->cusec, sizeof(auth->cusec));
+    MD5_Final (data, &md5);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_store(krb5_context context,
+             krb5_rcache id,
+             krb5_donot_replay *rep)
+{
+    struct rc_entry ent, tmp;
+    time_t t;
+    FILE *f;
+    int ret;
+
+    ent.stamp = time(NULL);
+    checksum_authenticator(rep, ent.data);
+    f = fopen(id->name, "r");
+    if(f == NULL) {
+       ret = errno;
+       krb5_set_error_string (context, "open(%s): %s", id->name,
+                              strerror(ret));
+       return ret;
+    }
+    fread(&tmp, sizeof(ent), 1, f);
+    t = ent.stamp - tmp.stamp;
+    while(fread(&tmp, sizeof(ent), 1, f)){
+       if(tmp.stamp < t)
+           continue;
+       if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){
+           fclose(f);
+           krb5_clear_error_string (context);
+           return KRB5_RC_REPLAY;
+       }
+    }
+    if(ferror(f)){
+       ret = errno;
+       fclose(f);
+       krb5_set_error_string (context, "%s: %s", id->name, strerror(ret));
+       return ret;
+    }
+    fclose(f);
+    f = fopen(id->name, "a");
+    if(f == NULL) {
+       krb5_set_error_string (context, "open(%s): %s", id->name,
+                              strerror(errno));
+       return KRB5_RC_IO_UNKNOWN;
+    }
+    fwrite(&ent, 1, sizeof(ent), f);
+    fclose(f);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_expunge(krb5_context context,
+               krb5_rcache id)
+{
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rc_get_lifespan(krb5_context context,
+                    krb5_rcache id,
+                    krb5_deltat *auth_lifespan)
+{
+    FILE *f = fopen(id->name, "r");
+    int r;
+    struct rc_entry ent;
+    r = fread(&ent, sizeof(ent), 1, f);
+    fclose(f);
+    if(r){
+       *auth_lifespan = ent.stamp;
+       return 0;
+    }
+    krb5_clear_error_string (context);
+    return KRB5_RC_IO_UNKNOWN;
+}
+
+const char* KRB5_LIB_FUNCTION
+krb5_rc_get_name(krb5_context context,
+                krb5_rcache id)
+{
+    return id->name;
+}
+                
+const char* KRB5_LIB_FUNCTION
+krb5_rc_get_type(krb5_context context,
+                krb5_rcache id)
+{
+    return "FILE";
+}
+                
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_server_rcache(krb5_context context, 
+                      const krb5_data *piece, 
+                      krb5_rcache *id)
+{
+    krb5_rcache rcache;
+    krb5_error_code ret;
+
+    char *tmp = malloc(4 * piece->length + 1);
+    char *name;
+
+    if(tmp == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL);
+#ifdef HAVE_GETEUID
+    asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid());
+#else
+    asprintf(&name, "FILE:rc_%s", tmp);
+#endif
+    free(tmp);
+    if(name == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+
+    ret = krb5_rc_resolve_full(context, &rcache, name);
+    free(name);
+    if(ret)
+       return ret;
+    *id = rcache;
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/send_to_kdc.c b/src/kerberosV/src/lib/krb5/send_to_kdc.c
new file mode 100644 (file)
index 0000000..acba331
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: send_to_kdc.c,v 1.55 2005/02/02 20:05:30 lha Exp $");
+
+/*
+ * send the data in `req' on the socket `fd' (which is datagram iff udp)
+ * waiting `tmout' for a reply and returning the reply in `rep'.
+ * iff limit read up to this many bytes
+ * returns 0 and data in `rep' if succesful, otherwise -1
+ */
+
+static int
+recv_loop (int fd,
+          time_t tmout,
+          int udp,
+          size_t limit,
+          krb5_data *rep)
+{
+     fd_set fdset;
+     struct timeval timeout;
+     int ret;
+     int nbytes;
+
+     if (fd >= FD_SETSIZE) {
+        return -1;
+     }
+
+     krb5_data_zero(rep);
+     do {
+        FD_ZERO(&fdset);
+        FD_SET(fd, &fdset);
+        timeout.tv_sec  = tmout;
+        timeout.tv_usec = 0;
+        ret = select (fd + 1, &fdset, NULL, NULL, &timeout);
+        if (ret < 0) {
+            if (errno == EINTR)
+                continue;
+            return -1;
+        } else if (ret == 0) {
+            return 0;
+        } else {
+            void *tmp;
+
+            if (ioctl (fd, FIONREAD, &nbytes) < 0) {
+                krb5_data_free (rep);
+                return -1;
+            }
+            if(nbytes == 0)
+                return 0;
+
+            if (limit)
+                nbytes = min(nbytes, limit - rep->length);
+
+            tmp = realloc (rep->data, rep->length + nbytes);
+            if (tmp == NULL) {
+                krb5_data_free (rep);
+                return -1;
+            }
+            rep->data = tmp;
+            ret = recv (fd, (char*)tmp + rep->length, nbytes, 0);
+            if (ret < 0) {
+                krb5_data_free (rep);
+                return -1;
+            }
+            rep->length += ret;
+        }
+     } while(!udp && (limit == 0 || rep->length < limit));
+     return 0;
+}
+
+/*
+ * Send kerberos requests and receive a reply on a udp or any other kind
+ * of a datagram socket.  See `recv_loop'.
+ */
+
+static int
+send_and_recv_udp(int fd, 
+                 time_t tmout,
+                 const krb5_data *req,
+                 krb5_data *rep)
+{
+    if (send (fd, req->data, req->length, 0) < 0)
+       return -1;
+
+    return recv_loop(fd, tmout, 1, 0, rep);
+}
+
+/*
+ * `send_and_recv' for a TCP (or any other stream) socket.
+ * Since there are no record limits on a stream socket the protocol here
+ * is to prepend the request with 4 bytes of its length and the reply
+ * is similarly encoded.
+ */
+
+static int
+send_and_recv_tcp(int fd, 
+                 time_t tmout,
+                 const krb5_data *req,
+                 krb5_data *rep)
+{
+    unsigned char len[4];
+    unsigned long rep_len;
+    krb5_data len_data;
+
+    _krb5_put_int(len, req->length, 4);
+    if(net_write(fd, len, sizeof(len)) < 0)
+       return -1;
+    if(net_write(fd, req->data, req->length) < 0)
+       return -1;
+    if (recv_loop (fd, tmout, 0, 4, &len_data) < 0)
+       return -1;
+    if (len_data.length != 4) {
+       krb5_data_free (&len_data);
+       return -1;
+    }
+    _krb5_get_int(len_data.data, &rep_len, 4);
+    krb5_data_free (&len_data);
+    if (recv_loop (fd, tmout, 0, rep_len, rep) < 0)
+       return -1;
+    if(rep->length != rep_len) {
+       krb5_data_free (rep);
+       return -1;
+    }
+    return 0;
+}
+
+int
+_krb5_send_and_recv_tcp(int fd,
+                       time_t tmout,
+                       const krb5_data *req,
+                       krb5_data *rep)
+{
+    return send_and_recv_tcp(fd, tmout, req, rep);
+}
+
+/*
+ * `send_and_recv' tailored for the HTTP protocol.
+ */
+
+static int
+send_and_recv_http(int fd, 
+                  time_t tmout,
+                  const char *prefix,
+                  const krb5_data *req,
+                  krb5_data *rep)
+{
+    char *request;
+    char *str;
+    int ret;
+    int len = base64_encode(req->data, req->length, &str);
+
+    if(len < 0)
+       return -1;
+    asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str);
+    free(str);
+    if (request == NULL)
+       return -1;
+    ret = net_write (fd, request, strlen(request));
+    free (request);
+    if (ret < 0)
+       return ret;
+    ret = recv_loop(fd, tmout, 0, 0, rep);
+    if(ret)
+       return ret;
+    {
+       unsigned long rep_len;
+       char *s, *p;
+
+       s = realloc(rep->data, rep->length + 1);
+       if (s == NULL) {
+           krb5_data_free (rep);
+           return -1;
+       }
+       s[rep->length] = 0;
+       p = strstr(s, "\r\n\r\n");
+       if(p == NULL) {
+           free(s);
+           return -1;
+       }
+       p += 4;
+       rep->data = s;
+       rep->length -= p - s;
+       if(rep->length < 4) { /* remove length */
+           free(s);
+           return -1;
+       }
+       rep->length -= 4;
+       _krb5_get_int(p, &rep_len, 4);
+       if (rep_len != rep->length) {
+           free(s);
+           return -1;
+       }
+       memmove(rep->data, p + 4, rep->length);
+    }
+    return 0;
+}
+
+static int
+init_port(const char *s, int fallback)
+{
+    if (s) {
+       int tmp;
+
+       sscanf (s, "%d", &tmp);
+       return htons(tmp);
+    } else
+       return fallback;
+}
+
+/*
+ * Return 0 if succesful, otherwise 1
+ */
+
+static int
+send_via_proxy (krb5_context context,
+               const krb5_krbhst_info *hi,
+               const krb5_data *send_data,
+               krb5_data *receive)
+{
+    char *proxy2 = strdup(context->http_proxy);
+    char *proxy  = proxy2;
+    char *prefix;
+    char *colon;
+    struct addrinfo hints;
+    struct addrinfo *ai, *a;
+    int ret;
+    int s = -1;
+    char portstr[NI_MAXSERV];
+                
+    if (proxy == NULL)
+       return ENOMEM;
+    if (strncmp (proxy, "http://", 7) == 0)
+       proxy += 7;
+
+    colon = strchr(proxy, ':');
+    if(colon != NULL)
+       *colon++ = '\0';
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_family   = PF_UNSPEC;
+    hints.ai_socktype = SOCK_STREAM;
+    snprintf (portstr, sizeof(portstr), "%d",
+             ntohs(init_port (colon, htons(80))));
+    ret = getaddrinfo (proxy, portstr, &hints, &ai);
+    free (proxy2);
+    if (ret)
+       return krb5_eai_to_heim_errno(ret, errno);
+
+    for (a = ai; a != NULL; a = a->ai_next) {
+       s = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (s < 0)
+           continue;
+       if (connect (s, a->ai_addr, a->ai_addrlen) < 0) {
+           close (s);
+           continue;
+       }
+       break;
+    }
+    if (a == NULL) {
+       freeaddrinfo (ai);
+       return 1;
+    }
+    freeaddrinfo (ai);
+
+    asprintf(&prefix, "http://%s/", hi->hostname);
+    if(prefix == NULL) {
+       close(s);
+       return 1;
+    }
+    ret = send_and_recv_http(s, context->kdc_timeout,
+                            prefix, send_data, receive);
+    close (s);
+    free(prefix);
+    if(ret == 0 && receive->length != 0)
+       return 0;
+    return 1;
+}
+
+/*
+ * Send the data `send' to one host from `handle` and get back the reply
+ * in `receive'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto (krb5_context context,
+            const krb5_data *send_data,
+            krb5_krbhst_handle handle,      
+            krb5_data *receive)
+{
+     krb5_error_code ret = 0;
+     int fd;
+     int i;
+
+     for (i = 0; i < context->max_retries; ++i) {
+        krb5_krbhst_info *hi;
+
+        while (krb5_krbhst_next(context, handle, &hi) == 0) {
+            int ret;
+            struct addrinfo *ai, *a;
+
+            if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) {
+                if (send_via_proxy (context, hi, send_data, receive))
+                    continue;
+                else
+                    goto out;
+            }
+
+            ret = krb5_krbhst_get_addrinfo(context, hi, &ai);
+            if (ret)
+                continue;
+
+            for (a = ai; a != NULL; a = a->ai_next) {
+                fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+                if (fd < 0)
+                    continue;
+                if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) {
+                    close (fd);
+                    continue;
+                }
+                switch (hi->proto) {
+                case KRB5_KRBHST_HTTP :
+                    ret = send_and_recv_http(fd, context->kdc_timeout,
+                                             "", send_data, receive);
+                    break;
+                case KRB5_KRBHST_TCP :
+                    ret = send_and_recv_tcp (fd, context->kdc_timeout,
+                                             send_data, receive);
+                    break;
+                case KRB5_KRBHST_UDP :
+                    ret = send_and_recv_udp (fd, context->kdc_timeout,
+                                             send_data, receive);
+                    break;
+                }
+                close (fd);
+                if(ret == 0 && receive->length != 0)
+                    goto out;
+            }
+        }
+        krb5_krbhst_reset(context, handle);
+     }
+     krb5_clear_error_string (context);
+     ret = KRB5_KDC_UNREACH;
+out:
+     return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_kdc(krb5_context context,
+               const krb5_data *send_data,
+               const krb5_realm *realm,
+               krb5_data *receive)
+{
+    return krb5_sendto_kdc_flags(context, send_data, realm, receive, 0);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_kdc_flags(krb5_context context,
+                     const krb5_data *send_data,
+                     const krb5_realm *realm,
+                     krb5_data *receive,
+                     int flags)
+{
+    krb5_error_code ret;
+    krb5_krbhst_handle handle;
+    int type;
+
+    if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
+       type = KRB5_KRBHST_ADMIN;
+    else
+       type = KRB5_KRBHST_KDC;
+
+    if (send_data->length > context->large_msg_size)
+       flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
+
+    ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle);
+    if (ret)
+       return ret;
+
+    ret = krb5_sendto(context, send_data, handle, receive);
+    krb5_krbhst_free(context, handle);
+    if (ret == KRB5_KDC_UNREACH)
+       krb5_set_error_string(context,
+                             "unable to reach any KDC in realm %s", *realm);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/sendauth.c b/src/kerberosV/src/lib/krb5/sendauth.c
new file mode 100644 (file)
index 0000000..2c867e2
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: sendauth.c,v 1.21 2004/11/01 09:04:40 lha Exp $");
+
+/*
+ * The format seems to be:
+ * client -> server
+ *
+ * 4 bytes - length
+ * KRB5_SENDAUTH_V1.0 (including zero)
+ * 4 bytes - length
+ * protocol string (with terminating zero)
+ *
+ * server -> client
+ * 1 byte - (0 = OK, else some kind of error)
+ *
+ * client -> server
+ * 4 bytes - length
+ * AP-REQ
+ *
+ * server -> client
+ * 4 bytes - length (0 = OK, else length of error)
+ * (error)
+ *
+ * if(mutual) {
+ * server -> client
+ * 4 bytes - length
+ * AP-REP
+ * }
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendauth(krb5_context context,
+             krb5_auth_context *auth_context,
+             krb5_pointer p_fd,
+             const 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 **ret_error,
+             krb5_ap_rep_enc_part **rep_result,
+             krb5_creds **out_creds)
+{
+    krb5_error_code ret;
+    u_int32_t len, net_len;
+    const char *version = KRB5_SENDAUTH_VERSION;
+    u_char repl;
+    krb5_data ap_req, error_data;
+    krb5_creds this_cred;
+    krb5_principal this_client = NULL;
+    krb5_creds *creds;
+    ssize_t sret;
+    krb5_boolean my_ccache = FALSE;
+
+    len = strlen(version) + 1;
+    net_len = htonl(len);
+    if (krb5_net_write (context, p_fd, &net_len, 4) != 4
+       || krb5_net_write (context, p_fd, version, len) != len) {
+       ret = errno;
+       krb5_set_error_string (context, "write: %s", strerror(ret));
+       return ret;
+    }
+
+    len = strlen(appl_version) + 1;
+    net_len = htonl(len);
+    if (krb5_net_write (context, p_fd, &net_len, 4) != 4
+       || krb5_net_write (context, p_fd, appl_version, len) != len) {
+       ret = errno;
+       krb5_set_error_string (context, "write: %s", strerror(ret));
+       return ret;
+    }
+
+    sret = krb5_net_read (context, p_fd, &repl, sizeof(repl));
+    if (sret < 0) {
+       ret = errno;
+       krb5_set_error_string (context, "read: %s", strerror(ret));
+       return ret;
+    } else if (sret != sizeof(repl)) {
+       krb5_clear_error_string (context);
+       return KRB5_SENDAUTH_BADRESPONSE;
+    }
+
+    if (repl != 0) {
+       krb5_clear_error_string (context);
+       return KRB5_SENDAUTH_REJECTED;
+    }
+
+    if (in_creds == NULL) {
+       if (ccache == NULL) {
+           ret = krb5_cc_default (context, &ccache);
+           if (ret)
+               return ret;
+           my_ccache = TRUE;
+       }
+
+       if (client == NULL) {
+           ret = krb5_cc_get_principal (context, ccache, &this_client);
+           if (ret) {
+               if(my_ccache)
+                   krb5_cc_close(context, ccache);
+               return ret;
+           }
+           client = this_client;
+       }
+       memset(&this_cred, 0, sizeof(this_cred));
+       this_cred.client = client;
+       this_cred.server = server;
+       this_cred.times.endtime = 0;
+       this_cred.ticket.length = 0;
+       in_creds = &this_cred;
+    }
+    if (in_creds->ticket.length == 0) {
+       ret = krb5_get_credentials (context, 0, ccache, in_creds, &creds);
+       if (ret) {
+           if(my_ccache)
+               krb5_cc_close(context, ccache);
+           return ret;
+       }
+    } else {
+       creds = in_creds;
+    }
+    if(my_ccache)
+       krb5_cc_close(context, ccache);
+    ret = krb5_mk_req_extended (context,
+                               auth_context,
+                               ap_req_options,
+                               in_data,
+                               creds,
+                               &ap_req);
+
+    if (out_creds)
+       *out_creds = creds;
+    else
+       krb5_free_creds(context, creds);
+    if(this_client)
+       krb5_free_principal(context, this_client);
+
+    if (ret)
+       return ret;
+
+    ret = krb5_write_message (context,
+                             p_fd,
+                             &ap_req);
+    if (ret)
+       return ret;
+
+    krb5_data_free (&ap_req);
+
+    ret = krb5_read_message (context, p_fd, &error_data);
+    if (ret)
+       return ret;
+
+    if (error_data.length != 0) {
+       KRB_ERROR error;
+
+       ret = krb5_rd_error (context, &error_data, &error);
+       krb5_data_free (&error_data);
+       if (ret == 0) {
+           ret = krb5_error_from_rd_error(context, &error, NULL);
+           if (ret_error != NULL) {
+               *ret_error = malloc (sizeof(krb5_error));
+               if (*ret_error == NULL) {
+                   krb5_free_error_contents (context, &error);
+               } else {
+                   **ret_error = error;
+               }
+           } else {
+               krb5_free_error_contents (context, &error);
+           }
+           return ret;
+       } else {
+           krb5_clear_error_string(context);
+           return ret;
+       }
+    }
+
+    if (ap_req_options & AP_OPTS_MUTUAL_REQUIRED) {
+       krb5_data ap_rep;
+       krb5_ap_rep_enc_part *ignore;
+
+       krb5_data_zero (&ap_rep);
+       ret = krb5_read_message (context,
+                                p_fd,
+                                &ap_rep);
+       if (ret)
+           return ret;
+
+       ret = krb5_rd_rep (context, *auth_context, &ap_rep,
+                          rep_result ? rep_result : &ignore);
+       krb5_data_free (&ap_rep);
+       if (ret)
+           return ret;
+       if (rep_result == NULL)
+           krb5_free_ap_rep_enc_part (context, ignore);
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/set_default_realm.c b/src/kerberosV/src/lib/krb5/set_default_realm.c
new file mode 100644 (file)
index 0000000..896019a
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: set_default_realm.c,v 1.14 2004/05/25 21:42:26 lha Exp $");
+
+/*
+ * Convert the simple string `s' into a NULL-terminated and freshly allocated 
+ * list in `list'.  Return an error code.
+ */
+
+static krb5_error_code
+string_to_list (krb5_context context, const char *s, krb5_realm **list)
+{
+
+    *list = malloc (2 * sizeof(**list));
+    if (*list == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    (*list)[0] = strdup (s);
+    if ((*list)[0] == NULL) {
+       free (*list);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    (*list)[1] = NULL;
+    return 0;
+}
+
+/*
+ * Set the knowledge of the default realm(s) in `context'.
+ * If realm != NULL, that's the new default realm.
+ * Otherwise, the realm(s) are figured out from configuration or DNS.  
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_default_realm(krb5_context context,
+                      const char *realm)
+{
+    krb5_error_code ret = 0;
+    krb5_realm *realms = NULL;
+
+    if (realm == NULL) {
+       realms = krb5_config_get_strings (context, NULL,
+                                         "libdefaults",
+                                         "default_realm",
+                                         NULL);
+       if (realms == NULL)
+           ret = krb5_get_host_realm(context, NULL, &realms);
+    } else {
+       ret = string_to_list (context, realm, &realms);
+    }
+    if (ret)
+       return ret;
+    krb5_free_host_realm (context, context->default_realms);
+    context->default_realms = realms;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/sock_principal.c b/src/kerberosV/src/lib/krb5/sock_principal.c
new file mode 100644 (file)
index 0000000..29b3ef9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: sock_principal.c,v 1.17 2004/05/25 21:42:47 lha Exp $");
+                       
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sock_to_principal (krb5_context context,
+                       int sock,
+                       const char *sname,
+                       int32_t type,
+                       krb5_principal *ret_princ)
+{
+    krb5_error_code ret;
+    struct sockaddr_storage __ss;
+    struct sockaddr *sa = (struct sockaddr *)&__ss;
+    socklen_t salen = sizeof(__ss);
+    char hostname[NI_MAXHOST];
+
+    if (getsockname (sock, sa, &salen) < 0) {
+       ret = errno;
+       krb5_set_error_string (context, "getsockname: %s", strerror(ret));
+       return ret;
+    }
+    ret = getnameinfo (sa, salen, hostname, sizeof(hostname), NULL, 0, 0);
+    if (ret) {
+       int save_errno = errno;
+
+       krb5_set_error_string (context, "getnameinfo: %s", gai_strerror(ret));
+       return krb5_eai_to_heim_errno(ret, save_errno);
+    }
+
+    ret = krb5_sname_to_principal (context,
+                                  hostname,
+                                  sname,
+                                  type,
+                                  ret_princ);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/store-int.h b/src/kerberosV/src/lib/krb5/store-int.h
new file mode 100644 (file)
index 0000000..42e695a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 __store_int_h__
+#define __store_int_h__
+
+struct krb5_storage_data {
+    void *data;
+    ssize_t (*fetch)(struct krb5_storage_data*, void*, size_t);
+    ssize_t (*store)(struct krb5_storage_data*, const void*, size_t);
+    off_t (*seek)(struct krb5_storage_data*, off_t, int);
+    void (*free)(struct krb5_storage_data*);
+    krb5_flags flags;
+    int eof_code;
+};
+
+#endif /* __store_int_h__ */
diff --git a/src/kerberosV/src/lib/krb5/store-test.c b/src/kerberosV/src/lib/krb5/store-test.c
new file mode 100644 (file)
index 0000000..97c71d7
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2001 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. */
+
+#include "krb5_locl.h"
+
+RCSID("$KTH: store-test.c,v 1.1 2001/05/11 16:06:25 joda Exp $");
+
+static void
+print_data(unsigned char *data, size_t len)
+{
+    int i;
+    for(i = 0; i < len; i++) {
+       if(i > 0 && (i % 16) == 0)
+           printf("\n            ");
+       printf("%02x ", data[i]);
+    }
+    printf("\n");
+}
+
+static int
+compare(const char *name, krb5_storage *sp, void *expected, size_t len)
+{
+    int ret = 0;
+    krb5_data data;
+    krb5_storage_to_data(sp, &data);
+    krb5_storage_free(sp);
+    if(data.length != len || memcmp(data.data, expected, len) != 0) {
+       printf("%s mismatch\n", name);
+       printf("  Expected: ");
+       print_data(expected, len);
+       printf("  Actual:   ");
+       print_data(data.data, data.length);
+       ret++;
+    }
+    krb5_data_free(&data);
+    return ret;
+}
+
+int
+main(int argc, char **argv)
+{
+    int nerr = 0;
+    krb5_storage *sp;
+    krb5_context context;
+    krb5_principal principal;
+       
+
+    krb5_init_context(&context);
+
+    sp = krb5_storage_emem();
+    krb5_store_int32(sp, 0x01020304);
+    nerr += compare("Integer", sp, "\x1\x2\x3\x4", 4);
+
+    sp = krb5_storage_emem();
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
+    krb5_store_int32(sp, 0x01020304);
+    nerr += compare("Integer (LE)", sp, "\x4\x3\x2\x1", 4);
+
+    sp = krb5_storage_emem();
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+    krb5_store_int32(sp, 0x01020304);
+    nerr += compare("Integer (BE)", sp, "\x1\x2\x3\x4", 4);
+
+    sp = krb5_storage_emem();
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST);
+    krb5_store_int32(sp, 0x01020304);
+    {
+       int test = 1;
+       void *data;
+       if(*(char*)&test) 
+           data = "\x4\x3\x2\x1";
+       else 
+           data = "\x1\x2\x3\x4";
+       nerr += compare("Integer (host)", sp, data, 4);
+    }
+
+    sp = krb5_storage_emem();
+    krb5_make_principal(context, &principal, "TEST", "foobar", NULL);
+    krb5_store_principal(sp, principal);
+    nerr += compare("Principal", sp, "\x0\x0\x0\x1"
+                   "\x0\x0\x0\x1"
+                   "\x0\x0\x0\x4TEST"
+                   "\x0\x0\x0\x6""foobar", 26);
+    
+    return nerr ? 1 : 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/store.c b/src/kerberosV/src/lib/krb5/store.c
new file mode 100644 (file)
index 0000000..b9b2ad8
--- /dev/null
@@ -0,0 +1,902 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include "store-int.h"
+
+RCSID("$KTH: store.c,v 1.49 2005/06/01 10:40:05 lha Exp $");
+
+#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
+#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
+#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
+#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \
+                              krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER))
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags)
+{
+    sp->flags |= flags;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
+{
+    sp->flags &= ~flags;
+}
+
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
+{
+    return (sp->flags & flags) == flags;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
+{
+    sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK;
+    sp->flags |= byteorder;
+}
+
+krb5_flags KRB5_LIB_FUNCTION
+krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
+{
+    return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
+}
+
+off_t KRB5_LIB_FUNCTION
+krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
+{
+    return (*sp->seek)(sp, offset, whence);
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
+{
+    return sp->fetch(sp, buf, len);
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
+{
+    return sp->store(sp, buf, len);
+}
+
+void KRB5_LIB_FUNCTION
+krb5_storage_set_eof_code(krb5_storage *sp, int code)
+{
+    sp->eof_code = code;
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+_krb5_put_int(void *buffer, unsigned long value, size_t size)
+{
+    unsigned char *p = buffer;
+    int i;
+    for (i = size - 1; i >= 0; i--) {
+       p[i] = value & 0xff;
+       value >>= 8;
+    }
+    return size;
+}
+
+krb5_ssize_t KRB5_LIB_FUNCTION
+_krb5_get_int(void *buffer, unsigned long *value, size_t size)
+{
+    unsigned char *p = buffer;
+    unsigned long v = 0;
+    int i;
+    for (i = 0; i < size; i++)
+       v = (v << 8) + p[i];
+    *value = v;
+    return size;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_storage_free(krb5_storage *sp)
+{
+    if(sp->free)
+       (*sp->free)(sp);
+    free(sp->data);
+    free(sp);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
+{
+    off_t pos;
+    size_t size;
+    krb5_error_code ret;
+
+    pos = sp->seek(sp, 0, SEEK_CUR);
+    size = (size_t)sp->seek(sp, 0, SEEK_END);
+    ret = krb5_data_alloc (data, size);
+    if (ret) {
+       sp->seek(sp, pos, SEEK_SET);
+       return ret;
+    }
+    if (size) {
+       sp->seek(sp, 0, SEEK_SET);
+       sp->fetch(sp, data->data, data->length);
+       sp->seek(sp, pos, SEEK_SET);
+    }
+    return 0;
+}
+
+static krb5_error_code
+krb5_store_int(krb5_storage *sp,
+              int32_t value,
+              size_t len)
+{
+    int ret;
+    unsigned char v[16];
+
+    if(len > sizeof(v))
+       return EINVAL;
+    _krb5_put_int(v, value, len);
+    ret = sp->store(sp, v, len);
+    if (ret != len)
+       return (ret<0)?errno:sp->eof_code;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_int32(krb5_storage *sp,
+                int32_t value)
+{
+    if(BYTEORDER_IS_HOST(sp))
+       value = htonl(value);
+    else if(BYTEORDER_IS_LE(sp))
+       value = bswap32(value);
+    return krb5_store_int(sp, value, 4);
+}
+
+static krb5_error_code
+krb5_ret_int(krb5_storage *sp,
+            int32_t *value,
+            size_t len)
+{
+    int ret;
+    unsigned char v[4];
+    unsigned long w;
+    ret = sp->fetch(sp, v, len);
+    if(ret != len)
+       return (ret<0)?errno:sp->eof_code;
+    _krb5_get_int(v, &w, len);
+    *value = w;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_int32(krb5_storage *sp,
+              int32_t *value)
+{
+    krb5_error_code ret = krb5_ret_int(sp, value, 4);
+    if(ret)
+       return ret;
+    if(BYTEORDER_IS_HOST(sp))
+       *value = htonl(*value);
+    else if(BYTEORDER_IS_LE(sp))
+       *value = bswap32(*value);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_int16(krb5_storage *sp,
+                int16_t value)
+{
+    if(BYTEORDER_IS_HOST(sp))
+       value = htons(value);
+    else if(BYTEORDER_IS_LE(sp))
+       value = bswap16(value);
+    return krb5_store_int(sp, value, 2);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_int16(krb5_storage *sp,
+              int16_t *value)
+{
+    int32_t v;
+    int ret;
+    ret = krb5_ret_int(sp, &v, 2);
+    if(ret)
+       return ret;
+    *value = v;
+    if(BYTEORDER_IS_HOST(sp))
+       *value = htons(*value);
+    else if(BYTEORDER_IS_LE(sp))
+       *value = bswap16(*value);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_int8(krb5_storage *sp,
+               int8_t value)
+{
+    int ret;
+
+    ret = sp->store(sp, &value, sizeof(value));
+    if (ret != sizeof(value))
+       return (ret<0)?errno:sp->eof_code;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_int8(krb5_storage *sp,
+             int8_t *value)
+{
+    int ret;
+
+    ret = sp->fetch(sp, value, sizeof(*value));
+    if (ret != sizeof(*value))
+       return (ret<0)?errno:sp->eof_code;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_data(krb5_storage *sp,
+               krb5_data data)
+{
+    int ret;
+    ret = krb5_store_int32(sp, data.length);
+    if(ret < 0)
+       return ret;
+    ret = sp->store(sp, data.data, data.length);
+    if(ret != data.length){
+       if(ret < 0)
+           return errno;
+       return sp->eof_code;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_data(krb5_storage *sp,
+             krb5_data *data)
+{
+    int ret;
+    int32_t size;
+
+    ret = krb5_ret_int32(sp, &size);
+    if(ret)
+       return ret;
+    ret = krb5_data_alloc (data, size);
+    if (ret)
+       return ret;
+    if (size) {
+       ret = sp->fetch(sp, data->data, size);
+       if(ret != size)
+           return (ret < 0)? errno : sp->eof_code;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_string(krb5_storage *sp, const char *s)
+{
+    krb5_data data;
+    data.length = strlen(s);
+    data.data = (void*)s;
+    return krb5_store_data(sp, data);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_string(krb5_storage *sp,
+               char **string)
+{
+    int ret;
+    krb5_data data;
+    ret = krb5_ret_data(sp, &data);
+    if(ret)
+       return ret;
+    *string = realloc(data.data, data.length + 1);
+    if(*string == NULL){
+       free(data.data);
+       return ENOMEM;
+    }
+    (*string)[data.length] = 0;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_stringz(krb5_storage *sp, const char *s)
+{
+    size_t len = strlen(s) + 1;
+    ssize_t ret;
+
+    ret = sp->store(sp, s, len);
+    if(ret != len) {
+       if(ret < 0)
+           return ret;
+       else
+           return sp->eof_code;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_stringz(krb5_storage *sp,
+               char **string)
+{
+    char c;
+    char *s = NULL;
+    size_t len = 0;
+    ssize_t ret;
+
+    while((ret = sp->fetch(sp, &c, 1)) == 1){
+       char *tmp;
+
+       len++;
+       tmp = realloc (s, len);
+       if (tmp == NULL) {
+           free (s);
+           return ENOMEM;
+       }
+       s = tmp;
+       s[len - 1] = c;
+       if(c == 0)
+           break;
+    }
+    if(ret != 1){
+       free(s);
+       if(ret == 0)
+           return sp->eof_code;
+       return ret;
+    }
+    *string = s;
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_principal(krb5_storage *sp,
+                    krb5_principal p)
+{
+    int i;
+    int ret;
+
+    if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) {
+    ret = krb5_store_int32(sp, p->name.name_type);
+    if(ret) return ret;
+    }
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
+       ret = krb5_store_int32(sp, p->name.name_string.len + 1);
+    else
+    ret = krb5_store_int32(sp, p->name.name_string.len);
+    
+    if(ret) return ret;
+    ret = krb5_store_string(sp, p->realm);
+    if(ret) return ret;
+    for(i = 0; i < p->name.name_string.len; i++){
+       ret = krb5_store_string(sp, p->name.name_string.val[i]);
+       if(ret) return ret;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_principal(krb5_storage *sp,
+                  krb5_principal *princ)
+{
+    int i;
+    int ret;
+    krb5_principal p;
+    int32_t type;
+    int32_t ncomp;
+    
+    p = calloc(1, sizeof(*p));
+    if(p == NULL)
+       return ENOMEM;
+
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE))
+       type = KRB5_NT_UNKNOWN;
+    else if((ret = krb5_ret_int32(sp, &type))){
+       free(p);
+       return ret;
+    }
+    if((ret = krb5_ret_int32(sp, &ncomp))){
+       free(p);
+       return ret;
+    }
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS))
+       ncomp--;
+    if (ncomp < 0) {
+       free(p);
+       return EINVAL;
+    }
+    p->name.name_type = type;
+    p->name.name_string.len = ncomp;
+    ret = krb5_ret_string(sp, &p->realm);
+    if(ret) {
+       free(p);
+       return ret;
+    }
+    p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val));
+    if(p->name.name_string.val == NULL && ncomp != 0){
+       free(p->realm);
+       return ENOMEM;
+    }
+    for(i = 0; i < ncomp; i++){
+       ret = krb5_ret_string(sp, &p->name.name_string.val[i]);
+       if(ret) {
+           while (i >= 0)
+               free(p->name.name_string.val[i--]);
+           free(p->realm);
+           free(p);
+           return ret;
+       }
+    }
+    *princ = p;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
+{
+    int ret;
+    ret = krb5_store_int16(sp, p.keytype);
+    if(ret) return ret;
+
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
+       /* this should really be enctype, but it is the same as
+           keytype nowadays */
+    ret = krb5_store_int16(sp, p.keytype);
+    if(ret) return ret;
+    }
+
+    ret = krb5_store_data(sp, p.keyvalue);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
+{
+    int ret;
+    int16_t tmp;
+
+    ret = krb5_ret_int16(sp, &tmp);
+    if(ret) return ret;
+    p->keytype = tmp;
+
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){
+    ret = krb5_ret_int16(sp, &tmp);
+    if(ret) return ret;
+    }
+
+    ret = krb5_ret_data(sp, &p->keyvalue);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_times(krb5_storage *sp, krb5_times times)
+{
+    int ret;
+    ret = krb5_store_int32(sp, times.authtime);
+    if(ret) return ret;
+    ret = krb5_store_int32(sp, times.starttime);
+    if(ret) return ret;
+    ret = krb5_store_int32(sp, times.endtime);
+    if(ret) return ret;
+    ret = krb5_store_int32(sp, times.renew_till);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_times(krb5_storage *sp, krb5_times *times)
+{
+    int ret;
+    int32_t tmp;
+    ret = krb5_ret_int32(sp, &tmp);
+    times->authtime = tmp;
+    if(ret) return ret;
+    ret = krb5_ret_int32(sp, &tmp);
+    times->starttime = tmp;
+    if(ret) return ret;
+    ret = krb5_ret_int32(sp, &tmp);
+    times->endtime = tmp;
+    if(ret) return ret;
+    ret = krb5_ret_int32(sp, &tmp);
+    times->renew_till = tmp;
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_address(krb5_storage *sp, krb5_address p)
+{
+    int ret;
+    ret = krb5_store_int16(sp, p.addr_type);
+    if(ret) return ret;
+    ret = krb5_store_data(sp, p.address);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_address(krb5_storage *sp, krb5_address *adr)
+{
+    int16_t t;
+    int ret;
+    ret = krb5_ret_int16(sp, &t);
+    if(ret) return ret;
+    adr->addr_type = t;
+    ret = krb5_ret_data(sp, &adr->address);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_addrs(krb5_storage *sp, krb5_addresses p)
+{
+    int i;
+    int ret;
+    ret = krb5_store_int32(sp, p.len);
+    if(ret) return ret;
+    for(i = 0; i<p.len; i++){
+       ret = krb5_store_address(sp, p.val[i]);
+       if(ret) break;
+    }
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_addrs(krb5_storage *sp, krb5_addresses *adr)
+{
+    int i;
+    int ret;
+    int32_t tmp;
+
+    ret = krb5_ret_int32(sp, &tmp);
+    if(ret) return ret;
+    adr->len = tmp;
+    ALLOC(adr->val, adr->len);
+    if (adr->val == NULL && adr->len != 0)
+       return ENOMEM;
+    for(i = 0; i < adr->len; i++){
+       ret = krb5_ret_address(sp, &adr->val[i]);
+       if(ret) break;
+    }
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_authdata(krb5_storage *sp, krb5_authdata auth)
+{
+    krb5_error_code ret;
+    int i;
+    ret = krb5_store_int32(sp, auth.len);
+    if(ret) return ret;
+    for(i = 0; i < auth.len; i++){
+       ret = krb5_store_int16(sp, auth.val[i].ad_type);
+       if(ret) break;
+       ret = krb5_store_data(sp, auth.val[i].ad_data);
+       if(ret) break;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth)
+{
+    krb5_error_code ret;
+    int32_t tmp;
+    int16_t tmp2;
+    int i;
+    ret = krb5_ret_int32(sp, &tmp);
+    if(ret) return ret;
+    ALLOC_SEQ(auth, tmp);
+    if (auth->val == NULL && tmp != 0)
+       return ENOMEM;
+    for(i = 0; i < tmp; i++){
+       ret = krb5_ret_int16(sp, &tmp2);
+       if(ret) break;
+       auth->val[i].ad_type = tmp2;
+       ret = krb5_ret_data(sp, &auth->val[i].ad_data);
+       if(ret) break;
+    }
+    return ret;
+}
+
+static int32_t
+bitswap32(int32_t b)
+{
+    int32_t r = 0;
+    int i;
+    for (i = 0; i < 32; i++) {
+       r = r << 1 | (b & 1);
+       b = b >> 1;
+    }
+    return r;
+}
+
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_creds(krb5_storage *sp, krb5_creds *creds)
+{
+    int ret;
+
+    ret = krb5_store_principal(sp, creds->client);
+    if(ret)
+       return ret;
+    ret = krb5_store_principal(sp, creds->server);
+    if(ret)
+       return ret;
+    ret = krb5_store_keyblock(sp, creds->session);
+    if(ret)
+       return ret;
+    ret = krb5_store_times(sp, creds->times);
+    if(ret)
+       return ret;
+    ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
+    if(ret)
+       return ret;
+
+    if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER))
+       ret = krb5_store_int32(sp, creds->flags.i);
+    else
+       ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
+    if(ret)
+       return ret;
+
+    ret = krb5_store_addrs(sp, creds->addresses);
+    if(ret)
+       return ret;
+    ret = krb5_store_authdata(sp, creds->authdata);
+    if(ret)
+       return ret;
+    ret = krb5_store_data(sp, creds->ticket);
+    if(ret)
+       return ret;
+    ret = krb5_store_data(sp, creds->second_ticket);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_creds(krb5_storage *sp, krb5_creds *creds)
+{
+    krb5_error_code ret;
+    int8_t dummy8;
+    int32_t dummy32;
+
+    memset(creds, 0, sizeof(*creds));
+    ret = krb5_ret_principal (sp,  &creds->client);
+    if(ret) goto cleanup;
+    ret = krb5_ret_principal (sp,  &creds->server);
+    if(ret) goto cleanup;
+    ret = krb5_ret_keyblock (sp,  &creds->session);
+    if(ret) goto cleanup;
+    ret = krb5_ret_times (sp,  &creds->times);
+    if(ret) goto cleanup;
+    ret = krb5_ret_int8 (sp,  &dummy8);
+    if(ret) goto cleanup;
+    ret = krb5_ret_int32 (sp,  &dummy32);
+    if(ret) goto cleanup;
+    /*
+     * Runtime detect the what is the higher bits of the bitfield. If
+     * any of the higher bits are set in the input data, its either a
+     * new ticket flag (and this code need to be removed), or its a
+     * MIT cache (or new Heimdal cache), lets change it to our current
+     * format.
+     */
+    {
+       u_int32_t mask = 0xffff0000;
+       creds->flags.i = 0;
+       creds->flags.b.anonymous = 1;
+       if (creds->flags.i & mask)
+           mask = ~mask;
+       if (dummy32 & mask)
+           dummy32 = bitswap32(dummy32);
+    }
+    creds->flags.i = dummy32;
+    ret = krb5_ret_addrs (sp,  &creds->addresses);
+    if(ret) goto cleanup;
+    ret = krb5_ret_authdata (sp,  &creds->authdata);
+    if(ret) goto cleanup;
+    ret = krb5_ret_data (sp,  &creds->ticket);
+    if(ret) goto cleanup;
+    ret = krb5_ret_data (sp,  &creds->second_ticket);
+cleanup:
+    if(ret) {
+#if 0  
+       krb5_free_cred_contents(context, creds); /* XXX */
+#endif
+    }
+    return ret;
+}
+
+#define SC_CLIENT_PRINCIPAL        0x0001
+#define SC_SERVER_PRINCIPAL        0x0002
+#define SC_SESSION_KEY             0x0004
+#define SC_TICKET                  0x0008
+#define SC_SECOND_TICKET           0x0010
+#define SC_AUTHDATA                0x0020
+#define SC_ADDRESSES               0x0040
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_store_creds_tag(krb5_storage *sp,
+                    krb5_creds *creds)
+{
+    int ret;
+    int32_t header = 0;
+
+    if (creds->client)
+       header |= SC_CLIENT_PRINCIPAL;
+    if (creds->server)
+       header |= SC_SERVER_PRINCIPAL;
+    if (creds->session.keyvalue.data)
+       header |= SC_SESSION_KEY;
+    if (creds->ticket.data)
+       header |= SC_TICKET;
+    if (creds->second_ticket.length)
+       header |= SC_SECOND_TICKET;
+    if (creds->authdata.len)
+       header |= SC_AUTHDATA;
+    if (creds->addresses.len)
+       header |= SC_ADDRESSES;
+
+    ret = krb5_store_int32(sp, header);
+
+    if (creds->client) {
+       ret = krb5_store_principal(sp, creds->client);
+       if(ret)
+           return ret;
+    }
+
+    if (creds->server) {
+       ret = krb5_store_principal(sp, creds->server);
+       if(ret)
+           return ret;
+    }
+
+    if (creds->session.keyvalue.data) {
+       ret = krb5_store_keyblock(sp, creds->session);
+       if(ret)
+           return ret;
+    }
+
+    ret = krb5_store_times(sp, creds->times);
+    if(ret)
+       return ret;
+    ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */
+    if(ret)
+       return ret;
+
+    ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b)));
+    if(ret)
+       return ret;
+
+    if (creds->addresses.len) {
+       ret = krb5_store_addrs(sp, creds->addresses);
+       if(ret)
+           return ret;
+    }
+
+    if (creds->authdata.len) {
+       ret = krb5_store_authdata(sp, creds->authdata);
+       if(ret)
+           return ret;
+    }
+
+    if (creds->ticket.data) {
+       ret = krb5_store_data(sp, creds->ticket);
+       if(ret)
+           return ret;
+    }
+
+    if (creds->second_ticket.data) {
+       ret = krb5_store_data(sp, creds->second_ticket);
+       if (ret)
+           return ret;
+    }
+
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ret_creds_tag(krb5_storage *sp,
+                  krb5_creds *creds)
+{
+    krb5_error_code ret;
+    int8_t dummy8;
+    int32_t dummy32, header;
+
+    memset(creds, 0, sizeof(*creds));
+
+    ret = krb5_ret_int32 (sp, &header);
+    if (ret) goto cleanup;
+
+    if (header & SC_CLIENT_PRINCIPAL) {
+       ret = krb5_ret_principal (sp,  &creds->client);
+       if(ret) goto cleanup;
+    }
+    if (header & SC_SERVER_PRINCIPAL) {
+       ret = krb5_ret_principal (sp,  &creds->server);
+       if(ret) goto cleanup;
+    }
+    if (header & SC_SESSION_KEY) {
+       ret = krb5_ret_keyblock (sp,  &creds->session);
+       if(ret) goto cleanup;
+    }
+    ret = krb5_ret_times (sp,  &creds->times);
+    if(ret) goto cleanup;
+    ret = krb5_ret_int8 (sp,  &dummy8);
+    if(ret) goto cleanup;
+    ret = krb5_ret_int32 (sp,  &dummy32);
+    if(ret) goto cleanup;
+    /*
+     * Runtime detect the what is the higher bits of the bitfield. If
+     * any of the higher bits are set in the input data, its either a
+     * new ticket flag (and this code need to be removed), or its a
+     * MIT cache (or new Heimdal cache), lets change it to our current
+     * format.
+     */
+    {
+       u_int32_t mask = 0xffff0000;
+       creds->flags.i = 0;
+       creds->flags.b.anonymous = 1;
+       if (creds->flags.i & mask)
+           mask = ~mask;
+       if (dummy32 & mask)
+           dummy32 = bitswap32(dummy32);
+    }
+    creds->flags.i = dummy32;
+    if (header & SC_ADDRESSES) {
+       ret = krb5_ret_addrs (sp,  &creds->addresses);
+       if(ret) goto cleanup;
+    }
+    if (header & SC_AUTHDATA) {
+       ret = krb5_ret_authdata (sp,  &creds->authdata);
+       if(ret) goto cleanup;
+    }
+    if (header & SC_TICKET) {
+       ret = krb5_ret_data (sp,  &creds->ticket);
+       if(ret) goto cleanup;
+    }
+    if (header & SC_SECOND_TICKET) {
+       ret = krb5_ret_data (sp,  &creds->second_ticket);
+       if(ret) goto cleanup;
+    }
+
+cleanup:
+    if(ret) {
+#if 0  
+       krb5_free_cred_contents(context, creds); /* XXX */
+#endif
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/store_emem.c b/src/kerberosV/src/lib/krb5/store_emem.c
new file mode 100644 (file)
index 0000000..3f9c70f
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include "store-int.h"
+
+RCSID("$KTH: store_emem.c,v 1.14 2004/05/25 21:43:29 lha Exp $");
+
+typedef struct emem_storage{
+    unsigned char *base;
+    size_t size;
+    size_t len;
+    unsigned char *ptr;
+}emem_storage;
+
+static ssize_t
+emem_fetch(krb5_storage *sp, void *data, size_t size)
+{
+    emem_storage *s = (emem_storage*)sp->data;
+    if(s->base + s->len - s->ptr < size)
+       size = s->base + s->len - s->ptr;
+    memmove(data, s->ptr, size);
+    sp->seek(sp, size, SEEK_CUR);
+    return size;
+}
+
+static ssize_t
+emem_store(krb5_storage *sp, const void *data, size_t size)
+{
+    emem_storage *s = (emem_storage*)sp->data;
+    if(size > s->base + s->size - s->ptr){
+       void *base;
+       size_t sz, off;
+       off = s->ptr - s->base;
+       sz = off + size;
+       if (sz < 4096)
+           sz *= 2;
+       base = realloc(s->base, sz);
+       if(base == NULL)
+           return 0;
+       s->size = sz;
+       s->base = base;
+       s->ptr = (unsigned char*)base + off;
+    }
+    memmove(s->ptr, data, size);
+    sp->seek(sp, size, SEEK_CUR);
+    return size;
+}
+
+static off_t
+emem_seek(krb5_storage *sp, off_t offset, int whence)
+{
+    emem_storage *s = (emem_storage*)sp->data;
+    switch(whence){
+    case SEEK_SET:
+       if(offset > s->size)
+           offset = s->size;
+       if(offset < 0)
+           offset = 0;
+       s->ptr = s->base + offset;
+       if(offset > s->len)
+           s->len = offset;
+       break;
+    case SEEK_CUR:
+       sp->seek(sp,s->ptr - s->base + offset, SEEK_SET);
+       break;
+    case SEEK_END:
+       sp->seek(sp, s->len + offset, SEEK_SET);
+       break;
+    default:
+       errno = EINVAL;
+       return -1;
+    }
+    return s->ptr - s->base;
+}
+
+static void
+emem_free(krb5_storage *sp)
+{
+    emem_storage *s = sp->data;
+    memset(s->base, 0, s->len);
+    free(s->base);
+}
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_emem(void)
+{
+    krb5_storage *sp = malloc(sizeof(krb5_storage));
+    emem_storage *s = malloc(sizeof(*s));
+    sp->data = s;
+    sp->flags = 0;
+    sp->eof_code = HEIM_ERR_EOF;
+    s->size = 1024;
+    s->base = malloc(s->size);
+    s->len = 0;
+    s->ptr = s->base;
+    sp->fetch = emem_fetch;
+    sp->store = emem_store;
+    sp->seek = emem_seek;
+    sp->free = emem_free;
+    return sp;
+}
diff --git a/src/kerberosV/src/lib/krb5/store_fd.c b/src/kerberosV/src/lib/krb5/store_fd.c
new file mode 100644 (file)
index 0000000..0a95eba
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1997 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include "store-int.h"
+
+RCSID("$KTH: store_fd.c,v 1.12 2004/05/25 21:43:57 lha Exp $");
+
+typedef struct fd_storage {
+    int fd;
+} fd_storage;
+
+#define FD(S) (((fd_storage*)(S)->data)->fd)
+
+static ssize_t
+fd_fetch(krb5_storage * sp, void *data, size_t size)
+{
+    return net_read(FD(sp), data, size);
+}
+
+static ssize_t
+fd_store(krb5_storage * sp, const void *data, size_t size)
+{
+    return net_write(FD(sp), data, size);
+}
+
+static off_t
+fd_seek(krb5_storage * sp, off_t offset, int whence)
+{
+    return lseek(FD(sp), offset, whence);
+}
+
+static void
+fd_free(krb5_storage * sp)
+{
+    close(FD(sp));
+}
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_from_fd(int fd)
+{
+    krb5_storage *sp;
+
+    fd = dup(fd);
+    if (fd < 0)
+       return NULL;
+    sp = malloc(sizeof(krb5_storage));
+
+    if (sp == NULL)
+       return NULL;
+
+    sp->data = malloc(sizeof(fd_storage));
+    if (sp->data == NULL) {
+       free(sp);
+       return NULL;
+    }
+    sp->flags = 0;
+    sp->eof_code = HEIM_ERR_EOF;
+    FD(sp) = fd;
+    sp->fetch = fd_fetch;
+    sp->store = fd_store;
+    sp->seek = fd_seek;
+    sp->free = fd_free;
+    return sp;
+}
diff --git a/src/kerberosV/src/lib/krb5/store_mem.c b/src/kerberosV/src/lib/krb5/store_mem.c
new file mode 100644 (file)
index 0000000..bdcb9ef
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 1997 - 2000, 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include "store-int.h"
+
+RCSID("$KTH: store_mem.c,v 1.12 2004/05/25 21:44:17 lha Exp $");
+
+typedef struct mem_storage{
+    unsigned char *base;
+    size_t size;
+    unsigned char *ptr;
+}mem_storage;
+
+static ssize_t
+mem_fetch(krb5_storage *sp, void *data, size_t size)
+{
+    mem_storage *s = (mem_storage*)sp->data;
+    if(size > s->base + s->size - s->ptr)
+       size = s->base + s->size - s->ptr;
+    memmove(data, s->ptr, size);
+    sp->seek(sp, size, SEEK_CUR);
+    return size;
+}
+
+static ssize_t
+mem_store(krb5_storage *sp, const void *data, size_t size)
+{
+    mem_storage *s = (mem_storage*)sp->data;
+    if(size > s->base + s->size - s->ptr)
+       size = s->base + s->size - s->ptr;
+    memmove(s->ptr, data, size);
+    sp->seek(sp, size, SEEK_CUR);
+    return size;
+}
+
+static off_t
+mem_seek(krb5_storage *sp, off_t offset, int whence)
+{
+    mem_storage *s = (mem_storage*)sp->data;
+    switch(whence){
+    case SEEK_SET:
+       if(offset > s->size)
+           offset = s->size;
+       if(offset < 0)
+           offset = 0;
+       s->ptr = s->base + offset;
+       break;
+    case SEEK_CUR:
+       return sp->seek(sp, s->ptr - s->base + offset, SEEK_SET);
+    case SEEK_END:
+       return sp->seek(sp, s->size + offset, SEEK_SET);
+    default:
+       errno = EINVAL;
+       return -1;
+    }
+    return s->ptr - s->base;
+}
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_from_mem(void *buf, size_t len)
+{
+    krb5_storage *sp = malloc(sizeof(krb5_storage));
+    mem_storage *s;
+    if(sp == NULL)
+       return NULL;
+    s = malloc(sizeof(*s));
+    if(s == NULL) {
+       free(sp);
+       return NULL;
+    }
+    sp->data = s;
+    sp->flags = 0;
+    sp->eof_code = HEIM_ERR_EOF;
+    s->base = buf;
+    s->size = len;
+    s->ptr = buf;
+    sp->fetch = mem_fetch;
+    sp->store = mem_store;
+    sp->seek = mem_seek;
+    sp->free = NULL;
+    return sp;
+}
+
+krb5_storage * KRB5_LIB_FUNCTION
+krb5_storage_from_data(krb5_data *data)
+{
+       return krb5_storage_from_mem(data->data, data->length);
+}
diff --git a/src/kerberosV/src/lib/krb5/string-to-key-test.c b/src/kerberosV/src/lib/krb5/string-to-key-test.c
new file mode 100644 (file)
index 0000000..457e75a
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 1999 - 2001 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: string-to-key-test.c,v 1.9 2005/04/30 15:17:56 lha Exp $");
+
+enum { MAXSIZE = 24 };
+
+static struct testcase {
+    const char *principal_name;
+    const char *password;
+    krb5_enctype enctype;
+    unsigned char res[MAXSIZE];
+} tests[] = {
+    {"@", "", ETYPE_DES_CBC_MD5,
+     {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xf1}},
+    {"nisse@FOO.SE", "hej", ETYPE_DES_CBC_MD5,
+     {0xfe, 0x67, 0xbf, 0x9e, 0x57, 0x6b, 0xfe, 0x52}},
+    {"assar/liten@FOO.SE", "hemligt", ETYPE_DES_CBC_MD5,
+     {0x5b, 0x9b, 0xcb, 0xf2, 0x97, 0x43, 0xc8, 0x40}},
+#if 0
+    {"@", "", ETYPE_DES3_CBC_SHA1,
+     {0xce, 0xa2, 0x2f, 0x9b, 0x52, 0x2c, 0xb0, 0x15, 0x6e, 0x6b, 0x64,
+      0x73, 0x62, 0x64, 0x73, 0x4f, 0x6e, 0x73, 0xce, 0xa2, 0x2f, 0x9b,
+      0x52, 0x57}},
+#endif
+    {"nisse@FOO.SE", "hej", ETYPE_DES3_CBC_SHA1,
+     {0x0e, 0xbc, 0x23, 0x9d, 0x68, 0x46, 0xf2, 0xd5, 0x51, 0x98, 0x5b,
+      0x57, 0xc1, 0x57, 0x01, 0x79, 0x04, 0xc4, 0xe9, 0xfe, 0xc1, 0x0e,
+      0x13, 0xd0}},
+    {"assar/liten@FOO.SE", "hemligt", ETYPE_DES3_CBC_SHA1,
+     {0x7f, 0x40, 0x67, 0xb9, 0xbc, 0xc4, 0x40, 0xfb, 0x43, 0x73, 0xd9,
+      0xd3, 0xcd, 0x7c, 0xc7, 0x67, 0xe6, 0x79, 0x94, 0xd0, 0xa8, 0x34,
+      0xdf, 0x62}},
+    {"does/not@MATTER", "foo", ETYPE_ARCFOUR_HMAC_MD5,
+     {0xac, 0x8e, 0x65, 0x7f, 0x83, 0xdf, 0x82, 0xbe,
+      0xea, 0x5d, 0x43, 0xbd, 0xaf, 0x78, 0x00, 0xcc}},
+    {"raeburn@ATHENA.MIT.EDU", "password", ETYPE_DES_CBC_MD5,
+     {0xcb, 0xc2, 0x2f, 0xae, 0x23, 0x52, 0x98, 0xe3}},
+    {"danny@WHITEHOUSE.GOV", "potatoe", ETYPE_DES_CBC_MD5,
+     {0xdf, 0x3d, 0x32, 0xa7, 0x4f, 0xd9, 0x2a, 0x01}},
+    {"buckaroo@EXAMPLE.COM", "penny", ETYPE_DES_CBC_MD5,
+     {0x94, 0x43, 0xa2, 0xe5, 0x32, 0xfd, 0xc4, 0xf1}},
+    {"Juri\xc5\xa1i\xc4\x87@ATHENA.MIT.EDU", "\xc3\x9f", ETYPE_DES_CBC_MD5,
+     {0x62, 0xc8, 0x1a, 0x52, 0x32, 0xb5, 0xe6, 0x9d}},
+    {"AAAAAAAA", "11119999", ETYPE_DES_CBC_MD5,
+     {0x98, 0x40, 0x54, 0xd0, 0xf1, 0xa7, 0x3e, 0x31}},
+    {"FFFFAAAA", "NNNN6666", ETYPE_DES_CBC_MD5,
+     {0xc4, 0xbf, 0x6b, 0x25, 0xad, 0xf7, 0xa4, 0xf8}},
+    {"raeburn@ATHENA.MIT.EDU", "password", ETYPE_DES3_CBC_SHA1,
+     {0x85, 0x0b, 0xb5, 0x13, 0x58, 0x54, 0x8c, 0xd0, 0x5e, 0x86, 0x76, 0x8c, 0x31, 0x3e, 0x3b, 0xfe, 0xf7, 0x51, 0x19, 0x37, 0xdc, 0xf7, 0x2c, 0x3e}},
+    {"danny@WHITEHOUSE.GOV", "potatoe", ETYPE_DES3_CBC_SHA1,
+     {0xdf, 0xcd, 0x23, 0x3d, 0xd0, 0xa4, 0x32, 0x04, 0xea, 0x6d, 0xc4, 0x37, 0xfb, 0x15, 0xe0, 0x61, 0xb0, 0x29, 0x79, 0xc1, 0xf7, 0x4f, 0x37, 0x7a}},
+    {"buckaroo@EXAMPLE.COM", "penny", ETYPE_DES3_CBC_SHA1,
+     {0x6d, 0x2f, 0xcd, 0xf2, 0xd6, 0xfb, 0xbc, 0x3d, 0xdc, 0xad, 0xb5, 0xda, 0x57, 0x10, 0xa2, 0x34, 0x89, 0xb0, 0xd3, 0xb6, 0x9d, 0x5d, 0x9d, 0x4a}},
+    {"Juri\xc5\xa1i\xc4\x87@ATHENA.MIT.EDU", "\xc3\x9f", ETYPE_DES3_CBC_SHA1,
+     {0x16, 0xd5, 0xa4, 0x0e, 0x1c, 0xe3, 0xba, 0xcb, 0x61, 0xb9, 0xdc, 0xe0, 0x04, 0x70, 0x32, 0x4c, 0x83, 0x19, 0x73, 0xa7, 0xb9, 0x52, 0xfe, 0xb0}},
+    {NULL}
+};
+
+int
+main(int argc, char **argv)
+{
+    struct testcase *t;
+    krb5_context context;
+    krb5_error_code ret;
+    int val = 0;
+
+    ret = krb5_init_context (&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    /* to enable realm-less principal name above */
+
+    krb5_set_default_realm(context, "");
+
+    for (t = tests; t->principal_name; ++t) {
+       krb5_keyblock key;
+       krb5_principal principal;
+       int i;
+
+       ret = krb5_parse_name (context, t->principal_name, &principal);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_parse_name %s",
+                     t->principal_name);
+       ret = krb5_string_to_key (context, t->enctype, t->password,
+                                 principal, &key);
+       if (ret)
+           krb5_err (context, 1, ret, "krb5_string_to_key");
+       krb5_free_principal (context, principal);
+       if (memcmp (key.keyvalue.data, t->res, key.keyvalue.length) != 0) {
+           const unsigned char *p = key.keyvalue.data;
+
+           printf ("string_to_key(%s, %s) failed\n",
+                   t->principal_name, t->password);
+           printf ("should be: ");
+           for (i = 0; i < key.keyvalue.length; ++i)
+               printf ("%02x", t->res[i]);
+           printf ("\nresult was: ");
+           for (i = 0; i < key.keyvalue.length; ++i)
+               printf ("%02x", p[i]);
+           printf ("\n");
+           val = 1;
+       }
+    }
+    return val;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_acl.c b/src/kerberosV/src/lib/krb5/test_acl.c
new file mode 100644 (file)
index 0000000..6e949ad
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2004 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_acl.c,v 1.3 2005/04/30 15:18:57 lha Exp $");
+
+#define RETVAL(c, r, e, s) \
+       do { if (r != e) krb5_errx(c, 1, "%s", s); } while (0)
+#define STRINGMATCH(c, s, _s1, _s2) \
+       do {                                                    \
+               if (_s1 == NULL || _s2 == NULL)                 \
+                       krb5_errx(c, 1, "s1 or s2 is NULL");    \
+               if (strcmp(_s1,_s2) != 0)                       \
+                       krb5_errx(c, 1, "%s", s);               \
+       } while (0)
+
+static void
+test_match_string(krb5_context context)
+{
+    krb5_error_code ret;
+    char *s1, *s2;
+
+    ret = krb5_acl_match_string(context, "foo", "s", "foo");
+    RETVAL(context, ret, 0, "single s");
+    ret = krb5_acl_match_string(context, "foo foo", "s", "foo");
+    RETVAL(context, ret, EACCES, "too many strings");
+    ret = krb5_acl_match_string(context, "foo bar", "ss", "foo", "bar");
+    RETVAL(context, ret, 0, "two strings");
+    ret = krb5_acl_match_string(context, "foo  bar", "ss", "foo", "bar");
+    RETVAL(context, ret, 0, "two strings double space");
+    ret = krb5_acl_match_string(context, "foo \tbar", "ss", "foo", "bar");
+    RETVAL(context, ret, 0, "two strings space + tab");
+    ret = krb5_acl_match_string(context, "foo", "ss", "foo", "bar");
+    RETVAL(context, ret, EACCES, "one string, two format strings");
+    ret = krb5_acl_match_string(context, "foo", "ss", "foo", "foo");
+    RETVAL(context, ret, EACCES, "one string, two format strings (same)");
+    ret = krb5_acl_match_string(context, "foo  \t", "s", "foo");
+    RETVAL(context, ret, 0, "ending space");
+
+    ret = krb5_acl_match_string(context, "foo/bar", "f", "foo/bar");
+    RETVAL(context, ret, 0, "liternal fnmatch");
+    ret = krb5_acl_match_string(context, "foo/bar", "f", "foo/*");
+    RETVAL(context, ret, 0, "foo/*");
+    ret = krb5_acl_match_string(context, "foo/bar/baz", "f", "foo/*/baz");
+    RETVAL(context, ret, 0, "foo/*/baz");
+
+    ret = krb5_acl_match_string(context, "foo", "r", &s1);
+    RETVAL(context, ret, 0, "ret 1");
+    STRINGMATCH(context, "ret 1 match", s1, "foo"); free(s1);
+
+    ret = krb5_acl_match_string(context, "foo bar", "rr", &s1, &s2);
+    RETVAL(context, ret, 0, "ret 2");
+    STRINGMATCH(context, "ret 2 match 1", s1, "foo"); free(s1);
+    STRINGMATCH(context, "ret 2 match 2", s2, "bar"); free(s2);
+
+    ret = krb5_acl_match_string(context, "foo bar", "sr", "bar", &s1);
+    RETVAL(context, ret, EACCES, "ret mismatch");
+    if (s1 != NULL) krb5_errx(context, 1, "s1 not NULL");
+
+    ret = krb5_acl_match_string(context, "foo", "l", "foo");
+    RETVAL(context, ret, EINVAL, "unknown letter");
+}
+
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+
+    setprogname(argv[0]);
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    test_match_string(context);
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_addr.c b/src/kerberosV/src/lib/krb5/test_addr.c
new file mode 100644 (file)
index 0000000..cf5f186
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2005 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_addr.c,v 1.6 2005/04/30 15:18:41 lha Exp $");
+
+static void
+print_addr(krb5_context context, const char *addr)
+{
+    krb5_addresses addresses;
+    krb5_error_code ret;
+    char buf[38];
+    char buf2[1000];
+    size_t len;
+    int i;
+
+    ret = krb5_parse_address(context, addr, &addresses);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_address");
+
+    if (addresses.len < 1)
+       krb5_err(context, 1, ret, "too few addresses");
+    
+    for (i = 0; i < addresses.len; i++) {
+       krb5_print_address(&addresses.val[i], buf, sizeof(buf), &len);
+#if 0
+       printf("addr %d: %s (%d/%d)\n", i, buf, (int)len, (int)strlen(buf)); 
+#endif
+       if (strlen(buf) > sizeof(buf))
+           abort();
+       krb5_print_address(&addresses.val[i], buf2, sizeof(buf2), &len);
+#if 0
+       printf("addr %d: %s (%d/%d)\n", i, buf2, (int)len, (int)strlen(buf2)); 
+#endif
+       if (strlen(buf2) > sizeof(buf2))
+           abort();
+
+    }
+    krb5_free_addresses(context, &addresses);
+
+}
+
+static void
+truncated_addr(krb5_context context, const char *addr, 
+              size_t truncate_len, size_t outlen)
+{
+    krb5_addresses addresses;
+    krb5_error_code ret;
+    char *buf;
+    size_t len;
+
+    buf = ecalloc(1, outlen + 1);
+
+    ret = krb5_parse_address(context, addr, &addresses);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_address");
+
+    if (addresses.len != 1)
+       krb5_err(context, 1, ret, "addresses should be one");
+    
+    krb5_print_address(&addresses.val[0], buf, truncate_len, &len);
+    
+#if 0
+    printf("addr %s (%d/%d)\n", buf, (int)len, (int)strlen(buf)); 
+#endif
+    
+    if (truncate_len > strlen(buf) + 1)
+       abort();
+    if (outlen != len)
+       abort();
+    
+    krb5_print_address(&addresses.val[0], buf, outlen + 1, &len);
+
+#if 0
+    printf("addr %s (%d/%d)\n", buf, (int)len, (int)strlen(buf)); 
+#endif
+
+    if (len != outlen)
+       abort();
+    if (strlen(buf) != len)
+       abort();
+
+    krb5_free_addresses(context, &addresses);
+    free(buf);
+}
+
+static void
+check_truncation(krb5_context context, const char *addr)
+{
+    int i, len = strlen(addr);
+
+    for (i = 0; i < len; i++)
+       truncated_addr(context, addr, i, len);
+}
+
+static void
+match_addr(krb5_context context, const char *range_addr, 
+          const char *one_addr, int match)
+{
+    krb5_addresses range, one;
+    krb5_error_code ret;
+
+    ret = krb5_parse_address(context, range_addr, &range);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_address");
+
+    if (range.len != 1)
+       krb5_err(context, 1, ret, "wrong num of addresses");
+    
+    ret = krb5_parse_address(context, one_addr, &one);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_address");
+
+    if (one.len != 1)
+       krb5_err(context, 1, ret, "wrong num of addresses");
+
+    if (krb5_address_order(context, &range.val[0], &one.val[0]) == 0) {
+       if (!match)
+           krb5_errx(context, 1, "match when one shouldn't be");
+    } else {
+       if (match)
+           krb5_errx(context, 1, "no match when one should be");
+    }
+
+    krb5_free_addresses(context, &range);
+    krb5_free_addresses(context, &one);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+
+    setprogname(argv[0]);
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    print_addr(context, "RANGE:127.0.0.0/8");
+    print_addr(context, "RANGE:127.0.0.0/24");
+    print_addr(context, "RANGE:IPv4:127.0.0.0-IPv4:127.0.0.255");
+    print_addr(context, "RANGE:130.237.237.4/29");
+#ifdef HAVE_IPV6
+    print_addr(context, "RANGE:fe80::209:6bff:fea0:e522/64");
+    print_addr(context, "RANGE:IPv6:fe80::209:6bff:fea0:e522/64");
+    print_addr(context, "RANGE:IPv6:fe80::-IPv6:fe80::ffff:ffff:ffff:ffff");
+    print_addr(context, "RANGE:fe80::-fe80::ffff:ffff:ffff:ffff");
+#endif
+
+    check_truncation(context, "IPv4:127.0.0.0");
+    check_truncation(context, "RANGE:IPv4:127.0.0.0-IPv4:127.0.0.255");
+#ifdef HAVE_IPV6
+    check_truncation(context, "IPv6:::1");
+    check_truncation(context, "IPv6:fe80::ffff:ffff:ffff:ffff");
+#endif
+
+    match_addr(context, "RANGE:127.0.0.0/8", "inet:127.0.0.0", 1);
+    match_addr(context, "RANGE:127.0.0.0/8", "inet:127.255.255.255", 1);
+    match_addr(context, "RANGE:127.0.0.0/8", "inet:128.0.0.0", 0);
+
+    match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.7", 0);
+    match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.8", 1);
+    match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.15", 1);
+    match_addr(context, "RANGE:130.237.237.8/29", "inet:130.237.237.16", 0);
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_alname.c b/src/kerberosV/src/lib/krb5/test_alname.c
new file mode 100644 (file)
index 0000000..b465474
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2003 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. */
+
+#include "krb5_locl.h"
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$KTH: test_alname.c,v 1.5 2005/03/31 00:44:37 lha Exp $");
+
+static void
+test_alname(krb5_context context, krb5_const_realm realm,
+           const char *user, const char *inst, 
+           const char *localuser, int ok)
+{
+    krb5_principal p;
+    char localname[1024];
+    krb5_error_code ret;
+    char *princ;
+
+    ret = krb5_make_principal(context, &p, realm, user, inst, NULL);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_build_principal");
+
+    ret = krb5_unparse_name(context, p, &princ);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_unparse_name");
+
+    ret = krb5_aname_to_localname(context, p, sizeof(localname), localname);
+    krb5_free_principal(context, p);
+    free(princ);
+    if (ret) {
+       if (!ok)
+           return;
+       krb5_err(context, 1, ret, "krb5_aname_to_localname: %s -> %s", 
+                princ, localuser);
+    }
+
+    if (strcmp(localname, localuser) != 0) {
+       if (ok)
+           errx(1, "compared failed %s != %s (should have succeded)", 
+                localname, localuser);
+    } else {
+       if (!ok)
+           errx(1, "compared failed %s == %s (should have failed)", 
+                localname, localuser);
+    }
+    
+}
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_realm realm;
+    int optind = 0;
+    char *user;
+
+    setprogname(argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 1)
+       errx(1, "first argument should be a local user that in root .k5login");
+
+    user = argv[0];
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    ret = krb5_get_default_realm(context, &realm);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_get_default_realm");
+
+    test_alname(context, realm, user, NULL, user, 1);
+    test_alname(context, realm, user, "root", "root", 1);
+
+    test_alname(context, "FOO.BAR.BAZ.KAKA", user, NULL, user, 0);
+    test_alname(context, "FOO.BAR.BAZ.KAKA", user, "root", "root", 0);
+
+    test_alname(context, realm, user, NULL, 
+               "not-same-as-user", 0);
+    test_alname(context, realm, user, "root",
+               "not-same-as-user", 0);
+
+    test_alname(context, "FOO.BAR.BAZ.KAKA", user, NULL, 
+               "not-same-as-user", 0);
+    test_alname(context, "FOO.BAR.BAZ.KAKA", user, "root",
+               "not-same-as-user", 0);
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_cc.c b/src/kerberosV/src/lib/krb5/test_cc.c
new file mode 100644 (file)
index 0000000..80c05e4
--- /dev/null
@@ -0,0 +1,334 @@
+/*
+ * Copyright (c) 2003 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_cc.c,v 1.7 2005/05/29 16:18:21 lha Exp $");
+
+static void
+test_default_name(krb5_context context)
+{
+    krb5_error_code ret;
+    const char *p, *test_cc_name = "/tmp/krb5-cc-test-foo";
+    char *p1, *p2, *p3;
+
+    p = krb5_cc_default_name(context);
+    if (p == NULL)
+       krb5_errx (context, 1, "krb5_cc_default_name 1 failed");
+    p1 = estrdup(p);
+
+    ret = krb5_cc_set_default_name(context, NULL);
+    if (p == NULL)
+       krb5_errx (context, 1, "krb5_cc_set_default_name failed");
+
+    p = krb5_cc_default_name(context);
+    if (p == NULL)
+       krb5_errx (context, 1, "krb5_cc_default_name 2 failed");
+    p2 = estrdup(p);
+
+    if (strcmp(p1, p2) != 0)
+       krb5_errx (context, 1, "krb5_cc_default_name no longer same");
+       
+    ret = krb5_cc_set_default_name(context, test_cc_name);
+    if (p == NULL)
+       krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed");
+    
+    p = krb5_cc_default_name(context);
+    if (p == NULL)
+       krb5_errx (context, 1, "krb5_cc_default_name 2 failed");
+    p3 = estrdup(p);
+    
+    if (strcmp(p3, test_cc_name) != 0)
+       krb5_errx (context, 1, "krb5_cc_set_default_name 1 failed");
+}
+
+/*
+ * Check that a closed cc still keeps it data and that its no longer
+ * there when its destroyed.
+ */
+
+static void
+test_mcache(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_ccache id, id2;
+    const char *nc, *tc;
+    char *n, *t, *c;
+    krb5_principal p, p2;
+
+    ret = krb5_parse_name(context, "lha@SU.SE", &p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+
+    ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_gen_new");
+
+    ret = krb5_cc_initialize(context, id, p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+    nc = krb5_cc_get_name(context, id);
+    if (nc == NULL)
+       krb5_errx(context, 1, "krb5_cc_get_name");
+
+    tc = krb5_cc_get_type(context, id);
+    if (tc == NULL)
+       krb5_errx(context, 1, "krb5_cc_get_name");
+
+    n = estrdup(nc);
+    t = estrdup(tc);
+
+    asprintf(&c, "%s:%s", t, n);
+
+    krb5_cc_close(context, id);
+
+    ret = krb5_cc_resolve(context, c, &id2);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_resolve");
+
+    ret = krb5_cc_get_principal(context, id2, &p2);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_get_principal");
+
+    if (krb5_principal_compare(context, p, p2) == FALSE)
+       krb5_errx(context, 1, "p != p2");
+
+    krb5_cc_destroy(context, id2);
+    krb5_free_principal(context, p);
+    krb5_free_principal(context, p2);
+
+    ret = krb5_cc_resolve(context, c, &id2);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_resolve");
+
+    ret = krb5_cc_get_principal(context, id2, &p2);
+    if (ret == 0)
+       krb5_errx(context, 1, "krb5_cc_get_principal");
+
+    krb5_cc_destroy(context, id2);
+}
+
+/*
+ * Test that init works on a destroyed cc.
+ */
+
+static void
+test_init_vs_destroy(krb5_context context, const krb5_cc_ops *ops)
+{
+    krb5_error_code ret;
+    krb5_ccache id, id2;
+    krb5_principal p, p2;
+    char *n;
+
+    ret = krb5_parse_name(context, "lha@SU.SE", &p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+
+    ret = krb5_cc_gen_new(context, ops, &id);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_gen_new");
+
+    asprintf(&n, "%s:%s",
+            krb5_cc_get_type(context, id),
+            krb5_cc_get_name(context, id));
+
+    ret = krb5_cc_resolve(context, n, &id2);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_resolve");
+
+    krb5_cc_destroy(context, id);
+
+    ret = krb5_cc_initialize(context, id2, p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+    ret = krb5_cc_get_principal(context, id2, &p2);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_get_principal");
+
+    krb5_cc_destroy(context, id2);
+    krb5_free_principal(context, p);
+    krb5_free_principal(context, p2);
+}
+
+static void
+test_fcache_remove(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_ccache id;
+    krb5_principal p;
+    krb5_creds cred;
+
+    ret = krb5_parse_name(context, "lha@SU.SE", &p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+
+    ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &id);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_gen_new");
+
+    ret = krb5_cc_initialize(context, id, p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_initialize");
+
+    /* */
+    memset(&cred, 0, sizeof(cred));
+    ret = krb5_parse_name(context, "krbtgt/SU.SE@SU.SE", &cred.server);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+    ret = krb5_parse_name(context, "lha@SU.SE", &cred.client);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+
+    ret = krb5_cc_store_cred(context, id, &cred);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_store_cred");
+
+    ret = krb5_cc_remove_cred(context, id, 0, &cred);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_remove_cred");
+
+    ret = krb5_cc_destroy(context, id);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_cc_destroy");
+
+    krb5_free_principal(context, p);
+    krb5_free_principal(context, cred.server);
+    krb5_free_principal(context, cred.client);
+}
+
+static void
+test_mcc_default(void)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_ccache id, id2;
+    int i;
+
+    for (i = 0; i < 10; i++) {
+
+       ret = krb5_init_context(&context);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_init_context");
+
+       ret = krb5_cc_set_default_name(context, "MEMORY:foo");
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_set_default_name");
+
+       ret = krb5_cc_default(context, &id);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_default");
+
+       ret = krb5_cc_default(context, &id2);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_default");
+
+       ret = krb5_cc_close(context, id);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_close");
+
+       ret = krb5_cc_close(context, id2);
+       if (ret)
+           krb5_err(context, 1, ret, "krb5_cc_close");
+
+       krb5_free_context(context);
+    }
+}
+
+struct {
+    char *str;
+    int fail;
+    char *res;
+} cc_names[] = {
+    { "foo", 0, "foo" },
+    { "%{uid}", 0 },
+    { "foo%{null}", 0, "foo" },
+    { "foo%{null}bar", 0, "foobar" },
+    { "%{", 1 },
+    { "%{foo %{", 1 },
+    { "%{{", 1 },
+};
+
+static void
+test_def_cc_name(krb5_context context)
+{
+    krb5_error_code ret;
+    char *str;
+    int i;
+
+    for (i = 0; i < sizeof(cc_names)/sizeof(cc_names[0]); i++) {
+       ret = _krb5_expand_default_cc_name(context, cc_names[i].str, &str);
+       if (ret) {
+           if (cc_names[i].fail == 0)
+               krb5_errx(context, 1, "test %d \"%s\" failed", 
+                         i, cc_names[i].str);
+       } else {
+           if (cc_names[i].fail)
+               krb5_errx(context, 1, "test %d \"%s\" was successful", 
+                         i, cc_names[i].str);
+           if (cc_names[i].res && strcmp(cc_names[i].res, str) != 0)
+               krb5_errx(context, 1, "test %d %s != %s", 
+                         i, cc_names[i].res, str);
+#if 0
+           printf("%s => %s\n", cc_names[i].str, str);
+#endif
+           free(str);
+       }
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+
+    setprogname(argv[0]);
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    test_fcache_remove(context);
+    test_default_name(context);
+    test_mcache(context);
+    test_init_vs_destroy(context, &krb5_mcc_ops);
+    test_init_vs_destroy(context, &krb5_fcc_ops);
+    test_mcc_default();
+    test_def_cc_name(context);
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_config.c b/src/kerberosV/src/lib/krb5/test_config.c
new file mode 100644 (file)
index 0000000..a91712a
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_config.c,v 1.2 2005/04/30 15:19:18 lha Exp $");
+
+static int
+check_config_file(krb5_context context, char *filelist, char **res, int def)
+{
+    krb5_error_code ret;
+    char **pp;
+    int i;
+
+    pp = NULL;
+
+    if (def)
+       ret = krb5_prepend_config_files_default(filelist, &pp);
+    else
+       ret = krb5_prepend_config_files(filelist, NULL, &pp);
+    
+    if (ret)
+       krb5_err(context, 1, ret, "prepend_config_files");
+    
+    for (i = 0; res[i] && pp[i]; i++)
+       if (strcmp(pp[i], res[i]) != 0)
+           krb5_errx(context, 1, "'%s' != '%s'", pp[i], res[i]);
+    
+    if (res[i] != NULL)
+       krb5_errx(context, 1, "pp ended before res list");
+    
+    if (def) {
+       char **deflist;
+       int j;
+       
+       ret = krb5_get_default_config_files(&deflist);
+       if (ret)
+           krb5_err(context, 1, ret, "get_default_config_files");
+       
+       for (j = 0 ; pp[i] && deflist[j]; i++, j++)
+           if (strcmp(pp[i], deflist[j]) != 0)
+               krb5_errx(context, 1, "'%s' != '%s'", pp[i], deflist[j]);
+       
+       if (deflist[j] != NULL)
+           krb5_errx(context, 1, "pp ended before def list");
+       krb5_free_config_files(deflist);
+    }
+    
+    if (pp[i] != NULL)
+       krb5_errx(context, 1, "pp ended after res (and def) list");
+    
+    krb5_free_config_files(pp);
+    
+    return 0;
+}
+
+char *list0[] =  { "/tmp/foo", NULL };
+char *list1[] =  { "/tmp/foo", "/tmp/foo/bar", NULL };
+char *list2[] =  { "", NULL };
+
+struct {
+    char *fl;
+    char **res;
+} test[] = {
+    { "/tmp/foo", NULL },
+    { "/tmp/foo:/tmp/foo/bar", NULL },
+    { "", NULL }
+};
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    int i;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx(1, "krb5_init_context %d", ret);
+
+    test[0].res = list0;
+    test[1].res = list1;
+    test[2].res = list2;
+
+    for (i = 0; i < sizeof(test)/sizeof(*test); i++) {
+       check_config_file(context, test[i].fl, test[i].res, 0);
+       check_config_file(context, test[i].fl, test[i].res, 1);
+    }
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_crypto.c b/src/kerberosV/src/lib/krb5/test_crypto.c
new file mode 100644 (file)
index 0000000..1c13fd0
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2003 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+#include <getarg.h>
+
+RCSID("$KTH: test_crypto.c,v 1.3 2005/04/04 17:54:50 lha Exp $");
+
+static void
+time_encryption(krb5_context context, size_t size,
+               krb5_enctype etype, int iterations)
+{
+    struct timeval tv1, tv2;
+    krb5_error_code ret;
+    krb5_keyblock key;
+    krb5_crypto crypto;
+    krb5_data data;
+    char *etype_name;
+    void *buf;
+    int i;
+
+    ret = krb5_generate_random_keyblock(context, etype, &key);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_generate_random_keyblock");
+
+    ret = krb5_enctype_to_string(context, etype, &etype_name);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_enctype_to_string");
+
+    buf = malloc(size);
+    if (buf == NULL)
+       krb5_errx(context, 1, "out of memory");
+    memset(buf, 0, size);
+
+    ret = krb5_crypto_init(context, &key, 0, &crypto);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_crypto_init");
+
+    gettimeofday(&tv1, NULL);
+
+    for (i = 0; i < iterations; i++) {
+       ret = krb5_encrypt(context, crypto, 0, buf, size, &data);
+       if (ret)
+           krb5_err(context, 1, ret, "encrypt: %d", i);
+       krb5_data_free(&data);
+    }
+
+    gettimeofday(&tv2, NULL);
+
+    timevalsub(&tv2, &tv1);
+
+    printf("%s size: %7lu iterations: %d time: %3ld.%06ld\n", 
+          etype_name, (unsigned long)size, iterations,
+          (long)tv2.tv_sec, (long)tv2.tv_usec);
+
+    krb5_crypto_destroy(context, crypto);
+    krb5_free_keyblock_contents(context, &key);
+}
+
+
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    int i, iterations;
+    int optind = 0;
+
+    krb5_enctype enctypes[] = { 
+       ETYPE_DES_CBC_CRC,
+       ETYPE_DES3_CBC_SHA1,
+       ETYPE_ARCFOUR_HMAC_MD5,
+       ETYPE_AES128_CTS_HMAC_SHA1_96,
+       ETYPE_AES256_CTS_HMAC_SHA1_96
+    };
+
+    setprogname(argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    iterations = 1000;
+
+    for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) {
+       time_encryption(context, 16, enctypes[i], iterations);
+       time_encryption(context, 32, enctypes[i], iterations);
+       time_encryption(context, 512, enctypes[i], iterations);
+       time_encryption(context, 1024, enctypes[i], iterations);
+       time_encryption(context, 2048, enctypes[i], iterations);
+       time_encryption(context, 4096, enctypes[i], iterations);
+       time_encryption(context, 8192, enctypes[i], iterations);
+       time_encryption(context, 16384, enctypes[i], iterations);
+       time_encryption(context, 32768, enctypes[i], iterations);
+    }
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_get_addrs.c b/src/kerberosV/src/lib/krb5/test_get_addrs.c
new file mode 100644 (file)
index 0000000..ed0aba3
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2000 - 2002 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+#include <getarg.h>
+
+RCSID("$KTH: test_get_addrs.c,v 1.4 2002/08/23 03:42:54 assar Exp $");
+
+/* print all addresses that we find */
+
+static void
+print_addresses (krb5_context context, const krb5_addresses *addrs)
+{
+    int i;
+    char buf[256];
+    size_t len;
+    
+    for (i = 0; i < addrs->len; ++i) {
+       krb5_print_address (&addrs->val[i], buf, sizeof(buf), &len);
+       printf ("%s\n", buf);
+    }
+}
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_addresses addrs;
+    int optind = 0;
+
+    setprogname (argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    ret = krb5_get_all_client_addrs (context, &addrs);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_get_all_client_addrs");
+    printf ("client addresses\n");
+    print_addresses (context, &addrs);
+    krb5_free_addresses (context, &addrs);
+
+    ret = krb5_get_all_server_addrs (context, &addrs);
+    if (ret)
+       krb5_err (context, 1, ret, "krb5_get_all_server_addrs");
+    printf ("server addresses\n");
+    print_addresses (context, &addrs);
+    krb5_free_addresses (context, &addrs);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_keytab.c b/src/kerberosV/src/lib/krb5/test_keytab.c
new file mode 100644 (file)
index 0000000..d682e73
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2005 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_keytab.c,v 1.2 2005/05/20 09:01:29 lha Exp $");
+
+/*
+ * Test that removal entry from of empty keytab doesn't corrupts
+ * memory.
+ */
+
+static void
+test_empty_keytab(krb5_context context, const char *keytab)
+{
+    krb5_error_code ret;
+    krb5_keytab id;
+    krb5_keytab_entry entry;
+
+    ret = krb5_kt_resolve(context, keytab, &id);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_kt_resolve");
+
+    memset(&entry, 0, sizeof(entry));
+
+    krb5_kt_remove_entry(context, id, &entry);
+
+    ret = krb5_kt_close(context, id);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_kt_close");
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+
+    setprogname(argv[0]);
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    test_empty_keytab(context, "MEMORY:foo");
+    test_empty_keytab(context, "FILE:foo");
+    test_empty_keytab(context, "KRB4:foo");
+
+    krb5_free_context(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_kuserok.c b/src/kerberosV/src/lib/krb5/test_kuserok.c
new file mode 100644 (file)
index 0000000..825a63f
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2005 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. */
+
+#include "krb5_locl.h"
+#include <getarg.h>
+#include <err.h>
+
+RCSID("$KTH: test_kuserok.c,v 1.3 2005/04/30 15:15:38 lha Exp $");
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "principal luser");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_principal principal;
+    char *p;
+    int o = 0;
+
+    setprogname(argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &o))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= o;
+    argv += o;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx (1, "krb5_init_context failed: %d", ret);
+
+    if (argc != 2)
+       usage(1);
+
+    ret = krb5_parse_name(context, argv[0], &principal);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_parse_name");
+    
+    ret = krb5_unparse_name(context, principal, &p);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_unparse_name");
+
+    ret = krb5_kuserok(context, principal, argv[1]);
+
+    krb5_free_context(context);
+
+    printf("%s is %sallowed to login as %s\n", p, ret ? "" : "NOT ", argv[1]);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_mem.c b/src/kerberosV/src/lib/krb5/test_mem.c
new file mode 100644 (file)
index 0000000..6ed11e9
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2005 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. */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_mem.c,v 1.1 2005/06/14 01:41:50 lha Exp $");
+
+/*
+ * Test run functions, to be used with valgrind to detect memoryleaks.
+ */
+
+static void
+check_log(void)
+{
+    int i;
+
+    for (i = 0; i < 10; i++) {
+       krb5_log_facility *logf;
+       krb5_context context;
+       krb5_error_code ret;
+
+       ret = krb5_init_context(&context);
+       if (ret)
+           errx (1, "krb5_init_context failed: %d", ret);
+    
+       krb5_initlog(context, "test-mem", &logf);
+       krb5_addlog_dest(context, logf, "0/STDERR:");
+       krb5_set_warn_dest(context, logf);
+    
+       krb5_free_context(context);
+    }
+}
+
+
+int
+main(int argc, char **argv)
+{
+    setprogname(argv[0]);
+
+    check_log();
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/test_time.c b/src/kerberosV/src/lib/krb5/test_time.c
new file mode 100644 (file)
index 0000000..bd38d4d
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003 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.
+ */
+
+#include "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: test_time.c,v 1.2 2005/04/30 15:19:04 lha Exp $");
+
+static void
+check_set_time(krb5_context context)
+{
+    krb5_error_code ret;
+    krb5_timestamp sec;
+    int32_t usec;
+    struct timeval tv;
+    int diff = 10;
+    int diff2;
+
+    gettimeofday(&tv, NULL);
+
+    ret = krb5_set_real_time(context, tv.tv_sec + diff, tv.tv_usec);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_us_timeofday");
+    
+    ret = krb5_us_timeofday(context, &sec, &usec);
+    if (ret)
+       krb5_err(context, 1, ret, "krb5_us_timeofday");
+
+    diff2 = abs(sec - tv.tv_sec);
+
+    if (diff2 < 9 || diff > 11)
+       krb5_errx(context, 1, "set time error: diff: %d",
+                 abs(sec - tv.tv_sec));
+}
+
+
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+
+    ret = krb5_init_context(&context);
+    if (ret)
+       errx(1, "krb5_init_context %d", ret);
+
+    check_set_time(context);
+    check_set_time(context);
+    check_set_time(context);
+    check_set_time(context);
+    check_set_time(context);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/ticket.c b/src/kerberosV/src/lib/krb5/ticket.c
new file mode 100644 (file)
index 0000000..0c62961
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: ticket.c,v 1.12 2004/05/25 21:44:47 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_free_ticket(krb5_context context,
+                krb5_ticket *ticket)
+{
+    free_EncTicketPart(&ticket->ticket);
+    krb5_free_principal(context, ticket->client);
+    krb5_free_principal(context, ticket->server);
+    free(ticket);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_copy_ticket(krb5_context context,
+                const krb5_ticket *from,
+                krb5_ticket **to)
+{
+    krb5_error_code ret;
+    krb5_ticket *tmp;
+
+    *to = NULL;
+    tmp = malloc(sizeof(*tmp));
+    if(tmp == NULL) {
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){
+       free(tmp);
+       return ret;
+    }
+    ret = krb5_copy_principal(context, from->client, &tmp->client);
+    if(ret){
+       free_EncTicketPart(&tmp->ticket);
+       free(tmp);
+       return ret;
+    }
+    ret = krb5_copy_principal(context, from->server, &tmp->server);
+    if(ret){
+       krb5_free_principal(context, tmp->client);
+       free_EncTicketPart(&tmp->ticket);
+       free(tmp);
+       return ret;
+    }
+    *to = tmp;
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ticket_get_client(krb5_context context,
+                      const krb5_ticket *ticket,
+                      krb5_principal *client)
+{
+    return krb5_copy_principal(context, ticket->client, client);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ticket_get_server(krb5_context context,
+                      const krb5_ticket *ticket,
+                      krb5_principal *server)
+{
+    return krb5_copy_principal(context, ticket->server, server);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_ticket_get_authorization_data_type(krb5_context context,
+                                       krb5_ticket *ticket,
+                                       int type,
+                                       krb5_data *data)
+{
+    AuthorizationData *ad;
+    int i;
+
+    data->length = 0;
+    data->data = NULL;
+
+    ad = ticket->ticket.authorization_data;
+    if (ad == NULL) {
+       krb5_set_error_string(context, "Ticket have not authorization data");
+       return ENOENT; /* XXX */
+    }
+
+    for (i = 0; i < ad->len; i++) {
+       if (ad->val[i].ad_type == type)
+           return copy_octet_string(&ad->val[i].ad_data, data);
+    }
+    krb5_set_error_string(context, "Ticket have not authorization "
+                         "data of type %d", type);
+    return ENOENT; /* XXX */
+}
diff --git a/src/kerberosV/src/lib/krb5/time.c b/src/kerberosV/src/lib/krb5/time.c
new file mode 100644 (file)
index 0000000..bd5712d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: time.c,v 1.13 2004/10/13 17:57:11 lha Exp $");
+
+/*
+ * Set the absolute time that the caller knows the kdc has so the
+ * kerberos library can calculate the relative diffrence beteen the
+ * KDC time and local system time.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_real_time (krb5_context context,
+                   krb5_timestamp sec,
+                   int32_t usec)
+{
+    struct timeval tv;
+    
+    gettimeofday(&tv, NULL);
+
+    context->kdc_sec_offset = sec - tv.tv_sec;
+    context->kdc_usec_offset = usec - tv.tv_usec;
+
+    if (context->kdc_usec_offset < 0) {
+       context->kdc_sec_offset--;
+       context->kdc_usec_offset += 1000000;
+    }
+    return 0;
+}
+
+/*
+ * return ``corrected'' time in `timeret'.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_timeofday (krb5_context context,
+               krb5_timestamp *timeret)
+{
+    *timeret = time(NULL) + context->kdc_sec_offset;
+    return 0;
+}
+
+/*
+ * like gettimeofday but with time correction to the KDC
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_us_timeofday (krb5_context context,
+                  krb5_timestamp *sec,
+                  int32_t *usec)
+{
+    struct timeval tv;
+
+    gettimeofday (&tv, NULL);
+
+    *sec  = tv.tv_sec + context->kdc_sec_offset;
+    *usec = tv.tv_usec;                /* XXX */
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_format_time(krb5_context context, time_t t, 
+                char *s, size_t len, krb5_boolean include_time)
+{
+    struct tm *tm;
+    if(context->log_utc)
+       tm = gmtime (&t);
+    else
+       tm = localtime(&t);
+    if(tm == NULL ||
+       strftime(s, len, include_time ? context->time_fmt : context->date_fmt, tm) == 0)
+       snprintf(s, len, "%ld", (long)t);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_string_to_deltat(const char *string, krb5_deltat *deltat)
+{
+    if((*deltat = parse_time(string, "s")) == -1)
+       return KRB5_DELTAT_BADFORMAT;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/transited.c b/src/kerberosV/src/lib/krb5/transited.c
new file mode 100644 (file)
index 0000000..b617625
--- /dev/null
@@ -0,0 +1,483 @@
+/*
+ * Copyright (c) 1997 - 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: transited.c,v 1.15 2004/05/25 21:45:27 lha Exp $");
+
+/* this is an attempt at one of the most horrible `compression'
+   schemes that has ever been invented; it's so amazingly brain-dead
+   that words can not describe it, and all this just to save a few
+   silly bytes */
+
+struct tr_realm {
+    char *realm;
+    unsigned leading_space:1;
+    unsigned leading_slash:1;
+    unsigned trailing_dot:1;
+    struct tr_realm *next;
+};
+
+static void
+free_realms(struct tr_realm *r)
+{
+    struct tr_realm *p;
+    while(r){
+       p = r;
+       r = r->next;
+       free(p->realm);
+       free(p);
+    }  
+}
+
+static int
+make_path(krb5_context context, struct tr_realm *r,
+         const char *from, const char *to)
+{
+    const char *p;
+    struct tr_realm *path = r->next;
+    struct tr_realm *tmp;
+
+    if(strlen(from) < strlen(to)){
+       const char *tmp;
+       tmp = from;
+       from = to;
+       to = tmp;
+    }
+       
+    if(strcmp(from + strlen(from) - strlen(to), to) == 0){
+       p = from;
+       while(1){
+           p = strchr(p, '.');
+           if(p == NULL) {
+               krb5_clear_error_string (context);
+               return KRB5KDC_ERR_POLICY;
+           }
+           p++;
+           if(strcmp(p, to) == 0)
+               break;
+           tmp = calloc(1, sizeof(*tmp));
+           tmp->next = path;
+           path = tmp;
+           path->realm = strdup(p);
+           if(path->realm == NULL){
+               r->next = path; /* XXX */
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+       }
+    }else if(strncmp(from, to, strlen(to)) == 0){
+       p = from + strlen(from);
+       while(1){
+           while(p >= from && *p != '/') p--;
+           if(p == from) {
+               r->next = path; /* XXX */
+               return KRB5KDC_ERR_POLICY;
+           }
+           if(strncmp(to, from, p - from) == 0)
+               break;
+           tmp = calloc(1, sizeof(*tmp));
+           tmp->next = path;
+           path = tmp;
+           path->realm = malloc(p - from + 1);
+           if(path->realm == NULL){
+               r->next = path; /* XXX */
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           memcpy(path->realm, from, p - from);
+           path->realm[p - from] = '\0';
+           p--;
+       }
+    } else {
+       krb5_clear_error_string (context);
+       return KRB5KDC_ERR_POLICY;
+    }
+    r->next = path;
+    
+    return 0;
+}
+
+static int
+make_paths(krb5_context context,
+          struct tr_realm *realms, const char *client_realm, 
+          const char *server_realm)
+{
+    struct tr_realm *r;
+    int ret;
+    const char *prev_realm = client_realm;
+    const char *next_realm = NULL;
+    for(r = realms; r; r = r->next){
+       /* it *might* be that you can have more than one empty
+          component in a row, at least that's how I interpret the
+          "," exception in 1510 */
+       if(r->realm[0] == '\0'){
+           while(r->next && r->next->realm[0] == '\0')
+               r = r->next;
+           if(r->next)
+               next_realm = r->next->realm;
+           else
+               next_realm = server_realm;
+           ret = make_path(context, r, prev_realm, next_realm);
+           if(ret){
+               free_realms(realms);
+               return ret;
+           }
+       }
+       prev_realm = r->realm;
+    }
+    return 0;
+}
+
+static int
+expand_realms(krb5_context context,
+             struct tr_realm *realms, const char *client_realm)
+{
+    struct tr_realm *r;
+    const char *prev_realm = NULL;
+    for(r = realms; r; r = r->next){
+       if(r->trailing_dot){
+           char *tmp;
+           size_t len = strlen(r->realm) + strlen(prev_realm) + 1;
+
+           if(prev_realm == NULL)
+               prev_realm = client_realm;
+           tmp = realloc(r->realm, len);
+           if(tmp == NULL){
+               free_realms(realms);
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           r->realm = tmp;
+           strlcat(r->realm, prev_realm, len);
+       }else if(r->leading_slash && !r->leading_space && prev_realm){
+           /* yet another exception: if you use x500-names, the
+               leading realm doesn't have to be "quoted" with a space */
+           char *tmp;
+           size_t len = strlen(r->realm) + strlen(prev_realm) + 1;
+
+           tmp = malloc(len);
+           if(tmp == NULL){
+               free_realms(realms);
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           strlcpy(tmp, prev_realm, len);
+           strlcat(tmp, r->realm, len);
+           free(r->realm);
+           r->realm = tmp;
+       }
+       prev_realm = r->realm;
+    }
+    return 0;
+}
+
+static struct tr_realm *
+make_realm(char *realm)
+{
+    struct tr_realm *r;
+    char *p, *q;
+    int quote = 0;
+    r = calloc(1, sizeof(*r));
+    if(r == NULL){
+       free(realm);
+       return NULL;
+    }
+    r->realm = realm;
+    for(p = q = r->realm; *p; p++){
+       if(p == r->realm && *p == ' '){
+           r->leading_space = 1;
+           continue;
+       }
+       if(q == r->realm && *p == '/')
+           r->leading_slash = 1;
+       if(quote){
+           *q++ = *p;
+           quote = 0;
+           continue;
+       }
+       if(*p == '\\'){
+           quote = 1;
+           continue;
+       }
+       if(p[0] == '.' && p[1] == '\0')
+           r->trailing_dot = 1;
+       *q++ = *p;
+    }
+    *q = '\0';
+    return r;
+}
+
+static struct tr_realm*
+append_realm(struct tr_realm *head, struct tr_realm *r)
+{
+    struct tr_realm *p;
+    if(head == NULL){
+       r->next = NULL;
+       return r;
+    }
+    p = head;
+    while(p->next) p = p->next;
+    p->next = r;
+    return head;
+}
+
+static int
+decode_realms(krb5_context context,
+             const char *tr, int length, struct tr_realm **realms)
+{
+    struct tr_realm *r = NULL;
+
+    char *tmp;
+    int quote = 0;
+    const char *start = tr;
+    int i;
+
+    for(i = 0; i < length; i++){
+       if(quote){
+           quote = 0;
+           continue;
+       }
+       if(tr[i] == '\\'){
+           quote = 1;
+           continue;
+       }
+       if(tr[i] == ','){
+           tmp = malloc(tr + i - start + 1);
+           memcpy(tmp, start, tr + i - start);
+           tmp[tr + i - start] = '\0';
+           r = make_realm(tmp);
+           if(r == NULL){
+               free_realms(*realms);
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           *realms = append_realm(*realms, r);
+           start = tr + i + 1;
+       }
+    }
+    tmp = malloc(tr + i - start + 1);
+    memcpy(tmp, start, tr + i - start);
+    tmp[tr + i - start] = '\0';
+    r = make_realm(tmp);
+    if(r == NULL){
+       free_realms(*realms);
+       krb5_set_error_string (context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    *realms = append_realm(*realms, r);
+    
+    return 0;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_domain_x500_decode(krb5_context context,
+                       krb5_data tr, char ***realms, int *num_realms, 
+                       const char *client_realm, const char *server_realm)
+{
+    struct tr_realm *r = NULL;
+    struct tr_realm *p, **q;
+    int ret;
+    
+    if(tr.length == 0) {
+       *realms = NULL;
+       *num_realms = 0;
+       return 0;
+    }
+
+    /* split string in components */
+    ret = decode_realms(context, tr.data, tr.length, &r);
+    if(ret)
+       return ret;
+    
+    /* apply prefix rule */
+    ret = expand_realms(context, r, client_realm);
+    if(ret)
+       return ret;
+    
+    ret = make_paths(context, r, client_realm, server_realm);
+    if(ret)
+       return ret;
+    
+    /* remove empty components and count realms */
+    q = &r;
+    *num_realms = 0;
+    for(p = r; p; ){
+       if(p->realm[0] == '\0'){
+           free(p->realm);
+           *q = p->next;
+           free(p);
+           p = *q;
+       }else{
+           q = &p->next;
+           p = p->next;
+           (*num_realms)++;
+       }
+    }
+    if (*num_realms < 0 || *num_realms + 1 > UINT_MAX/sizeof(**realms))
+       return ERANGE;
+
+    {
+       char **R;
+       R = malloc((*num_realms + 1) * sizeof(*R));
+       if (R == NULL)
+           return ENOMEM;
+       *realms = R;
+       while(r){
+           *R++ = r->realm;
+           p = r->next;
+           free(r);
+           r = p;
+       }
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding)
+{
+    char *s = NULL;
+    int len = 0;
+    int i;
+    krb5_data_zero(encoding);
+    if (num_realms == 0)
+       return 0;
+    for(i = 0; i < num_realms; i++){
+       len += strlen(realms[i]);
+       if(realms[i][0] == '/')
+           len++;
+    }
+    len += num_realms - 1;
+    s = malloc(len + 1);
+    if (s == NULL)
+       return ENOMEM;
+    *s = '\0';
+    for(i = 0; i < num_realms; i++){
+       if(i && i < num_realms - 1)
+           strlcat(s, ",", len + 1);
+       if(realms[i][0] == '/')
+           strlcat(s, " ", len + 1);
+       strlcat(s, realms[i], len + 1);
+    }
+    encoding->data = s;
+    encoding->length = strlen(s);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_check_transited(krb5_context context,
+                    krb5_const_realm client_realm,
+                    krb5_const_realm server_realm,
+                    krb5_realm *realms,
+                    int num_realms,
+                    int *bad_realm)
+{
+    char **tr_realms;
+    char **p;
+    int i;
+
+    if(num_realms == 0)
+       return 0;
+    
+    tr_realms = krb5_config_get_strings(context, NULL, 
+                                       "capaths", 
+                                       client_realm, 
+                                       server_realm, 
+                                       NULL);
+    for(i = 0; i < num_realms; i++) {
+       for(p = tr_realms; p && *p; p++) {
+           if(strcmp(*p, realms[i]) == 0)
+               break;
+       }
+       if(p == NULL || *p == NULL) {
+           krb5_config_free_strings(tr_realms);
+           krb5_set_error_string (context, "no transit through realm %s",
+                                  realms[i]);
+           if(bad_realm)
+               *bad_realm = i;
+           return KRB5KRB_AP_ERR_ILL_CR_TKT;
+       }
+    }
+    krb5_config_free_strings(tr_realms);
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_check_transited_realms(krb5_context context,
+                           const char *const *realms, 
+                           int num_realms, 
+                           int *bad_realm)
+{
+    int i;
+    int ret = 0;
+    char **bad_realms = krb5_config_get_strings(context, NULL, 
+                                               "libdefaults", 
+                                               "transited_realms_reject", 
+                                               NULL);
+    if(bad_realms == NULL)
+       return 0;
+
+    for(i = 0; i < num_realms; i++) {
+       char **p;
+       for(p = bad_realms; *p; p++)
+           if(strcmp(*p, realms[i]) == 0) {
+               krb5_set_error_string (context, "no transit through realm %s",
+                                      *p);
+               ret = KRB5KRB_AP_ERR_ILL_CR_TKT;
+               if(bad_realm)
+                   *bad_realm = i;
+               break;
+           }
+    }
+    krb5_config_free_strings(bad_realms);
+    return ret;
+}
+
+#if 0
+int
+main(int argc, char **argv)
+{
+    krb5_data x;
+    char **r;
+    int num, i;
+    x.data = argv[1];
+    x.length = strlen(x.data);
+    if(domain_expand(x, &r, &num, argv[2], argv[3]))
+       exit(1);
+    for(i = 0; i < num; i++)
+       printf("%s\n", r[i]);
+    return 0;
+}
+#endif
+
diff --git a/src/kerberosV/src/lib/krb5/v4_glue.c b/src/kerberosV/src/lib/krb5/v4_glue.c
new file mode 100644 (file)
index 0000000..d875751
--- /dev/null
@@ -0,0 +1,922 @@
+/*
+ * Copyright (c) 1997 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+RCSID("$KTH: v4_glue.c,v 1.2 2005/04/24 13:44:02 lha Exp $");
+
+#include "krb5-v4compat.h"
+
+/*
+ *
+ */
+
+#define RCHECK(r,func,label) \
+       do { (r) = func ; if (r) goto label; } while(0);
+
+
+/* include this here, to avoid dependencies on libkrb */
+
+static const int _tkt_lifetimes[TKTLIFENUMFIXED] = {
+   38400,   41055,   43894,   46929,   50174,   53643,   57352,   61318,
+   65558,   70091,   74937,   80119,   85658,   91581,   97914,  104684,
+  111922,  119661,  127935,  136781,  146239,  156350,  167161,  178720,
+  191077,  204289,  218415,  233517,  249664,  266926,  285383,  305116,
+  326213,  348769,  372885,  398668,  426234,  455705,  487215,  520904,
+  556921,  595430,  636601,  680618,  727680,  777995,  831789,  889303,
+  950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247,
+ 1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000
+};
+
+int KRB5_LIB_FUNCTION
+_krb5_krb_time_to_life(time_t start, time_t end)
+{
+    int i;
+    time_t life = end - start;
+
+    if (life > MAXTKTLIFETIME || life <= 0) 
+       return 0;
+#if 0    
+    if (krb_no_long_lifetimes) 
+       return (life + 5*60 - 1)/(5*60);
+#endif
+    
+    if (end >= NEVERDATE)
+       return TKTLIFENOEXPIRE;
+    if (life < _tkt_lifetimes[0]) 
+       return (life + 5*60 - 1)/(5*60);
+    for (i=0; i<TKTLIFENUMFIXED; i++)
+       if (life <= _tkt_lifetimes[i])
+           return i + TKTLIFEMINFIXED;
+    return 0;
+    
+}
+
+time_t KRB5_LIB_FUNCTION
+_krb5_krb_life_to_time(int start, int life_)
+{
+    unsigned char life = (unsigned char) life_;
+
+#if 0    
+    if (krb_no_long_lifetimes)
+       return start + life*5*60;
+#endif
+
+    if (life == TKTLIFENOEXPIRE)
+       return NEVERDATE;
+    if (life < TKTLIFEMINFIXED)
+       return start + life*5*60;
+    if (life > TKTLIFEMAXFIXED)
+       return start + MAXTKTLIFETIME;
+    return start + _tkt_lifetimes[life - TKTLIFEMINFIXED];
+}
+
+/*
+ * Get the name of the krb4 credentials cache, will use `tkfile' as
+ * the name if that is passed in. `cc' must be free()ed by caller,
+ */
+
+static krb5_error_code
+get_krb4_cc_name(const char *tkfile, char **cc)
+{
+
+    *cc = NULL;
+    if(tkfile == NULL) {
+       char *path;
+       if(!issuid()) {
+           path = getenv("KRBTKFILE");
+           if (path)
+               *cc = strdup(path);
+       }
+       if(*cc == NULL)
+           if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0)
+               return errno;
+    } else {
+       *cc = strdup(tkfile);
+       if (*cc == NULL)
+           return ENOMEM;
+    }
+    return 0;
+}
+
+/*
+ * Write a Kerberos 4 ticket file
+ */
+
+#define KRB5_TF_LCK_RETRY_COUNT 50
+#define KRB5_TF_LCK_RETRY 1
+
+static krb5_error_code
+write_v4_cc(krb5_context context, const char *tkfile, 
+           krb5_storage *sp, int append)
+{
+    krb5_error_code ret;
+    struct stat sb;
+    krb5_data data;
+    char *path;
+    int fd, i;
+
+    ret = get_krb4_cc_name(tkfile, &path);
+    if (ret) {
+       krb5_set_error_string(context, 
+                             "krb5_krb_tf_setup: failed getting "
+                             "the krb4 credentials cache name"); 
+       return ret;
+    }
+
+    fd = open(path, O_WRONLY|O_CREAT, 0600);
+    if (fd < 0) {
+       free(path);
+       krb5_set_error_string(context, 
+                             "krb5_krb_tf_setup: error opening file %s", 
+                             path);
+       return errno;
+    }
+
+    if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) {
+       free(path);
+       close(fd);
+       krb5_set_error_string(context, 
+                             "krb5_krb_tf_setup: tktfile %s is not a file",
+                             path);
+       return KRB5_FCC_PERM;
+    }
+
+    for (i = 0; i < KRB5_TF_LCK_RETRY_COUNT; i++) {
+       if (flock(fd, LOCK_EX | LOCK_NB) < 0) {
+           sleep(KRB5_TF_LCK_RETRY);
+       } else
+           break;
+    }
+    if (i == KRB5_TF_LCK_RETRY_COUNT) {
+       free(path);
+       close(fd);
+       krb5_set_error_string(context,
+                             "krb5_krb_tf_setup: failed to lock %s",
+                             path);
+       return KRB5_FCC_PERM;
+    }
+
+    if (!append) {
+       ret = ftruncate(fd, 0);
+       if (ret < 0) {
+           flock(fd, LOCK_UN);
+           free(path);
+           close(fd);
+           krb5_set_error_string(context,
+                                 "krb5_krb_tf_setup: failed to truncate %s",
+                                 path);
+           return KRB5_FCC_PERM;
+       }
+    }
+    ret = lseek(fd, 0L, SEEK_END);
+    if (ret < 0) {
+       ret = errno;
+       flock(fd, LOCK_UN);
+       free(path);
+       close(fd);
+       return ret;
+    }
+
+    krb5_storage_to_data(sp, &data);
+
+    ret = write(fd, data.data, data.length);
+    if (ret != data.length)
+       ret = KRB5_CC_IO;
+
+    krb5_free_data_contents(context, &data);
+
+    flock(fd, LOCK_UN);
+    free(path);
+    close(fd);
+
+    return 0;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_tf_setup(krb5_context context, 
+                  struct credentials *v4creds, 
+                  const char *tkfile,
+                  int append)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+
+    sp = krb5_storage_emem();
+    if (sp == NULL)
+       return ENOMEM;
+
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST);
+    krb5_storage_set_eof_code(sp, KRB5_CC_IO);
+
+    krb5_clear_error_string(context);
+
+    if (!append) {
+       RCHECK(ret, krb5_store_stringz(sp, v4creds->pname), error);
+       RCHECK(ret, krb5_store_stringz(sp, v4creds->pinst), error);
+    }
+
+    /* cred */
+    RCHECK(ret, krb5_store_stringz(sp, v4creds->service), error);
+    RCHECK(ret, krb5_store_stringz(sp, v4creds->instance), error);
+    RCHECK(ret, krb5_store_stringz(sp, v4creds->realm), error);
+    ret = krb5_storage_write(sp, v4creds->session, 8);
+    if (ret != 8) {
+       ret = KRB5_CC_IO;
+       goto error;
+    }
+    RCHECK(ret, krb5_store_int32(sp, v4creds->lifetime), error);
+    RCHECK(ret, krb5_store_int32(sp, v4creds->kvno), error);
+    RCHECK(ret, krb5_store_int32(sp, v4creds->ticket_st.length), error);
+
+    ret = krb5_storage_write(sp, v4creds->ticket_st.dat, 
+                            v4creds->ticket_st.length);
+    if (ret != v4creds->ticket_st.length) {
+       ret = KRB5_CC_IO;
+       goto error;
+    }
+    RCHECK(ret, krb5_store_int32(sp, v4creds->issue_date), error);
+
+    ret = write_v4_cc(context, tkfile, sp, append);
+
+ error:
+    krb5_storage_free(sp);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_dest_tkt(krb5_context context, const char *tkfile)
+{
+    krb5_error_code ret;
+    char *path;
+
+    ret = get_krb4_cc_name(tkfile, &path);
+    if (ret) {
+       krb5_set_error_string(context, 
+                             "krb5_krb_tf_setup: failed getting "
+                             "the krb4 credentials cache name"); 
+       return ret;
+    }
+
+    if (unlink(path) < 0) {
+       ret = errno;
+       krb5_set_error_string(context, 
+                             "krb5_krb_dest_tkt failed removing the cache "
+                             "with error %s", strerror(ret));
+    }
+    free(path);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+decrypt_etext(krb5_context context, const krb5_keyblock *key,
+             const krb5_data *cdata, krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+
+    ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto);
+    if (ret)
+       return ret;
+
+    ret = krb5_decrypt(context, crypto, 0, cdata->data, cdata->length, data);
+    krb5_crypto_destroy(context, crypto);
+
+    return ret;
+}
+
+
+/*
+ *
+ */
+
+static const char eightzeros[8] = "\x00\x00\x00\x00\x00\x00\x00\x00";
+
+static krb5_error_code
+storage_to_etext(krb5_context context,
+                krb5_storage *sp,
+                const krb5_keyblock *key, 
+                krb5_data *enc_data)
+{
+    krb5_error_code ret;
+    krb5_crypto crypto;
+    krb5_ssize_t size;
+    krb5_data data;
+
+    /* multiple of eight bytes */
+
+    size = krb5_storage_seek(sp, 0, SEEK_END);
+    if (size < 0)
+       return EINVAL;
+    size = 8 - (size & 7);
+
+    ret = krb5_storage_write(sp, eightzeros, size);
+    if (ret != size)
+       return EINVAL;
+
+    ret = krb5_storage_to_data(sp, &data);
+    if (ret)
+       return ret;
+
+    ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto);
+    if (ret) {
+       krb5_data_free(&data);
+       return ret;
+    }
+
+    ret = krb5_encrypt(context, crypto, 0, data.data, data.length, enc_data);
+
+    krb5_data_free(&data);
+    krb5_crypto_destroy(context, crypto);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+static krb5_error_code
+put_nir(krb5_storage *sp, const char *name,
+       const char *instance, const char *realm)
+{
+    krb5_error_code ret;
+
+    RCHECK(ret, krb5_store_stringz(sp, name), error);
+    RCHECK(ret, krb5_store_stringz(sp, instance), error);
+    if (realm) {
+       RCHECK(ret, krb5_store_stringz(sp, realm), error);
+    }
+ error:
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_create_ticket(krb5_context context,
+                       unsigned char flags,
+                       const char *pname,
+                       const char *pinstance,
+                       const char *prealm,
+                       int32_t paddress,
+                       const krb5_keyblock *session,
+                       int16_t life,
+                       int32_t life_sec,
+                       const char *sname,
+                       const char *sinstance,
+                       const krb5_keyblock *key,
+                       krb5_data *enc_data)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+
+    krb5_data_zero(enc_data);
+
+    sp = krb5_storage_emem();
+    if (sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+
+    RCHECK(ret, krb5_store_int8(sp, flags), error);
+    RCHECK(ret, put_nir(sp, pname, pinstance, prealm), error);
+    RCHECK(ret, krb5_store_int32(sp, ntohl(paddress)), error);
+
+    /* session key */
+    ret = krb5_storage_write(sp,
+                            session->keyvalue.data, 
+                            session->keyvalue.length);
+    if (ret != session->keyvalue.length) {
+       ret = EINVAL;
+       goto error;
+    }
+
+    RCHECK(ret, krb5_store_int8(sp, life), error);
+    RCHECK(ret, krb5_store_int32(sp, life_sec), error);
+    RCHECK(ret, put_nir(sp, sname, sinstance, NULL), error);
+
+    ret = storage_to_etext(context, sp, key, enc_data);
+
+ error:
+    krb5_storage_free(sp);
+    if (ret)
+       krb5_set_error_string(context, "Failed to encode kerberos 4 ticket");
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_create_ciph(krb5_context context,
+                     const krb5_keyblock *session,
+                     const char *service,
+                     const char *instance,
+                     const char *realm,
+                     u_int32_t life,
+                     unsigned char kvno,
+                     const krb5_data *ticket,
+                     u_int32_t kdc_time,
+                     const krb5_keyblock *key,
+                     krb5_data *enc_data)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+
+    krb5_data_zero(enc_data);
+
+    sp = krb5_storage_emem();
+    if (sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+
+    /* session key */
+    ret = krb5_storage_write(sp,
+                            session->keyvalue.data, 
+                            session->keyvalue.length);
+    if (ret != session->keyvalue.length) {
+       ret = EINVAL;
+       goto error;
+    }
+
+    RCHECK(ret, put_nir(sp, service, instance, realm), error);
+    RCHECK(ret, krb5_store_int8(sp, life), error);
+    RCHECK(ret, krb5_store_int8(sp, kvno), error);
+    RCHECK(ret, krb5_store_int8(sp, ticket->length), error);
+    ret = krb5_storage_write(sp, ticket->data, ticket->length);
+    if (ret != ticket->length) {
+       ret = EINVAL;
+       goto error;
+    }
+    RCHECK(ret, krb5_store_int32(sp, kdc_time), error);
+
+    ret = storage_to_etext(context, sp, key, enc_data);
+
+ error:
+    krb5_storage_free(sp);
+    if (ret)
+       krb5_set_error_string(context, "Failed to encode kerberos 4 ticket");
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_create_auth_reply(krb5_context context,
+                           const char *pname,
+                           const char *pinst,
+                           const char *prealm,
+                           int32_t time_ws,
+                           int n,
+                           u_int32_t x_date,
+                           unsigned char kvno,
+                           const krb5_data *cipher,
+                           krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+
+    krb5_data_zero(data);
+
+    sp = krb5_storage_emem();
+    if (sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+
+    RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error);
+    RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_KDC_REPLY), error);
+    RCHECK(ret, put_nir(sp, pname, pinst, prealm), error);
+    RCHECK(ret, krb5_store_int32(sp, time_ws), error);
+    RCHECK(ret, krb5_store_int8(sp, n), error);
+    RCHECK(ret, krb5_store_int32(sp, x_date), error);
+    RCHECK(ret, krb5_store_int8(sp, kvno), error);
+    RCHECK(ret, krb5_store_int16(sp, cipher->length), error);
+    ret = krb5_storage_write(sp, cipher->data, cipher->length);
+    if (ret != cipher->length) {
+       ret = EINVAL;
+       goto error;
+    }
+
+    ret = krb5_storage_to_data(sp, data);
+
+ error:
+    krb5_storage_free(sp);
+    if (ret)
+       krb5_set_error_string(context, "Failed to encode kerberos 4 ticket");
+       
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_cr_err_reply(krb5_context context,
+                      const char *name,
+                      const char *inst,
+                      const char *realm,
+                      u_int32_t time_ws,
+                      u_int32_t e,
+                      const char *e_string,
+                      krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+
+    krb5_data_zero(data);
+
+    if (name == NULL) name = "";
+    if (inst == NULL) inst = "";
+    if (realm == NULL) realm = "";
+    if (e_string == NULL) e_string = "";
+
+    sp = krb5_storage_emem();
+    if (sp == NULL) {
+       krb5_set_error_string(context, "malloc: out of memory");
+       return ENOMEM;
+    }
+    krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+
+    RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error);
+    RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error);
+    RCHECK(ret, put_nir(sp, name, inst, realm), error);
+    RCHECK(ret, krb5_store_int32(sp, time_ws), error);
+    RCHECK(ret, krb5_store_int32(sp, e), error);
+    RCHECK(ret, krb5_store_stringz(sp, e_string), error);
+
+    ret = krb5_storage_to_data(sp, data);
+
+ error:
+    krb5_storage_free(sp);
+    if (ret)
+       krb5_set_error_string(context, "Failed to encode kerberos 4 error");
+       
+    return 0;
+}
+
+static krb5_error_code
+get_v4_stringz(krb5_storage *sp, char **str, size_t max_len)
+{
+    krb5_error_code ret;
+
+    ret = krb5_ret_stringz(sp, str);
+    if (ret)
+       return ret;
+    if (strlen(*str) > max_len) {
+       free(*str);
+       *str = NULL;
+       return EINVAL;
+    }
+    return 0;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_decomp_ticket(krb5_context context,
+                       const krb5_data *enc_ticket,
+                       const krb5_keyblock *key,
+                       const char *local_realm,
+                       char **sname,
+                       char **sinstance,
+                       struct _krb5_krb_auth_data *ad)
+{
+    krb5_error_code ret;
+    krb5_ssize_t size;
+    krb5_storage *sp = NULL;
+    krb5_data ticket;
+    unsigned char des_key[8];
+
+    memset(ad, 0, sizeof(*ad));
+    krb5_data_zero(&ticket);
+
+    *sname = NULL;
+    *sinstance = NULL;
+
+    RCHECK(ret, decrypt_etext(context, key, enc_ticket, &ticket), error);
+
+    sp = krb5_storage_from_data(&ticket);
+    if (sp == NULL) {
+       krb5_data_free(&ticket);
+       krb5_set_error_string(context, "alloc: out of memory");
+       return ENOMEM;
+    }
+
+    krb5_storage_set_eof_code(sp, EINVAL); /* XXX */
+
+    RCHECK(ret, krb5_ret_int8(sp, &ad->k_flags), error);
+    RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error);
+    RCHECK(ret, get_v4_stringz(sp, &ad->pinst, INST_SZ), error);
+    RCHECK(ret, get_v4_stringz(sp, &ad->prealm, REALM_SZ), error);
+    RCHECK(ret, krb5_ret_int32(sp, &ad->address), error);
+       
+    size = krb5_storage_read(sp, des_key, sizeof(des_key));
+    if (size != sizeof(des_key)) {
+       ret = EINVAL; /* XXX */
+       goto error;
+    }
+
+    RCHECK(ret, krb5_ret_int8(sp, &ad->life), error);
+
+    if (ad->k_flags & 1)
+       krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
+    else
+       krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+
+    RCHECK(ret, krb5_ret_int32(sp, &ad->time_sec), error);
+
+    RCHECK(ret, get_v4_stringz(sp, sname, ANAME_SZ), error);
+    RCHECK(ret, get_v4_stringz(sp, sinstance, INST_SZ), error);
+
+    ret = krb5_keyblock_init(context, ETYPE_DES_PCBC_NONE,
+                            des_key, sizeof(des_key), &ad->session);
+    if (ret)
+       goto error;
+
+    if (strlen(ad->prealm) == 0) {
+       free(ad->prealm);
+       ad->prealm = strdup(local_realm);
+       if (ad->prealm == NULL) {
+           ret = ENOMEM;
+           goto error;
+       }
+    }
+
+ error:
+    memset(des_key, 0, sizeof(des_key));
+    if (sp)
+       krb5_storage_free(sp);
+    krb5_data_free(&ticket);
+    if (ret) {
+       if (*sname) {
+           free(*sname);
+           *sname = NULL;
+       }
+       if (*sinstance) {
+           free(*sinstance);
+           *sinstance = NULL;
+       }
+       _krb5_krb_free_auth_data(context, ad);
+       krb5_set_error_string(context, "Failed to decode v4 ticket");
+    }
+    return ret;
+}
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_krb_rd_req(krb5_context context,
+                krb5_data *authent,
+                const char *service,
+                const char *instance,
+                const char *local_realm,
+                int32_t from_addr,
+                const krb5_keyblock *key,
+                struct _krb5_krb_auth_data *ad)
+{
+    krb5_error_code ret;
+    krb5_storage *sp;
+    krb5_data ticket, eaut, aut;
+    krb5_ssize_t size;
+    int little_endian;
+    int8_t pvno;
+    int8_t type;
+    int8_t s_kvno;
+    u_int8_t ticket_length;
+    u_int8_t eaut_length;
+    u_int8_t time_5ms;
+    char *realm = NULL;
+    char *sname = NULL;
+    char *sinstance = NULL;
+    char *r_realm = NULL;
+    char *r_name = NULL;
+    char *r_instance = NULL;
+
+    u_int32_t r_time_sec;      /* Coarse time from authenticator */
+    unsigned long delta_t;      /* Time in authenticator - local time */
+    long tkt_age;              /* Age of ticket */
+
+    struct timeval tv;
+
+    krb5_data_zero(&ticket);
+    krb5_data_zero(&eaut);
+    krb5_data_zero(&aut);
+
+    sp = krb5_storage_from_data(authent);
+    if (sp == NULL) {
+       krb5_set_error_string(context, "alloc: out of memory");
+       return ENOMEM;
+    }
+
+    krb5_storage_set_eof_code(sp, EINVAL); /* XXX */
+
+    ret = krb5_ret_int8(sp, &pvno);
+    if (ret)
+       goto error;
+
+    if (pvno != KRB_PROT_VERSION) {
+       ret = EINVAL; /* XXX */
+       goto error;
+    }
+
+    ret = krb5_ret_int8(sp, &type);
+    if (ret)
+       goto error;
+
+    little_endian = type & 1;
+    type &= ~1;
+    
+    if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) {
+       ret = EINVAL; /* RD_AP_MSG_TYPE */
+       goto error;
+    }
+
+    RCHECK(ret, krb5_ret_int8(sp, &s_kvno), error);
+    RCHECK(ret, get_v4_stringz(sp, &realm, REALM_SZ), error);
+    RCHECK(ret, krb5_ret_int8(sp, &ticket_length), error);
+    RCHECK(ret, krb5_ret_int8(sp, &eaut_length), error);
+    RCHECK(ret, krb5_data_alloc(&ticket, ticket_length), error);
+
+    size = krb5_storage_read(sp, ticket.data, ticket.length);
+    if (size != ticket.length) {
+       ret = EINVAL;
+       goto error;
+    }
+
+    /* Decrypt and take apart ticket */
+    ret = _krb5_krb_decomp_ticket(context, &ticket, key, local_realm, 
+                                 &sname, &sinstance, ad);
+    if (ret)
+       goto error;
+
+    RCHECK(ret, krb5_data_alloc(&eaut, eaut_length), error);
+
+    size = krb5_storage_read(sp, eaut.data, eaut.length);
+    if (size != eaut.length) {
+       ret = EINVAL;
+       goto error;
+    }
+
+    krb5_storage_free(sp);
+    sp = NULL;
+
+    ret = decrypt_etext(context, &ad->session, &eaut, &aut);
+    if (ret)
+       goto error;
+
+    sp = krb5_storage_from_data(&aut);
+    if (sp == NULL) {
+       krb5_set_error_string(context, "alloc: out of memory");
+       ret = ENOMEM;
+       goto error;
+    }
+
+    if (little_endian)
+       krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
+    else
+       krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE);
+
+    RCHECK(ret, get_v4_stringz(sp, &r_name, ANAME_SZ), error);
+    RCHECK(ret, get_v4_stringz(sp, &r_instance, INST_SZ), error);
+    RCHECK(ret, get_v4_stringz(sp, &r_realm, REALM_SZ), error);
+
+    RCHECK(ret, krb5_ret_int32(sp, &ad->checksum), error);
+    RCHECK(ret, krb5_ret_int8(sp, &time_5ms), error);
+    RCHECK(ret, krb5_ret_int32(sp, &r_time_sec), error);
+
+    if (strcmp(ad->pname, r_name) != 0 ||
+       strcmp(ad->pinst, r_instance) != 0 ||
+       strcmp(ad->prealm, r_realm) != 0) {
+       ret = EINVAL; /* RD_AP_INCON */
+       goto error;
+    }
+    
+    if (from_addr && from_addr == ad->address) {
+       ret = EINVAL; /* RD_AP_BADD */
+       goto error;
+    }
+
+    gettimeofday(&tv, NULL);
+    delta_t = abs((int)(tv.tv_sec - r_time_sec));
+    if (delta_t > CLOCK_SKEW) {
+        ret = EINVAL; /* RD_AP_TIME */
+       goto error;
+    }
+
+    /* Now check for expiration of ticket */
+
+    tkt_age = tv.tv_sec - ad->time_sec;
+    
+    if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) {
+        ret = EINVAL; /* RD_AP_NYV */
+       goto error;
+    }
+
+    if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) {
+       ret = EINVAL; /* RD_AP_EXP */
+       goto error;
+    }
+
+    ret = 0;
+ error:
+    krb5_data_free(&ticket);
+    krb5_data_free(&eaut);
+    krb5_data_free(&aut);
+    if (realm)
+       free(realm);
+    if (sname)
+       free(sname);
+    if (sinstance)
+       free(sinstance);
+    if (r_name)
+       free(r_name);
+    if (r_instance)
+       free(r_instance);
+    if (r_realm)
+       free(r_realm);
+    if (sp)
+       krb5_storage_free(sp);
+
+    if (ret)
+       krb5_clear_error_string(context);
+
+    return ret;
+}
+
+/*
+ *
+ */
+
+void KRB5_LIB_FUNCTION
+_krb5_krb_free_auth_data(krb5_context context, struct _krb5_krb_auth_data *ad)
+{
+    if (ad->pname)
+       free(ad->pname);
+    if (ad->pinst)
+       free(ad->pinst);
+    if (ad->prealm)
+       free(ad->prealm);
+    krb5_free_keyblock_contents(context, &ad->session);
+    memset(ad, 0, sizeof(*ad));
+}
diff --git a/src/kerberosV/src/lib/krb5/verify_init.c b/src/kerberosV/src/lib/krb5/verify_init.c
new file mode 100644 (file)
index 0000000..5d76998
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: verify_init.c,v 1.18 2004/05/25 21:45:47 lha Exp $");
+
+void KRB5_LIB_FUNCTION
+krb5_verify_init_creds_opt_init(krb5_verify_init_creds_opt *options)
+{
+    memset (options, 0, sizeof(*options));
+}
+
+void KRB5_LIB_FUNCTION
+krb5_verify_init_creds_opt_set_ap_req_nofail(krb5_verify_init_creds_opt *options,
+                                            int ap_req_nofail)
+{
+    options->flags |= KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL;
+    options->ap_req_nofail = ap_req_nofail;
+}
+
+/*
+ *
+ */
+
+static krb5_boolean
+fail_verify_is_ok (krb5_context context,
+                  krb5_verify_init_creds_opt *options)
+{
+    if ((options->flags & KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL
+        && options->ap_req_nofail != 0)
+       || krb5_config_get_bool (context,
+                                NULL,
+                                "libdefaults",
+                                "verify_ap_req_nofail",
+                                NULL))
+       return FALSE;
+    else
+       return TRUE;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+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 *options)
+{
+    krb5_error_code ret;
+    krb5_data req;
+    krb5_ccache local_ccache = NULL;
+    krb5_keytab_entry entry;
+    krb5_creds *new_creds = NULL;
+    krb5_auth_context auth_context = NULL;
+    krb5_principal server = NULL;
+    krb5_keytab keytab = NULL;
+
+    krb5_data_zero (&req);
+    memset (&entry, 0, sizeof(entry));
+
+    if (ap_req_server == NULL) {
+       char local_hostname[MAXHOSTNAMELEN];
+
+       if (gethostname (local_hostname, sizeof(local_hostname)) < 0) {
+           ret = errno;
+           krb5_set_error_string (context, "gethostname: %s",
+                                  strerror(ret));
+           return ret;
+       }
+
+       ret = krb5_sname_to_principal (context,
+                                      local_hostname,
+                                      "host",
+                                      KRB5_NT_SRV_HST,
+                                      &server);
+       if (ret)
+           goto cleanup;
+    } else
+       server = ap_req_server;
+
+    if (ap_req_keytab == NULL) {
+       ret = krb5_kt_default (context, &keytab);
+       if (ret)
+           goto cleanup;
+    } else
+       keytab = ap_req_keytab;
+
+    if (ccache && *ccache)
+       local_ccache = *ccache;
+    else {
+       ret = krb5_cc_gen_new (context, &krb5_mcc_ops, &local_ccache);
+       if (ret)
+           goto cleanup;
+       ret = krb5_cc_initialize (context,
+                                 local_ccache,
+                                 creds->client);
+       if (ret)
+           goto cleanup;
+       ret = krb5_cc_store_cred (context,
+                                 local_ccache,
+                                 creds);
+       if (ret)
+           goto cleanup;
+    }
+
+    if (!krb5_principal_compare (context, server, creds->server)) {
+       krb5_creds match_cred;
+
+       memset (&match_cred, 0, sizeof(match_cred));
+
+       match_cred.client = creds->client;
+       match_cred.server = server;
+
+       ret = krb5_get_credentials (context,
+                                   0,
+                                   local_ccache,
+                                   &match_cred,
+                                   &new_creds);
+       if (ret) {
+           if (fail_verify_is_ok (context, options))
+               ret = 0;
+           goto cleanup;
+       }
+       creds = new_creds;
+    }
+
+    ret = krb5_mk_req_extended (context,
+                               &auth_context,
+                               0,
+                               NULL,
+                               creds,
+                               &req);
+    
+    krb5_auth_con_free (context, auth_context);
+    auth_context = NULL;
+
+    if (ret)
+       goto cleanup;
+
+    ret = krb5_rd_req (context,
+                      &auth_context,
+                      &req,
+                      server,
+                      keytab,
+                      0,
+                      NULL);
+
+    if (ret == KRB5_KT_NOTFOUND && fail_verify_is_ok (context, options))
+       ret = 0;
+cleanup:
+    if (auth_context)
+       krb5_auth_con_free (context, auth_context);
+    krb5_data_free (&req);
+    krb5_kt_free_entry (context, &entry);
+    if (new_creds != NULL)
+       krb5_free_creds (context, new_creds);
+    if (ap_req_server == NULL && server)
+       krb5_free_principal (context, server);
+    if (ap_req_keytab == NULL && keytab)
+       krb5_kt_close (context, keytab);
+    if (local_ccache != NULL
+       &&
+       (ccache == NULL
+        || (ret != 0 && *ccache == NULL)))
+       krb5_cc_destroy (context, local_ccache);
+
+    if (ret == 0 && ccache != NULL && *ccache == NULL)
+       *ccache = local_ccache;
+
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/krb5/verify_krb5_conf.8 b/src/kerberosV/src/lib/krb5/verify_krb5_conf.8
new file mode 100644 (file)
index 0000000..3a75814
--- /dev/null
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2000 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $KTH: verify_krb5_conf.8,v 1.11 2004/12/08 17:52:41 lha Exp $
+.\"
+.Dd December  8, 2004
+.Dt VERIFY_KRB5_CONF 8
+.Os HEIMDAL
+.Sh NAME
+.Nm verify_krb5_conf
+.Nd checks krb5.conf for obvious errors
+.Sh SYNOPSIS
+.Nm
+.Ar [config-file]
+.Sh DESCRIPTION
+.Nm
+reads the configuration file
+.Pa krb5.conf ,
+or the file given on the command line,
+and parses it, thereby verifying that the syntax is correct.
+.Pp
+If the file is syntactically correct,
+.Nm
+tries to verify that the contents of the file is of relevant nature.
+.Sh ENVIRONMENT
+.Ev KRB5_CONFIG
+points to the configuration file to read.
+.Sh FILES
+.Bl -tag -width /etc/kerberosV/krb5.conf -compact
+.It Pa /etc/kerberosV/krb5.conf
+Kerberos 5 configuration file
+.El
+.Sh DIAGNOSTICS
+Possible output from
+.Nm
+include:
+.Bl -tag -width "FpathF"
+.It "<path>: failed to parse <something> as size/time/number/boolean"
+Usually means that <something> is misspelled, or that it contains
+weird characters. The parsing done by
+.Nm
+is more strict than the one performed by libkrb5, so strings that
+work in real life might be reported as bad.
+.It "<path>: host not found (<hostname>)"
+Means that <path> is supposed to point to a host, but it can't be
+recognised as one.
+.It <path>: unknown or wrong type
+Means that <path> is either a string when it should be a list, vice
+versa, or just that
+.Nm
+is confused.
+.It <path>: unknown entry
+Means that <string> is unknown to
+.Nm Ns .
+.El
+.Sh SEE ALSO
+.Xr krb5.conf 5
+.Sh BUGS
+Since each application can put almost anything in the config file,
+it's hard to come up with a watertight verification process. Most of
+the default settings are sanity checked, but this does not mean that
+every problem is discovered, or that everything that is reported as a
+possible problem actually is one. This tool should thus be used with
+some care.
+.Pp
+It should warn about obsolete data, or bad practice, but currently
+doesn't.
diff --git a/src/kerberosV/src/lib/krb5/verify_krb5_conf.c b/src/kerberosV/src/lib/krb5/verify_krb5_conf.c
new file mode 100644 (file)
index 0000000..20a6e51
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * Copyright (c) 1999 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <getarg.h>
+#include <parse_bytes.h>
+#include <err.h>
+RCSID("$KTH: verify_krb5_conf.c,v 1.33 2005/06/14 00:06:17 lha Exp $");
+
+/* verify krb5.conf */
+
+static int dumpconfig_flag = 0;
+static int version_flag = 0;
+static int help_flag   = 0;
+static int warn_mit_syntax_flag = 0;
+
+static struct getargs args[] = {
+    {"dumpconfig", 0,      arg_flag,       &dumpconfig_flag, 
+     "show the parsed config files", NULL },
+    {"warn-mit-syntax", 0, arg_flag,       &warn_mit_syntax_flag, 
+     "show the parsed config files", NULL },
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "[config-file]");
+    exit (ret);
+}
+
+static int
+check_bytes(krb5_context context, const char *path, char *data)
+{
+    if(parse_bytes(data, NULL) == -1) {
+       krb5_warnx(context, "%s: failed to parse \"%s\" as size", path, data);
+       return 1;
+    }
+    return 0;
+}
+
+static int
+check_time(krb5_context context, const char *path, char *data)
+{
+    if(parse_time(data, NULL) == -1) {
+       krb5_warnx(context, "%s: failed to parse \"%s\" as time", path, data);
+       return 1;
+    }
+    return 0;
+}
+
+static int
+check_numeric(krb5_context context, const char *path, char *data)
+{
+    long int v;
+    char *end;
+    v = strtol(data, &end, 0);
+    if(*end != '\0') {
+       krb5_warnx(context, "%s: failed to parse \"%s\" as a number", 
+                  path, data);
+       return 1;
+    }
+    return 0;
+}
+
+static int
+check_boolean(krb5_context context, const char *path, char *data)
+{
+    long int v;
+    char *end;
+    if(strcasecmp(data, "yes") == 0 ||
+       strcasecmp(data, "true") == 0 ||
+       strcasecmp(data, "no") == 0 ||
+       strcasecmp(data, "false") == 0)
+       return 0;
+    v = strtol(data, &end, 0);
+    if(*end != '\0') {
+       krb5_warnx(context, "%s: failed to parse \"%s\" as a boolean", 
+                  path, data);
+       return 1;
+    }
+    if(v != 0 && v != 1)
+       krb5_warnx(context, "%s: numeric value \"%s\" is treated as \"true\"", 
+                  path, data);
+    return 0;
+}
+
+static int
+check_524(krb5_context context, const char *path, char *data)
+{
+    if(strcasecmp(data, "yes") == 0 ||
+       strcasecmp(data, "no") == 0 ||
+       strcasecmp(data, "2b") == 0 ||
+       strcasecmp(data, "local") == 0)
+       return 0;
+
+    krb5_warnx(context, "%s: didn't contain a valid option `%s'", 
+              path, data);
+    return 1;
+}
+
+static int
+check_host(krb5_context context, const char *path, char *data)
+{
+    int ret;
+    char hostname[128];
+    const char *p = data;
+    struct addrinfo hints;
+    char service[32];
+    int defport;
+    struct addrinfo *ai;
+
+    hints.ai_flags = 0;
+    hints.ai_family = PF_UNSPEC;
+    hints.ai_socktype = 0;
+    hints.ai_protocol = 0;
+
+    hints.ai_addrlen = 0;
+    hints.ai_canonname = NULL;
+    hints.ai_addr = NULL;
+    hints.ai_next = NULL;
+    
+    /* XXX data could be a list of hosts that this code can't handle */
+    /* XXX copied from krbhst.c */
+    if(strncmp(p, "http://", 7) == 0){
+        p += 7;
+       hints.ai_socktype = SOCK_STREAM;
+       strlcpy(service, "http", sizeof(service));
+       defport = 80;
+    } else if(strncmp(p, "http/", 5) == 0) {
+        p += 5;
+       hints.ai_socktype = SOCK_STREAM;
+       strlcpy(service, "http", sizeof(service));
+       defport = 80;
+    }else if(strncmp(p, "tcp/", 4) == 0){
+        p += 4;
+       hints.ai_socktype = SOCK_STREAM;
+       strlcpy(service, "kerberos", sizeof(service));
+       defport = 88;
+    } else if(strncmp(p, "udp/", 4) == 0) {
+        p += 4;
+       hints.ai_socktype = SOCK_DGRAM;
+       strlcpy(service, "kerberos", sizeof(service));
+       defport = 88;
+    } else {
+       hints.ai_socktype = SOCK_DGRAM;
+       strlcpy(service, "kerberos", sizeof(service));
+       defport = 88;
+    }
+    if(strsep_copy(&p, ":", hostname, sizeof(hostname)) < 0) {
+       return 1;
+    }
+    hostname[strcspn(hostname, "/")] = '\0';
+    if(p != NULL) {
+       char *end;
+       int tmp = strtol(p, &end, 0);
+       if(end == p) {
+           krb5_warnx(context, "%s: failed to parse port number in %s", 
+                      path, data);
+           return 1;
+       }
+       defport = tmp;
+       snprintf(service, sizeof(service), "%u", defport);
+    }
+    ret = getaddrinfo(hostname, service, &hints, &ai);
+    if(ret == EAI_SERVICE && !isdigit((unsigned char)service[0])) {
+       snprintf(service, sizeof(service), "%u", defport);
+       ret = getaddrinfo(hostname, service, &hints, &ai);
+    }
+    if(ret != 0) {
+       krb5_warnx(context, "%s: %s (%s)", path, gai_strerror(ret), hostname);
+       return 1;
+    }
+    return 0;
+}
+
+static int
+mit_entry(krb5_context context, const char *path, char *data)
+{
+    if (warn_mit_syntax_flag)
+       krb5_warnx(context, "%s is only used by MIT Kerberos", path);
+    return 0;
+}
+
+struct s2i {
+    const char *s;
+    int val;
+};
+
+#define L(X) { #X, LOG_ ## X }
+
+static struct s2i syslogvals[] = {
+    /* severity */
+    L(EMERG),
+    L(ALERT),
+    L(CRIT),
+    L(ERR),
+    L(WARNING),
+    L(NOTICE),
+    L(INFO),
+    L(DEBUG),
+    /* facility */
+    L(AUTH),
+#ifdef LOG_AUTHPRIV
+    L(AUTHPRIV),
+#endif
+#ifdef LOG_CRON
+    L(CRON),
+#endif
+    L(DAEMON),
+#ifdef LOG_FTP
+    L(FTP),
+#endif
+    L(KERN),
+    L(LPR),
+    L(MAIL),
+#ifdef LOG_NEWS
+    L(NEWS),
+#endif
+    L(SYSLOG),
+    L(USER),
+#ifdef LOG_UUCP
+    L(UUCP),
+#endif
+    L(LOCAL0),
+    L(LOCAL1),
+    L(LOCAL2),
+    L(LOCAL3),
+    L(LOCAL4),
+    L(LOCAL5),
+    L(LOCAL6),
+    L(LOCAL7),
+    { NULL, -1 }
+};
+
+static int
+find_value(const char *s, struct s2i *table)
+{
+    while(table->s && strcasecmp(table->s, s))
+       table++;
+    return table->val;
+}
+
+static int
+check_log(krb5_context context, const char *path, char *data)
+{
+    /* XXX sync with log.c */
+    int min = 0, max = -1, n;
+    char c;
+    const char *p = data;
+
+    n = sscanf(p, "%d%c%d/", &min, &c, &max);
+    if(n == 2){
+       if(c == '/') {
+           if(min < 0){
+               max = -min;
+               min = 0;
+           }else{
+               max = min;
+           }
+       }
+    }
+    if(n){
+       p = strchr(p, '/');
+       if(p == NULL) {
+           krb5_warnx(context, "%s: failed to parse \"%s\"", path, data);
+           return 1;
+       }
+       p++;
+    }
+    if(strcmp(p, "STDERR") == 0 || 
+       strcmp(p, "CONSOLE") == 0 ||
+       (strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')) ||
+       (strncmp(p, "DEVICE", 6) == 0 && p[6] == '='))
+       return 0;
+    if(strncmp(p, "SYSLOG", 6) == 0){
+       int ret = 0;
+       char severity[128] = "";
+       char facility[128] = "";
+       p += 6;
+       if(*p != '\0')
+           p++;
+       if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1)
+           strsep_copy(&p, ":", facility, sizeof(facility));
+       if(*severity == '\0')
+           strlcpy(severity, "ERR", sizeof(severity));
+       if(*facility == '\0')
+           strlcpy(facility, "AUTH", sizeof(facility));
+       if(find_value(severity, syslogvals) == -1) {
+           krb5_warnx(context, "%s: unknown syslog facility \"%s\"", 
+                      path, facility);
+           ret++;
+       }
+       if(find_value(severity, syslogvals) == -1) {
+           krb5_warnx(context, "%s: unknown syslog severity \"%s\"", 
+                      path, severity);
+           ret++;
+       }
+       return ret;
+    }else{
+       krb5_warnx(context, "%s: unknown log type: \"%s\"", path, data);
+       return 1;
+    }
+}
+
+typedef int (*check_func_t)(krb5_context, const char*, char*);
+struct entry {
+    const char *name;
+    int type;
+    void *check_data;
+};
+
+struct entry all_strings[] = {
+    { "", krb5_config_string, NULL },
+    { NULL }
+};
+
+struct entry all_boolean[] = {
+    { "", krb5_config_string, check_boolean },
+    { NULL }
+};
+
+
+struct entry v4_name_convert_entries[] = {
+    { "host", krb5_config_list, all_strings },
+    { "plain", krb5_config_list, all_strings },
+    { NULL }
+};
+
+struct entry libdefaults_entries[] = {
+    { "accept_null_addresses", krb5_config_string, check_boolean },
+    { "capath", krb5_config_list, all_strings },
+    { "clockskew", krb5_config_string, check_time },
+    { "date_format", krb5_config_string, NULL },
+    { "default_etypes", krb5_config_string, NULL },
+    { "default_etypes_des", krb5_config_string, NULL },
+    { "default_keytab_modify_name", krb5_config_string, NULL },
+    { "default_keytab_name", krb5_config_string, NULL },
+    { "default_realm", krb5_config_string, NULL },
+    { "dns_proxy", krb5_config_string, NULL },
+    { "dns_lookup_kdc", krb5_config_string, check_boolean },
+    { "dns_lookup_realm", krb5_config_string, check_boolean },
+    { "dns_lookup_realm_labels", krb5_config_string, NULL },
+    { "egd_socket", krb5_config_string, NULL },
+    { "encrypt", krb5_config_string, check_boolean },
+    { "extra_addresses", krb5_config_string, NULL },
+    { "fcache_version", krb5_config_string, check_numeric },
+    { "fcc-mit-ticketflags", krb5_config_string, check_boolean },
+    { "forward", krb5_config_string, check_boolean },
+    { "forwardable", krb5_config_string, check_boolean },
+    { "http_proxy", krb5_config_string, check_host /* XXX */ },
+    { "ignore_addresses", krb5_config_string, NULL },
+    { "kdc_timeout", krb5_config_string, check_time },
+    { "kdc_timesync", krb5_config_string, check_boolean },
+    { "log_utc", krb5_config_string, check_boolean },
+    { "maxretries", krb5_config_string, check_numeric },
+    { "scan_interfaces", krb5_config_string, check_boolean },
+    { "srv_lookup", krb5_config_string, check_boolean },
+    { "srv_try_txt", krb5_config_string, check_boolean }, 
+    { "ticket_lifetime", krb5_config_string, check_time },
+    { "time_format", krb5_config_string, NULL },
+    { "transited_realms_reject", krb5_config_string, NULL },
+    { "no-addresses", krb5_config_string, check_boolean },
+    { "v4_instance_resolve", krb5_config_string, check_boolean },
+    { "v4_name_convert", krb5_config_list, v4_name_convert_entries },
+    { "verify_ap_req_nofail", krb5_config_string, check_boolean },
+    { "pkinit-openssl-engine", krb5_config_string, NULL },
+    { "max_retries", krb5_config_string, check_time },
+    { "renew_lifetime", krb5_config_string, check_time },
+    { "proxiable", krb5_config_string, check_boolean },
+    { "warn_pwexpire", krb5_config_string, check_time },
+    /* MIT stuff */
+    { "permitted_enctypes", krb5_config_string, mit_entry },
+    { "default_tgs_enctypes", krb5_config_string, mit_entry },
+    { "default_tkt_enctypes", krb5_config_string, mit_entry },
+    { NULL }
+};
+
+struct entry appdefaults_entries[] = {
+    { "afslog", krb5_config_string, check_boolean },
+    { "afs-use-524", krb5_config_string, check_524 },
+    { "encrypt", krb5_config_string, check_boolean },
+    { "forward", krb5_config_string, check_boolean },
+    { "forwardable", krb5_config_string, check_boolean },
+    { "proxiable", krb5_config_string, check_boolean },
+    { "ticket_lifetime", krb5_config_string, check_time },
+    { "renew_lifetime", krb5_config_string, check_time },
+    { "no-addresses", krb5_config_string, check_boolean },
+    { "krb4_get_tickets", krb5_config_string, check_boolean },
+    { "pkinit-anchors", krb5_config_string, NULL },
+#if 0
+    { "anonymous", krb5_config_string, check_boolean },
+#endif
+    { "", krb5_config_list, appdefaults_entries },
+    { NULL }
+};
+
+struct entry realms_entries[] = {
+    { "forwardable", krb5_config_string, check_boolean },
+    { "proxiable", krb5_config_string, check_boolean },
+    { "ticket_lifetime", krb5_config_string, check_time },
+    { "renew_lifetime", krb5_config_string, check_time },
+    { "warn_pwexpire", krb5_config_string, check_time },
+    { "kdc", krb5_config_string, check_host },
+    { "admin_server", krb5_config_string, check_host },
+    { "kpasswd_server", krb5_config_string, check_host },
+    { "krb524_server", krb5_config_string, check_host },
+    { "v4_name_convert", krb5_config_list, v4_name_convert_entries },
+    { "v4_instance_convert", krb5_config_list, all_strings },
+    { "v4_domains", krb5_config_string, NULL },
+    { "default_domain", krb5_config_string, NULL },
+    { "win2k_pkinit", krb5_config_string, NULL },
+    /* MIT stuff */
+    { "admin_keytab", krb5_config_string, mit_entry },
+    { "acl_file", krb5_config_string, mit_entry },
+    { "dict_file", krb5_config_string, mit_entry },
+    { "kadmind_port", krb5_config_string, mit_entry },
+    { "kpasswd_port", krb5_config_string, mit_entry },
+    { "master_key_name", krb5_config_string, mit_entry },
+    { "master_key_type", krb5_config_string, mit_entry },
+    { "key_stash_file", krb5_config_string, mit_entry },
+    { "max_life", krb5_config_string, mit_entry },
+    { "max_renewable_life", krb5_config_string, mit_entry },
+    { "default_principal_expiration", krb5_config_string, mit_entry },
+    { "default_principal_flags", krb5_config_string, mit_entry },
+    { "supported_enctypes", krb5_config_string, mit_entry },
+    { "database_name", krb5_config_string, mit_entry },
+    { NULL }
+};
+
+struct entry realms_foobar[] = {
+    { "", krb5_config_list, realms_entries },
+    { NULL }
+};
+
+
+struct entry kdc_database_entries[] = {
+    { "realm", krb5_config_string, NULL },
+    { "dbname", krb5_config_string, NULL },
+    { "mkey_file", krb5_config_string, NULL },
+    { "acl_file", krb5_config_string, NULL },
+    { "log_file", krb5_config_string, NULL },
+    { NULL }
+};
+
+struct entry kdc_entries[] = {
+    { "database", krb5_config_list, kdc_database_entries },
+    { "key-file", krb5_config_string, NULL },
+    { "logging", krb5_config_string, check_log },
+    { "max-request", krb5_config_string, check_bytes },
+    { "require-preauth", krb5_config_string, check_boolean },
+    { "ports", krb5_config_string, NULL },
+    { "addresses", krb5_config_string, NULL },
+    { "enable-kerberos4", krb5_config_string, check_boolean },
+    { "enable-524", krb5_config_string, check_boolean },
+    { "enable-http", krb5_config_string, check_boolean },
+    { "check-ticket-addresses", krb5_config_string, check_boolean },
+    { "allow-null-ticket-addresses", krb5_config_string, check_boolean },
+    { "allow-anonymous", krb5_config_string, check_boolean },
+    { "v4_realm", krb5_config_string, NULL },
+    { "enable-kaserver", krb5_config_string, check_boolean },
+    { "encode_as_rep_as_tgs_rep", krb5_config_string, check_boolean },
+    { "kdc_warn_pwexpire", krb5_config_string, check_time },
+    { "use_2b", krb5_config_list, NULL },
+    { "enable-pkinit", krb5_config_string, check_boolean },
+    { "pki-identity", krb5_config_string, NULL },
+    { "pki-anchors", krb5_config_string, NULL },
+    { "hdb-ldap-create-base", krb5_config_string, NULL },
+    { "v4-realm", krb5_config_string, NULL },
+    { NULL }
+};
+
+struct entry kadmin_entries[] = {
+    { "password_lifetime", krb5_config_string, check_time },
+    { "default_keys", krb5_config_string, NULL },
+    { "use_v4_salt", krb5_config_string, NULL },
+    { "require-preauth", krb5_config_string, check_boolean },
+    { NULL }
+};
+struct entry log_strings[] = {
+    { "", krb5_config_string, check_log },
+    { NULL }
+};
+
+
+/* MIT stuff */
+struct entry kdcdefaults_entries[] = {
+    { "kdc_ports", krb5_config_string, mit_entry },
+    { "v4_mode", krb5_config_string, mit_entry },
+    { NULL }
+};
+
+struct entry capaths_entries[] = {
+    { "", krb5_config_list, all_strings },
+    { NULL }
+};
+
+struct entry password_quality_entries[] = {
+    { "policies", krb5_config_string, NULL },
+    { "external_program", krb5_config_string, NULL },
+    { "", krb5_config_list, all_strings },
+    { NULL }
+};
+
+struct entry toplevel_sections[] = {
+    { "libdefaults" , krb5_config_list, libdefaults_entries },
+    { "realms", krb5_config_list, realms_foobar },
+    { "domain_realm", krb5_config_list, all_strings },
+    { "logging", krb5_config_list, log_strings },
+    { "kdc", krb5_config_list, kdc_entries },
+    { "kadmin", krb5_config_list, kadmin_entries },
+    { "appdefaults", krb5_config_list, appdefaults_entries },
+    { "gssapi", krb5_config_list, NULL },
+    { "capaths", krb5_config_list, capaths_entries },
+    { "password_quality", krb5_config_list, password_quality_entries },
+    /* MIT stuff */
+    { "kdcdefaults", krb5_config_list, kdcdefaults_entries },
+    { NULL }
+};
+
+
+static int
+check_section(krb5_context context, const char *path, krb5_config_section *cf, 
+             struct entry *entries)
+{
+    int error = 0;
+    krb5_config_section *p;
+    struct entry *e;
+    
+    char *local;
+    
+    for(p = cf; p != NULL; p = p->next) {
+       asprintf(&local, "%s/%s", path, p->name);
+       for(e = entries; e->name != NULL; e++) {
+           if(*e->name == '\0' || strcmp(e->name, p->name) == 0) {
+               if(e->type != p->type) {
+                   krb5_warnx(context, "%s: unknown or wrong type", local);
+                   error |= 1;
+               } else if(p->type == krb5_config_string && e->check_data != NULL) {
+                   error |= (*(check_func_t)e->check_data)(context, local, p->u.string);
+               } else if(p->type == krb5_config_list && e->check_data != NULL) {
+                   error |= check_section(context, local, p->u.list, e->check_data);
+               }
+               break;
+           }
+       }
+       if(e->name == NULL) {
+           krb5_warnx(context, "%s: unknown entry", local);
+           error |= 1;
+       }
+       free(local);
+    }
+    return error;
+}
+
+
+static void
+dumpconfig(int level, krb5_config_section *top)
+{
+    krb5_config_section *x;
+    for(x = top; x; x = x->next) {
+       switch(x->type) {
+       case krb5_config_list:
+           if(level == 0) {
+               printf("[%s]\n", x->name);
+           } else {
+               printf("%*s%s = {\n", 4 * level, " ", x->name);
+           }
+           dumpconfig(level + 1, x->u.list);
+           if(level > 0)
+               printf("%*s}\n", 4 * level, " ");
+           break;
+       case krb5_config_string:
+           printf("%*s%s = %s\n", 4 * level, " ", x->name, x->u.string);
+           break;
+       }
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    krb5_context context;
+    krb5_error_code ret;
+    krb5_config_section *tmp_cf;
+    int optind = 0;
+
+    ret = krb5_init_context(&context);
+    if (ret == KRB5_CONFIG_BADFORMAT)
+       errx (1, "krb5_init_context failed to parse configuration file");
+    else if (ret)
+       errx (1, "krb5_init_context failed with %d", ret);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       print_version(NULL);
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    tmp_cf = NULL;
+    if(argc == 0)
+       krb5_get_default_config_files(&argv);
+
+    while(*argv) {
+       ret = krb5_config_parse_file_multi(context, *argv, &tmp_cf);
+       if (ret != 0)
+           krb5_warn (context, ret, "krb5_config_parse_file");
+       argv++;
+    }
+
+    if(dumpconfig_flag)
+       dumpconfig(0, tmp_cf);
+    
+    return check_section(context, "", tmp_cf, toplevel_sections);
+}
diff --git a/src/kerberosV/src/lib/krb5/verify_user.c b/src/kerberosV/src/lib/krb5/verify_user.c
new file mode 100644 (file)
index 0000000..1fad592
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 1997-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: verify_user.c,v 1.22 2004/05/25 21:46:06 lha Exp $");
+
+static krb5_error_code
+verify_common (krb5_context context,
+              krb5_principal principal,
+              krb5_ccache ccache,
+              krb5_keytab keytab,
+              krb5_boolean secure,
+              const char *service,
+              krb5_creds cred)
+{
+    krb5_error_code ret;
+    krb5_principal server;
+    krb5_verify_init_creds_opt vopt;
+    krb5_ccache id;
+
+    ret = krb5_sname_to_principal (context, NULL, service, KRB5_NT_SRV_HST,
+                                  &server);
+    if(ret)
+       return ret;
+
+    krb5_verify_init_creds_opt_init(&vopt);
+    krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure);
+
+    ret = krb5_verify_init_creds(context,
+                                &cred,
+                                server,
+                                keytab,
+                                NULL,
+                                &vopt);
+    krb5_free_principal(context, server);
+    if(ret)
+       return ret;
+    if(ccache == NULL)
+       ret = krb5_cc_default (context, &id);
+    else
+       id = ccache;
+    if(ret == 0){
+       ret = krb5_cc_initialize(context, id, principal);
+       if(ret == 0){
+           ret = krb5_cc_store_cred(context, id, &cred);
+       }
+       if(ccache == NULL)
+           krb5_cc_close(context, id);
+    }
+    krb5_free_cred_contents(context, &cred);
+    return ret;
+}
+
+/*
+ * Verify user `principal' with `password'.
+ *
+ * If `secure', also verify against local service key for `service'.
+ *
+ * As a side effect, fresh tickets are obtained and stored in `ccache'.
+ */
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_init(krb5_verify_opt *opt)
+{
+    memset(opt, 0, sizeof(*opt));
+    opt->secure = TRUE;
+    opt->service = "host";
+}
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_ccache(krb5_verify_opt *opt, krb5_ccache ccache)
+{
+    opt->ccache = ccache;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_keytab(krb5_verify_opt *opt, krb5_keytab keytab)
+{
+    opt->keytab = keytab;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_secure(krb5_verify_opt *opt, krb5_boolean secure)
+{
+    opt->secure = secure;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_service(krb5_verify_opt *opt, const char *service)
+{
+    opt->service = service;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_verify_opt_set_flags(krb5_verify_opt *opt, unsigned int flags)
+{
+    opt->flags |= flags;
+}
+
+static krb5_error_code
+verify_user_opt_int(krb5_context context,
+                   krb5_principal principal,
+                   const char *password,
+                   krb5_verify_opt *vopt)
+
+{
+    krb5_error_code ret;
+    krb5_get_init_creds_opt *opt;
+    krb5_creds cred;
+
+    ret = krb5_get_init_creds_opt_alloc (context, &opt);
+    if (ret)
+       return ret;
+    krb5_get_init_creds_opt_set_default_flags(context, NULL, 
+                                             krb5_principal_get_realm(context, principal), 
+                                             opt);
+    ret = krb5_get_init_creds_password (context,
+                                       &cred,
+                                       principal,
+                                       password,
+                                       krb5_prompter_posix,
+                                       NULL,
+                                       0,
+                                       NULL,
+                                       opt);
+    krb5_get_init_creds_opt_free(opt);
+    if(ret)
+       return ret;
+#define OPT(V, D) ((vopt && (vopt->V)) ? (vopt->V) : (D))
+    return verify_common (context, principal, OPT(ccache, NULL), 
+                         OPT(keytab, NULL), vopt ? vopt->secure : TRUE, 
+                         OPT(service, "host"), cred);
+#undef OPT
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_user_opt(krb5_context context,
+                    krb5_principal principal,
+                    const char *password,
+                    krb5_verify_opt *opt)
+{
+    krb5_error_code ret;
+
+    if(opt && (opt->flags & KRB5_VERIFY_LREALMS)) {
+       krb5_realm *realms, *r;
+       ret = krb5_get_default_realms (context, &realms);
+       if (ret)
+           return ret;
+       ret = KRB5_CONFIG_NODEFREALM;
+       
+       for (r = realms; *r != NULL && ret != 0; ++r) {
+           char *tmp = strdup (*r);
+           
+           if (tmp == NULL) {
+               krb5_free_host_realm (context, realms);
+               krb5_set_error_string (context, "malloc: out of memory");
+               return ENOMEM;
+           }
+           free (*krb5_princ_realm (context, principal));
+           krb5_princ_set_realm (context, principal, &tmp);
+           
+           ret = verify_user_opt_int(context, principal, password, opt);
+       }
+       krb5_free_host_realm (context, realms);
+       if(ret)
+           return ret;
+    } else
+       ret = verify_user_opt_int(context, principal, password, opt);
+    return ret;
+}
+
+/* compat function that calls above */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_user(krb5_context context, 
+                krb5_principal principal,
+                krb5_ccache ccache,
+                const char *password,
+                krb5_boolean secure,
+                const char *service)
+{
+    krb5_verify_opt opt;
+    
+    krb5_verify_opt_init(&opt);
+    
+    krb5_verify_opt_set_ccache(&opt, ccache);
+    krb5_verify_opt_set_secure(&opt, secure);
+    krb5_verify_opt_set_service(&opt, service);
+    
+    return krb5_verify_user_opt(context, principal, password, &opt);
+}
+
+/*
+ * A variant of `krb5_verify_user'.  The realm of `principal' is
+ * ignored and all the local realms are tried.
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_user_lrealm(krb5_context context, 
+                       krb5_principal principal,
+                       krb5_ccache ccache,
+                       const char *password,
+                       krb5_boolean secure,
+                       const char *service)
+{
+    krb5_verify_opt opt;
+    
+    krb5_verify_opt_init(&opt);
+    
+    krb5_verify_opt_set_ccache(&opt, ccache);
+    krb5_verify_opt_set_secure(&opt, secure);
+    krb5_verify_opt_set_service(&opt, service);
+    krb5_verify_opt_set_flags(&opt, KRB5_VERIFY_LREALMS);
+    
+    return krb5_verify_user_opt(context, principal, password, &opt);
+}
diff --git a/src/kerberosV/src/lib/krb5/version.c b/src/kerberosV/src/lib/krb5/version.c
new file mode 100644 (file)
index 0000000..0bb5508
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: version.c,v 1.3 1999/12/02 17:05:13 joda Exp $");
+
+/* this is just to get a version stamp in the library file */
+
+#define heimdal_version __heimdal_version
+#define heimdal_long_version __heimdal_long_version
+#include "version.h"
+
diff --git a/src/kerberosV/src/lib/krb5/warn.c b/src/kerberosV/src/lib/krb5/warn.c
new file mode 100644 (file)
index 0000000..be4980d
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+#include <err.h>
+
+RCSID("$KTH: warn.c,v 1.15 2004/05/25 21:46:26 lha Exp $");
+
+static krb5_error_code _warnerr(krb5_context context, int do_errtext, 
+        krb5_error_code code, int level, const char *fmt, va_list ap)
+       __attribute__((__format__(__printf__, 5, 0)));
+       
+static krb5_error_code
+_warnerr(krb5_context context, int do_errtext, 
+        krb5_error_code code, int level, const char *fmt, va_list ap)
+{
+    char xfmt[7] = "";
+    const char *args[2], **arg;
+    char *msg = NULL;
+    char *err_str = NULL;
+    
+    args[0] = args[1] = NULL;
+    arg = args;
+    if(fmt){
+       strlcat(xfmt, "%s", sizeof(xfmt));
+       if(do_errtext)
+           strlcat(xfmt, ": ", sizeof(xfmt));
+       vasprintf(&msg, fmt, ap);
+       if(msg == NULL)
+           return ENOMEM;
+       *arg++ = msg;
+    }
+    if(context && do_errtext){
+       const char *err_msg;
+
+       strlcat(xfmt, "%s", sizeof(xfmt));
+
+       err_str = krb5_get_error_string(context);
+       if (err_str != NULL) {
+           *arg++ = err_str;
+       } else {
+           err_msg = krb5_get_err_text(context, code);
+           if (err_msg)
+               *arg++ = err_msg;
+           else
+               *arg++ = "<unknown error>";
+       }
+    }
+       
+    if(context && context->warn_dest)
+       krb5_log(context, context->warn_dest, level, xfmt, args[0], args[1]);
+    else
+       warnx(xfmt, args[0], args[1]);
+    free(msg);
+    free(err_str);
+    return 0;
+}
+
+#define FUNC(ETEXT, CODE, LEVEL)                                       \
+    krb5_error_code ret;                                               \
+    va_list ap;                                                                \
+    va_start(ap, fmt);                                                 \
+    ret = _warnerr(context, ETEXT, CODE, LEVEL, fmt, ap);              \
+    va_end(ap);
+
+#undef __attribute__
+#define __attribute__(X)
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vwarn(krb5_context context, krb5_error_code code, 
+          const char *fmt, va_list ap)
+     __attribute__ ((format (printf, 3, 0)))
+{
+    return _warnerr(context, 1, code, 1, fmt, ap);
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
+     __attribute__ ((format (printf, 3, 4)))
+{
+    FUNC(1, code, 1);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
+     __attribute__ ((format (printf, 2, 0)))
+{
+    return _warnerr(context, 0, 0, 1, fmt, ap);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_warnx(krb5_context context, const char *fmt, ...)
+     __attribute__ ((format (printf, 2, 3)))
+{
+    FUNC(0, 0, 1);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verr(krb5_context context, int eval, krb5_error_code code, 
+         const char *fmt, va_list ap)
+     __attribute__ ((noreturn, format (printf, 4, 0)))
+{
+    _warnerr(context, 1, code, 0, fmt, ap);
+    exit(eval);
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_err(krb5_context context, int eval, krb5_error_code code, 
+        const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 4, 5)))
+{
+    FUNC(1, code, 0);
+    exit(eval);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
+     __attribute__ ((noreturn, format (printf, 3, 0)))
+{
+    _warnerr(context, 0, 0, 0, fmt, ap);
+    exit(eval);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_errx(krb5_context context, int eval, const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 3, 4)))
+{
+    FUNC(0, 0, 0);
+    exit(eval);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vabort(krb5_context context, krb5_error_code code, 
+           const char *fmt, va_list ap)
+     __attribute__ ((noreturn, format (printf, 3, 0)))
+{
+    _warnerr(context, 1, code, 0, fmt, ap);
+    abort();
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 3, 4)))
+{
+    FUNC(1, code, 0);
+    abort();
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_vabortx(krb5_context context, const char *fmt, va_list ap)
+     __attribute__ ((noreturn, format (printf, 2, 0)))
+{
+    _warnerr(context, 0, 0, 0, fmt, ap);
+    abort();
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_abortx(krb5_context context, const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 2, 3)))
+{
+    FUNC(0, 0, 0);
+    abort();
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
+{
+    context->warn_dest = fac;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/krb5/write_message.c b/src/kerberosV/src/lib/krb5/write_message.c
new file mode 100644 (file)
index 0000000..ec35ee7
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "krb5_locl.h"
+
+RCSID("$KTH: write_message.c,v 1.9 2004/05/25 21:46:46 lha Exp $");
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_write_message (krb5_context context,
+                   krb5_pointer p_fd,
+                   krb5_data *data)
+{
+    u_int32_t len;
+    u_int8_t buf[4];
+    int ret;
+
+    len = data->length;
+    _krb5_put_int(buf, len, 4);
+    if (krb5_net_write (context, p_fd, buf, 4) != 4
+       || krb5_net_write (context, p_fd, data->data, len) != len) {
+       ret = errno;
+       krb5_set_error_string (context, "write: %s", strerror(ret));
+       return ret;
+    }
+    return 0;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_write_priv_message(krb5_context context,
+                       krb5_auth_context ac,
+                       krb5_pointer p_fd,
+                       krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_data packet;
+
+    ret = krb5_mk_priv (context, ac, data, &packet, NULL);
+    if(ret)
+       return ret;
+    ret = krb5_write_message(context, p_fd, &packet);
+    krb5_data_free(&packet);
+    return ret;
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_write_safe_message(krb5_context context,
+                       krb5_auth_context ac,
+                       krb5_pointer p_fd,
+                       krb5_data *data)
+{
+    krb5_error_code ret;
+    krb5_data packet;
+    ret = krb5_mk_safe (context, ac, data, &packet, NULL);
+    if(ret)
+       return ret;
+    ret = krb5_write_message(context, p_fd, &packet);
+    krb5_data_free(&packet);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/CVS/Entries b/src/kerberosV/src/lib/roken/CVS/Entries
new file mode 100644 (file)
index 0000000..4d462c2
--- /dev/null
@@ -0,0 +1,160 @@
+/ChangeLog/1.1.1.6/Fri Apr 14 07:33:37 2006//
+/acconfig.h/1.1.1.1/Fri May 25 07:51:06 2001//
+/base64-test.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/base64.c/1.1.1.3/Fri Apr 14 07:33:37 2006//
+/base64.h/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/bswap.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/chown.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/closefrom.c/1.1.1.1/Fri Apr 14 07:33:37 2006//
+/compile/1.1.1.1/Wed Feb  6 08:55:54 2002//
+/concat.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/config.h.in/1.1.1.1/Fri May 25 07:51:05 2001//
+/copyhostent.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/daemon.c/1.3/Fri Apr 14 08:15:05 2006//
+/ecalloc.3/1.1.1.1/Fri Apr 14 07:33:37 2006//
+/ecalloc.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/emalloc.c/1.1.1.3/Fri Apr 14 07:33:37 2006//
+/environment.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/eread.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/erealloc.c/1.1.1.3/Fri Apr 14 07:33:37 2006//
+/err.c/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/err.hin/1.1.1.2/Fri Apr 14 07:33:37 2006//
+/errx.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/esetenv.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/estrdup.c/1.1.1.3/Fri Apr 14 07:33:38 2006//
+/ewrite.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/fchown.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/flock.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/fnmatch.c/1.3/Fri Apr 14 08:15:05 2006//
+/fnmatch.hin/1.3/Fri Apr 14 08:15:05 2006//
+/freeaddrinfo.c/1.1.1.3/Fri Apr 14 07:33:38 2006//
+/freehostent.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/gai_strerror.c/1.1.1.3/Fri Apr 14 07:33:38 2006//
+/get_default_username.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/get_window_size.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/getaddrinfo-test.c/1.3/Fri Apr 14 08:15:05 2006//
+/getaddrinfo.c/1.1.1.3/Fri Apr 14 07:33:38 2006//
+/getaddrinfo_hostspec.c/1.1.1.2/Fri Apr 14 07:33:38 2006//
+/getarg.3/1.1.1.3/Fri Apr 14 07:33:38 2006//
+/getarg.c/1.4/Fri Apr 14 08:15:05 2006//
+/getarg.h/1.1.1.4/Fri Apr 14 07:33:39 2006//
+/getcap.c/1.5/Fri Apr 14 08:15:05 2006//
+/getcwd.c/1.1.1.2/Fri Apr 14 07:33:39 2006//
+/getdtablesize.c/1.1.1.3/Fri Apr 14 07:33:39 2006//
+/getegid.c/1.1.1.2/Fri Apr 14 07:33:39 2006//
+/geteuid.c/1.1.1.2/Fri Apr 14 07:33:39 2006//
+/getgid.c/1.1.1.2/Fri Apr 14 07:33:39 2006//
+/gethostname.c/1.1.1.2/Fri Apr 14 07:33:39 2006//
+/getifaddrs.c/1.1.1.5/Fri Apr 14 07:33:40 2006//
+/getipnodebyaddr.c/1.1.1.2/Fri Apr 14 07:33:40 2006//
+/getipnodebyname.c/1.1.1.2/Fri Apr 14 07:33:40 2006//
+/getnameinfo.c/1.1.1.4/Fri Apr 14 07:33:40 2006//
+/getnameinfo_verified.c/1.1.1.4/Fri Apr 14 07:33:40 2006//
+/getopt.c/1.3/Fri Apr 14 08:15:05 2006//
+/getprogname.c/1.3/Fri Apr 14 08:15:05 2006//
+/gettimeofday.c/1.1.1.2/Fri Apr 14 07:33:40 2006//
+/getuid.c/1.1.1.2/Fri Apr 14 07:33:40 2006//
+/getusershell.c/1.3/Fri Apr 14 08:15:05 2006//
+/glob.c/1.3/Fri Apr 14 08:15:05 2006//
+/glob.hin/1.3/Fri Apr 14 08:15:05 2006//
+/h_errno.c/1.1.1.1/Wed Feb  6 08:55:47 2002//
+/hex-test.c/1.1.1.1/Fri Apr 14 07:33:41 2006//
+/hex.c/1.1.1.1/Fri Apr 14 07:33:41 2006//
+/hex.h/1.1.1.1/Fri Apr 14 07:33:41 2006//
+/hostent_find_fqdn.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/hstrerror.c/1.1.1.3/Fri Apr 14 07:33:41 2006//
+/ifaddrs.hin/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/inet_aton.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/inet_ntop.c/1.1.1.3/Fri Apr 14 07:33:41 2006//
+/inet_pton.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/initgroups.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/innetgr.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/install-sh/1.1.1.1/Fri May 25 07:51:14 2001//
+/iruserok.c/1.3/Fri Apr 14 08:15:05 2006//
+/issuid.c/1.1.1.3/Fri Apr 14 07:33:41 2006//
+/k_getpwnam.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/k_getpwuid.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/localtime_r.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/lstat.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/make-print-version.c/1.1.1.1/Fri May 25 07:51:14 2001//
+/memmove.c/1.1.1.2/Fri Apr 14 07:33:41 2006//
+/missing/1.1.1.1/Fri May 25 07:51:15 2001//
+/mkinstalldirs/1.1.1.1/Fri May 25 07:51:15 2001//
+/mkstemp.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/ndbm_wrap.c/1.4/Fri Apr 14 08:15:05 2006//
+/ndbm_wrap.h/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/net_read.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/net_write.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/parse_bytes-test.c/1.1.1.2/Sun May 11 02:16:07 2003//
+/parse_bytes.c/1.1.1.3/Fri Apr 14 07:33:42 2006//
+/parse_bytes.h/1.1.1.3/Fri Apr 14 07:33:42 2006//
+/parse_reply-test.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/parse_time-test.c/1.1.1.1/Fri Apr 14 07:33:42 2006//
+/parse_time.3/1.2/Tue Jun 13 07:07:21 2006//
+/parse_time.c/1.1.1.3/Fri Apr 14 07:33:42 2006//
+/parse_time.h/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/parse_units.c/1.3/Fri Apr 14 08:15:05 2006//
+/parse_units.h/1.1.1.3/Fri Apr 14 07:33:42 2006//
+/print_version.c/1.4/Fri Apr 14 08:15:05 2006//
+/putenv.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/rcmd.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/readv.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/realloc.c/1.1.1.1/Fri Apr 14 07:33:42 2006//
+/recvmsg.c/1.1.1.2/Fri Apr 14 07:33:42 2006//
+/resolve-test.c/1.1.1.1/Fri Apr 14 07:33:42 2006//
+/resolve.c/1.8/Fri Apr 14 08:15:05 2006//
+/resolve.h/1.1.1.4/Fri Apr 14 07:33:43 2006//
+/resource.h/1.1.1.1/Fri May 25 07:51:17 2001//
+/roken-common.h/1.1.1.5/Fri Apr 14 07:33:43 2006//
+/roken.awk/1.1.1.3/Sun May 11 02:16:07 2003//
+/roken.h.in/1.1.1.5/Fri Apr 14 07:33:43 2006//
+/rtbl.3/1.1.1.1/Fri Apr 14 07:33:43 2006//
+/rtbl.c/1.1.1.3/Fri Apr 14 07:33:44 2006//
+/rtbl.h/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/sendmsg.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/setegid.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/setenv.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/seteuid.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/setprogname.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/signal.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/simple_exec.c/1.1.1.3/Fri Apr 14 07:33:44 2006//
+/socket.c/1.1.1.4/Fri Apr 14 07:33:44 2006//
+/strcasecmp.c/1.1.1.3/Fri Apr 14 07:33:44 2006//
+/strcollect.c/1.1.1.2/Fri Apr 14 07:33:44 2006//
+/strlcat.c/1.1.1.3/Fri Apr 14 07:33:45 2006//
+/strlcpy.c/1.1.1.3/Fri Apr 14 07:33:45 2006//
+/strlwr.c/1.1.1.3/Fri Apr 14 07:33:45 2006//
+/strncasecmp.c/1.1.1.3/Fri Apr 14 07:33:45 2006//
+/strndup.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/strnlen.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/strpftime-test.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/strptime.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/strsep.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/strsep_copy.c/1.1.1.3/Fri Apr 14 07:33:45 2006//
+/strtok_r.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/strupr.c/1.1.1.3/Fri Apr 14 07:33:45 2006//
+/swab.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/test-mem.c/1.1.1.1/Fri Apr 14 07:33:45 2006//
+/test-mem.h/1.1.1.1/Fri Apr 14 07:33:45 2006//
+/test-readenv.c/1.1.1.1/Fri Apr 14 07:33:45 2006//
+/timeval.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/tm2time.c/1.1.1.2/Fri Apr 14 07:33:45 2006//
+/unsetenv.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/unvis.c/1.3/Fri Apr 14 08:15:05 2006//
+/verify.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/verr.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/verrx.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/vis.c/1.4/Fri Oct 17 18:30:19 2008//
+/vis.hin/1.3/Fri Apr 14 08:15:05 2006//
+/vsyslog.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/vwarn.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/vwarnx.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/warn.c/1.1.1.1/Fri May 25 07:51:24 2001//
+/warnerr.c/1.3/Fri Apr 14 08:15:05 2006//
+/warnx.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/write_pid.c/1.4/Fri Apr 14 08:15:05 2006//
+/writev.c/1.1.1.2/Fri Apr 14 07:33:46 2006//
+/xdbm.h/1.1.1.3/Sun May 11 02:16:10 2003//
+/roken_gethostby.c/1.2/Sat Jan  2 15:00:40 2010//
+/mini_inetd.c/1.2/Wed Nov 18 04:58:47 2009//
+D
diff --git a/src/kerberosV/src/lib/roken/CVS/Repository b/src/kerberosV/src/lib/roken/CVS/Repository
new file mode 100644 (file)
index 0000000..9a384a9
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/roken
diff --git a/src/kerberosV/src/lib/roken/CVS/Root b/src/kerberosV/src/lib/roken/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/roken/ChangeLog b/src/kerberosV/src/lib/roken/ChangeLog
new file mode 100644 (file)
index 0000000..bb4c875
--- /dev/null
@@ -0,0 +1,1818 @@
+2005-05-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * parse_reply-test.c: avoid signedness warnings
+
+       * test-mem.c: avoid signedness warnings
+
+2005-05-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * hex.c: include "roken.h" to avoid undefined size_t/ssize_t
+
+2005-05-24  Dave Love  <fx@gnu.org>
+
+       * Makefile.am (snprintf_test_SOURCES): Add snprintf-test.h.
+
+2005-05-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * environment.c (rk_read_env_file): move assignment to later to
+       make pre c99 compiler happy
+
+2005-05-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * strptime.c: use english spelling of March
+
+2005-05-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: only link with dblib if we need it
+       
+       * Makefile.am: add test_readenv
+       
+       * test-readenv.c: test for read_environment()
+       
+       * environment.c: eliminate duplicates
+       
+2005-05-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * issuid.c (issuid): change the #ifdef order to avoid unreachable
+       code warning.
+
+2005-05-10  Dave Love  <fx@gnu.org>
+
+       * roken.h.in: Get daemon declared on Solaris (it's in unistd.h but
+       masked by a feature test), just to avoid a warning, since it has
+       int args. Include err.h unconditionally, since it's always
+       supplied.
+
+2005-05-04  Dave Love  <fx@gnu.org>
+
+       * snprintf-test.c: Include snprintf-test.h earlier.
+
+2005-05-03  Dave Love  <fx@gnu.org>
+
+       * snprintf.c: Include snprintf-test.h earlier.
+       
+       * test-mem.c: Add member fd to map.
+       (rk_test_mem_alloc, rk_test_mem_free): Use it.
+
+2005-04-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * getifaddrs.c: add break on default: statements, from Douglas
+       E. Engert
+
+       * snprintf.c (vsnprintf): don't write the NUL into the string if
+       the length was 0
+
+       * snprintf-test.c: add check that snprintf doesn't write the NUL
+       into the last byte when its a zero length input string
+
+       * parse_time-test.c: Include <err.h>.
+       
+2005-04-27  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * parse_time-test.c: improve testing
+       
+       * roken-common.h: add rk_realloc
+
+       * Makefile.am: add realloc
+
+       * realloc.c: add rk_realloc, unbroken version of realloc
+
+2005-04-26  Dave Love  <fx@gnu.org>
+
+       * getusershell.c: Include roken.h
+
+2005-04-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * unvis.c: cast to unsigned char to make sure its not negative
+       when passing it to is* functions
+
+       * strptime.c: cast to unsigned char to make sure its not negative
+       when passing it to to* functions
+
+2005-04-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * simple_exec.c: don't close stderr, close all fd that is num 3
+       and larger
+
+       * simple_exec.c (pipe_execv): use closefrom
+
+       * add closefrom
+
+2005-04-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * add ROKEN_LIB_FUNCTION to all exported functions
+
+2005-04-10  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve-test.c: print DS
+
+2005-04-07  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * parse_time-test.c: remove unused variable
+       
+2005-04-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * strpftime-test.c: print size_t by casting to unsigned long
+       
+       * base64-test.c: print size_t by casting to unsigned long
+       
+       * hex-test.c: print size_t by casting to unsigned long
+       
+       * resolve-test.c: print size_t by casting to unsigned long
+       
+2005-04-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * snprintf-test.c (try): reset va_list argument between reuse,
+       from Peter Kruty <xkruty@fi.muni.cz>
+
+2005-03-30  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * roken_gethostby.c (roken_gethostby): s/sin/addr/ to avoid
+       shadowing
+
+       * resolve.c (dns_lookup_int): s/stat/state/ to avoid shadowing
+
+       * parse_units.c: avoid shadowing div
+
+2005-03-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * snprintf.c: use defined(TEST_SNPRINTF) like on all other places
+       in the same file
+
+2005-03-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * hex.c: check for overflows
+
+2005-03-18  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * vis.c: use RCSID instead of __RCSID
+
+2005-03-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: check_PROGRAMS += hex-test
+       
+       * hex-test.c: hex encoding/decoding test
+       
+       * hex.c: fix decodeing, it processed to much data and thus
+       returned the wrong length
+
+2005-03-04  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: add hex.[ch]
+
+       * hex.c: add hex encoder/decoder
+
+2005-03-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * daemon.c fnmatch.c fnmatch.hin getcap.c getopt.c getusershell.c
+       glob.c glob.hin iruserok.c unvis.c vis.hin:
+       
+       In 1997, the University of California, Berkeley issued a statement
+       retroactively relicensing all code held under their copyright from
+       a 4-clause 'traditional' BSD license to a new 3-clause 'revised'
+       BSD license, which removed the advertising clause.
+
+       From NetBSD, via Joel Baker, and Alistair G. Crooks
+       
+       * getaddrinfo-test.c: remove stray ( in output
+       
+       * vis.c: Update new revision from NetBSD (copyright update)
+
+2005-02-24  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: bump version to 17:0:1
+
+2005-01-19  Dave Love  <d.love@dl.ac.uk>
+
+       * getusershell.c: Include ctype.h, cast argument to isspace to
+       unsigned char.
+
+2004-10-31  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * parse_time.3, parse_units.c: Change the behavior of the
+       parse_unit code to return the number of bytes needed to print the
+       whole string (minus the trailing '\0'), just like snprintf.  Idea
+       from bugreport from Gabriel Kihlman <gk@stacken.kth.se>.
+
+       * parse_time-test.c Makefile.am test-mem.c test-mem.h: test parse_time
+
+2004-10-16  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve.c: put dns_type_to_string and dns_string_to_type in the
+       abi
+
+       * resolve.c: add ds_record
+       
+       * resolve.h: add ds_record
+       
+2004-10-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ndbm_wrap.c: undefine open so this works on solaris with large
+       file support From netbsd's pkgsrc via Gavan Fantom
+       
+2004-09-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve-test.c: add --version/--help
+       
+2004-09-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * Makefile.am: make resolve-test a noinst program
+       
+2004-09-11  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve-test.c: test program for libroken resolve from resolve.c
+       
+       * Makefile.am: add resolve-test
+       
+       * resolve.h: add constant for max DNS protocol packet size
+       
+       * resolve.c (dns_lookup_int): grow the answer buffer to the size
+       the server send to us if the answer buffer was too small (limited
+       to the dns protocol max packet size)
+       
+2004-08-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * err.hin: no need to declare __progname here
+
+       * Makefile.am: always clean generated headers
+
+2004-06-26  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * rtbl.3: use .In for header, remove trailing space
+       
+2004-06-23  Johan Danielsson  <joda@pdc.kth.se>
+
+       * rtbl.h: add protos and macros
+       
+       * rtbl.c: implement a bunch of stuff:
+         - column separator (instead of global column prefix)
+         - per column suffix
+         - indexing columns by id-number instead of column header
+         - optional header supression (via settable flags)
+         - ability to end a row
+         - don't extend last column to full width
+       
+2004-06-20  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve.[ch]: add and use and bind9 version of rr type
+       (rk_ns_t_XXX) instead of the old bind4 version (T_XXX)
+
+2004-05-25  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve.c (stot): add AAAA
+       
+2004-02-17  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * getarg.c (add_string): catch error from realloc
+       
+2004-02-12  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * roken-common.h: add simple_execve_timed
+       
+       * roken-common.h: add timed simple_exec
+       
+       * simple_exec.c: add timed simple_exec
+       
+2004-01-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * gai_strerror.c: correct ifdef for EAI_ADDRFAMILY
+
+2003-12-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve.c: parse dns header, add support for SSHFP
+       
+       * resolve.h: add cpp rewrite for sshfp_record
+       
+       * resolve.h: add SSHFP, clean up the the dns_header
+       
+2003-12-14  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve.h: remove HEADER (only used for crays)
+       
+       * resolve.c: number-of fields no longer stored in network order
+       
+2003-12-13  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolve.c: remove depency on c99 types in resolv.h
+       
+       * resolve.h: remove depency on c99 types
+       
+2003-12-06  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * resolv.h: add more T_ types and inline the dns headers, all this
+       for bind9 resolvers
+
+2003-12-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+       
+       * gai_strerror.c: EAI_ADDRFAMILY and EAI_NODATA is deprecated
+       
+       * roken-common.h: use EAI_NONAME instead of EAI_ADDRFAMILY to
+       check for if we need EAI_ macros
+
+2003-10-04   Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * strptime.c: let t and n match zero or more whitespaces
+       
+2003-08-29  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * ndbm_wrap.c: patch for working with DB4 on heimdal-discuss
+       From: Luke Howard <lukeh@PADL.COM>
+       
+2003-08-27  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: don't include discovered files in EXTRA_SOURCES;
+       don't depend on all header files, just the built ones
+
+2003-08-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * emalloc.3: manpage
+       
+2003-07-11  Love  <lha@stacken.kth.se>
+
+       * resolve.c: AIX have broken res_nsearch() in 5.1 (5.0 also ?)  so
+       just don't use res_nsearch on AIX
+
+2003-06-29  Johan Danielsson  <joda@pdc.kth.se>
+
+       * snprintf.c: * don't ever print sign for unsigned conversions *
+       don't break when right justifying a number past the end of the
+       buffer * handle zero precision and the value zero more correctly
+
+2003-06-14  Love  <lha@stacken.kth.se>
+
+       * glob.hin: prefix glob symbols with rk_
+       
+2003-04-22  Love  <lha@stacken.kth.se>
+
+       * resolve.c: copy NUL too, from janj@wenf.org via openbsd
+       
+2003-04-16  Love  <lha@stacken.kth.se>
+
+       * parse_units.h: remove typedef for units to avoid problems with
+       shadowing
+
+       * resolve.c: use strlcpy, from openbsd
+       
+       * getcap.c: use strlcpy, from openbsd
+       
+       * getarg.3: Change .Fd #include <header.h> to .In header.h
+       from Thomas Klausner <wiz@netbsd.org>
+
+2003-04-15  Love  <lha@stacken.kth.se>
+
+       * socket.c (socket_set_tos): if setsockopt failed with EINVAL
+       failed, just ignore it, sock was probably a just a non AF_INET
+       socket
+
+2003-04-14  Love  <lha@stacken.kth.se>
+
+       * strncasecmp.c: cast argument to toupper to unsigned char, from
+       Christian Biere <christianbiere@gmx.de> via NetBSD
+       
+       * strlwr.c: cast argument to tolower to unsigned char, from
+       Christian Biere <christianbiere@gmx.de> via NetBSD
+       
+       * strcasecmp.c: cast argument to toupper to unsigned char, from
+       Christian Biere <christianbiere@gmx.de> via NetBSD
+       
+2003-03-19  Love  <lha@stacken.kth.se>
+
+       * getarg.3: spelling, from <jmc@prioris.mini.pw.edu.pl>
+       
+2003-03-07  Love  <lha@stacken.kth.se>
+
+       * parse_bytes.c: use struct units instead of units
+       
+       * parse_time.c: use struct units instead of units
+       
+2003-03-04  Love  <lha@stacken.kth.se>
+
+       * roken.awk: use full prototype for main
+       
+2002-10-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * resolve.c: check length of txt records
+
+2002-09-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.awk: include config.h before stdio.h (breaks with
+       _FILE_OFFSET_BITS on solaris otherwise)
+
+2002-09-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * resolve.c: fix res_nsearch call, but don't use it for now, AIX5
+       has a broken version that trashes memory
+
+       * roken-common.h: fix typo in previous
+
+       * roken-common.h: change IRIX == 4 to IRIX4
+
+2002-09-04  Assar Westerlund  <assar@kth.se>
+
+       * getifaddrs.c: remove some warnings from the linux-portion
+
+       * getnameinfo_verified.c (getnameinfo_verified): handle the case
+       of forward but no backward DNS information, and also describe the
+       desired behaviour.  from Love <lha@stacken.kth.se>
+
+2002-09-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * rtbl.c (rtbl_destroy): free whole table
+
+       * resolve.c: use res_nsearch if we have it (from Larry Greenfield)
+
+2002-09-03  Assar Westerlund  <assar@kth.se>
+
+       * getifaddrs.c: add Linux AF_NETLINK getifaddrs from Hideaki
+       YOSHIFUJI of the Usagi project
+       
+       * parse_reply-test.c: make this build and return 77 if there is no
+       mmap
+
+       * Makefile.am (parse_reply-test): add
+       * parse_reply-test.c: add a test case for parse_reply reading past
+       the given buffer
+       * resolve.c (parse_reply): update the arguments to more reasonable
+       types.  allow parse_reply-test to call it
+
+2002-08-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * resolve.c (dns_srv_order): do alignment tricks with the random()
+       state (from NetBSD)
+
+2002-08-27  Assar Westerlund  <assar@kth.se>
+
+       * resolve.c (parse_reply): verify the lengths (both external and
+       internal) are consistent and not too long
+       (dns_lookup_int): be conservative in the length sent in to to
+       parse_reply
+
+2002-08-26  Assar Westerlund  <assar@kth.se>
+
+       * roken.h.in: add prototypes for str, unvis functions
+       * resolve.h: add fallback definition for T_AAAA
+
+2002-08-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.h.in: we may need a prototype for strndup
+
+2002-08-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.h.in: typedef ssize_t here
+
+       * getarg.c: don't put Ns before comma
+
+       * resolve.c: _res might not be available
+
+       * localtime_r.c: include stdio.h and roken.h
+
+       * strftime.c: only use altzone if we have it
+
+       * roken-common.h: AI_NUMERICHOST needs special handling
+
+       * strlcat.c: add some consistency checks
+
+       * strlcpy.c: make the logic simpler, and handle dst_sz == 0
+
+2002-08-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * resolve.h: prefix these functions to avoid conflicts with other
+       packages
+
+2002-08-14  Johan Danielsson  <joda@pdc.kth.se>
+
+       * strsep_copy.c: don't write to buf if len == 0
+
+2002-05-31  Assar Westerlund  <assar@pdc.kth.se>
+
+       * Makefile.am: *_LDADD: add LDADD, so that libroken is used
+
+2002-05-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * xdbm.h: remove old dbm part
+
+2002-04-30  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ndbm_wrap.{c,h}: ndbm wrapper for newer db libraries
+
+2002-04-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.h.in: move mini_inetd protos to after addrinfo definition
+
+       * snprintf.c (append_number): make rep const
+
+       * getarg.h: rename optind and optarg to avoid some gcc warnings
+
+       * getarg.c: rename optind and optarg to avoid some gcc warnings
+
+2002-02-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * mini_inetd.c: mini_inetd_addrinfo that takes an addrinfo instead
+       of a port number
+
+2001-11-30  Assar Westerlund  <assar@sics.se>
+
+       * getifaddrs.c: support SIOCGLIFCONF and SIOCGLIFFLAGS which are
+       used on Solaris 8 to retrieve addresses larger than `struct
+       sockaddr'.  From Magnus Ahltorp <ahltorp@nada.kth.se> (with some
+       modifications by me)
+
+2001-10-27  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): set version to 15:0:6
+
+2001-10-22  Assar Westerlund  <assar@sics.se>
+
+       * localtime_r.c: add
+
+2001-10-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * resolve.c (dns_srv_order): don't try to return a value
+
+2001-09-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * snprintf.c: va_{start,end} fixes; from Thomas Klausner
+
+2001-09-20  Assar Westerlund  <assar@sics.se>
+
+       * resolve.c (dns_srv_order): make sure of not reading after the
+       array
+
+2001-09-17  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): bump to 14:4:5
+       * snprintf.c: rename 'struct state' -> 'struct snprintf_test' to
+       avoid collision with resolv.h on aix
+
+2001-09-04  Assar Westerlund  <assar@sics.se>
+
+       * parse_bytes-test.c, parse_bytes.c, parse_bytes.h, parse_units.c,
+       parse_units.h: use int instead of size_t as return values to be
+       compatible with snprintf
+
+       * strftime.c (strftime): check for return values from snprintf() <
+       0
+
+2001-09-03  Johan Danielsson  <joda@pdc.kth.se>
+
+       * socket.c: restrict is a keyword
+
+2001-09-03  Assar Westerlund  <assar@sics.se>
+
+       * write_pid.c: handle atexit or on_exit
+
+       * Makefile.am (EXTRA_libroken_la_SOURCES): add vis.hin to help
+       solaris make
+
+2001-08-30  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: use LDADD directly
+
+2001-08-28  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): set to 14:3:5
+
+       * issuid.c (issuid): call issetugid if it exists
+
+2001-08-24  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: make it play better with recent automake
+
+2001-08-21  Assar Westerlund  <assar@sics.se>
+
+       * glob.c: provide a fallback for ARG_MAX.  from <tol@stacken.kth.se>
+
+       * roken.h.in: remove all winsock.h
+       for now, it does more harm than good under cygwin and if it should be
+       used, the correct conditional needs to be found
+       from <tol@stacken.kth.se>
+
+2001-08-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getaddrinfo.c: include a definition of in6addr_loopback if it
+       doesn't exist
+
+2001-08-10  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): update to 14:2:5
+
+2001-08-08  Assar Westerlund  <assar@sics.se>
+
+       * hstrerror.c: move h_errno to its own file (h_errno.c)
+
+2001-08-04  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add getarg.3
+
+2001-08-01  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (mini_inetd): explicitly use PF_UNSPEC.  be more
+       resilient to bind/listen failing.
+
+2001-07-31  Assar Westerlund  <assar@sics.se>
+
+       * getifaddrs.c (getifaddrs2): remove unused variables
+
+2001-07-31  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): update version to 14:1:5
+
+2001-07-23  Assar Westerlund  <assar@sics.se>
+
+       * getarg.c (arg_match_long): fix parsing of arg_counter optional
+       argument
+
+2001-07-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): bump version to 14:0:5
+       
+2001-07-17  Assar Westerlund  <assar@sics.se>
+
+       * snprintf-test.h: add a file with renaming of the snprintf
+       functions, to be used for running the tests
+
+2001-07-11  Assar Westerlund  <assar@sics.se>
+
+       * snprintf-test.c: add more %X tests, and long and conditional
+       long long tests
+       * snprintf.c: add support for printing long long (if available)
+
+2001-07-10  Assar Westerlund  <assar@sics.se>
+
+       * getaddrinfo.c (add_hostent): adapt to const hostent_find_fqdn
+       * hostent_find_fqdn.c (hostent_find_fqdn): const-ize
+
+2001-07-09  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h (hostent_find_fqdn): add
+       * hostent_find_fqdn.c: separate out hostent_find_fqdn
+
+       * warnerr.c: move out getprogname, setprogname
+
+2001-07-03  Assar Westerlund  <assar@sics.se>
+
+       * warnerr.c (setprogname): add const cast
+       * vis.c (SVIS): add some (unsigned char) before calling isfoo*
+       * Makefile.am (libroken_la_LDFLAGS:) set version to 13:0:4
+
+       * Makefile.am: add snprintf_test
+       * snprintf.c: rewrite so that it does not stop as soon as there
+       are no more characters to print, we need to figure out how long
+       the string would have to be.  this also fixes snprintf(NULL, 0
+
+2001-06-21  Assar Westerlund  <assar@sics.se>
+
+       * simple_exec.c (pipe_execv): remove unused variable
+
+2001-06-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getdtablesize.c: fix typo in obviously never used sysctl case
+
+       * simple_exec.c: rename check_status to wait_for_process, and
+       export it; function pipe_execv similar to popen, but with more
+       control over input and output
+
+       * roken-common.h: prototypes for wait_for_process and pipe_execv
+
+2001-06-17  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h: move emalloc et al to roken.h.in
+       * Makefile.am: make emalloc,ecalloc,erealloc,estrdup conditional
+       * emalloc.c, erealloc.c, estrup.c: use errx, since errno might not
+       be set reliably
+       * ecalloc.c: add for symmetry
+
+2001-06-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * resolve.c: dns_srv_order to order srv records
+
+2001-06-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getarg.c: Grog tries to figure out if to use mdoc.old instead of
+       mdoc by looking at some macros that were only present in the old
+       version, and by looking at the number of .Oo's present. In
+       mdoc.old .Oo was a toggle, but in mdoc it's closed by .Oc, so if
+       the number of .Oo's is bigger than the number of .Oc's, it figures
+       it must be mdoc.old. This doesn't however account for called Oc's,
+       and thus grog thinks that valid pages are mdoc.old when they
+       infact are mdoc. So let's make sure that Oc's are not called by
+       other macros.
+
+2001-05-29  Assar Westerlund  <assar@sics.se>
+
+       * base64-test.c (main): initialize numerr
+
+2001-05-28  Johan Danielsson  <joda@pdc.kth.se>
+
+       * base64.c: clean up the decode mess somewhat
+
+       * base64-test.c: base64 tests
+
+2001-05-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.h.in: just use standard C types with bswap*
+
+       * bswap.c: just use standard C types
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in: include all the headers that AC_GROK_TYPES tries for
+       finding u_int17_t et al
+
+       * Makefile.am: bump version to 12:0:3
+       * roken.h.in: re-add set_progname and get_progname for backwards
+       compatability
+       * warnerr.c: re-add set_progname and get_progname for backwards
+       compatability
+
+2001-05-12  Assar Westerlund  <assar@sics.se>
+
+       * glob.c: add limits.h, from <shadow@dementia.org>
+
+2001-05-11  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: bswap.c
+       
+       * bswap.c: bswap{16,32}
+       
+2001-05-08  Assar Westerlund  <assar@sics.se>
+
+       * freeaddrinfo.c (freeaddrinfo): also free every `struct
+       addrinfo'.  from <tmartin@mirapoint.com>
+
+2001-04-25  Assar Westerlund  <assar@sics.se>
+
+       * getarg.h (free_getarg_strings): add prototype
+       * getarg.c (free_getarg_strings): add function
+
+2001-04-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getarg.c: pack short flag options togther, to shorten the usage
+       string
+
+2001-04-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getifaddrs.c (getifaddrs2): close socket when done
+
+2001-03-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.awk: END has to be last with Sun's awk
+
+2001-03-26  Assar Westerlund  <assar@sics.se>
+
+       * parse_units.c (parse_something): do not check the return value
+       from strtod, it might return != 0.0 when the string has no digits.
+       just testing if it consumed any characters is enough and more
+       resilient
+       * glob.c: add GLOB_LIMIT (from NetBSD)
+
+2001-02-20  Assar Westerlund  <assar@sics.se>
+
+       * warnerr.c (warnerr): do not use __progname
+       * roken.h.in (setprogname, getprogname): add prototypes
+       * warnerr.c (setprogname, getprogname): rename to. change all
+       callers
+       
+2001-02-12  Assar Westerlund  <assar@sics.se>
+
+       * getnameinfo_verified.c (getnameinfo_verified): do the first
+       getnameinfo with NI_NUMERICSERV to avoid the error that bind 8.2.3
+       reports on not finding the service
+       (ENI_NOSERVNAME).  reported by Ake Sandgren <ake@cs.umu.se>
+
+2001-02-09  Assar Westerlund  <assar@sics.se>
+
+       * getnameinfo.c (doit): call inet_ntop with correct af, noted by
+       Ake Sandgren <ake@cs.umu.se>
+
+2001-02-08  Assar Westerlund  <assar@sics.se>
+
+       * getnameinfo_verified.c (getnameinfo_verified): always capture
+       the service from getnameinfo so it can be sent back to getaddrinfo
+       and set socktype to avoid getaddrinfo not returning any addresses
+
+2001-01-30  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): bump version to 11:1:2
+       * print_version.c (print_version): add 2001
+
+2001-01-29  Assar Westerlund  <assar@sics.se>
+
+       * getifaddrs.c (getifaddrs2): copy the entire sockaddr
+
+       * roken-common.h (_PATH_BSHELL): add
+
+2001-01-27  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in: move __attribute__ to roken-common.h
+
+       * esetenv.c (esetenv): cast to handle a setenv that takes a `char
+       * which is the case on Unicos
+
+2000-12-29  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (EXTRA_libroken_la_SOURCES): ifaddrs.h ->
+       ifaddrs.hin
+
+2000-12-25  Assar Westerlund  <assar@sics.se>
+
+       * getarg.c (print_arg): add a case for arg_strings
+
+2000-12-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * snprintf.c (append_string): handle NULL strings by printing
+       `(null)'
+
+2000-12-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken-common.h: add c++ externs
+
+       * roken.h.in: fix last commit differently
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * err.hin (warnerr): remove, it's not part of the err.h interface
+       * roken-common.h (warnerr): moved here from err.hin
+       * Makefile.am (libroken_la_LDFLAGS): set version to 11:0:2
+       * vis.c: s/u_int32_t/unsigned/ for systems that do not define
+       u_int32_t
+
+2000-12-10  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: rename some headers to avoid conflict with possible
+       system headers
+
+2000-12-06  Johan Danielsson  <joda@pdc.kth.se>
+
+       * vis.c: make sure _DIAGASSERT is defined
+
+       * unvis.c: make sure _DIAGASSERT is defined
+
+       * Makefile.am: unvis.c, and vis.h
+
+       * vis.h: vis.h from NetBSD
+
+       * unvis.c: unvis from NetBSD
+
+       * roken.h.in: cleanup previous
+
+       * roken-common.h: make `extern "C"' into a macro, this make emacs
+       much happier
+
+       * vis.c: strvis implementation from NetBSD
+
+       * roken.h.in: add prototypes for strvis*
+
+2000-12-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ifaddrs.h: fix freeifaddrs prototype, and add ifa_broadaddr
+       macro
+
+       * getifaddrs.c: free some memory
+
+2000-12-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * ifaddrs.h: getifaddrs implementation using SIOCGIFCONFIG etc
+
+       * getifaddrs.c: getifaddrs implementation using SIOCGIFCONFIG etc
+
+2000-10-08  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (mini_inetd): check that fds are not too large to
+       select on
+
+2000-09-24  Assar Westerlund  <assar@sics.se>
+
+       *  esetenv.c: new file/function
+
+2000-08-16  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 10:0:1
+
+2000-08-10  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (accept_it): type-correctness on parameters to
+       accept
+
+2000-08-07  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.h.in: add proto compat for getsockname
+
+2000-08-04  Johan Danielsson  <joda@pdc.kth.se>
+
+       * write_pid.c: conditionalise pidfile
+
+       * write_pid.c: add pidfile function
+
+2000-07-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: bump version to 9:0:0
+
+       * warnerr.c: add get_progname
+
+2000-07-24  Assar Westerlund  <assar@sics.se>
+
+       * getaddrinfo.c (add_hostent): if there's no fqdn in `he' try
+       reverse resolving to see if there's a fuller name there.  don't
+       use just-freed memory
+
+2000-07-22  Assar Westerlund  <assar@sics.se>
+
+       * xdbm.h: do not define ndbm functions in terms of dbm functions
+       if we're using db
+
+2000-07-20  Assar Westerlund  <assar@sics.se>
+
+       * rtbl.c (rtbl_format): avoid printing an empty row at the end
+
+2000-07-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: make this compatible with `make dist'
+
+       * Makefile.am: revert version number for now
+
+2000-07-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * configure.in: AM_PROG_LIBTOOL -> AC_PROG_LIBTOOL
+
+2000-07-17  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: set ACLOCAL_AMFLAGS
+
+2000-07-15  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getaddrinfo_hostspec.c: add new function that takes socktype
+       hint as parameter
+
+2000-07-09  Assar Westerlund  <assar@sics.se>
+
+       * rtbl.c (rtbl_add_column): initialize `col' completely
+
+       * configure.in: bring headers and functions more in-line with
+       what's actually being used
+
+2000-07-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.h.in: declare ether_addr and sockaddr_dl for AIX
+
+       * rtbl.{c,h}: simple table functions
+
+2000-07-08  Assar Westerlund  <assar@sics.se>
+
+       * configure.in (AM_INIT_AUTOMAKE): bump version to 10
+       * configure.in (AC_BROKEN): add strsep_copy
+       * Makefile.am (ACLOCAL): fetch files from cf
+
+2000-07-01  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h (pid_file_*): fix protos
+
+2000-06-28  Assar Westerlund  <assar@sics.se>
+
+       * getnameinfo_verified.c (getnameinfo_verified): free memory
+       returned from getaddrinfo
+
+2000-06-27  Assar Westerlund  <assar@sics.se>
+
+       * resolve.c: export string_to_type and type_to_string
+       * resolve.c: add key,sig,cert update test-program
+       * resolve.h: add key,sig,cert
+
+2000-06-21  Assar Westerlund  <assar@sics.se>
+
+       * resolve.h: add T_SIG, T_KEY
+       * resolve.c: add SIG and KEY
+       * Makefile.am (libroken_la_SOURCES): add environment.c and
+       write_pid.c
+
+       * write_pid.c: new file for writing a pid file.
+
+       * environment.c: new file with functionality for reading
+       /etc/environment.  From Ake Sandgren <ake@cs.umu.se>
+
+2000-06-12  Johan Danielsson  <joda@pdc.kth.se>
+
+       * strsep_copy.c: strsep, but with const stringp so returns string
+       in separate buffer
+
+2000-05-23  Assar Westerlund  <assar@sics.se>
+
+       * vsyslog.c (vsyslog): calculate length of new format string
+       correctly
+
+2000-05-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getusershell.c: implment the AIX version use
+       /etc/security/login.cfg
+
+2000-05-21  Assar Westerlund  <assar@sics.se>
+
+       * vsyslog.c (vsyslog): actually handle `%m'
+
+2000-05-15  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): set version to 8:1:3
+
+       * roken-common.h: moved __attribute__ to roken.h.in
+
+2000-04-14  Assar Westerlund  <assar@sics.se>
+
+       * getaddrinfo_hostspec.c (roken_getaddrinfo_hostspec): copy the
+       correct length from `hostspec'.  based on a patch from Love
+       <lha@s3.kth.se>
+
+2000-04-09  Assar Westerlund  <assar@sics.se>
+
+       * xdbm.h: only include one of db.h and the dbm-series
+
+2000-04-05  Assar Westerlund  <assar@sics.se>
+
+       * resolve.c (_resolve_debug): explicitly set to zero.  this moves
+       the variable from bss to data and the dynamic linker on MacOS
+       X/Darwin seems unhappy with stuff in the bss segment.
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 8:0:3
+
+2000-03-11  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (_SS_PAD1SIZE): try to write an inpenetrable
+       expression that also works on Crays
+
+2000-03-09  Assar Westerlund  <assar@sics.se>
+
+       * getarg.c (arg_match_short): backup optind when there's a missing
+       argument so that the error can point at the flag and not the
+       non-existant argument
+
+2000-03-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (SOURCES): add timeval.c
+       * Makefile.am (libroken_la_SOURCES): add timeval.c
+       * timeval.c: new file
+
+2000-02-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 7:1:2
+       
+2000-02-16  Assar Westerlund  <assar@sics.se>
+
+       * snprintf.c (PARSE_INT_FORMAT): note that shorts are actually
+       transmitted as ints
+       (according to the integer protomotion rules) in variable arguments
+       lists.  Therefore, we should not call va_arg with short but rather
+       with int.  See <http://www.debian.org/Bugs/db/57/57919.html> for
+       original bug report
+
+2000-02-13  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 7:0:2
+
+       * getarg.c (mandoc_template): also fix no- prefix in .Sh OPTIONS
+       * getarg.c (mandoc_template): better man-stuff for negative
+       options
+
+2000-02-07  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 6:0:1
+
+2000-02-06  Assar Westerlund  <assar@sics.se>
+
+       * xdbm.h: hopefully catch a few more declarations by including
+       <ndbm.h> even if <db.h> was found
+
+2000-01-26  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (mini_inetd): separate number of allocated sockets
+       and number of actual ones
+       * mini_inetd.c (mini_inetd): count sockets properly.  and fail if
+       we cannot bind any
+       * mini_inetd.c (mini_inetd): make failing to create a socket
+       non-fatal
+
+2000-01-09  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am(libroken_la_SOURCES): add strcollect.c
+       * Makefile.in: add strcollect.[co]
+       * simple_exec.c: use vstrcollect
+       * roken-common.h (_PATH_DEV): add
+       (strcollect, vstrcollect): add prototypes
+       * strcollect.c: new file.  functions for collapsing an `va_list'
+       into an `char **'
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 5:0:0
+
+1999-12-30  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (strpftime_test_SOURCES): correct source file name
+
+       * roken.h.in (sockaddr_storage): change padding so that we have
+       one char[] of pad and then an unsigned long[] (for alignment and
+       padding).  this works much better in practice.
+
+1999-12-22  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (sockaddr_storage): drop leading underscore on
+       `public' fields.  this was the consensus on the ipng mailing list
+
+1999-12-21  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (strpftime-test): define sources to avoid having
+       '.o'
+       * Makefile.am (print_version.h): use $(EXEEXT)
+       * Makefile.am (roken.h): add $(EXEEXT) to make this work on cygwin
+       et al
+
+1999-12-20  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): bump version to 4:3:0
+
+       * getaddrinfo.c (get_nodes): use getipnodebyname instead of
+       gethostbyname(2)
+
+1999-12-16  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_LDFLAGS): bump version to 4:2:0
+
+       * roken.h.in (struct sockaddr_storage): redefine with the example
+       code from rfc2553
+
+       * getaddrinfo.c (get_null): set loopback with correct endianess
+       for v4.  dunno about v6.
+
+1999-12-13  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in: add prototypes for str[pf]time
+
+       * signal.c: macosx = rhapsody ~= nextstep also can't handle
+       various definitions of the same symbol.
+
+1999-12-12  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 4:1:0
+
+1999-12-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 4:0:0
+
+1999-12-05  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in: replace inaddr2str with getnameinfo_verified
+
+       * roken-common.h (INADDR_LOOPBACK): add fallback definition
+
+       * roken-common.h: move getnameinfo_verified to roken.h.in
+       * roken.h.in (inaddr2str): remove
+       * Makefile.am (libroken_la_SOURCES); removed inaddr2str
+       * roken-common.h (getnameinfo_verified): add prototype
+       * getnameinfo_verified.c: new file
+
+1999-12-04  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h: add constants for getaddrinfo, getnameinfo
+       * roken.h.in (socklen_t): make independent of sockaddr_storage
+       (AI_*, NI_*, EAI_*): move to roken-common.h
+
+1999-12-03  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (mini_inted): rewrite to use `getaddrinfo'
+       * getaddrinfo.c (const_v*): no sizeof(sizeof())
+       * getaddrinfo.c (add_hostent): search for the canonical name among
+       all aliases
+       (getaddrinfo): handle AI_NUMERICHOST correctly
+       * Makefile.am (EXTRA_libroken_la_SOURCES): add freeaddinfo,
+       getaddrinfo, getnameinfo, gai_strerror
+       (getaddrinfo_test): add
+       * Makefile.in (SOURCES): add freeaddinfo, getaddrinfo,
+       getnameinfo, gai_strerror
+       (getaddrinfo_test): add
+       * roken.h.in: arpa/inet.h: include
+       (socklen_t): add
+       (struct addrinfo): add
+       (EAI_*): add
+       (NI_*): add
+       (AI_*): add
+       (getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror): add
+       * getnameinfo.c: new file
+       * getaddrinfo-test.c: new file
+       * gai_strerror.c: new file
+       * getaddrinfo.c: new file
+       * freeaddrinfo.c: new file
+
+1999-11-25  Assar Westerlund  <assar@sics.se>
+
+       * getopt.c (getopt): return -1 instead of EOF.  From
+       <art@stacken.kth.se>
+
+1999-11-13  Assar Westerlund  <assar@sics.se>
+
+       * strftime.c (strftime): handle `%z' and `%Z' in a tm_gmtoff-less
+       world
+
+       * getcap.c: make sure to use db only if we have both the library
+       and the header file
+       
+1999-11-12  Assar Westerlund  <assar@sics.se>
+
+       * getarg.h: add arg_counter
+       * getarg.c: add a new type of argument: `arg_counter' re-organize
+       the code somewhat
+       
+       * Makefile.am: add strptime and strpftime-test
+       
+       * snprintf.c (xyzprintf): try to do the right thing with an % at
+       the end of the format string
+       
+       * strptime.c (strptime): implement '%U', '%V', '%W'
+       * strftime.c (strftime): implement '%U', '%V', '%W', '%z'
+       
+       * strftime.c (strftime): correct %E and %O handling.  do something
+       reasonable with "...%"
+
+       * strftime.c: replace the BSD implementation by one of our own
+       coding
+
+       * strptime.c : new file
+       * strpftime-test.c: new file
+
+1999-11-07  Assar Westerlund  <assar@sics.se>
+
+       * parse_bytes-test.c: new file
+
+       * Makefile.am: add parse_bytes-test
+
+       * parse_units.c (parse_something): try to handle the case of no
+       value specified a little bit better
+
+1999-11-04  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 3:2:0
+
+1999-10-30  Assar Westerlund  <assar@sics.se>
+
+       * snprintf.c (PARSE_INT_FORMAT): add redundant casts to work
+       around a gcc-bug that manifests itself on Linux-PPC.  From Tom
+       Rini <trini@kernel.crashing.org>
+
+1999-10-28  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump version to 3:1:0
+
+       * roken.h.in: use `unsigned char' instead of `u_int8_t' to avoid
+       having to have that definition.  this is the easy way out instead
+       of getting the definition here where it's needed.  flame me.
+
+Fri Oct 22 15:39:31 1999  Bjoern Groenvall  <bg@sics.se>
+
+       * k_getpwuid.c (k_getpwuid): getspuid() does not exist (even
+       though it should), use getspnam().
+
+1999-10-20  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 3:0:0
+
+1999-10-18  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getarg.3: document arg_collect
+
+       * getarg.c: change the way arg_collect works; it's still quite
+       horrible though
+
+       * getarg.h: change type of the collect function
+
+1999-10-17  Assar Westerlund  <assar@sics.se>
+
+       * xdbm.h: undo last commit
+
+       * xdbm.h: reorder db includes
+
+1999-10-10  Assar Westerlund  <assar@sics.se>
+
+       * socket.c: const-ize and comment
+
+       * net_write.c: const-ize
+
+       * base64.c: const-ize
+
+1999-10-06  Assar Westerlund  <assar@sics.se>
+
+       * getarg.c (getarg): also set optind when returning error
+
+1999-09-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add parse_bytes.[ch]
+
+1999-09-24  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getarg.3: getarg manpage
+
+       * getarg.{c,h}: add a callback type to do more complicated processing
+
+       * getarg.{c,h}: add floating point support
+
+1999-09-16  Assar Westerlund  <assar@sics.se>
+
+       * strlcat.c (strlcat): call strlcpy
+
+       * strlcpy.c: update name and prototype
+
+       * strlcat.c: update name and prototype
+
+       * roken.h.in: rename strc{py,at}_truncate to strlc{py,at}
+
+       * Makefile.am: rename strc{py,at}_truncate -> strlc{py,at}
+
+       * Makefile.in: rename strc{py,at}_truncate -> strlc{py,at}
+
+       * strcpy_truncate.c (strcpy_truncate): change return value to be
+       the length of `src'
+
+1999-08-16  Assar Westerlund  <assar@sics.se>
+
+       * getcap.c: try to make this work on systems with DB
+
+1999-08-16  Johan Danielsson  <joda@pdc.kth.se>
+
+       * getcap.c: protect from db-less systems
+
+1999-08-09  Johan Danielsson  <joda@pdc.kth.se>
+
+       * simple_exec.c: add simple_exec{ve,le}
+
+       * getcap.c: getcap from NetBSD
+
+1999-08-06  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (sockaddr_storage): cater for those that have
+       v6-support also
+
+1999-08-05  Assar Westerlund  <assar@sics.se>
+
+       * inet_ntop.c (inet_ntop_v4): remember to call ntohl
+
+1999-08-04  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h: add shutdown constants
+
+       * mini_inetd.c (listen_v4, listen_v6): handle the case of the
+       protocol not being supported
+
+1999-08-01  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (socket_set_reuseaddr): remove duplicate
+
+1999-07-29  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c (mini_inetd): fix my stupid bugs
+
+1999-07-28  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h: add socket* functions
+
+       * Makefile.am (libroken_la_SOURCES): add socket.c
+
+       * socket.c: new file, originally from appl/ftp/common
+
+       * Makefile.am: set version to 2:0:2
+
+       * roken.h.in (inet_pton): add prototype
+
+       * Makefile.am (EXTRA_libroken_la_SOURCES): add inet_pton
+
+       * inet_pton.c: new file
+
+       * getipnodebyname.c (getipnodebyname): try gethostbyname2 if we
+       have it
+
+1999-07-27  Assar Westerlund  <assar@sics.se>
+
+       * mini_inetd.c: support IPv6
+
+1999-07-26  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 1:0:1
+
+       * roken.h.in (inet_ntop): add prototype
+
+       * roken-common.h: (INET{,6}_ADDRSTRLEN): add
+
+       * inet_ntop.c: new file
+
+       * Makefile.am (EXTRA_libroken_la_SOURCES): add inet_ntop.c
+
+       * Makefile.am: move some files from libroken_la_SOURCES to
+       EXTRA_libroken_la_SOURCES
+
+       * snprintf.c: some signed vs unsigned casts
+       
+1999-07-24  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (struct sockaddr_storage): define it needed
+
+1999-07-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libroken_la_SOURCES): add copyhostent.c,
+       freehostent.c, getipnodebyname.c, getipnodebyaddr.c
+       
+       * roken.h.in: <netdb.h>: include
+       (copyhostent, freehostent, getipnodebyname, getipnodebyaddr): add
+       prototypes
+
+       * roken-common.h: new constants for getipnodeby*
+
+       * Makefile.in (SOURCES): add freehostent, copyhostent,
+       getipnodebyname, getipnodebyaddr
+
+       * freehostent.c: new file
+
+       * copyhostent.c: new file
+
+       * getipnodebyaddr.c: new file
+
+       * getipnodebyname.c: new file
+
+1999-07-13  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (k_getpwnam): update prototype
+
+       * k_getpwnam.c (k_getpwnam): const-ize
+
+       * get_default_username.c (get_default_username): a better way of
+       guessing when the user has su:ed
+
+1999-07-08  Johan Danielsson  <joda@pdc.kth.se>
+
+       * roken.awk: use puts, as suggested by Jeffrey Hutzelman
+       <jhutz+@cmu.edu>
+
+1999-07-06  Assar Westerlund  <assar@sics.se>
+
+       * readv.c (readv): typo
+
+1999-07-03  Assar Westerlund  <assar@sics.se>
+
+       * writev.c (writev): error check malloc properly
+
+       * sendmsg.c (sendmsg): error check malloc properly
+
+       * resolve.c (parse_reply): error check malloc properly
+
+       * recvmsg.c (recvmsg): error check malloc properly
+
+       * readv.c (readv): error check malloc properly
+
+1999-06-23  Assar Westerlund  <assar@sics.se>
+
+       * parse_units.c (acc_units): move the special case of 0 -> 1 to
+       parse_something to avoid having it happen at the end of the string
+
+1999-06-15  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in: add get_default_username
+
+       * get_default_username.c: new file
+
+       * roken.h.in (get_default_username): add prototype
+
+       * Makefile.am: add get_default_username
+
+1999-05-08  Assar Westerlund  <assar@sics.se>
+
+       * xdbm.h: also try <db.h> with DB_DBM_HSEARCH == 1
+
+       * strnlen.c (strnlen): update prototype
+
+       * Makefile.am: strndup.c: add
+
+       * Makefile.in: strndup.c: add
+
+       * roken.h.in (strndup): add
+       (strnlen): update prototype
+
+       * strndup.c: new file
+
+Fri Apr 16 17:59:30 1999  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in: include strsep prototype if needed
+
+Thu Apr 15 14:04:03 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: make make-print-version.o depend on version.h
+
+Wed Apr  7 14:11:00 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: make it compile w/o krb4
+
+Sat Mar 27 17:33:03 1999  Johan Danielsson  <joda@blubb.pdc.kth.se>
+
+       * snprintf.c (vasnprintf): correct check if realloc returns NULL
+
+Sat Mar 27 12:37:55 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: link print_version with -ldes to avoid unresolved
+       references if -lkrb is shared
+
+Sat Mar 20 03:42:30 1999  Assar Westerlund  <assar@sics.se>
+
+       * roken-common.h (eread, ewrite): add
+
+       * simple_exec.c: add <roken.h>
+
+Fri Mar 19 21:29:58 1999  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in: add eread, ewrite
+
+       * eread.c, ewrite.c: new files
+
+       * Makefile.am (libroken_la_SOURCES): add eread and ewrite
+
+Fri Mar 19 14:52:57 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: add version-info
+
+Thu Mar 18 12:53:32 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: remove include_dir hack
+
+       * Makefile.am: parse_units.h
+
+       * Makefile.am: include Makefile.am.common
+
+Sat Mar 13 23:31:35 1999  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (SOURCES): add glob.c
+
+Thu Mar 11 15:02:21 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * iruserok.c: move innetgr() to separate file
+
+       * innetgr.c: move innetgr() to separate file
+
+       * hstrerror.c (hstrerror): add const to return type
+
+       * erealloc.c: fix types in format string
+
+       * emalloc.c: fix types in format string
+
+Wed Mar 10 16:36:55 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * resolve.c: ugly fix for crays
+
+Mon Mar  8 11:52:20 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * roken.h.in: protos for {un,}setenv
+
+1999-02-16  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (SOURCES): add fnmatch
+
+       * roken-common.h (abs): add
+
+Sat Feb 13 17:12:53 1999  Assar Westerlund  <assar@sics.se>
+
+       * emalloc.c, erealloc.c, estrup.c: new files
+
+       * roken.h.in (mkstemp, gethostname): also includes prototypes if
+       they are needed.
+
+1998-12-23  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in: mkstemp: add prototype
+
+1998-12-20  Assar Westerlund  <assar@sics.se>
+
+       * snprintf.c, iruserok.c, parse-units.c: unsigned char-correctness
+
+       * roken.h.in (inet_aton): also chedk NEED_INET_ATON_PROTO
+
+       * roken-common.h: __attribute__: check for autoconf'd
+       HAVE___ATTRIBUTE__ instead of GNUC
+
+Sun Dec  6 19:53:21 1998  Assar Westerlund  <assar@sics.se>
+
+       * parse_units.c (parse_something): func is called with val == 0 if
+       no unit was given
+       (acc_flags, acc_units): update to new standard
+
+Fri Nov 27 03:09:42 1998  Assar Westerlund  <assar@sics.se>
+
+       * resolve.c (stot): constify
+       (type_to_string): always declare
+       (dns_lookup_int): correct debug output
+
+Thu Nov 26 23:43:55 1998  Assar Westerlund  <assar@sics.se>
+
+       * resolve.c (dns_lookup_int): send rr_class to res_search
+
+Thu Nov 26 17:09:47 1998  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * resolve.c: some cleanup
+
+       * resolve.h: add T_NAPTR
+
+Sun Nov 22 10:23:07 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (WFLAGS): set
+
+       * k_getpwnam.c (k_getpwnam): check for `struct spwd'
+
+       * k_getpwuid.c (k_getpwuid): check for `struct spwd'
+
+Tue Sep  8 05:18:31 1998  Assar Westerlund  <assar@sics.se>
+
+       * recvmsg.c (recvmsg): patch from bpreece@unity.ncsu.edu
+
+Fri Sep  4 16:29:27 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * vsyslog.c: asprintf -> vasprintf
+
+Tue Aug 18 22:25:52 1998  Assar Westerlund  <assar@sics.se>
+
+       * getarg.h (arg_printusage): new signature
+
+       * getarg.c (arg_printusage): new parameter `progname'.  NULL means
+       __progname.
+
+Sun Aug  9 14:53:44 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Makefile.am: net_{read,write}.c
+
+Fri Jul 24 21:56:02 1998  Assar Westerlund  <assar@sics.se>
+
+       * simple_exec.c (simple_execvp): loop around waitpid when errno ==
+       EINTR
+
+Thu Jul 23 20:24:35 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Makefile.am: net_{read,write}.c
+
+Wed Jul 22 21:38:35 1998  Assar Westerlund  <assar@sics.se>
+
+       * simple_exec.c (simple_execlp): initialize `argv'
+
+Mon Jul 13 23:01:22 1998  Assar Westerlund  <assar@sics.se>
+
+       * inaddr2str.c (inaddr2str): don't advance hostent->h_addr_list,
+       use a copy instead
+
+Fri Jul 10 01:20:08 1998  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (net_write, net_read): add prototypes
+
+       * Makefile.in: net_{read,write}.c: add
+
+       * net_{read,write}.c: new files
+
+Tue Jun 30 17:29:09 1998  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in (issuid): add
+
+       * get_window_size.c: fix misspelling of TIOCGWINSZ and bad use of
+       fields
+
+Sun May 31 03:24:34 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * getarg.c (mandoc_template): Put short and long options in
+       SYNOPSIS within the same [ ] pair.
+
+Sat May 30 00:13:01 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * getarg.c (arg_printusage): try to keep options shorter than
+       column width
+
+       * get_window_size.c (get_window_size): check COLUMNS and LINES
+
+Fri May 29 00:05:04 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * getarg.c (mandoc_template): Put short and long options in
+       DESCRIPTION on the same line.
+
+       * getarg.c (arg_match_long): make sure you only get an exact match
+       if the strings are the same length
+
+Thu May 14 02:23:40 1998  Assar Westerlund  <assar@sics.se>
+
+       * roken.awk: stupid cray awk wants \#
+
+Fri May  1 01:29:36 1998  Assar Westerlund  <assar@sics.se>
+
+       * print_version.c (print_version): according to ISO/ANSI C the
+       elements of `arg' are not constant and therefore not settable at
+       compile-time.  Set the at run-time instead.
+
+Sun Apr 19 10:00:06 1998  Assar Westerlund  <assar@sics.se>
+
+       * roken.h.in: include paths.h
+
+Sun Apr  5 12:30:49 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (SOURCES): add roken_gethostby.c to make solaris
+       make happy
+
+Thu Mar 19 20:41:25 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * simple_exec.c: Simple fork+exec system() replacement.
+
+Fri Mar  6 00:21:53 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * roken_gethostby.c: Make `roken_gethostby_setup' take URL-like
+       specification instead of split up versions. Makes it easier for
+       calling applications.
+
+       * roken_gethostby.c: Another miracle of the 20th century:
+       gethostby* over HTTP.
+
+Sat Feb 21 15:18:36 1998  assar westerlund  <assar@sics.se>
+
+       * parse_time.c (unparse_time_approx): new function that calls
+       `unparse_units_approx'
+
+       * parse_units.c (unparse_units_approx): new function that will
+       only print the first unit.
+
+       * Makefile.in: include parse_{time,units}
+
+Thu Feb 12 03:30:08 1998  Assar Westerlund  <assar@sics.se>
+
+       * parse_time.c (print_time_table): don't return a void value.
+
+Tue Feb  3 11:06:24 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * getarg.c (mandoc_template): Change date format to full month
+       name, and day of month without leading zero.
+
+Thu Jan 22 21:23:23 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * getarg.c: Fix long form of negative flags.
+
+Mon Dec 29 23:31:10 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * roken.h.in: Include <err.h>, to get linux __progname.
+
+Sun Dec 21 09:45:18 1997  Assar Westerlund  <assar@sics.se>
+
+       * parse_time.c (print_time_table): new function
+
+       * parse_units.c (print_flags_table, print_units_table): new
+       functions.
+
+Thu Dec  4 02:51:46 1997  Assar Westerlund  <assar@sics.se>
+
+       * iruserok.c: moved here.
+
+       * snprintf.c (sn_append_char): don't write any terminating zero.
+       (as_reserve): don't loop.  better heuristic for how much space to
+       realloc.
+       (vasnprintf): simplify initializing to one.
+
+Sun Nov 30 14:56:59 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * getarg.c: Add mandoc help back-end to getarg.
+
+Wed Nov 12 01:09:17 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * verr.c, verrx.c: Fix warnings by moving exit from.
+
+Tue Nov 11 21:12:09 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * parse_units.c: Change the list of separating characters (between
+       units) to comma, space, and tab, removing digits. Having digits in
+       this list makes a flag like `T42 generate a parse error. This
+       change makes `17m3s' an invalid time-spec (you need a space).
+
+Tue Nov 11 02:38:44 1997  Assar Westerlund  <assar@sics.se>
+
+       * roken.h: add <sys/socket.h>
+
+Sun Nov  9 04:48:46 1997  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * fnmatch.c: Add fnmatch from NetBSD
+
+Sun Nov  9 02:00:08 1997  Assar Westerlund  <assar@sics.se>
+
+       * parse_units.c (parse_something): ignore white-space and ','
+
+Mon Nov  3 22:38:32 1997  Assar Westerlund  <assar@sics.se>
+       
+       * roken.h: fclose prototype
+
+       * roken.h: add prototype for vsyslog
+
+       * Makefile.in: add some more source files to make soriasis make
+       happy
+
+Sat Nov  1 00:19:21 1997  Assar Westerlund  <assar@sics.se>
+
+       * roken.h: include <sys/uio.h> and <errno.h>.
+       prototypes for readv and writev
+
+       * readv.c, writev.c: new files
+
+Wed Oct 29 02:21:38 1997  Assar Westerlund  <assar@sics.se>
+
+       * roken.h: Add ugly macros for openlog, gethostbyname,
+       gethostbyaddr, and getservbyname for the benefit of Crays.  Add
+       default definition of MAXPATHLEN
diff --git a/src/kerberosV/src/lib/roken/acconfig.h b/src/kerberosV/src/lib/roken/acconfig.h
new file mode 100644 (file)
index 0000000..5fbe685
--- /dev/null
@@ -0,0 +1,36 @@
+@BOTTOM@
+
+#ifdef BROKEN_REALLOC
+#define realloc(X, Y) isoc_realloc((X), (Y))
+#define isoc_realloc(X, Y) ((X) ? realloc((X), (Y)) : malloc(Y))
+#endif
+
+#ifdef VOID_RETSIGTYPE
+#define SIGRETURN(x) return
+#else
+#define SIGRETURN(x) return (RETSIGTYPE)(x)
+#endif
+
+#define RCSID(msg) \
+static /**/const char *const rcsid[] = { (const char *)rcsid, "\100(#)" msg }
+
+#undef PROTOTYPES
+
+/* Maximum values on all known systems */
+#define MaxHostNameLen (64+4)
+#define MaxPathLen (1024+4)
+
+/*
+ * Define NDBM if you are using the 4.3 ndbm library (which is part of
+ * libc).  If not defined, 4.2 dbm will be assumed.
+ */
+#if defined(HAVE_DBM_FIRSTKEY)
+#define NDBM
+#endif
+
+/*
+ * Defining this enables lots of useful (and used) extensions on
+ * glibc-based systems such as Linux
+ */
+
+#define _GNU_SOURCE
diff --git a/src/kerberosV/src/lib/roken/base64-test.c b/src/kerberosV/src/lib/roken/base64-test.c
new file mode 100644 (file)
index 0000000..f67f176
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: base64-test.c,v 1.3 2005/04/04 19:24:18 lha Exp $");
+#endif
+
+#include <roken.h>
+#include <base64.h>
+
+int
+main(int argc, char **argv)
+{
+    int numerr = 0;
+    int numtest = 1;
+    struct test {
+       void *data;
+       size_t len;
+       const char *result;
+    } *t, tests[] = {
+       { "", 0 , "" },
+       { "1", 1, "MQ==" },
+       { "22", 2, "MjI=" },
+       { "333", 3, "MzMz" },
+       { "4444", 4, "NDQ0NA==" },
+       { "55555", 5, "NTU1NTU=" },
+       { "abc:def", 7, "YWJjOmRlZg==" },
+       { NULL }
+    };
+    for(t = tests; t->data; t++) {
+       char *str;
+       int len;
+       len = base64_encode(t->data, t->len, &str);
+       if(strcmp(str, t->result) != 0) {
+           fprintf(stderr, "failed test %d: %s != %s\n", numtest, 
+                   str, t->result);
+           numerr++;
+       }
+       free(str);
+       str = strdup(t->result);
+       len = base64_decode(t->result, str);
+       if(len != t->len) {
+           fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
+                   (unsigned long)len, (unsigned long)t->len);
+           numerr++;
+       } else if(memcmp(str, t->data, t->len) != 0) {
+           fprintf(stderr, "failed test %d: data\n", numtest);
+           numerr++;
+       }
+       free(str);
+       numtest++;
+    }
+
+    {
+       char str[32];
+       if(base64_decode("M=M=", str) != -1) {
+           fprintf(stderr, "failed test %d: successful decode of `M=M='\n", 
+                   numtest++);
+           numerr++;
+       }
+       if(base64_decode("MQ===", str) != -1) {
+           fprintf(stderr, "failed test %d: successful decode of `MQ==='\n", 
+                   numtest++);
+           numerr++;
+       }
+    }
+    return numerr;
+}
diff --git a/src/kerberosV/src/lib/roken/base64.c b/src/kerberosV/src/lib/roken/base64.c
new file mode 100644 (file)
index 0000000..1a4d6bc
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1995-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: base64.c,v 1.6 2005/04/12 11:28:34 lha Exp $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "base64.h"
+
+static char base64_chars[] = 
+    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+static int 
+pos(char c)
+{
+    char *p;
+    for (p = base64_chars; *p; p++)
+       if (*p == c)
+           return p - base64_chars;
+    return -1;
+}
+
+int ROKEN_LIB_FUNCTION
+base64_encode(const void *data, int size, char **str)
+{
+    char *s, *p;
+    int i;
+    int c;
+    const unsigned char *q;
+
+    p = s = (char *) malloc(size * 4 / 3 + 4);
+    if (p == NULL)
+       return -1;
+    q = (const unsigned char *) data;
+    i = 0;
+    for (i = 0; i < size;) {
+       c = q[i++];
+       c *= 256;
+       if (i < size)
+           c += q[i];
+       i++;
+       c *= 256;
+       if (i < size)
+           c += q[i];
+       i++;
+       p[0] = base64_chars[(c & 0x00fc0000) >> 18];
+       p[1] = base64_chars[(c & 0x0003f000) >> 12];
+       p[2] = base64_chars[(c & 0x00000fc0) >> 6];
+       p[3] = base64_chars[(c & 0x0000003f) >> 0];
+       if (i > size)
+           p[3] = '=';
+       if (i > size + 1)
+           p[2] = '=';
+       p += 4;
+    }
+    *p = 0;
+    *str = s;
+    return strlen(s);
+}
+
+#define DECODE_ERROR 0xffffffff
+
+static unsigned int
+token_decode(const char *token)
+{
+    int i;
+    unsigned int val = 0;
+    int marker = 0;
+    if (strlen(token) < 4)
+       return DECODE_ERROR;
+    for (i = 0; i < 4; i++) {
+       val *= 64;
+       if (token[i] == '=')
+           marker++;
+       else if (marker > 0)
+           return DECODE_ERROR;
+       else
+           val += pos(token[i]);
+    }
+    if (marker > 2)
+       return DECODE_ERROR;
+    return (marker << 24) | val;
+}
+
+int ROKEN_LIB_FUNCTION
+base64_decode(const char *str, void *data)
+{
+    const char *p;
+    unsigned char *q;
+
+    q = data;
+    for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) {
+       unsigned int val = token_decode(p);
+       unsigned int marker = (val >> 24) & 0xff;
+       if (val == DECODE_ERROR)
+           return -1;
+       *q++ = (val >> 16) & 0xff;
+       if (marker < 2)
+           *q++ = (val >> 8) & 0xff;
+       if (marker < 1)
+           *q++ = val & 0xff;
+    }
+    return q - (unsigned char *) data;
+}
diff --git a/src/kerberosV/src/lib/roken/base64.h b/src/kerberosV/src/lib/roken/base64.h
new file mode 100644 (file)
index 0000000..192e788
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: base64.h,v 1.3 2005/04/12 11:28:34 lha Exp $ */
+
+#ifndef _BASE64_H_
+#define _BASE64_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+int ROKEN_LIB_FUNCTION
+base64_encode(const void *data, int size, char **str);
+
+int ROKEN_LIB_FUNCTION
+base64_decode(const char *str, void *data);
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/bswap.c b/src/kerberosV/src/lib/roken/bswap.c
new file mode 100644 (file)
index 0000000..4fac2cb
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$KTH: bswap.c,v 1.4 2005/04/12 11:28:35 lha Exp $");
+
+#ifndef HAVE_BSWAP32
+
+unsigned int ROKEN_LIB_FUNCTION
+bswap32 (unsigned int val)
+{
+    return (val & 0xff) << 24 |
+       (val & 0xff00) << 8 |
+       (val & 0xff0000) >> 8 |
+       (val & 0xff000000) >> 24;
+}
+#endif
+
+#ifndef HAVE_BSWAP16
+
+unsigned short ROKEN_LIB_FUNCTION
+bswap16 (unsigned short val)
+{
+    return (val & 0xff) << 8 |
+       (val & 0xff00) >> 8;
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/chown.c b/src/kerberosV/src/lib/roken/chown.c
new file mode 100644 (file)
index 0000000..e547ccd
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: chown.c,v 1.4 2005/04/12 11:28:35 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+chown(const char *path, uid_t owner, gid_t group)
+{
+  return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/closefrom.c b/src/kerberosV/src/lib/roken/closefrom.c
new file mode 100644 (file)
index 0000000..5bbdee2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: closefrom.c,v 1.2 2005/04/13 08:01:38 lha Exp $");
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <roken.h>
+
+int ROKEN_LIB_FUNCTION
+closefrom(int fd)
+{
+    int num = getdtablesize();
+
+    if (num < 0)
+       num = 1024; /* XXX */
+
+    for (; fd <= num; fd++)
+       close(fd);
+
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/compile b/src/kerberosV/src/lib/roken/compile
new file mode 100644 (file)
index 0000000..d4a34aa
--- /dev/null
@@ -0,0 +1,82 @@
+#! /bin/sh
+
+# Wrapper for compilers which do not understand `-c -o'.
+
+# Copyright 1999, 2000 Free Software Foundation, Inc.
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# 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.
+
+# Usage:
+# compile PROGRAM [ARGS]...
+# `-o FOO.o' is removed from the args passed to the actual compile.
+
+prog=$1
+shift
+
+ofile=
+cfile=
+args=
+while test $# -gt 0; do
+   case "$1" in
+    -o)
+       ofile=$2
+       shift
+       ;;
+    *.c)
+       cfile=$1
+       args="$args $1"
+       ;;
+    *)
+       args="$args $1"
+       ;;
+   esac
+   shift
+done
+
+test -z "$ofile" && {
+   echo "compile: no \`-o' option seen" 1>&2
+   exit 1
+}
+
+test -z "$cfile" && {
+   echo "compile: no \`.c' file seen" 1>&2
+   exit 1
+}
+
+# Name of file we expect compiler to create.
+cofile=`echo $cfile | sed -e 's|^.*/||' -e 's/\.c$/.o/'`
+
+# Create the lock directory.
+lockdir=`echo $ofile | sed -e 's|/|_|g'`
+while true; do
+   if mkdir $lockdir > /dev/null 2>&1; then
+      break
+   fi
+   sleep 1
+done
+# FIXME: race condition here if user kills between mkdir and trap.
+trap "rmdir $lockdir; exit 1" 1 2 15
+
+# Run the compile.
+"$prog" $args
+status=$?
+
+if test -f "$cofile"; then
+   mv "$cofile" "$ofile"
+fi
+
+rmdir $lockdir
+exit $status
diff --git a/src/kerberosV/src/lib/roken/concat.c b/src/kerberosV/src/lib/roken/concat.c
new file mode 100644 (file)
index 0000000..623c54f
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: concat.c,v 1.5 2005/04/12 11:28:35 lha Exp $");
+#endif
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+roken_concat (char *s, size_t len, ...)
+{
+    int ret;
+    va_list args;
+
+    va_start(args, len);
+    ret = roken_vconcat (s, len, args);
+    va_end(args);
+    return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+roken_vconcat (char *s, size_t len, va_list args)
+{
+    const char *a;
+
+    while ((a = va_arg(args, const char*))) {
+       size_t n = strlen (a);
+
+       if (n >= len)
+           return -1;
+       memcpy (s, a, n);
+       s += n;
+       len -= n;
+    }
+    *s = '\0';
+    return 0;
+}
+
+size_t ROKEN_LIB_FUNCTION
+roken_vmconcat (char **s, size_t max_len, va_list args)
+{
+    const char *a;
+    char *p, *q;
+    size_t len = 0;
+    *s = NULL;
+    p = malloc(1);
+    if(p == NULL)
+       return 0;
+    len = 1;
+    while ((a = va_arg(args, const char*))) {
+       size_t n = strlen (a);
+       
+       if(max_len && len + n > max_len){
+           free(p);
+           return 0;
+       }
+       q = realloc(p, len + n);
+       if(q == NULL){
+           free(p);
+           return 0;
+       }
+       p = q;
+       memcpy (p + len - 1, a, n);
+       len += n;
+    }
+    p[len - 1] = '\0';
+    *s = p;
+    return len;
+}
+
+size_t ROKEN_LIB_FUNCTION
+roken_mconcat (char **s, size_t max_len, ...)
+{
+    int ret;
+    va_list args;
+
+    va_start(args, max_len);
+    ret = roken_vmconcat (s, max_len, args);
+    va_end(args);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/config.h.in b/src/kerberosV/src/lib/roken/config.h.in
new file mode 100644 (file)
index 0000000..b3df989
--- /dev/null
@@ -0,0 +1 @@
+/*autoheader*/
diff --git a/src/kerberosV/src/lib/roken/copyhostent.c b/src/kerberosV/src/lib/roken/copyhostent.c
new file mode 100644 (file)
index 0000000..4a20aab
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: copyhostent.c,v 1.3 2005/04/12 11:28:36 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * return a malloced copy of `h'
+ */
+
+struct hostent * ROKEN_LIB_FUNCTION
+copyhostent (const struct hostent *h)
+{
+    struct hostent *res;
+    char **p;
+    int i, n;
+
+    res = malloc (sizeof (*res));
+    if (res == NULL)
+       return NULL;
+    res->h_name      = NULL;
+    res->h_aliases   = NULL;
+    res->h_addrtype  = h->h_addrtype;
+    res->h_length    = h->h_length;
+    res->h_addr_list = NULL;
+    res->h_name = strdup (h->h_name);
+    if (res->h_name == NULL) {
+       freehostent (res);
+       return NULL;
+    }
+    for (n = 0, p = h->h_aliases; *p != NULL; ++p)
+       ++n;
+    res->h_aliases = malloc ((n + 1) * sizeof(*res->h_aliases));
+    if (res->h_aliases == NULL) {
+       freehostent (res);
+       return NULL;
+    }
+    for (i = 0; i < n + 1; ++i)
+       res->h_aliases[i] = NULL;
+    for (i = 0; i < n; ++i) {
+       res->h_aliases[i] = strdup (h->h_aliases[i]);
+       if (res->h_aliases[i] == NULL) {
+           freehostent (res);
+           return NULL;
+       }
+    }
+
+    for (n = 0, p = h->h_addr_list; *p != NULL; ++p)
+       ++n;
+    res->h_addr_list = malloc ((n + 1) * sizeof(*res->h_addr_list));
+    if (res->h_addr_list == NULL) {
+       freehostent (res);
+       return NULL;
+    }
+    for (i = 0; i < n + 1; ++i) {
+       res->h_addr_list[i] = NULL;
+    }
+    for (i = 0; i < n; ++i) {
+       res->h_addr_list[i] = malloc (h->h_length);
+       if (res->h_addr_list[i] == NULL) {
+           freehostent (res);
+           return NULL;
+       }
+       memcpy (res->h_addr_list[i], h->h_addr_list[i], h->h_length);
+    }
+    return res;
+}
+
diff --git a/src/kerberosV/src/lib/roken/daemon.c b/src/kerberosV/src/lib/roken/daemon.c
new file mode 100644 (file)
index 0000000..bafb951
--- /dev/null
@@ -0,0 +1,84 @@
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)daemon.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: daemon.c,v 1.5 2005/04/12 11:28:36 lha Exp $");
+
+#ifndef HAVE_DAEMON
+
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+daemon(int nochdir, int noclose)
+{
+    int fd;
+
+    switch (fork()) {
+    case -1:
+       return (-1);
+    case 0:
+       break;
+    default:
+       _exit(0);
+    }
+
+    if (setsid() == -1)
+       return (-1);
+
+    if (!nochdir)
+       chdir("/");
+
+    if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+       dup2(fd, STDIN_FILENO);
+       dup2(fd, STDOUT_FILENO);
+       dup2(fd, STDERR_FILENO);
+       if (fd > 2)
+           close (fd);
+    }
+    return (0);
+}
+
+#endif /* HAVE_DAEMON */
diff --git a/src/kerberosV/src/lib/roken/ecalloc.3 b/src/kerberosV/src/lib/roken/ecalloc.3
new file mode 100644 (file)
index 0000000..c57c0b6
--- /dev/null
@@ -0,0 +1,84 @@
+.\" Copyright (c) 2001, 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" $KTH: ecalloc.3,v 1.1 2003/08/15 12:28:14 joda Exp $
+.\"
+.Dd August 14, 2003
+.Dt ECALLOC 3
+.Os HEIMDAL
+.Sh NAME
+.Nm ecalloc ,
+.Nm emalloc ,
+.Nm eread ,
+.Nm erealloc ,
+.Nm esetenv ,
+.Nm estrdup ,
+.Nm ewrite
+.Nd exit-on-failure wrapper functions
+.Sh LIBRARY
+The roken library (libroken, -lroken)
+.Sh SYNOPSIS
+.Fd #include <roken.h>
+.Ft "void *"
+.Fn ecalloc "size_t number" "size_t size"
+.Ft "void *"
+.Fn emalloc "size_t sz"
+.Ft ssize_t
+.Fn eread "int fd" "void *buf" "size_t nbytes"
+.Ft "void *"
+.Fn erealloc "void *ptr" "size_t sz"
+.Ft void
+.Fn esetenv "const char *var" "const char *val" "int rewrite"
+.Ft "char *"
+.Fn estrdup "const char *str"
+.Ft ssize_t
+.Fn ewrite "int fd" "const void *buf" "size_t nbytes"
+.Sh DESCRIPTION
+These functions do the same as the ones without the 
+.Dq e
+prefix, but if there is an error they will print a message with 
+.Xr errx 3 ,
+and exit. For
+.Nm eread
+and 
+.Nm ewrite
+this is also true for partial data.
+.Pp
+This is useful in applications when there is no need for a more
+advanced failure mode.
+.Sh SEE ALSO
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr calloc 3 ,
+.Xr errx 3 ,
+.Xr malloc 3 ,
+.Xr realloc 3 ,
+.Xr setenv 3 ,
+.Xr strdup 3
diff --git a/src/kerberosV/src/lib/roken/ecalloc.c b/src/kerberosV/src/lib/roken/ecalloc.c
new file mode 100644 (file)
index 0000000..3558fa3
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: ecalloc.c,v 1.2 2005/04/12 11:28:36 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include <roken.h>
+
+/*
+ * Like calloc but never fails.
+ */
+
+void * ROKEN_LIB_FUNCTION
+ecalloc (size_t number, size_t size)
+{
+    void *tmp = calloc (number, size);
+
+    if (tmp == NULL && number * size != 0)
+       errx (1, "calloc %lu failed", (unsigned long)number * size);
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/roken/emalloc.c b/src/kerberosV/src/lib/roken/emalloc.c
new file mode 100644 (file)
index 0000000..e77b5a6
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: emalloc.c,v 1.6 2005/04/12 11:28:37 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include <roken.h>
+
+/*
+ * Like malloc but never fails.
+ */
+
+void * ROKEN_LIB_FUNCTION
+emalloc (size_t sz)
+{
+    void *tmp = malloc (sz);
+
+    if (tmp == NULL && sz != 0)
+       errx (1, "malloc %lu failed", (unsigned long)sz);
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/roken/environment.c b/src/kerberosV/src/lib/roken/environment.c
new file mode 100644 (file)
index 0000000..16d0636
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2000, 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: environment.c,v 1.4 2005/05/20 07:50:56 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "roken.h"
+
+/* find assignment in env list; len is length of variable including
+ * equal 
+ */
+
+static int
+find_var(char **env, char *assignment, size_t len)
+{
+    int i;
+    for(i = 0; env != NULL && env[i] != NULL; i++)
+       if(strncmp(env[i], assignment, len) == 0)
+           return i;
+    return -1;
+}
+
+/*
+ * return count of environment assignments from open file F in
+ * assigned and list of malloced strings in env, return 0 or errno
+ * number
+ */
+
+static int
+rk_read_env_file(FILE *F, char ***env, int *assigned)
+{
+    int index = 0;
+    int i;
+    char **l;
+    char buf[BUFSIZ], *p, *r;
+    char **tmp;
+    int ret = 0;
+
+    *assigned = 0;
+
+    for(index = 0; *env != NULL && (*env)[index] != NULL; index++);
+    l = *env;
+
+    /* This is somewhat more relaxed on what it accepts then
+     * Wietses sysv_environ from K4 was...
+     */
+    while (fgets(buf, BUFSIZ, F) != NULL) {
+       buf[strcspn(buf, "#\n")] = '\0';
+
+       for(p = buf; isspace((unsigned char)*p); p++);
+       if (*p == '\0')
+           continue;
+
+       /* Here one should check that it's a 'valid' env string... */
+       r = strchr(p, '=');
+       if (r == NULL)
+           continue;
+
+       if((i = find_var(l, p, r - p + 1)) >= 0) {
+           char *val = strdup(p);
+           if(val == NULL) {
+               ret = ENOMEM;
+               break;
+           }
+           free(l[i]);
+           l[i] = val;
+           (*assigned)++;
+           continue;
+       }
+
+       tmp = realloc(l, (index+2) * sizeof (char *));
+       if(tmp == NULL) {
+           ret = ENOMEM;
+           break;
+       }
+
+       l = tmp;
+       l[index] = strdup(p);
+       if(l[index] == NULL) {
+           ret = ENOMEM;
+           break;
+       }
+       l[++index] = NULL;
+       (*assigned)++;
+    }
+    if(ferror(F))
+       ret = errno;
+    *env = l;
+    return ret;
+}
+
+/*
+ * return count of environment assignments from file and 
+ * list of malloced strings in `env'
+ */
+
+int ROKEN_LIB_FUNCTION
+read_environment(const char *file, char ***env)
+{
+    int assigned;
+    FILE *F;
+
+    if ((F = fopen(file, "r")) == NULL)
+       return 0;
+
+    rk_read_env_file(F, env, &assigned);
+    fclose(F);
+    return assigned;
+}
diff --git a/src/kerberosV/src/lib/roken/eread.c b/src/kerberosV/src/lib/roken/eread.c
new file mode 100644 (file)
index 0000000..bf9d449
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: eread.c,v 1.3 2005/04/12 11:28:37 lha Exp $");
+#endif
+
+#include <unistd.h>
+#include <err.h>
+
+#include <roken.h>
+
+/*
+ * Like read but never fails (and never returns partial data).
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+eread (int fd, void *buf, size_t nbytes)
+{
+    ssize_t ret;
+
+    ret = net_read (fd, buf, nbytes);
+    if (ret < 0)
+       err (1, "read");
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/erealloc.c b/src/kerberosV/src/lib/roken/erealloc.c
new file mode 100644 (file)
index 0000000..93e6e39
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: erealloc.c,v 1.6 2005/04/12 11:28:37 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include <roken.h>
+
+/*
+ * Like realloc but never fails.
+ */
+
+void * ROKEN_LIB_FUNCTION
+erealloc (void *ptr, size_t sz)
+{
+    void *tmp = realloc (ptr, sz);
+
+    if (tmp == NULL && sz != 0)
+       errx (1, "realloc %lu failed", (unsigned long)sz);
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/roken/err.c b/src/kerberosV/src/lib/roken/err.c
new file mode 100644 (file)
index 0000000..e654793
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: err.c,v 1.7 2005/04/12 11:28:38 lha Exp $");
+#endif
+
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+err(int eval, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  verr(eval, fmt, ap);
+  va_end(ap);
+}
diff --git a/src/kerberosV/src/lib/roken/err.hin b/src/kerberosV/src/lib/roken/err.hin
new file mode 100644 (file)
index 0000000..5968157
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1995 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: err.hin,v 1.18 2005/04/12 11:28:38 lha Exp $ */
+
+#ifndef __ERR_H__
+#define __ERR_H__
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(x)
+#endif
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+void ROKEN_LIB_FUNCTION
+verr(int eval, const char *fmt, va_list ap)
+     __attribute__ ((noreturn, format (printf, 2, 0)));
+
+void ROKEN_LIB_FUNCTION
+err(int eval, const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 2, 3)));
+
+void ROKEN_LIB_FUNCTION
+verrx(int eval, const char *fmt, va_list ap)
+     __attribute__ ((noreturn, format (printf, 2, 0)));
+
+void ROKEN_LIB_FUNCTION
+errx(int eval, const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 2, 3)));
+void ROKEN_LIB_FUNCTION
+vwarn(const char *fmt, va_list ap)
+     __attribute__ ((format (printf, 1, 0)));
+
+void ROKEN_LIB_FUNCTION
+warn(const char *fmt, ...)
+     __attribute__ ((format (printf, 1, 2)));
+
+void ROKEN_LIB_FUNCTION
+vwarnx(const char *fmt, va_list ap)
+     __attribute__ ((format (printf, 1, 0)));
+
+void ROKEN_LIB_FUNCTION
+warnx(const char *fmt, ...)
+     __attribute__ ((format (printf, 1, 2)));
+
+#endif /* __ERR_H__ */
diff --git a/src/kerberosV/src/lib/roken/errx.c b/src/kerberosV/src/lib/roken/errx.c
new file mode 100644 (file)
index 0000000..208994b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: errx.c,v 1.7 2005/04/12 11:28:38 lha Exp $");
+#endif
+
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+errx(int eval, const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  verrx(eval, fmt, ap);
+  va_end(ap);
+}
diff --git a/src/kerberosV/src/lib/roken/esetenv.c b/src/kerberosV/src/lib/roken/esetenv.c
new file mode 100644 (file)
index 0000000..dcce0a5
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2000, 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: esetenv.c,v 1.4 2005/04/12 11:28:39 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+esetenv(const char *var, const char *val, int rewrite)
+{
+    if (setenv ((char *)var, (char *)val, rewrite))
+       errx (1, "failed setting environment variable %s", var);
+}
diff --git a/src/kerberosV/src/lib/roken/estrdup.c b/src/kerberosV/src/lib/roken/estrdup.c
new file mode 100644 (file)
index 0000000..e5d413a
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: estrdup.c,v 1.4 2005/04/12 11:28:39 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <err.h>
+
+#include <roken.h>
+
+/*
+ * Like strdup but never fails.
+ */
+
+char * ROKEN_LIB_FUNCTION
+estrdup (const char *str)
+{
+    char *tmp = strdup (str);
+
+    if (tmp == NULL)
+       errx (1, "strdup failed");
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/roken/ewrite.c b/src/kerberosV/src/lib/roken/ewrite.c
new file mode 100644 (file)
index 0000000..fb72bb4
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: ewrite.c,v 1.3 2005/04/12 11:28:39 lha Exp $");
+#endif
+
+#include <unistd.h>
+#include <err.h>
+
+#include <roken.h>
+
+/*
+ * Like write but never fails (and never returns partial data).
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+ewrite (int fd, const void *buf, size_t nbytes)
+{
+    ssize_t ret;
+
+    ret = net_write (fd, buf, nbytes);
+    if (ret < 0)
+       err (1, "write");
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/fchown.c b/src/kerberosV/src/lib/roken/fchown.c
new file mode 100644 (file)
index 0000000..f2a886a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: fchown.c,v 1.4 2005/04/12 11:28:40 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+fchown(int fd, uid_t owner, gid_t group)
+{
+  return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/flock.c b/src/kerberosV/src/lib/roken/flock.c
new file mode 100644 (file)
index 0000000..54e42b2
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_FLOCK
+RCSID("$KTH: flock.c,v 1.5 2005/04/12 11:28:40 lha Exp $");
+
+#include "roken.h"
+
+
+#define OP_MASK (LOCK_SH | LOCK_EX | LOCK_UN)
+
+int ROKEN_LIB_FUNCTION
+flock(int fd, int operation)
+{
+#if defined(HAVE_FCNTL) && defined(F_SETLK)
+  struct flock arg;
+  int code, cmd;
+  
+  arg.l_whence = SEEK_SET;
+  arg.l_start = 0;
+  arg.l_len = 0;               /* means to EOF */
+
+  if (operation & LOCK_NB)
+    cmd = F_SETLK;
+  else
+    cmd = F_SETLKW;            /* Blocking */
+
+  switch (operation & OP_MASK) {
+  case LOCK_UN:
+    arg.l_type = F_UNLCK;
+    code = fcntl(fd, F_SETLK, &arg);
+    break;
+  case LOCK_SH:
+    arg.l_type = F_RDLCK;
+    code = fcntl(fd, cmd, &arg);
+    break;
+  case LOCK_EX:
+    arg.l_type = F_WRLCK;
+    code = fcntl(fd, cmd, &arg);
+    break;
+  default:
+    errno = EINVAL;
+    code = -1;
+    break;
+  }
+  return code;
+#else
+  return -1;
+#endif
+}
+
+#endif
+
diff --git a/src/kerberosV/src/lib/roken/fnmatch.c b/src/kerberosV/src/lib/roken/fnmatch.c
new file mode 100644 (file)
index 0000000..d3620ca
--- /dev/null
@@ -0,0 +1,169 @@
+/*     $NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp $ */
+
+/*
+ * Copyright (c) 1989, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fnmatch.c  8.2 (Berkeley) 4/16/94";
+#else
+static char rcsid[] = "$NetBSD: fnmatch.c,v 1.11 1995/02/27 03:43:06 cgd Exp $";
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+#include <fnmatch.h>
+#include <string.h>
+
+#define        EOS     '\0'
+
+static const char *rangematch (const char *, int, int);
+
+int ROKEN_LIB_FUNCTION
+fnmatch(const char *pattern, const char *string, int flags)
+{
+       const char *stringstart;
+       char c, test;
+
+       for (stringstart = string;;)
+               switch (c = *pattern++) {
+               case EOS:
+                       return (*string == EOS ? 0 : FNM_NOMATCH);
+               case '?':
+                       if (*string == EOS)
+                               return (FNM_NOMATCH);
+                       if (*string == '/' && (flags & FNM_PATHNAME))
+                               return (FNM_NOMATCH);
+                       if (*string == '.' && (flags & FNM_PERIOD) &&
+                           (string == stringstart ||
+                           ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+                               return (FNM_NOMATCH);
+                       ++string;
+                       break;
+               case '*':
+                       c = *pattern;
+                       /* Collapse multiple stars. */
+                       while (c == '*')
+                               c = *++pattern;
+
+                       if (*string == '.' && (flags & FNM_PERIOD) &&
+                           (string == stringstart ||
+                           ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+                               return (FNM_NOMATCH);
+
+                       /* Optimize for pattern with * at end or before /. */
+                       if (c == EOS)
+                               if (flags & FNM_PATHNAME)
+                                       return (strchr(string, '/') == NULL ?
+                                           0 : FNM_NOMATCH);
+                               else
+                                       return (0);
+                       else if (c == '/' && flags & FNM_PATHNAME) {
+                               if ((string = strchr(string, '/')) == NULL)
+                                       return (FNM_NOMATCH);
+                               break;
+                       }
+
+                       /* General case, use recursion. */
+                       while ((test = *string) != EOS) {
+                               if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
+                                       return (0);
+                               if (test == '/' && flags & FNM_PATHNAME)
+                                       break;
+                               ++string;
+                       }
+                       return (FNM_NOMATCH);
+               case '[':
+                       if (*string == EOS)
+                               return (FNM_NOMATCH);
+                       if (*string == '/' && flags & FNM_PATHNAME)
+                               return (FNM_NOMATCH);
+                       if ((pattern =
+                           rangematch(pattern, *string, flags)) == NULL)
+                               return (FNM_NOMATCH);
+                       ++string;
+                       break;
+               case '\\':
+                       if (!(flags & FNM_NOESCAPE)) {
+                               if ((c = *pattern++) == EOS) {
+                                       c = '\\';
+                                       --pattern;
+                               }
+                       }
+                       /* FALLTHROUGH */
+               default:
+                       if (c != *string++)
+                               return (FNM_NOMATCH);
+                       break;
+               }
+       /* NOTREACHED */
+}
+
+static const char *
+rangematch(const char *pattern, int test, int flags)
+{
+       int negate, ok;
+       char c, c2;
+
+       /*
+        * A bracket expression starting with an unquoted circumflex
+        * character produces unspecified results (IEEE 1003.2-1992,
+        * 3.13.2).  This implementation treats it like '!', for
+        * consistency with the regular expression syntax.
+        * J.T. Conklin (conklin@ngai.kaleida.com)
+        */
+       if (negate = (*pattern == '!' || *pattern == '^'))
+               ++pattern;
+       
+       for (ok = 0; (c = *pattern++) != ']';) {
+               if (c == '\\' && !(flags & FNM_NOESCAPE))
+                       c = *pattern++;
+               if (c == EOS)
+                       return (NULL);
+               if (*pattern == '-' 
+                   && (c2 = *(pattern+1)) != EOS && c2 != ']') {
+                       pattern += 2;
+                       if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+                               c2 = *pattern++;
+                       if (c2 == EOS)
+                               return (NULL);
+                       if (c <= test && test <= c2)
+                               ok = 1;
+               } else if (c == test)
+                       ok = 1;
+       }
+       return (ok == negate ? NULL : pattern);
+}
diff --git a/src/kerberosV/src/lib/roken/fnmatch.hin b/src/kerberosV/src/lib/roken/fnmatch.hin
new file mode 100644 (file)
index 0000000..47beb8d
--- /dev/null
@@ -0,0 +1,54 @@
+/*     $NetBSD: fnmatch.h,v 1.5 1994/10/26 00:55:53 cgd Exp $  */
+
+/*-
+ * 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. 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.
+ *
+ *     @(#)fnmatch.h   8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef        _FNMATCH_H_
+#define        _FNMATCH_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#define        FNM_NOMATCH     1       /* Match failed. */
+
+#define        FNM_NOESCAPE    0x01    /* Disable backslash escaping. */
+#define        FNM_PATHNAME    0x02    /* Slash must be matched by slash. */
+#define        FNM_PERIOD      0x04    /* Period must be matched by period. */
+
+int ROKEN_LIB_FUNCTION
+fnmatch (const char *, const char *, int);
+
+#endif /* !_FNMATCH_H_ */
diff --git a/src/kerberosV/src/lib/roken/freeaddrinfo.c b/src/kerberosV/src/lib/roken/freeaddrinfo.c
new file mode 100644 (file)
index 0000000..4686b98
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: freeaddrinfo.c,v 1.5 2005/04/12 11:28:41 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * free the list of `struct addrinfo' starting at `ai'
+ */
+
+void ROKEN_LIB_FUNCTION
+freeaddrinfo(struct addrinfo *ai)
+{
+    struct addrinfo *tofree;
+
+    while(ai != NULL) {
+       free (ai->ai_canonname);
+       free (ai->ai_addr);
+       tofree = ai;
+       ai = ai->ai_next;
+       free (tofree);
+    }
+}
diff --git a/src/kerberosV/src/lib/roken/freehostent.c b/src/kerberosV/src/lib/roken/freehostent.c
new file mode 100644 (file)
index 0000000..812733c
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: freehostent.c,v 1.3 2005/04/12 11:28:41 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * free a malloced hostent
+ */
+
+void ROKEN_LIB_FUNCTION
+freehostent (struct hostent *h)
+{
+    char **p;
+
+    free (h->h_name);
+    if (h->h_aliases != NULL) {
+       for (p = h->h_aliases; *p != NULL; ++p)
+           free (*p);
+       free (h->h_aliases);
+    }
+    if (h->h_addr_list != NULL) {
+       for (p = h->h_addr_list; *p != NULL; ++p)
+           free (*p);
+       free (h->h_addr_list);
+    }
+    free (h);
+}
diff --git a/src/kerberosV/src/lib/roken/gai_strerror.c b/src/kerberosV/src/lib/roken/gai_strerror.c
new file mode 100644 (file)
index 0000000..5a712c1
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: gai_strerror.c,v 1.5 2005/04/12 11:28:42 lha Exp $");
+#endif
+
+#include "roken.h"
+
+static struct gai_error {
+    int code;
+    char *str;
+} errors[] = {
+{EAI_NOERROR,          "no error"},
+#ifdef EAI_ADDRFAMILY
+{EAI_ADDRFAMILY,       "address family for nodename not supported"},
+#endif
+{EAI_AGAIN,            "temporary failure in name resolution"},
+{EAI_BADFLAGS,         "invalid value for ai_flags"},
+{EAI_FAIL,             "non-recoverable failure in name resolution"},
+{EAI_FAMILY,           "ai_family not supported"},
+{EAI_MEMORY,           "memory allocation failure"},
+#ifdef EAI_NODATA
+{EAI_NODATA,           "no address associated with nodename"},
+#endif
+{EAI_NONAME,           "nodename nor servname provided, or not known"},
+{EAI_SERVICE,          "servname not supported for ai_socktype"},
+{EAI_SOCKTYPE,         "ai_socktype not supported"},
+{EAI_SYSTEM,           "system error returned in errno"},
+{0,                    NULL},
+};
+
+/*
+ *
+ */
+
+char * ROKEN_LIB_FUNCTION
+gai_strerror(int ecode)
+{
+    struct gai_error *g;
+
+    for (g = errors; g->str != NULL; ++g)
+       if (g->code == ecode)
+           return g->str;
+    return "unknown error code in gai_strerror";
+}
diff --git a/src/kerberosV/src/lib/roken/get_default_username.c b/src/kerberosV/src/lib/roken/get_default_username.c
new file mode 100644 (file)
index 0000000..38d7502
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1997 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: get_default_username.c,v 1.4 2005/04/12 11:28:42 lha Exp $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+
+/*
+ * Try to return what should be considered the default username or
+ * NULL if we can't guess at all.
+ */
+
+const char * ROKEN_LIB_FUNCTION
+get_default_username (void)
+{
+    const char *user;
+
+    user = getenv ("USER");
+    if (user == NULL)
+       user = getenv ("LOGNAME");
+    if (user == NULL)
+       user = getenv ("USERNAME");
+
+#if defined(HAVE_GETLOGIN) && !defined(POSIX_GETLOGIN)
+    if (user == NULL) {
+       user = (const char *)getlogin ();
+       if (user != NULL)
+           return user;
+    }
+#endif
+#ifdef HAVE_PWD_H
+    {
+       uid_t uid = getuid ();
+       struct passwd *pwd;
+
+       if (user != NULL) {
+           pwd = k_getpwnam (user);
+           if (pwd != NULL && pwd->pw_uid == uid)
+               return user;
+       }
+       pwd = k_getpwuid (uid);
+       if (pwd != NULL)
+           return pwd->pw_name;
+    }
+#endif
+    return user;
+}
diff --git a/src/kerberosV/src/lib/roken/get_window_size.c b/src/kerberosV/src/lib/roken/get_window_size.c
new file mode 100644 (file)
index 0000000..ff8a4e7
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: get_window_size.c,v 1.10 2005/04/12 11:28:42 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#if 0 /* Where were those needed? /confused */
+#ifdef HAVE_SYS_PROC_H
+#include <sys/proc.h>
+#endif
+
+#ifdef HAVE_SYS_TTY_H
+#include <sys/tty.h>
+#endif
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+
+#include <roken.h>
+
+int ROKEN_LIB_FUNCTION
+get_window_size(int fd, struct winsize *wp)
+{
+    int ret = -1;
+    
+    memset(wp, 0, sizeof(*wp));
+
+#if defined(TIOCGWINSZ)
+    ret = ioctl(fd, TIOCGWINSZ, wp);
+#elif defined(TIOCGSIZE)
+    {
+       struct ttysize ts;
+       
+       ret = ioctl(fd, TIOCGSIZE, &ts);
+       if(ret == 0) {
+           wp->ws_row = ts.ts_lines;
+           wp->ws_col = ts.ts_cols;
+       }
+    }
+#elif defined(HAVE__SCRSIZE)
+    {
+       int dst[2];
+       
+       _scrsize(dst);
+       wp->ws_row = dst[1];
+       wp->ws_col = dst[0];
+       ret = 0;
+    }
+#endif
+    if (ret != 0) {
+        char *s;
+        if((s = getenv("COLUMNS")))
+           wp->ws_col = atoi(s);
+       if((s = getenv("LINES")))
+           wp->ws_row = atoi(s);
+       if(wp->ws_col > 0 && wp->ws_row > 0)
+           ret = 0;
+    }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/getaddrinfo-test.c b/src/kerberosV/src/lib/roken/getaddrinfo-test.c
new file mode 100644 (file)
index 0000000..3cdc8dd
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 1999 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getaddrinfo-test.c,v 1.5 2005/03/02 22:51:36 lha Exp $");
+#endif
+
+#include "roken.h"
+#include "getarg.h"
+
+static int flags;
+static int family;
+static int socktype;
+
+static int version_flag;
+static int help_flag;
+
+extern char *__progname;
+
+static struct getargs args[] = {
+    {"flags",  0,      arg_integer,    &flags,         "flags",        NULL},
+    {"family", 0,      arg_integer,    &family,        "family",       NULL},
+    {"socktype",0,     arg_integer,    &socktype,      "socktype",     NULL},
+    {"version",        0,      arg_flag,       &version_flag,  "print version",NULL},
+    {"help",   0,      arg_flag,       &help_flag,     NULL,           NULL}
+};
+
+static void
+usage(int ret)
+{
+    arg_printusage (args,
+                   sizeof(args) / sizeof(args[0]),
+                   NULL,
+                   "[nodename servname...]");
+    exit (ret);
+}
+
+static void
+doit (const char *nodename, const char *servname)
+{
+    struct addrinfo hints;
+    struct addrinfo *res, *r;
+    int ret;
+
+    printf ("(%s,%s)... ", nodename ? nodename : "null", servname);
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_flags    = flags;
+    hints.ai_family   = family;
+    hints.ai_socktype = socktype;
+
+    ret = getaddrinfo (nodename, servname, &hints, &res);
+    if (ret) {
+       printf ("error: %s\n", gai_strerror(ret));
+       return;
+    }
+    printf ("\n");
+
+    for (r = res; r != NULL; r = r->ai_next) {
+       char addrstr[256];
+
+       if (inet_ntop (r->ai_family, 
+                      socket_get_address (r->ai_addr),
+                      addrstr, sizeof(addrstr)) == NULL) {
+           printf ("\tbad address?\n");
+           continue;
+       } 
+       printf ("\tfamily = %d, socktype = %d, protocol = %d, "
+               "address = \"%s\", port = %d",
+               r->ai_family, r->ai_socktype, r->ai_protocol,
+               addrstr,
+               ntohs(socket_get_port (r->ai_addr)));
+       if (r->ai_canonname)
+           printf (", canonname = \"%s\"", r->ai_canonname);
+       printf ("\n");
+    }
+    freeaddrinfo (res);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    int i;
+
+    if (getarg (args, sizeof(args) / sizeof(args[0]), argc, argv,
+               &optind))
+       usage (1);
+
+    if (help_flag)
+       usage (0);
+
+    if (version_flag) {
+       fprintf (stderr, "%s from %s-%s)\n", __progname, PACKAGE, VERSION);
+       return 0;
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc % 2 != 0)
+       usage (1);
+
+    for (i = 0; i < argc; i += 2) {
+       const char *nodename = argv[i];
+
+       if (strcmp (nodename, "null") == 0)
+           nodename = NULL;
+
+       doit (nodename, argv[i+1]);
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/getaddrinfo.c b/src/kerberosV/src/lib/roken/getaddrinfo.c
new file mode 100644 (file)
index 0000000..5fc31d4
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getaddrinfo.c,v 1.13 2005/04/12 11:28:43 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * uses hints->ai_socktype and hints->ai_protocol
+ */
+
+static int
+get_port_protocol_socktype (const char *servname,
+                           const struct addrinfo *hints,
+                           int *port,
+                           int *protocol,
+                           int *socktype)
+{
+    struct servent *se;
+    const char *proto_str = NULL;
+
+    *socktype = 0;
+
+    if (hints != NULL && hints->ai_protocol != 0) {
+       struct protoent *protoent = getprotobynumber (hints->ai_protocol);
+
+       if (protoent == NULL)
+           return EAI_SOCKTYPE; /* XXX */
+
+       proto_str = protoent->p_name;
+       *protocol = protoent->p_proto;
+    }
+
+    if (hints != NULL)
+       *socktype = hints->ai_socktype;
+
+    if (*socktype == SOCK_STREAM) {
+       se = getservbyname (servname, proto_str ? proto_str : "tcp");
+       if (proto_str == NULL)
+           *protocol = IPPROTO_TCP;
+    } else if (*socktype == SOCK_DGRAM) {
+       se = getservbyname (servname, proto_str ? proto_str : "udp");
+       if (proto_str == NULL)
+           *protocol = IPPROTO_UDP;
+    } else if (*socktype == 0) {
+       if (proto_str != NULL) {
+           se = getservbyname (servname, proto_str);
+       } else {
+           se = getservbyname (servname, "tcp");
+           *protocol = IPPROTO_TCP;
+           *socktype = SOCK_STREAM;
+           if (se == NULL) {
+               se = getservbyname (servname, "udp");
+               *protocol = IPPROTO_UDP;
+               *socktype = SOCK_DGRAM;
+           }
+       }
+    } else
+       return EAI_SOCKTYPE;
+
+    if (se == NULL) {
+       char *endstr;
+
+       *port = htons(strtol (servname, &endstr, 10));
+       if (servname == endstr)
+           return EAI_NONAME;
+    } else {
+       *port = se->s_port;
+    }
+    return 0;
+}
+
+static int
+add_one (int port, int protocol, int socktype,
+        struct addrinfo ***ptr,
+        int (*func)(struct addrinfo *, void *data, int port),
+        void *data,
+        char *canonname)
+{
+    struct addrinfo *a;
+    int ret;
+
+    a = malloc (sizeof (*a));
+    if (a == NULL)
+       return EAI_MEMORY;
+    memset (a, 0, sizeof(*a));
+    a->ai_flags     = 0;
+    a->ai_next      = NULL;
+    a->ai_protocol  = protocol;
+    a->ai_socktype  = socktype;
+    a->ai_canonname = canonname;
+    ret = (*func)(a, data, port);
+    if (ret) {
+       free (a);
+       return ret;
+    }
+    **ptr = a;
+    *ptr = &a->ai_next;
+    return 0;
+}
+
+static int
+const_v4 (struct addrinfo *a, void *data, int port)
+{
+    struct sockaddr_in *sin;
+    struct in_addr *addr = (struct in_addr *)data;
+
+    a->ai_family  = PF_INET;
+    a->ai_addrlen = sizeof(*sin);
+    a->ai_addr    = malloc (sizeof(*sin));
+    if (a->ai_addr == NULL)
+       return EAI_MEMORY;
+    sin = (struct sockaddr_in *)a->ai_addr;
+    memset (sin, 0, sizeof(*sin));
+    sin->sin_family = AF_INET;
+    sin->sin_port   = port;
+    sin->sin_addr   = *addr;
+    return 0;
+}
+
+#ifdef HAVE_IPV6
+static int
+const_v6 (struct addrinfo *a, void *data, int port)
+{
+    struct sockaddr_in6 *sin6;
+    struct in6_addr *addr = (struct in6_addr *)data;
+
+    a->ai_family  = PF_INET6;
+    a->ai_addrlen = sizeof(*sin6);
+    a->ai_addr    = malloc (sizeof(*sin6));
+    if (a->ai_addr == NULL)
+       return EAI_MEMORY;
+    sin6 = (struct sockaddr_in6 *)a->ai_addr;
+    memset (sin6, 0, sizeof(*sin6));
+    sin6->sin6_family = AF_INET6;
+    sin6->sin6_port   = port;
+    sin6->sin6_addr   = *addr;
+    return 0;
+}
+#endif
+
+/* this is mostly a hack for some versions of AIX that has a prototype
+   for in6addr_loopback but no actual symbol in libc */
+#if defined(HAVE_IPV6) && !defined(HAVE_IN6ADDR_LOOPBACK) && defined(IN6ADDR_LOOPBACK_INIT)
+#define in6addr_loopback _roken_in6addr_loopback
+struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+#endif
+
+static int
+get_null (const struct addrinfo *hints,
+         int port, int protocol, int socktype,
+         struct addrinfo **res)
+{
+    struct in_addr v4_addr;
+#ifdef HAVE_IPV6
+    struct in6_addr v6_addr;
+#endif
+    struct addrinfo *first = NULL;
+    struct addrinfo **current = &first;
+    int family = PF_UNSPEC;
+    int ret;
+
+    if (hints != NULL)
+       family = hints->ai_family;
+
+    if (hints && hints->ai_flags & AI_PASSIVE) {
+       v4_addr.s_addr = INADDR_ANY;
+#ifdef HAVE_IPV6
+       v6_addr        = in6addr_any;
+#endif
+    } else {
+       v4_addr.s_addr = htonl(INADDR_LOOPBACK);
+#ifdef HAVE_IPV6
+       v6_addr        = in6addr_loopback;
+#endif
+    }
+
+#ifdef HAVE_IPV6
+    if (family == PF_INET6 || family == PF_UNSPEC) {
+       ret = add_one (port, protocol, socktype,
+                      &current, const_v6, &v6_addr, NULL);
+    }
+#endif
+    if (family == PF_INET || family == PF_UNSPEC) {
+       ret = add_one (port, protocol, socktype,
+                      &current, const_v4, &v4_addr, NULL);
+    }
+    *res = first;
+    return 0;
+}
+
+static int
+add_hostent (int port, int protocol, int socktype,
+            struct addrinfo ***current,
+            int (*func)(struct addrinfo *, void *data, int port),
+            struct hostent *he, int *flags)
+{
+    int ret;
+    char *canonname = NULL;
+    char **h;
+
+    if (*flags & AI_CANONNAME) {
+       struct hostent *he2 = NULL;
+       const char *tmp_canon;
+
+       tmp_canon = hostent_find_fqdn (he);
+       if (strchr (tmp_canon, '.') == NULL) {
+           int error;
+
+           he2 = getipnodebyaddr (he->h_addr_list[0], he->h_length,
+                                  he->h_addrtype, &error);
+           if (he2 != NULL) {
+               const char *tmp = hostent_find_fqdn (he2);
+
+               if (strchr (tmp, '.') != NULL)
+                   tmp_canon = tmp;
+           }
+       }
+
+       canonname = strdup (tmp_canon);
+       if (he2 != NULL)
+           freehostent (he2);
+       if (canonname == NULL)
+           return EAI_MEMORY;
+    }
+
+    for (h = he->h_addr_list; *h != NULL; ++h) {
+       ret = add_one (port, protocol, socktype,
+                      current, func, *h, canonname);
+       if (ret)
+           return ret;
+       if (*flags & AI_CANONNAME) {
+           *flags &= ~AI_CANONNAME;
+           canonname = NULL;
+       }
+    }
+    return 0;
+}
+
+static int
+get_number (const char *nodename,
+           const struct addrinfo *hints,
+           int port, int protocol, int socktype,
+           struct addrinfo **res)
+{
+    struct addrinfo *first = NULL;
+    struct addrinfo **current = &first;
+    int family = PF_UNSPEC;
+    int ret;
+
+    if (hints != NULL) {
+       family = hints->ai_family;
+    }
+
+#ifdef HAVE_IPV6
+    if (family == PF_INET6 || family == PF_UNSPEC) {
+       struct in6_addr v6_addr;
+
+       if (inet_pton (PF_INET6, nodename, &v6_addr) == 1) {
+           ret = add_one (port, protocol, socktype,
+                          &current, const_v6, &v6_addr, NULL);
+           *res = first;
+           return ret;
+       }
+    }
+#endif
+    if (family == PF_INET || family == PF_UNSPEC) {
+       struct in_addr v4_addr;
+
+       if (inet_pton (PF_INET, nodename, &v4_addr) == 1) {
+           ret = add_one (port, protocol, socktype,
+                          &current, const_v4, &v4_addr, NULL);
+           *res = first;
+           return ret;
+       }
+    }
+    return EAI_NONAME;
+}
+
+static int
+get_nodes (const char *nodename,
+          const struct addrinfo *hints,
+          int port, int protocol, int socktype,
+          struct addrinfo **res)
+{
+    struct addrinfo *first = NULL;
+    struct addrinfo **current = &first;
+    int family = PF_UNSPEC;
+    int flags  = 0;
+    int ret = EAI_NONAME;
+    int error;
+
+    if (hints != NULL) {
+       family = hints->ai_family;
+       flags  = hints->ai_flags;
+    }
+
+#ifdef HAVE_IPV6
+    if (family == PF_INET6 || family == PF_UNSPEC) {
+       struct hostent *he;
+
+       he = getipnodebyname (nodename, PF_INET6, 0, &error);
+
+       if (he != NULL) {
+           ret = add_hostent (port, protocol, socktype,
+                              &current, const_v6, he, &flags);
+           freehostent (he);
+       }
+    }
+#endif
+    if (family == PF_INET || family == PF_UNSPEC) {
+       struct hostent *he;
+
+       he = getipnodebyname (nodename, PF_INET, 0, &error);
+
+       if (he != NULL) {
+           ret = add_hostent (port, protocol, socktype,
+                              &current, const_v4, he, &flags);
+           freehostent (he);
+       }
+    }
+    *res = first;
+    return ret;
+}
+
+/*
+ * hints:
+ *
+ * struct addrinfo {
+ *     int    ai_flags;
+ *     int    ai_family;
+ *     int    ai_socktype;
+ *     int    ai_protocol;
+ * ...
+ * };
+ */
+
+int ROKEN_LIB_FUNCTION
+getaddrinfo(const char *nodename,
+           const char *servname,
+           const struct addrinfo *hints,
+           struct addrinfo **res)
+{
+    int ret;
+    int port     = 0;
+    int protocol = 0;
+    int socktype = 0;
+
+    *res = NULL;
+
+    if (servname == NULL && nodename == NULL)
+       return EAI_NONAME;
+
+    if (hints != NULL
+       && hints->ai_family != PF_UNSPEC
+       && hints->ai_family != PF_INET
+#ifdef HAVE_IPV6
+       && hints->ai_family != PF_INET6
+#endif
+       )
+       return EAI_FAMILY;
+
+    if (servname != NULL) {
+       ret = get_port_protocol_socktype (servname, hints,
+                                         &port, &protocol, &socktype);
+       if (ret)
+           return ret;
+    }
+    if (nodename != NULL) {
+       ret = get_number (nodename, hints, port, protocol, socktype, res);
+       if (ret) {
+           if(hints && hints->ai_flags & AI_NUMERICHOST)
+               ret = EAI_NONAME;
+           else
+               ret = get_nodes (nodename, hints, port, protocol, socktype,
+                                res);
+       }
+    } else {
+       ret = get_null (hints, port, protocol, socktype, res);
+    }
+    if (ret)
+       freeaddrinfo (*res);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/getaddrinfo_hostspec.c b/src/kerberosV/src/lib/roken/getaddrinfo_hostspec.c
new file mode 100644 (file)
index 0000000..e0d42a0
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getaddrinfo_hostspec.c,v 1.4 2005/04/12 11:28:43 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/* getaddrinfo via string specifying host and port */
+
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec2(const char *hostspec, 
+                           int socktype,
+                           int port,
+                           struct addrinfo **ai)
+{
+    const char *p;
+    char portstr[NI_MAXSERV];
+    char host[MAXHOSTNAMELEN];
+    struct addrinfo hints;
+    int hostspec_len;
+
+    struct hst {
+       const char *prefix;
+       int socktype;
+       int protocol;
+       int port;
+    } *hstp, hst[] = {
+       { "http://", SOCK_STREAM, IPPROTO_TCP, 80 },
+       { "http/", SOCK_STREAM, IPPROTO_TCP, 80 },
+       { "tcp/", SOCK_STREAM, IPPROTO_TCP },
+       { "udp/", SOCK_DGRAM, IPPROTO_UDP },
+       { NULL }
+    };
+
+    memset(&hints, 0, sizeof(hints));
+
+    hints.ai_socktype = socktype;
+       
+    for(hstp = hst; hstp->prefix; hstp++) {
+       if(strncmp(hostspec, hstp->prefix, strlen(hstp->prefix)) == 0) {
+           hints.ai_socktype = hstp->socktype;
+           hints.ai_protocol = hstp->protocol;
+           if(port == 0)
+               port = hstp->port;
+           hostspec += strlen(hstp->prefix);
+           break;
+       }
+    }
+    
+    p = strchr (hostspec, ':');
+    if (p != NULL) {
+       char *end;
+
+       port = strtol (p + 1, &end, 0);
+       hostspec_len = p - hostspec;
+    } else {
+       hostspec_len = strlen(hostspec);
+    }
+    snprintf (portstr, sizeof(portstr), "%u", port);
+    
+    snprintf (host, sizeof(host), "%.*s", hostspec_len, hostspec);
+    return getaddrinfo (host, portstr, &hints, ai);
+}
+
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec(const char *hostspec, 
+                          int port,
+                          struct addrinfo **ai)
+{
+    return roken_getaddrinfo_hostspec2(hostspec, 0, port, ai);
+}
diff --git a/src/kerberosV/src/lib/roken/getarg.3 b/src/kerberosV/src/lib/roken/getarg.3
new file mode 100644 (file)
index 0000000..a1dc3a8
--- /dev/null
@@ -0,0 +1,341 @@
+.\" Copyright (c) 1999 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: getarg.3,v 1.8 2004/02/17 12:04:59 lha Exp $
+.Dd September 24, 1999
+.Dt GETARG 3
+.Os ROKEN
+.Sh NAME
+.Nm getarg ,
+.Nm arg_printusage
+.Nd collect command line options
+.Sh SYNOPSIS
+.In getarg.h
+.Ft int
+.Fn getarg "struct getargs *args" "size_t num_args" "int argc" "char **argv" "int *optind"
+.Ft void
+.Fn arg_printusage "struct getargs *args" "size_t num_args" "const char *progname" "const char *extra_string"
+.Sh DESCRIPTION
+.Fn getarg
+collects any command line options given to a program in an easily used way.
+.Fn arg_printusage
+pretty-prints the available options, with a short help text.
+.Pp
+.Fa args
+is the option specification to use, and it's an array of
+.Fa struct getargs
+elements.
+.Fa num_args
+is the size of
+.Fa args
+(in elements).
+.Fa argc
+and
+.Fa argv
+are the argument count and argument vector to extract option from.
+.Fa optind
+is a pointer to an integer where the index to the last processed
+argument is stored, it must be initialised to the first index (minus
+one) to process (normally 0) before the first call.
+.Pp
+.Fa arg_printusage
+take the same
+.Fa args
+and
+.Fa num_args
+as getarg;
+.Fa progname
+is the name of the program (to be used in the help text), and
+.Fa extra_string
+is a string to print after the actual options to indicate more
+arguments. The usefulness of this function is realised only be people
+who has used programs that has help strings that doesn't match what
+the code does.
+.Pp
+The
+.Fa getargs
+struct has the following elements.
+.Bd -literal
+struct getargs{
+    const char *long_name;
+    char short_name;
+    enum { arg_integer,
+          arg_string,
+          arg_flag,
+          arg_negative_flag,
+          arg_strings,
+          arg_double,
+           arg_collect
+    } type;
+    void *value;
+    const char *help;
+    const char *arg_help;
+};
+.Ed
+.Pp
+.Fa long_name
+is the long name of the option, it can be
+.Dv NULL ,
+if you don't want a long name.
+.Fa short_name
+is the characted to use as short option, it can be zero. If the option
+has a value the
+.Fa value
+field gets filled in with that value interpreted as specified by the
+.Fa type
+field.
+.Fa help
+is a longer help string for the option as a whole, if it's
+.Dv NULL
+the help text for the option is omitted (but it's still displayed in
+the synopsis).
+.Fa arg_help
+is a description of the argument, if
+.Dv NULL
+a default value will be used, depending on the type of the option:
+.Pp
+.Bl -hang -width arg_negative_flag
+.It arg_integer
+the argument is a signed integer, and
+.Fa value
+should point to an
+.Fa int .
+.It Fa arg_string
+the argument is a string, and
+.Fa value
+should point to a
+.Fa char* .
+.It Fa arg_flag
+the argument is a flag, and
+.Fa value
+should point to a
+.Fa int .
+It gets filled in with either zero or one, depending on how the option
+is given, the normal case being one. Note that if the option isn't
+given, the value isn't altered, so it should be initialised to some
+useful default.
+.It Fa arg_negative_flag
+this is the same as
+.Fa arg_flag
+but it reverses the meaning of the flag (a given short option clears
+the flag), and the synopsis of a long option is negated.
+.It Fa arg_strings
+the argument can be given multiple times, and the values are collected
+in an array;
+.Fa value
+should be a pointer to a
+.Fa struct getarg_strings
+structure, which holds a length and a string pointer.
+.It Fa arg_double
+argument is a double precision floating point value, and
+.Fa value
+should point to a
+.Fa double .
+.It Fa arg_collect
+allows more fine-grained control of the option parsing process.
+.Fa value
+should be a pointer to a
+.Fa getarg_collect_info
+structure:
+.Bd -literal
+typedef int (*getarg_collect_func)(int short_opt,
+                                  int argc,
+                                  char **argv,
+                                  int *optind,
+                                  int *optarg,
+                                  void *data);
+
+typedef struct getarg_collect_info {
+    getarg_collect_func func;
+    void *data;
+} getarg_collect_info;
+.Ed
+.Pp
+With the
+.Fa func
+member set to a function to call, and
+.Fa data
+to some application specific data. The parameters to the collect function are:
+.Bl -inset
+.It Fa short_flag
+non-zero if this call is via a short option flag, zero otherwise
+.It Fa argc , argv
+the whole argument list
+.It Fa optind
+pointer to the index in argv where the flag is
+.It Fa optarg
+pointer to the index in argv[*optind] where the flag name starts
+.It Fa data
+application specific data
+.El
+.Pp
+You can modify
+.Fa *optind ,
+and
+.Fa *optarg ,
+but to do this correct you (more or less) have to know about the inner
+workings of getarg.
+.Pp
+You can skip parts of arguments by increasing
+.Fa *optarg
+(you could
+implement the
+.Fl z Ns Ar 3
+set of flags from
+.Nm gzip
+with this), or whole argument strings by increasing
+.Fa *optind
+(let's say you want a flag
+.Fl c Ar x y z
+to specify a coordinate); if you also have to set
+.Fa *optarg
+to a sane value.
+.Pp
+The collect function should return one of
+.Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG, ENOMEM
+on error, zero otherwise.
+.Pp
+For your convenience there is a function,
+.Fn getarg_optarg ,
+that returns the traditional argument string, and you pass it all
+arguments, sans data, that where given to the collection function.
+.Pp
+Don't use this more this unless you absolutely have to.
+.El
+.Pp
+Option parsing is similar to what
+.Xr getopt
+uses. Short options without arguments can be compressed
+.Pf ( Fl xyz
+is the same as
+.Fl x y z ) ,
+and short
+options with arguments take these as either the rest of the
+argv-string or as the next option
+.Pf ( Fl o Ns Ar foo ,
+or
+.Fl o Ar foo ) .
+.Pp
+Long option names are prefixed with -- (double dash), and the value
+with a = (equal),
+.Fl -foo= Ns Ar bar .
+Long option flags can either be specified as they are
+.Pf ( Fl -help ) ,
+or with an (boolean parsable) option
+.Pf ( Fl -help= Ns Ar yes ,
+.Fl -help= Ns Ar true ,
+or similar), or they can also be negated
+.Pf ( Fl -no-help
+is the same as
+.Fl -help= Ns no ) ,
+and if you're really confused you can do it multiple times
+.Pf ( Fl -no-no-help= Ns Ar false ,
+or even
+.Fl -no-no-help= Ns Ar maybe ) .
+.Sh EXAMPLE
+.Bd -literal
+#include <stdio.h>
+#include <string.h>
+#include <getarg.h>
+
+char *source = "Ouagadougou";
+char *destination;
+int weight;
+int include_catalog = 1;
+int help_flag;
+
+struct getargs args[] = {
+    { "source",      's', arg_string,  &source,
+      "source of shippment", "city" },
+    { "destination", 'd', arg_string,  &destination,
+      "destination of shippment", "city" },
+    { "weight",      'w', arg_integer, &weight,
+      "weight of shippment", "tons" },
+    { "catalog",     'c', arg_negative_flag, &include_catalog,
+      "include product catalog" },
+    { "help",        'h', arg_flag, &help_flag }
+};
+
+int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
+
+const char *progname = "ship++";
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+    if (getarg(args, num_args, argc, argv, &optind)) {
+       arg_printusage(args, num_args, progname, "stuff...");
+       exit (1);
+    }
+    if (help_flag) {
+       arg_printusage(args, num_args, progname, "stuff...");
+       exit (0);
+    }
+    if (destination == NULL) {
+       fprintf(stderr, "%s: must specify destination\en", progname);
+       exit(1);
+    }
+    if (strcmp(source, destination) == 0) {
+       fprintf(stderr, "%s: destination must be different from source\en");
+       exit(1);
+    }
+    /* include more stuff here ... */
+    exit(2);
+}
+.Ed
+.Pp
+The output help output from this program looks like this:
+.Bd -literal
+$ ship++ --help
+Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city]
+   [--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...
+-s city, --source=city      source of shippment
+-d city, --destination=city destination of shippment
+-w tons, --weight=tons      weight of shippment
+-c, --no-catalog            include product catalog
+.Ed
+.Sh BUGS
+It should be more flexible, so it would be possible to use other more
+complicated option syntaxes, such as what
+.Xr ps 1 ,
+and
+.Xr tar 1 ,
+uses, or the AFS model where you can skip the flag names as long as
+the options come in the correct order.
+.Pp
+Options with multiple arguments should be handled better.
+.Pp
+Should be integreated with SL.
+.Pp
+It's very confusing that the struct you pass in is called getargS.
+.Sh SEE ALSO
+.Xr getopt 3
diff --git a/src/kerberosV/src/lib/roken/getarg.c b/src/kerberosV/src/lib/roken/getarg.c
new file mode 100644 (file)
index 0000000..03633fc
--- /dev/null
@@ -0,0 +1,597 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getarg.c,v 1.48 2005/04/12 11:28:43 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <roken.h>
+#include "getarg.h"
+
+#define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
+
+extern char *__progname;
+
+static size_t
+print_arg (char *string, size_t len, int mdoc, int longp, struct getargs *arg)
+{
+    const char *s;
+
+    *string = '\0';
+
+    if (ISFLAG(*arg) || (!longp && arg->type == arg_counter))
+       return 0;
+
+    if(mdoc){
+       if(longp)
+           strlcat(string, "= Ns", len);
+       strlcat(string, " Ar ", len);
+    } else {
+       if (longp)
+           strlcat (string, "=", len);
+       else
+           strlcat (string, " ", len);
+    }
+
+    if (arg->arg_help)
+       s = arg->arg_help;
+    else if (arg->type == arg_integer || arg->type == arg_counter)
+       s = "integer";
+    else if (arg->type == arg_string)
+       s = "string";
+    else if (arg->type == arg_strings)
+       s = "strings";
+    else if (arg->type == arg_double)
+       s = "float";
+    else
+       s = "<undefined>";
+
+    strlcat(string, s, len);
+    return 1 + strlen(s);
+}
+
+static void
+mandoc_template(struct getargs *args,
+               size_t num_args,
+               const char *progname,
+               const char *extra_string)
+{
+    int i;
+    char timestr[64], cmd[64];
+    char buf[128];
+    const char *p;
+    time_t t;
+
+    printf(".\\\" Things to fix:\n");
+    printf(".\\\"   * correct section, and operating system\n");
+    printf(".\\\"   * remove Op from mandatory flags\n");
+    printf(".\\\"   * use better macros for arguments (like .Pa for files)\n");
+    printf(".\\\"\n");
+    t = time(NULL);
+    strftime(timestr, sizeof(timestr), "%B %e, %Y", localtime(&t));
+    printf(".Dd %s\n", timestr);
+    p = strrchr(progname, '/');
+    if(p) p++; else p = progname;
+    strlcpy(cmd, p, sizeof(cmd));
+    strupr(cmd);
+       
+    printf(".Dt %s SECTION\n", cmd);
+    printf(".Os OPERATING_SYSTEM\n");
+    printf(".Sh NAME\n");
+    printf(".Nm %s\n", p);
+    printf(".Nd\n");
+    printf("in search of a description\n");
+    printf(".Sh SYNOPSIS\n");
+    printf(".Nm\n");
+    for(i = 0; i < num_args; i++){
+       /* we seem to hit a limit on number of arguments if doing
+           short and long flags with arguments -- split on two lines */
+       if(ISFLAG(args[i]) || 
+          args[i].short_name == 0 || args[i].long_name == NULL) {
+           printf(".Op ");
+
+           if(args[i].short_name) {
+               print_arg(buf, sizeof(buf), 1, 0, args + i);
+               printf("Fl %c%s", args[i].short_name, buf);
+               if(args[i].long_name)
+                   printf(" | ");
+           }
+           if(args[i].long_name) {
+               print_arg(buf, sizeof(buf), 1, 1, args + i);
+               printf("Fl -%s%s%s",
+                      args[i].type == arg_negative_flag ? "no-" : "",
+                      args[i].long_name, buf);
+           }
+           printf("\n");
+       } else {
+           print_arg(buf, sizeof(buf), 1, 0, args + i);
+           printf(".Oo Fl %c%s \\*(Ba Xo\n", args[i].short_name, buf);
+           print_arg(buf, sizeof(buf), 1, 1, args + i);
+           printf(".Fl -%s%s\n.Xc\n.Oc\n", args[i].long_name, buf);
+       }
+    /*
+           if(args[i].type == arg_strings)
+               fprintf (stderr, "...");
+               */
+    }
+    if (extra_string && *extra_string)
+       printf (".Ar %s\n", extra_string);
+    printf(".Sh DESCRIPTION\n");
+    printf("Supported options:\n");
+    printf(".Bl -tag -width Ds\n");
+    for(i = 0; i < num_args; i++){
+       printf(".It Xo\n");
+       if(args[i].short_name){
+           printf(".Fl %c", args[i].short_name);
+           print_arg(buf, sizeof(buf), 1, 0, args + i);
+           printf("%s", buf);
+           if(args[i].long_name)
+               printf(" ,");
+           printf("\n");
+       }
+       if(args[i].long_name){
+           printf(".Fl -%s%s",
+                  args[i].type == arg_negative_flag ? "no-" : "",
+                  args[i].long_name);
+           print_arg(buf, sizeof(buf), 1, 1, args + i);
+           printf("%s\n", buf);
+       }
+       printf(".Xc\n");
+       if(args[i].help)
+           printf("%s\n", args[i].help);
+    /*
+           if(args[i].type == arg_strings)
+               fprintf (stderr, "...");
+               */
+    }
+    printf(".El\n");
+    printf(".\\\".Sh ENVIRONMENT\n");
+    printf(".\\\".Sh FILES\n");
+    printf(".\\\".Sh EXAMPLES\n");
+    printf(".\\\".Sh DIAGNOSTICS\n");
+    printf(".\\\".Sh SEE ALSO\n");
+    printf(".\\\".Sh STANDARDS\n");
+    printf(".\\\".Sh HISTORY\n");
+    printf(".\\\".Sh AUTHORS\n");
+    printf(".\\\".Sh BUGS\n");
+}
+
+static int
+check_column(FILE *f, int col, int len, int columns)
+{
+    if(col + len > columns) {
+       fprintf(f, "\n");
+       col = fprintf(f, "  ");
+    }
+    return col;
+}
+
+void ROKEN_LIB_FUNCTION
+arg_printusage (struct getargs *args,
+               size_t num_args,
+               const char *progname,
+               const char *extra_string)
+{
+    int i;
+    size_t max_len = 0;
+    char buf[128];
+    int col = 0, columns;
+    struct winsize ws;
+
+    if (progname == NULL)
+       progname = __progname;
+
+    if(getenv("GETARGMANDOC")){
+       mandoc_template(args, num_args, progname, extra_string);
+       return;
+    }
+    if(get_window_size(2, &ws) == 0)
+       columns = ws.ws_col;
+    else
+       columns = 80;
+    col = 0;
+    col += fprintf (stderr, "Usage: %s", progname);
+    buf[0] = '\0';
+    for (i = 0; i < num_args; ++i) {
+       if(args[i].short_name && ISFLAG(args[i])) {
+           char s[2];
+           if(buf[0] == '\0')
+               strlcpy(buf, "[-", sizeof(buf));
+           s[0] = args[i].short_name;
+           s[1] = '\0';
+           strlcat(buf, s, sizeof(buf));
+       }
+    }
+    if(buf[0] != '\0') {
+       strlcat(buf, "]", sizeof(buf));
+       col = check_column(stderr, col, strlen(buf) + 1, columns);
+       col += fprintf(stderr, " %s", buf);
+    }
+
+    for (i = 0; i < num_args; ++i) {
+       size_t len = 0;
+
+       if (args[i].long_name) {
+           buf[0] = '\0';
+           strlcat(buf, "[--", sizeof(buf));
+           len += 2;
+           if(args[i].type == arg_negative_flag) {
+               strlcat(buf, "no-", sizeof(buf));
+               len += 3;
+           }
+           strlcat(buf, args[i].long_name, sizeof(buf));
+           len += strlen(args[i].long_name);
+           len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf), 
+                            0, 1, &args[i]);
+           strlcat(buf, "]", sizeof(buf));
+           if(args[i].type == arg_strings)
+               strlcat(buf, "...", sizeof(buf));
+           col = check_column(stderr, col, strlen(buf) + 1, columns);
+           col += fprintf(stderr, " %s", buf);
+       }
+       if (args[i].short_name && !ISFLAG(args[i])) {
+           snprintf(buf, sizeof(buf), "[-%c", args[i].short_name);
+           len += 2;
+           len += print_arg(buf + strlen(buf), sizeof(buf) - strlen(buf), 
+                            0, 0, &args[i]);
+           strlcat(buf, "]", sizeof(buf));
+           if(args[i].type == arg_strings)
+               strlcat(buf, "...", sizeof(buf));
+           col = check_column(stderr, col, strlen(buf) + 1, columns);
+           col += fprintf(stderr, " %s", buf);
+       }
+       if (args[i].long_name && args[i].short_name)
+           len += 2; /* ", " */
+       max_len = max(max_len, len);
+    }
+    if (extra_string) {
+       col = check_column(stderr, col, strlen(extra_string) + 1, columns);
+       fprintf (stderr, " %s\n", extra_string);
+    } else
+       fprintf (stderr, "\n");
+    for (i = 0; i < num_args; ++i) {
+       if (args[i].help) {
+           size_t count = 0;
+
+           if (args[i].short_name) {
+               count += fprintf (stderr, "-%c", args[i].short_name);
+               print_arg (buf, sizeof(buf), 0, 0, &args[i]);
+               count += fprintf(stderr, "%s", buf);
+           }
+           if (args[i].short_name && args[i].long_name)
+               count += fprintf (stderr, ", ");
+           if (args[i].long_name) {
+               count += fprintf (stderr, "--");
+               if (args[i].type == arg_negative_flag)
+                   count += fprintf (stderr, "no-");
+               count += fprintf (stderr, "%s", args[i].long_name);
+               print_arg (buf, sizeof(buf), 0, 1, &args[i]);
+               count += fprintf(stderr, "%s", buf);
+           }
+           while(count++ <= max_len)
+               putc (' ', stderr);
+           fprintf (stderr, "%s\n", args[i].help);
+       }
+    }
+}
+
+static int
+add_string(getarg_strings *s, char *value)
+{
+    char **strings;
+
+    strings = realloc(s->strings, (s->num_strings + 1) * sizeof(*s->strings));
+    if (strings == NULL) {
+       free(s->strings);
+       s->strings = NULL;
+       s->num_strings = 0;
+       return ENOMEM;
+    }
+    s->strings = strings;
+    s->strings[s->num_strings] = value;
+    s->num_strings++;
+    return 0;
+}
+
+static int
+arg_match_long(struct getargs *args, size_t num_args,
+              char *argv, int argc, char **rargv, int *goptind)
+{
+    int i;
+    char *goptarg = NULL;
+    int negate = 0;
+    int partial_match = 0;
+    struct getargs *partial = NULL;
+    struct getargs *current = NULL;
+    int argv_len;
+    char *p;
+    int p_len;
+
+    argv_len = strlen(argv);
+    p = strchr (argv, '=');
+    if (p != NULL)
+       argv_len = p - argv;
+
+    for (i = 0; i < num_args; ++i) {
+       if(args[i].long_name) {
+           int len = strlen(args[i].long_name);
+           p = argv;
+           p_len = argv_len;
+           negate = 0;
+
+           for (;;) {
+               if (strncmp (args[i].long_name, p, p_len) == 0) {
+                   if(p_len == len)
+                       current = &args[i];
+                   else {
+                       ++partial_match;
+                       partial = &args[i];
+                   }
+                   goptarg  = p + p_len;
+               } else if (ISFLAG(args[i]) && strncmp (p, "no-", 3) == 0) {
+                   negate = !negate;
+                   p += 3;
+                   p_len -= 3;
+                   continue;
+               }
+               break;
+           }
+           if (current)
+               break;
+       }
+    }
+    if (current == NULL) {
+       if (partial_match == 1)
+           current = partial;
+       else
+           return ARG_ERR_NO_MATCH;
+    }
+    
+    if(*goptarg == '\0'
+       && !ISFLAG(*current)
+       && current->type != arg_collect
+       && current->type != arg_counter)
+       return ARG_ERR_NO_MATCH;
+    switch(current->type){
+    case arg_integer:
+    {
+       int tmp;
+       if(sscanf(goptarg + 1, "%d", &tmp) != 1)
+           return ARG_ERR_BAD_ARG;
+       *(int*)current->value = tmp;
+       return 0;
+    }
+    case arg_string:
+    {
+       *(char**)current->value = goptarg + 1;
+       return 0;
+    }
+    case arg_strings:
+    {
+       return add_string((getarg_strings*)current->value, goptarg + 1);
+    }
+    case arg_flag:
+    case arg_negative_flag:
+    {
+       int *flag = current->value;
+       if(*goptarg == '\0' ||
+          strcmp(goptarg + 1, "yes") == 0 || 
+          strcmp(goptarg + 1, "true") == 0){
+           *flag = !negate;
+           return 0;
+       } else if (*goptarg && strcmp(goptarg + 1, "maybe") == 0) {
+#ifdef HAVE_RANDOM
+           *flag = random() & 1;
+#else
+           *flag = rand() & 1;
+#endif
+       } else {
+           *flag = negate;
+           return 0;
+       }
+       return ARG_ERR_BAD_ARG;
+    }
+    case arg_counter :
+    {
+       int val;
+
+       if (*goptarg == '\0')
+           val = 1;
+       else if(sscanf(goptarg + 1, "%d", &val) != 1)
+           return ARG_ERR_BAD_ARG;
+       *(int *)current->value += val;
+       return 0;
+    }
+    case arg_double:
+    {
+       double tmp;
+       if(sscanf(goptarg + 1, "%lf", &tmp) != 1)
+           return ARG_ERR_BAD_ARG;
+       *(double*)current->value = tmp;
+       return 0;
+    }
+    case arg_collect:{
+       struct getarg_collect_info *c = current->value;
+       int o = argv - rargv[*goptind];
+       return (*c->func)(FALSE, argc, rargv, goptind, &o, c->data);
+    }
+
+    default:
+       abort ();
+    }
+}
+
+static int
+arg_match_short (struct getargs *args, size_t num_args,
+                char *argv, int argc, char **rargv, int *goptind)
+{
+    int j, k;
+
+    for(j = 1; j > 0 && j < strlen(rargv[*goptind]); j++) {
+       for(k = 0; k < num_args; k++) {
+           char *goptarg;
+
+           if(args[k].short_name == 0)
+               continue;
+           if(argv[j] == args[k].short_name) {
+               if(args[k].type == arg_flag) {
+                   *(int*)args[k].value = 1;
+                   break;
+               }
+               if(args[k].type == arg_negative_flag) {
+                   *(int*)args[k].value = 0;
+                   break;
+               } 
+               if(args[k].type == arg_counter) {
+                   ++*(int *)args[k].value;
+                   break;
+               }
+               if(args[k].type == arg_collect) {
+                   struct getarg_collect_info *c = args[k].value;
+
+                   if((*c->func)(TRUE, argc, rargv, goptind, &j, c->data))
+                       return ARG_ERR_BAD_ARG;
+                   break;
+               }
+
+               if(argv[j + 1])
+                   goptarg = &argv[j + 1];
+               else {
+                   ++*goptind;
+                   goptarg = rargv[*goptind];
+               }
+               if(goptarg == NULL) {
+                   --*goptind;
+                   return ARG_ERR_NO_ARG;
+               }
+               if(args[k].type == arg_integer) {
+                   int tmp;
+                   if(sscanf(goptarg, "%d", &tmp) != 1)
+                       return ARG_ERR_BAD_ARG;
+                   *(int*)args[k].value = tmp;
+                   return 0;
+               } else if(args[k].type == arg_string) {
+                   *(char**)args[k].value = goptarg;
+                   return 0;
+               } else if(args[k].type == arg_strings) {
+                   return add_string((getarg_strings*)args[k].value, goptarg);
+               } else if(args[k].type == arg_double) {
+                   double tmp;
+                   if(sscanf(goptarg, "%lf", &tmp) != 1)
+                       return ARG_ERR_BAD_ARG;
+                   *(double*)args[k].value = tmp;
+                   return 0;
+               }
+               return ARG_ERR_BAD_ARG;
+           }
+       }
+       if (k == num_args)
+           return ARG_ERR_NO_MATCH;
+    }
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+getarg(struct getargs *args, size_t num_args, 
+       int argc, char **argv, int *goptind)
+{
+    int i;
+    int ret = 0;
+
+#if defined(HAVE_SRANDOMDEV)
+    srandomdev();
+#elif defined(HAVE_RANDOM)
+    srandom(time(NULL));
+#else
+    srand (time(NULL));
+#endif
+    (*goptind)++;
+    for(i = *goptind; i < argc; i++) {
+       if(argv[i][0] != '-')
+           break;
+       if(argv[i][1] == '-'){
+           if(argv[i][2] == 0){
+               i++;
+               break;
+           }
+           ret = arg_match_long (args, num_args, argv[i] + 2, 
+                                 argc, argv, &i);
+       } else {
+           ret = arg_match_short (args, num_args, argv[i],
+                                  argc, argv, &i);
+       }
+       if(ret)
+           break;
+    }
+    *goptind = i;
+    return ret;
+}
+
+void ROKEN_LIB_FUNCTION
+free_getarg_strings (getarg_strings *s)
+{
+    free (s->strings);
+}
+
+#if TEST
+int foo_flag = 2;
+int flag1 = 0;
+int flag2 = 0;
+int bar_int;
+char *baz_string;
+
+struct getargs args[] = {
+    { NULL, '1', arg_flag, &flag1, "one", NULL },
+    { NULL, '2', arg_flag, &flag2, "two", NULL },
+    { "foo", 'f', arg_negative_flag, &foo_flag, "foo", NULL },
+    { "bar", 'b', arg_integer, &bar_int, "bar", "seconds"},
+    { "baz", 'x', arg_string, &baz_string, "baz", "name" },
+};
+
+int main(int argc, char **argv)
+{
+    int goptind = 0;
+    while(getarg(args, 5, argc, argv, &goptind))
+       printf("Bad arg: %s\n", argv[goptind]);
+    printf("flag1 = %d\n", flag1);  
+    printf("flag2 = %d\n", flag2);  
+    printf("foo_flag = %d\n", foo_flag);  
+    printf("bar_int = %d\n", bar_int);
+    printf("baz_flag = %s\n", baz_string);
+    arg_printusage (args, 5, argv[0], "nothing here");
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/getarg.h b/src/kerberosV/src/lib/roken/getarg.h
new file mode 100644 (file)
index 0000000..ef3e92d
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1997 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: getarg.h,v 1.14 2005/04/13 05:52:27 lha Exp $ */
+
+#ifndef __GETARG_H__
+#define __GETARG_H__
+
+#include <stddef.h>
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+struct getargs{
+    const char *long_name;
+    char short_name;
+    enum { arg_integer, 
+          arg_string, 
+          arg_flag, 
+          arg_negative_flag, 
+          arg_strings,
+          arg_double,
+          arg_collect,
+          arg_counter
+    } type;
+    void *value;
+    const char *help;
+    const char *arg_help;
+};
+
+enum {
+    ARG_ERR_NO_MATCH  = 1,
+    ARG_ERR_BAD_ARG,
+    ARG_ERR_NO_ARG
+};
+
+typedef struct getarg_strings {
+    int num_strings;
+    char **strings;
+} getarg_strings;
+
+typedef int (*getarg_collect_func)(int short_opt,
+                                  int argc,
+                                  char **argv,
+                                  int *goptind,
+                                  int *goptarg,
+                                  void *data);
+
+typedef struct getarg_collect_info {
+    getarg_collect_func func;
+    void *data;
+} getarg_collect_info;
+
+int ROKEN_LIB_FUNCTION
+getarg(struct getargs *args, size_t num_args, 
+       int argc, char **argv, int *goptind);
+
+void ROKEN_LIB_FUNCTION
+arg_printusage (struct getargs *args,
+               size_t num_args,
+               const char *progname,
+               const char *extra_string);
+
+void ROKEN_LIB_FUNCTION
+free_getarg_strings (getarg_strings *);
+
+#endif /* __GETARG_H__ */
diff --git a/src/kerberosV/src/lib/roken/getcap.c b/src/kerberosV/src/lib/roken/getcap.c
new file mode 100644 (file)
index 0000000..0bc2af2
--- /dev/null
@@ -0,0 +1,1115 @@
+/*     $NetBSD: getcap.c,v 1.29 1999/03/29 09:27:29 abs Exp $  */
+
+/*-
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Casey Leedom of Lawrence Livermore National Laboratory.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+RCSID("$KTH: getcap.c,v 1.10 2005/04/12 11:28:44 lha Exp $");
+
+#include <sys/types.h>
+#include <ctype.h>
+#if defined(HAVE_DB_185_H)
+#include <db_185.h>
+#elif defined(HAVE_DB_H)
+#include <db.h>
+#endif
+#include <errno.h>     
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define        BFRAG           1024
+#if 0
+#define        BSIZE           1024
+#endif
+#define        ESC             ('[' & 037)     /* ASCII ESC */
+#define        MAX_RECURSION   32              /* maximum getent recursion */
+#define        SFRAG           100             /* cgetstr mallocs in SFRAG chunks */
+
+#define RECOK  (char)0
+#define TCERR  (char)1
+#define        SHADOW  (char)2
+
+static size_t   topreclen;     /* toprec length */
+static char    *toprec;        /* Additional record specified by cgetset() */
+static int      gottoprec;     /* Flag indicating retrieval of toprecord */
+
+#if defined(HAVE_DBOPEN) && defined(HAVE_DB_H)
+#define USE_DB
+#endif
+
+#ifdef USE_DB
+static int     cdbget (DB *, char **, const char *);
+#endif
+static int     getent (char **, size_t *, char **, int, const char *, int, char *);
+static int     nfcmp (char *, char *);
+
+
+int ROKEN_LIB_FUNCTION cgetset(const char *ent);
+char *ROKEN_LIB_FUNCTION cgetcap(char *buf, const char *cap, int type);
+int ROKEN_LIB_FUNCTION cgetent(char **buf, char **db_array, const char *name);
+int ROKEN_LIB_FUNCTION cgetmatch(const char *buf, const char *name);
+int ROKEN_LIB_FUNCTION cgetclose(void);
+#if 0
+int cgetfirst(char **buf, char **db_array);
+int cgetnext(char **bp, char **db_array);
+#endif
+int ROKEN_LIB_FUNCTION cgetstr(char *buf, const char *cap, char **str);
+int ROKEN_LIB_FUNCTION cgetustr(char *buf, const char *cap, char **str);
+int ROKEN_LIB_FUNCTION cgetnum(char *buf, const char *cap, long *num);
+/*
+ * Cgetset() allows the addition of a user specified buffer to be added
+ * to the database array, in effect "pushing" the buffer on top of the
+ * virtual database. 0 is returned on success, -1 on failure.
+ */
+int ROKEN_LIB_FUNCTION
+cgetset(const char *ent)
+{
+    const char *source, *check;
+    char *dest;
+
+    if (ent == NULL) {
+       if (toprec)
+           free(toprec);
+       toprec = NULL;
+       topreclen = 0;
+       return (0);
+    }
+    topreclen = strlen(ent);
+    if ((toprec = malloc (topreclen + 1)) == NULL) {
+       errno = ENOMEM;
+       return (-1);
+    }
+    gottoprec = 0;
+
+    source=ent;
+    dest=toprec;
+    while (*source) { /* Strip whitespace */
+       *dest++ = *source++; /* Do not check first field */
+       while (*source == ':') {
+           check=source+1;
+           while (*check && (isspace((unsigned char)*check) ||
+                             (*check=='\\' && isspace((unsigned char)check[1]))))
+               ++check;
+           if( *check == ':' )
+               source=check;
+           else
+               break;
+
+       }
+    }
+    *dest=0;
+
+    return (0);
+}
+
+/*
+ * Cgetcap searches the capability record buf for the capability cap with
+ * type `type'.  A pointer to the value of cap is returned on success, NULL
+ * if the requested capability couldn't be found.
+ *
+ * Specifying a type of ':' means that nothing should follow cap (:cap:).
+ * In this case a pointer to the terminating ':' or NUL will be returned if
+ * cap is found.
+ *
+ * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
+ * return NULL.
+ */
+char * ROKEN_LIB_FUNCTION
+cgetcap(char *buf, const char *cap, int type)
+{
+    char *bp;
+    const char *cp;
+
+    bp = buf;
+    for (;;) {
+       /*
+        * Skip past the current capability field - it's either the
+        * name field if this is the first time through the loop, or
+        * the remainder of a field whose name failed to match cap.
+        */
+       for (;;)
+           if (*bp == '\0')
+               return (NULL);
+           else
+               if (*bp++ == ':')
+                   break;
+
+       /*
+        * Try to match (cap, type) in buf.
+        */
+       for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
+           continue;
+       if (*cp != '\0')
+           continue;
+       if (*bp == '@')
+           return (NULL);
+       if (type == ':') {
+           if (*bp != '\0' && *bp != ':')
+               continue;
+           return(bp);
+       }
+       if (*bp != type)
+           continue;
+       bp++;
+       return (*bp == '@' ? NULL : bp);
+    }
+    /* NOTREACHED */
+}
+
+/*
+ * Cgetent extracts the capability record name from the NULL terminated file
+ * array db_array and returns a pointer to a malloc'd copy of it in buf.
+ * Buf must be retained through all subsequent calls to cgetcap, cgetnum,
+ * cgetflag, and cgetstr, but may then be free'd.  0 is returned on success,
+ * -1 if the requested record couldn't be found, -2 if a system error was
+ * encountered (couldn't open/read a file, etc.), and -3 if a potential
+ * reference loop is detected.
+ */
+int ROKEN_LIB_FUNCTION
+cgetent(char **buf, char **db_array, const char *name)
+{
+    size_t dummy;
+
+    return (getent(buf, &dummy, db_array, -1, name, 0, NULL));
+}
+
+/*
+ * Getent implements the functions of cgetent.  If fd is non-negative,
+ * *db_array has already been opened and fd is the open file descriptor.  We
+ * do this to save time and avoid using up file descriptors for tc=
+ * recursions.
+ *
+ * Getent returns the same success/failure codes as cgetent.  On success, a
+ * pointer to a malloc'ed capability record with all tc= capabilities fully
+ * expanded and its length (not including trailing ASCII NUL) are left in
+ * *cap and *len.
+ *
+ * Basic algorithm:
+ *     + Allocate memory incrementally as needed in chunks of size BFRAG
+ *       for capability buffer.
+ *     + Recurse for each tc=name and interpolate result.  Stop when all
+ *       names interpolated, a name can't be found, or depth exceeds
+ *       MAX_RECURSION.
+ */
+static int
+getent(char **cap, size_t *len, char **db_array, int fd, 
+       const char *name, int depth, char *nfield)
+{
+    char *r_end, *rp = NULL, **db_p;   /* pacify gcc */
+    int myfd = 0, eof, foundit;
+    char *record;
+    int tc_not_resolved;
+       
+    /*
+     * Return with ``loop detected'' error if we've recursed more than
+     * MAX_RECURSION times.
+     */
+    if (depth > MAX_RECURSION)
+       return (-3);
+
+    /*
+     * Check if we have a top record from cgetset().
+     */
+    if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) {
+       size_t len = topreclen + BFRAG;
+       if ((record = malloc (len)) == NULL) {
+           errno = ENOMEM;
+           return (-2);
+       }
+       (void)strlcpy(record, toprec, len);
+       db_p = db_array;
+       rp = record + topreclen + 1;
+       r_end = rp + BFRAG;
+       goto tc_exp;
+    }
+    /*
+     * Allocate first chunk of memory.
+     */
+    if ((record = malloc(BFRAG)) == NULL) {
+       errno = ENOMEM;
+       return (-2);
+    }
+    r_end = record + BFRAG;
+    foundit = 0;
+    /*
+     * Loop through database array until finding the record.
+     */
+
+    for (db_p = db_array; *db_p != NULL; db_p++) {
+       eof = 0;
+
+       /*
+        * Open database if not already open.
+        */
+
+       if (fd >= 0) {
+           (void)lseek(fd, (off_t)0, SEEK_SET);
+       } else {
+#ifdef USE_DB
+           char pbuf[_POSIX_PATH_MAX];
+           char *cbuf;
+           size_t clen;
+           int retval;
+           DB *capdbp;
+
+           (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p);
+           if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0))
+               != NULL) {
+               free(record);
+               retval = cdbget(capdbp, &record, name);
+               if (retval < 0) {
+                   /* no record available */
+                   (void)capdbp->close(capdbp);
+                   return (retval);
+               }
+                               /* save the data; close frees it */
+               clen = strlen(record);
+               cbuf = malloc(clen + 1);
+               memmove(cbuf, record, clen + 1);
+               if (capdbp->close(capdbp) < 0) {
+                   free(cbuf);
+                   return (-2);
+               }
+               *len = clen;
+               *cap = cbuf;
+               return (retval);
+           } else
+#endif
+           {
+               fd = open(*db_p, O_RDONLY, 0);
+               if (fd < 0) {
+                   /* No error on unfound file. */
+                   continue;
+               }
+               myfd = 1;
+           }
+       }
+       /*
+        * Find the requested capability record ...
+        */
+       {
+           char buf[BUFSIZ];
+           char *b_end, *bp, *cp;
+           int c, slash;
+
+           /*
+            * Loop invariants:
+            *  There is always room for one more character in record.
+            *  R_end always points just past end of record.
+            *  Rp always points just past last character in record.
+            *  B_end always points just past last character in buf.
+            *  Bp always points at next character in buf.
+            *  Cp remembers where the last colon was.
+            */
+           b_end = buf;
+           bp = buf;
+           cp = 0;
+           slash = 0;
+           for (;;) {
+
+               /*
+                * Read in a line implementing (\, newline)
+                * line continuation.
+                */
+               rp = record;
+               for (;;) {
+                   if (bp >= b_end) {
+                       int n;
+               
+                       n = read(fd, buf, sizeof(buf));
+                       if (n <= 0) {
+                           if (myfd)
+                               (void)close(fd);
+                           if (n < 0) {
+                               free(record);
+                               return (-2);
+                           } else {
+                               fd = -1;
+                               eof = 1;
+                               break;
+                           }
+                       }
+                       b_end = buf+n;
+                       bp = buf;
+                   }
+       
+                   c = *bp++;
+                   if (c == '\n') {
+                       if (slash) {
+                           slash = 0;
+                           rp--;
+                           continue;
+                       } else
+                           break;
+                   }
+                   if (slash) {
+                       slash = 0;
+                       cp = 0;
+                   }
+                   if (c == ':') {
+                       /*
+                        * If the field was `empty' (i.e.
+                        * contained only white space), back up
+                        * to the colon (eliminating the
+                        * field).
+                        */
+                       if (cp)
+                           rp = cp;
+                       else
+                           cp = rp;
+                   } else if (c == '\\') {
+                       slash = 1;
+                   } else if (c != ' ' && c != '\t') {
+                       /*
+                        * Forget where the colon was, as this
+                        * is not an empty field.
+                        */
+                       cp = 0;
+                   }
+                   *rp++ = c;
+
+                               /*
+                                * Enforce loop invariant: if no room 
+                                * left in record buffer, try to get
+                                * some more.
+                                */
+                   if (rp >= r_end) {
+                       u_int pos;
+                       size_t newsize;
+
+                       pos = rp - record;
+                       newsize = r_end - record + BFRAG;
+                       record = realloc(record, newsize);
+                       if (record == NULL) {
+                           errno = ENOMEM;
+                           if (myfd)
+                               (void)close(fd);
+                           return (-2);
+                       }
+                       r_end = record + newsize;
+                       rp = record + pos;
+                   }
+               }
+               /* Eliminate any white space after the last colon. */
+               if (cp)
+                   rp = cp + 1;
+               /* Loop invariant lets us do this. */
+               *rp++ = '\0';
+
+               /*
+                * If encountered eof check next file.
+                */
+               if (eof)
+                   break;
+                               
+               /*
+                * Toss blank lines and comments.
+                */
+               if (*record == '\0' || *record == '#')
+                   continue;
+       
+               /*
+                * See if this is the record we want ...
+                */
+               if (cgetmatch(record, name) == 0) {
+                   if (nfield == NULL || !nfcmp(nfield, record)) {
+                       foundit = 1;
+                       break;  /* found it! */
+                   }
+               }
+           }
+       }
+       if (foundit)
+           break;
+    }
+
+    if (!foundit)
+       return (-1);
+
+    /*
+     * Got the capability record, but now we have to expand all tc=name
+     * references in it ...
+     */
+ tc_exp:       {
+       char *newicap, *s;
+       size_t ilen, newilen;
+       int diff, iret, tclen;
+       char *icap, *scan, *tc, *tcstart, *tcend;
+
+       /*
+        * Loop invariants:
+        *      There is room for one more character in record.
+        *      R_end points just past end of record.
+        *      Rp points just past last character in record.
+        *      Scan points at remainder of record that needs to be
+        *      scanned for tc=name constructs.
+        */
+       scan = record;
+       tc_not_resolved = 0;
+       for (;;) {
+           if ((tc = cgetcap(scan, "tc", '=')) == NULL)
+               break;
+
+           /*
+            * Find end of tc=name and stomp on the trailing `:'
+            * (if present) so we can use it to call ourselves.
+            */
+           s = tc;
+           for (;;)
+               if (*s == '\0')
+                   break;
+               else
+                   if (*s++ == ':') {
+                       *(s - 1) = '\0';
+                       break;
+                   }
+           tcstart = tc - 3;
+           tclen = s - tcstart;
+           tcend = s;
+
+           iret = getent(&icap, &ilen, db_p, fd, tc, depth+1, 
+                         NULL);
+           newicap = icap;             /* Put into a register. */
+           newilen = ilen;
+           if (iret != 0) {
+                               /* an error */
+               if (iret < -1) {
+                   if (myfd)
+                       (void)close(fd);
+                   free(record);
+                   return (iret);
+               }
+               if (iret == 1)
+                   tc_not_resolved = 1;
+                               /* couldn't resolve tc */
+               if (iret == -1) {
+                   *(s - 1) = ':';                     
+                   scan = s - 1;
+                   tc_not_resolved = 1;
+                   continue;
+                                       
+               }
+           }
+           /* not interested in name field of tc'ed record */
+           s = newicap;
+           for (;;)
+               if (*s == '\0')
+                   break;
+               else
+                   if (*s++ == ':')
+                       break;
+           newilen -= s - newicap;
+           newicap = s;
+
+           /* make sure interpolated record is `:'-terminated */
+           s += newilen;
+           if (*(s-1) != ':') {
+               *s = ':';       /* overwrite NUL with : */
+               newilen++;
+           }
+
+           /*
+            * Make sure there's enough room to insert the
+            * new record.
+            */
+           diff = newilen - tclen;
+           if (diff >= r_end - rp) {
+               u_int pos, tcpos, tcposend;
+               size_t newsize;
+
+               pos = rp - record;
+               newsize = r_end - record + diff + BFRAG;
+               tcpos = tcstart - record;
+               tcposend = tcend - record;
+               record = realloc(record, newsize);
+               if (record == NULL) {
+                   errno = ENOMEM;
+                   if (myfd)
+                       (void)close(fd);
+                   free(icap);
+                   return (-2);
+               }
+               r_end = record + newsize;
+               rp = record + pos;
+               tcstart = record + tcpos;
+               tcend = record + tcposend;
+           }
+
+           /*
+            * Insert tc'ed record into our record.
+            */
+           s = tcstart + newilen;
+           memmove(s, tcend,  (size_t)(rp - tcend));
+           memmove(tcstart, newicap, newilen);
+           rp += diff;
+           free(icap);
+
+           /*
+            * Start scan on `:' so next cgetcap works properly
+            * (cgetcap always skips first field).
+            */
+           scan = s-1;
+       }
+       
+    }
+    /*
+     * Close file (if we opened it), give back any extra memory, and
+     * return capability, length and success.
+     */
+    if (myfd)
+       (void)close(fd);
+    *len = rp - record - 1;    /* don't count NUL */
+    if (r_end > rp)
+       if ((record = 
+            realloc(record, (size_t)(rp - record))) == NULL) {
+           errno = ENOMEM;
+           return (-2);
+       }
+               
+    *cap = record;
+    if (tc_not_resolved)
+       return (1);
+    return (0);
+}      
+
+#ifdef USE_DB
+static int
+cdbget(DB *capdbp, char **bp, const char *name)
+{
+       DBT key;
+       DBT data;
+
+       /* LINTED key is not modified */
+       key.data = (char *)name;
+       key.size = strlen(name);
+
+       for (;;) {
+               /* Get the reference. */
+               switch(capdbp->get(capdbp, &key, &data, 0)) {
+               case -1:
+                       return (-2);
+               case 1:
+                       return (-1);
+               }
+
+               /* If not an index to another record, leave. */
+               if (((char *)data.data)[0] != SHADOW)
+                       break;
+
+               key.data = (char *)data.data + 1;
+               key.size = data.size - 1;
+       }
+       
+       *bp = (char *)data.data + 1;
+       return (((char *)(data.data))[0] == TCERR ? 1 : 0);
+}
+#endif /* USE_DB */
+
+/*
+ * Cgetmatch will return 0 if name is one of the names of the capability
+ * record buf, -1 if not.
+ */
+int
+cgetmatch(const char *buf, const char *name)
+{
+    const char *np, *bp;
+
+    /*
+     * Start search at beginning of record.
+     */
+    bp = buf;
+    for (;;) {
+       /*
+        * Try to match a record name.
+        */
+       np = name;
+       for (;;)
+           if (*np == '\0') {
+               if (*bp == '|' || *bp == ':' || *bp == '\0')
+                   return (0);
+               else
+                   break;
+           } else
+               if (*bp++ != *np++)
+                   break;
+
+       /*
+        * Match failed, skip to next name in record.
+        */
+       bp--;   /* a '|' or ':' may have stopped the match */
+       for (;;)
+           if (*bp == '\0' || *bp == ':')
+               return (-1);    /* match failed totally */
+           else
+               if (*bp++ == '|')
+                   break;      /* found next name */
+    }
+}
+
+#if 0
+int
+cgetfirst(char **buf, char **db_array)
+{
+    (void)cgetclose();
+    return (cgetnext(buf, db_array));
+}
+#endif
+
+static FILE *pfp;
+static int slash;
+static char **dbp;
+
+int ROKEN_LIB_FUNCTION
+cgetclose(void)
+{
+    if (pfp != NULL) {
+       (void)fclose(pfp);
+       pfp = NULL;
+    }
+    dbp = NULL;
+    gottoprec = 0;
+    slash = 0;
+    return(0);
+}
+
+#if 0
+/*
+ * Cgetnext() gets either the first or next entry in the logical database 
+ * specified by db_array.  It returns 0 upon completion of the database, 1
+ * upon returning an entry with more remaining, and -1 if an error occurs.
+ */
+int
+cgetnext(char **bp, char **db_array)
+{
+    size_t len;
+    int status, done;
+    char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
+    size_t dummy;
+
+    if (dbp == NULL)
+       dbp = db_array;
+
+    if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL) {
+       (void)cgetclose();
+       return (-1);
+    }
+    for(;;) {
+       if (toprec && !gottoprec) {
+           gottoprec = 1;
+           line = toprec;
+       } else {
+           line = fgetln(pfp, &len);
+           if (line == NULL && pfp) {
+               if (ferror(pfp)) {
+                   (void)cgetclose();
+                   return (-1);
+               } else {
+                   (void)fclose(pfp);
+                   pfp = NULL;
+                   if (*++dbp == NULL) {
+                       (void)cgetclose();
+                       return (0);
+                   } else if ((pfp =
+                               fopen(*dbp, "r")) == NULL) {
+                       (void)cgetclose();
+                       return (-1);
+                   } else
+                       continue;
+               }
+           } else
+               line[len - 1] = '\0';
+           if (len == 1) {
+               slash = 0;
+               continue;
+           }
+           if (isspace((unsigned char)*line) ||
+               *line == ':' || *line == '#' || slash) {
+               if (line[len - 2] == '\\')
+                   slash = 1;
+               else
+                   slash = 0;
+               continue;
+           }
+           if (line[len - 2] == '\\')
+               slash = 1;
+           else
+               slash = 0;
+       }                       
+
+
+       /* 
+        * Line points to a name line.
+        */
+       done = 0;
+       np = nbuf;
+       for (;;) {
+           for (cp = line; *cp != '\0'; cp++) {
+               if (*cp == ':') {
+                   *np++ = ':';
+                   done = 1;
+                   break;
+               }
+               if (*cp == '\\')
+                   break;
+               *np++ = *cp;
+           }
+           if (done) {
+               *np = '\0';
+               break;
+           } else { /* name field extends beyond the line */
+               line = fgetln(pfp, &len);
+               if (line == NULL && pfp) {
+                   if (ferror(pfp)) {
+                       (void)cgetclose();
+                       return (-1);
+                   }
+                   (void)fclose(pfp);
+                   pfp = NULL;
+                   *np = '\0';
+                   break;
+               } else
+                   line[len - 1] = '\0';
+           }
+       }
+       rp = buf;
+       for(cp = nbuf; *cp != '\0'; cp++)
+           if (*cp == '|' || *cp == ':')
+               break;
+           else
+               *rp++ = *cp;
+
+       *rp = '\0';
+       /* 
+        * XXX 
+        * Last argument of getent here should be nbuf if we want true
+        * sequential access in the case of duplicates.  
+        * With NULL, getent will return the first entry found
+        * rather than the duplicate entry record.  This is a 
+        * matter of semantics that should be resolved.
+        */
+       status = getent(bp, &dummy, db_array, -1, buf, 0, NULL);
+       if (status == -2 || status == -3)
+           (void)cgetclose();
+
+       return (status + 1);
+    }
+    /* NOTREACHED */
+}
+#endif
+
+/*
+ * Cgetstr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf.  A pointer to a decoded, NUL
+ * terminated, malloc'd copy of the string is returned in the char *
+ * pointed to by str.  The length of the string not including the trailing
+ * NUL is returned on success, -1 if the requested string capability
+ * couldn't be found, -2 if a system error was encountered (storage
+ * allocation failure).
+ */
+int ROKEN_LIB_FUNCTION
+cgetstr(char *buf, const char *cap, char **str)
+{
+    u_int m_room;
+    const char *bp;
+    char *mp;
+    int len;
+    char *mem;
+
+    /*
+     * Find string capability cap
+     */
+    bp = cgetcap(buf, cap, '=');
+    if (bp == NULL)
+       return (-1);
+
+    /*
+     * Conversion / storage allocation loop ...  Allocate memory in
+     * chunks SFRAG in size.
+     */
+    if ((mem = malloc(SFRAG)) == NULL) {
+       errno = ENOMEM;
+       return (-2);    /* couldn't even allocate the first fragment */
+    }
+    m_room = SFRAG;
+    mp = mem;
+
+    while (*bp != ':' && *bp != '\0') {
+       /*
+        * Loop invariants:
+        *      There is always room for one more character in mem.
+        *      Mp always points just past last character in mem.
+        *      Bp always points at next character in buf.
+        */
+       if (*bp == '^') {
+           bp++;
+           if (*bp == ':' || *bp == '\0')
+               break;  /* drop unfinished escape */
+           *mp++ = *bp++ & 037;
+       } else if (*bp == '\\') {
+           bp++;
+           if (*bp == ':' || *bp == '\0')
+               break;  /* drop unfinished escape */
+           if ('0' <= *bp && *bp <= '7') {
+               int n, i;
+
+               n = 0;
+               i = 3;  /* maximum of three octal digits */
+               do {
+                   n = n * 8 + (*bp++ - '0');
+               } while (--i && '0' <= *bp && *bp <= '7');
+               *mp++ = n;
+           }
+           else switch (*bp++) {
+           case 'b': case 'B':
+               *mp++ = '\b';
+               break;
+           case 't': case 'T':
+               *mp++ = '\t';
+               break;
+           case 'n': case 'N':
+               *mp++ = '\n';
+               break;
+           case 'f': case 'F':
+               *mp++ = '\f';
+               break;
+           case 'r': case 'R':
+               *mp++ = '\r';
+               break;
+           case 'e': case 'E':
+               *mp++ = ESC;
+               break;
+           case 'c': case 'C':
+               *mp++ = ':';
+               break;
+           default:
+               /*
+                * Catches '\', '^', and
+                *  everything else.
+                */
+               *mp++ = *(bp-1);
+               break;
+           }
+       } else
+           *mp++ = *bp++;
+       m_room--;
+
+       /*
+        * Enforce loop invariant: if no room left in current
+        * buffer, try to get some more.
+        */
+       if (m_room == 0) {
+           size_t size = mp - mem;
+
+           if ((mem = realloc(mem, size + SFRAG)) == NULL)
+               return (-2);
+           m_room = SFRAG;
+           mp = mem + size;
+       }
+    }
+    *mp++ = '\0';      /* loop invariant let's us do this */
+    m_room--;
+    len = mp - mem - 1;
+
+    /*
+     * Give back any extra memory and return value and success.
+     */
+    if (m_room != 0)
+       if ((mem = realloc(mem, (size_t)(mp - mem))) == NULL)
+           return (-2);
+    *str = mem;
+    return (len);
+}
+
+/*
+ * Cgetustr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf.  The difference between cgetustr()
+ * and cgetstr() is that cgetustr does not decode escapes but rather treats
+ * all characters literally.  A pointer to a  NUL terminated malloc'd 
+ * copy of the string is returned in the char pointed to by str.  The 
+ * length of the string not including the trailing NUL is returned on success,
+ * -1 if the requested string capability couldn't be found, -2 if a system 
+ * error was encountered (storage allocation failure).
+ */
+int ROKEN_LIB_FUNCTION
+cgetustr(char *buf, const char *cap, char **str)
+{
+    u_int m_room;
+    const char *bp;
+    char *mp;
+    int len;
+    char *mem;
+
+    /*
+     * Find string capability cap
+     */
+    if ((bp = cgetcap(buf, cap, '=')) == NULL)
+       return (-1);
+
+    /*
+     * Conversion / storage allocation loop ...  Allocate memory in
+     * chunks SFRAG in size.
+     */
+    if ((mem = malloc(SFRAG)) == NULL) {
+       errno = ENOMEM;
+       return (-2);    /* couldn't even allocate the first fragment */
+    }
+    m_room = SFRAG;
+    mp = mem;
+
+    while (*bp != ':' && *bp != '\0') {
+       /*
+        * Loop invariants:
+        *      There is always room for one more character in mem.
+        *      Mp always points just past last character in mem.
+        *      Bp always points at next character in buf.
+        */
+       *mp++ = *bp++;
+       m_room--;
+
+       /*
+        * Enforce loop invariant: if no room left in current
+        * buffer, try to get some more.
+        */
+       if (m_room == 0) {
+           size_t size = mp - mem;
+
+           if ((mem = realloc(mem, size + SFRAG)) == NULL)
+               return (-2);
+           m_room = SFRAG;
+           mp = mem + size;
+       }
+    }
+    *mp++ = '\0';      /* loop invariant let's us do this */
+    m_room--;
+    len = mp - mem - 1;
+
+    /*
+     * Give back any extra memory and return value and success.
+     */
+    if (m_room != 0)
+       if ((mem = realloc(mem, (size_t)(mp - mem))) == NULL)
+           return (-2);
+    *str = mem;
+    return (len);
+}
+
+/*
+ * Cgetnum retrieves the value of the numeric capability cap from the
+ * capability record pointed to by buf.  The numeric value is returned in
+ * the long pointed to by num.  0 is returned on success, -1 if the requested
+ * numeric capability couldn't be found.
+ */
+int ROKEN_LIB_FUNCTION
+cgetnum(char *buf, const char *cap, long *num)
+{
+    long n;
+    int base, digit;
+    const char *bp;
+
+    /*
+     * Find numeric capability cap
+     */
+    bp = cgetcap(buf, cap, '#');
+    if (bp == NULL)
+       return (-1);
+
+    /*
+     * Look at value and determine numeric base:
+     * 0x... or 0X...  hexadecimal,
+     * else    0...            octal,
+     * else                    decimal.
+     */
+    if (*bp == '0') {
+       bp++;
+       if (*bp == 'x' || *bp == 'X') {
+           bp++;
+           base = 16;
+       } else
+           base = 8;
+    } else
+       base = 10;
+
+    /*
+     * Conversion loop ...
+     */
+    n = 0;
+    for (;;) {
+       if ('0' <= *bp && *bp <= '9')
+           digit = *bp - '0';
+       else if ('a' <= *bp && *bp <= 'f')
+           digit = 10 + *bp - 'a';
+       else if ('A' <= *bp && *bp <= 'F')
+           digit = 10 + *bp - 'A';
+       else
+           break;
+
+       if (digit >= base)
+           break;
+
+       n = n * base + digit;
+       bp++;
+    }
+
+    /*
+     * Return value and success.
+     */
+    *num = n;
+    return (0);
+}
+
+
+/*
+ * Compare name field of record.
+ */
+static int
+nfcmp(char *nf, char *rec)
+{
+    char *cp, tmp;
+    int ret;
+       
+    for (cp = rec; *cp != ':'; cp++)
+       ;
+       
+    tmp = *(cp + 1);
+    *(cp + 1) = '\0';
+    ret = strcmp(nf, rec);
+    *(cp + 1) = tmp;
+
+    return (ret);
+}
diff --git a/src/kerberosV/src/lib/roken/getcwd.c b/src/kerberosV/src/lib/roken/getcwd.c
new file mode 100644 (file)
index 0000000..e5576d8
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getcwd.c,v 1.13 2005/04/12 11:28:44 lha Exp $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "roken.h"
+
+char* ROKEN_LIB_FUNCTION
+getcwd(char *path, size_t size)
+{
+    char xxx[MaxPathLen];
+    char *ret;
+    ret = getwd(xxx);
+    if(ret)
+       strlcpy(path, xxx, size);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/getdtablesize.c b/src/kerberosV/src/lib/roken/getdtablesize.c
new file mode 100644 (file)
index 0000000..dd97cf8
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1995-2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getdtablesize.c,v 1.12 2005/04/12 11:28:45 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
+int ROKEN_LIB_FUNCTION
+getdtablesize(void)
+{
+  int files = -1;
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+  files = sysconf(_SC_OPEN_MAX);
+#else /* !defined(HAVE_SYSCONF) */
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+  struct rlimit res;
+  if (getrlimit(RLIMIT_NOFILE, &res) == 0)
+    files = res.rlim_cur;
+#else /* !definded(HAVE_GETRLIMIT) */
+#if defined(HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_MAXFILES)
+  int mib[2];
+  size_t len;
+    
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_MAXFILES;
+  len = sizeof(files);
+  sysctl(&mib, 2, &files, sizeof(files), NULL, 0);
+#endif /* defined(HAVE_SYSCTL) */
+#endif /* !definded(HAVE_GETRLIMIT) */
+#endif /* !defined(HAVE_SYSCONF) */
+
+#ifdef OPEN_MAX
+  if (files < 0)
+    files = OPEN_MAX;
+#endif
+
+#ifdef NOFILE
+  if (files < 0)
+    files = NOFILE;
+#endif    
+    
+  return files;
+}
diff --git a/src/kerberosV/src/lib/roken/getegid.c b/src/kerberosV/src/lib/roken/getegid.c
new file mode 100644 (file)
index 0000000..cbed209
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETEGID
+
+RCSID("$KTH: getegid.c,v 1.3 2005/04/12 11:28:45 lha Exp $");
+
+int ROKEN_LIB_FUNCTION
+getegid(void)
+{
+    return getgid();
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/geteuid.c b/src/kerberosV/src/lib/roken/geteuid.c
new file mode 100644 (file)
index 0000000..9fc4501
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETEUID
+
+RCSID("$KTH: geteuid.c,v 1.3 2005/04/12 11:28:45 lha Exp $");
+
+int ROKEN_LIB_FUNCTION
+geteuid(void)
+{
+    return getuid();
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/getgid.c b/src/kerberosV/src/lib/roken/getgid.c
new file mode 100644 (file)
index 0000000..374dbaa
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETGID
+
+RCSID("$KTH: getgid.c,v 1.3 2005/04/12 11:28:46 lha Exp $");
+
+int ROKEN_LIB_FUNCTION
+getgid(void)
+{
+    return 17;
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/gethostname.c b/src/kerberosV/src/lib/roken/gethostname.c
new file mode 100644 (file)
index 0000000..f291ce2
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETHOSTNAME
+
+#ifdef HAVE_SYS_UTSNAME_H
+#include <sys/utsname.h>
+#endif
+
+/*
+ * Return the local host's name in "name", up to "namelen" characters.
+ * "name" will be null-terminated if "namelen" is big enough.
+ * The return code is 0 on success, -1 on failure.  (The calling
+ * interface is identical to gethostname(2).)
+ */
+
+int ROKEN_LIB_FUNCTION
+gethostname(char *name, int namelen)
+{
+#if defined(HAVE_UNAME)
+    {
+       struct utsname utsname;
+       int ret;
+
+       ret = uname (&utsname);
+       if (ret < 0)
+           return ret;
+       strlcpy (name, utsname.nodename, namelen);
+       return 0;
+    }
+#else
+    strlcpy (name, "some.random.host", namelen);
+    return 0;
+#endif
+}
+
+#endif /* GETHOSTNAME */
diff --git a/src/kerberosV/src/lib/roken/getifaddrs.c b/src/kerberosV/src/lib/roken/getifaddrs.c
new file mode 100644 (file)
index 0000000..948c568
--- /dev/null
@@ -0,0 +1,1186 @@
+/*
+ * Copyright (c) 2000 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getifaddrs.c,v 1.11 2005/04/30 15:45:47 lha Exp $");
+#endif
+#include "roken.h"
+
+#ifdef __osf__
+/* hate */
+struct rtentry;
+struct mbuf;
+#endif
+#ifdef HAVE_NET_IF_H
+#include <net/if.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif /* HAVE_SYS_SOCKIO_H */
+
+#ifdef HAVE_NETINET_IN6_VAR_H
+#include <netinet/in6_var.h>
+#endif /* HAVE_NETINET_IN6_VAR_H */
+
+#include <ifaddrs.h>
+
+#ifdef AF_NETLINK
+
+/*
+ * The linux - AF_NETLINK version of getifaddrs - from Usagi.
+ * Linux does not return v6 addresses from SIOCGIFCONF.
+ */
+
+/* $USAGI: ifaddrs.c,v 1.18 2002/03/06 01:50:46 yoshfuji Exp $ */
+
+/**************************************************************************
+ * ifaddrs.c
+ * Copyright (C)2000 Hideaki YOSHIFUJI, 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 author nor the names 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 AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 "config.h"
+
+#include <string.h>
+#include <time.h>
+#include <malloc.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <sys/socket.h>
+#include <asm/types.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netpacket/packet.h>
+#include <net/ethernet.h>     /* the L2 protocols */
+#include <sys/uio.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+
+#define __set_errno(e) (errno = (e))
+#define __close(fd) (close(fd))
+#undef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr
+#define IFA_NETMASK
+
+/* ====================================================================== */
+struct nlmsg_list{
+    struct nlmsg_list *nlm_next;
+    struct nlmsghdr *nlh;
+    int size;
+    time_t seq;
+};
+
+struct rtmaddr_ifamap {
+  void *address;
+  void *local;
+#ifdef IFA_NETMASK
+  void *netmask;
+#endif
+  void *broadcast;
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+  void *anycast;
+#endif
+  int address_len;
+  int local_len;
+#ifdef IFA_NETMASK
+  int netmask_len;
+#endif
+  int broadcast_len;
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+  int anycast_len;
+#endif
+};
+
+/* ====================================================================== */
+static size_t
+ifa_sa_len(sa_family_t family, int len)
+{
+  size_t size;
+  switch(family){
+  case AF_INET:
+    size = sizeof(struct sockaddr_in);
+    break;
+  case AF_INET6:
+    size = sizeof(struct sockaddr_in6);
+    break;
+  case AF_PACKET:
+    size = (size_t)(((struct sockaddr_ll *)NULL)->sll_addr) + len;
+    if (size < sizeof(struct sockaddr_ll))
+      size = sizeof(struct sockaddr_ll);
+    break;
+  default:
+    size = (size_t)(((struct sockaddr *)NULL)->sa_data) + len;
+    if (size < sizeof(struct sockaddr))
+      size = sizeof(struct sockaddr);
+    break;
+  }
+  return size;
+}
+
+static void 
+ifa_make_sockaddr(sa_family_t family, 
+                 struct sockaddr *sa, 
+                 void *p, size_t len,
+                 uint32_t scope, uint32_t scopeid)
+{
+  if (sa == NULL) return;
+  switch(family){
+  case AF_INET:
+    memcpy(&((struct sockaddr_in*)sa)->sin_addr, (char *)p, len);
+    break;
+  case AF_INET6:
+    memcpy(&((struct sockaddr_in6*)sa)->sin6_addr, (char *)p, len);
+    if (IN6_IS_ADDR_LINKLOCAL(p) ||
+       IN6_IS_ADDR_MC_LINKLOCAL(p)){
+      ((struct sockaddr_in6*)sa)->sin6_scope_id = scopeid;
+    }
+    break;
+  case AF_PACKET:
+    memcpy(((struct sockaddr_ll*)sa)->sll_addr, (char *)p, len);
+    ((struct sockaddr_ll*)sa)->sll_halen = len;
+    break;
+  default:
+    memcpy(sa->sa_data, p, len);       /*XXX*/
+    break;
+  }
+  sa->sa_family = family;
+#ifdef HAVE_SOCKADDR_SA_LEN
+  sa->sa_len = ifa_sa_len(family, len);
+#endif
+}
+
+#ifndef IFA_NETMASK
+static struct sockaddr *
+ifa_make_sockaddr_mask(sa_family_t family, 
+                      struct sockaddr *sa, 
+                      uint32_t prefixlen)
+{
+  int i;
+  char *p = NULL, c;
+  uint32_t max_prefixlen = 0;
+
+  if (sa == NULL) return NULL;
+  switch(family){
+  case AF_INET:
+    memset(&((struct sockaddr_in*)sa)->sin_addr, 0, sizeof(((struct sockaddr_in*)sa)->sin_addr));
+    p = (char *)&((struct sockaddr_in*)sa)->sin_addr;
+    max_prefixlen = 32;
+    break;
+  case AF_INET6:
+    memset(&((struct sockaddr_in6*)sa)->sin6_addr, 0, sizeof(((struct sockaddr_in6*)sa)->sin6_addr));
+    p = (char *)&((struct sockaddr_in6*)sa)->sin6_addr;
+#if 0  /* XXX: fill scope-id? */
+    if (IN6_IS_ADDR_LINKLOCAL(p) ||
+       IN6_IS_ADDR_MC_LINKLOCAL(p)){
+      ((struct sockaddr_in6*)sa)->sin6_scope_id = scopeid;
+    }
+#endif
+    max_prefixlen = 128;
+    break;
+  default:
+    return NULL;
+  }
+  sa->sa_family = family;
+#ifdef HAVE_SOCKADDR_SA_LEN
+  sa->sa_len = ifa_sa_len(family, len);
+#endif
+  if (p){
+    if (prefixlen > max_prefixlen)
+      prefixlen = max_prefixlen;
+    for (i=0; i<(prefixlen / 8); i++)
+      *p++ = 0xff;
+    c = 0xff;
+    c <<= (8 - (prefixlen % 8));
+    *p = c;
+  }
+  return sa;
+}
+#endif
+
+/* ====================================================================== */
+static int 
+nl_sendreq(int sd, int request, int flags, int *seq)
+{
+  char reqbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
+             NLMSG_ALIGN(sizeof(struct rtgenmsg))];
+  struct sockaddr_nl nladdr;
+  struct nlmsghdr *req_hdr;
+  struct rtgenmsg *req_msg;
+  time_t t = time(NULL);
+
+  if (seq) *seq = t;
+  memset(&reqbuf, 0, sizeof(reqbuf));
+  req_hdr = (struct nlmsghdr *)reqbuf;
+  req_msg = (struct rtgenmsg *)NLMSG_DATA(req_hdr);
+  req_hdr->nlmsg_len = NLMSG_LENGTH(sizeof(*req_msg));
+  req_hdr->nlmsg_type = request;
+  req_hdr->nlmsg_flags = flags | NLM_F_REQUEST;
+  req_hdr->nlmsg_pid = 0;
+  req_hdr->nlmsg_seq = t;
+  req_msg->rtgen_family = AF_UNSPEC;
+  memset(&nladdr, 0, sizeof(nladdr));
+  nladdr.nl_family = AF_NETLINK;
+  return (sendto(sd, (void *)req_hdr, req_hdr->nlmsg_len, 0,
+                (struct sockaddr *)&nladdr, sizeof(nladdr)));
+}
+
+static int 
+nl_recvmsg(int sd, int request, int seq, 
+          void *buf, size_t buflen, 
+          int *flags)
+{
+  struct msghdr msg;
+  struct iovec iov = { buf, buflen };
+  struct sockaddr_nl nladdr;
+  int read_len;
+
+  for (;;){
+    msg.msg_name = (void *)&nladdr;
+    msg.msg_namelen = sizeof(nladdr);
+    msg.msg_iov = &iov;
+    msg.msg_iovlen = 1;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_flags = 0;
+    read_len = recvmsg(sd, &msg, 0);
+    if ((read_len < 0 && errno == EINTR) || (msg.msg_flags & MSG_TRUNC))
+      continue;
+    if (flags) *flags = msg.msg_flags;
+    break;
+  }
+  return read_len;
+}
+
+static int 
+nl_getmsg(int sd, int request, int seq, 
+         struct nlmsghdr **nlhp,
+         int *done)
+{
+  struct nlmsghdr *nh;
+  size_t bufsize = 65536, lastbufsize = 0;
+  void *buff = NULL;
+  int result = 0, read_size;
+  int msg_flags;
+  pid_t pid = getpid();
+  for (;;){
+    void *newbuff = realloc(buff, bufsize);
+    if (newbuff == NULL || bufsize < lastbufsize) {
+      result = -1;
+      break;
+    }
+    buff = newbuff;
+    result = read_size = nl_recvmsg(sd, request, seq, buff, bufsize, &msg_flags);
+    if (read_size < 0 || (msg_flags & MSG_TRUNC)){
+      lastbufsize = bufsize;
+      bufsize *= 2;
+      continue;
+    }
+    if (read_size == 0) break;
+    nh = (struct nlmsghdr *)buff;
+    for (nh = (struct nlmsghdr *)buff;
+        NLMSG_OK(nh, read_size);
+        nh = (struct nlmsghdr *)NLMSG_NEXT(nh, read_size)){
+      if (nh->nlmsg_pid != pid ||
+         nh->nlmsg_seq != seq)
+       continue;
+      if (nh->nlmsg_type == NLMSG_DONE){
+       (*done)++;
+       break; /* ok */
+      }
+      if (nh->nlmsg_type == NLMSG_ERROR){
+       struct nlmsgerr *nlerr = (struct nlmsgerr *)NLMSG_DATA(nh);
+       result = -1;
+       if (nh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
+         __set_errno(EIO);
+       else
+         __set_errno(-nlerr->error);
+       break;
+      }
+    }
+    break;
+  }
+  if (result < 0)
+    if (buff){
+      int saved_errno = errno;
+      free(buff);
+      __set_errno(saved_errno);
+    }
+  *nlhp = (struct nlmsghdr *)buff;
+  return result;
+}
+
+static int
+nl_getlist(int sd, int seq,
+          int request,
+          struct nlmsg_list **nlm_list,
+          struct nlmsg_list **nlm_end)
+{
+  struct nlmsghdr *nlh = NULL;
+  int status;
+  int done = 0;
+
+  status = nl_sendreq(sd, request, NLM_F_ROOT|NLM_F_MATCH, &seq);
+  if (status < 0)
+    return status;
+  if (seq == 0)
+    seq = (int)time(NULL);
+  while(!done){
+    status = nl_getmsg(sd, request, seq, &nlh, &done);
+    if (status < 0)
+      return status;
+    if (nlh){
+      struct nlmsg_list *nlm_next = (struct nlmsg_list *)malloc(sizeof(struct nlmsg_list));
+      if (nlm_next == NULL){
+       int saved_errno = errno;
+       free(nlh);
+       __set_errno(saved_errno);
+       status = -1;
+      } else {
+       nlm_next->nlm_next = NULL;
+       nlm_next->nlh = (struct nlmsghdr *)nlh;
+       nlm_next->size = status;
+       nlm_next->seq = seq;
+       if (*nlm_list == NULL){
+         *nlm_list = nlm_next;
+         *nlm_end = nlm_next;
+       } else {
+         (*nlm_end)->nlm_next = nlm_next;
+         *nlm_end = nlm_next;
+       }
+      }
+    }
+  }
+  return status >= 0 ? seq : status;
+}
+
+/* ---------------------------------------------------------------------- */
+static void 
+free_nlmsglist(struct nlmsg_list *nlm0)
+{
+  struct nlmsg_list *nlm;
+  int saved_errno;
+  if (!nlm0)
+    return;
+  saved_errno = errno;
+  for (nlm=nlm0; nlm; nlm=nlm->nlm_next){
+    if (nlm->nlh)
+      free(nlm->nlh);
+  }
+  free(nlm0);
+  __set_errno(saved_errno);
+}
+
+static void 
+free_data(void *data, void *ifdata)
+{
+  int saved_errno = errno;
+  if (data != NULL) free(data);
+  if (ifdata != NULL) free(ifdata);
+  __set_errno(saved_errno);
+}
+
+/* ---------------------------------------------------------------------- */
+static void 
+nl_close(int sd)
+{
+  int saved_errno = errno;
+  if (sd >= 0) __close(sd);
+  __set_errno(saved_errno);
+}
+
+/* ---------------------------------------------------------------------- */
+static int 
+nl_open(void)
+{
+  struct sockaddr_nl nladdr;
+  int sd;
+
+  sd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+  if (sd < 0) return -1;
+  memset(&nladdr, 0, sizeof(nladdr));
+  nladdr.nl_family = AF_NETLINK;
+  if (bind(sd, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0){
+    nl_close(sd);
+    return -1;
+  }
+  return sd;
+}
+
+/* ====================================================================== */
+int ROKEN_LIB_FUNCTION
+getifaddrs(struct ifaddrs **ifap)
+{
+  int sd;
+  struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm;
+  /* - - - - - - - - - - - - - - - */
+  int icnt;
+  size_t dlen, xlen, nlen;
+  uint32_t max_ifindex = 0;
+
+  pid_t pid = getpid();
+  int seq;
+  int result;
+  int build     ; /* 0 or 1 */
+
+/* ---------------------------------- */
+  /* initialize */
+  icnt = dlen = xlen = nlen = 0;
+  nlmsg_list = nlmsg_end = NULL;
+
+  if (ifap)
+    *ifap = NULL;
+
+/* ---------------------------------- */
+  /* open socket and bind */
+  sd = nl_open();
+  if (sd < 0)
+    return -1;
+
+/* ---------------------------------- */
+   /* gather info */
+  if ((seq = nl_getlist(sd, 0, RTM_GETLINK,
+                       &nlmsg_list, &nlmsg_end)) < 0){
+    free_nlmsglist(nlmsg_list);
+    nl_close(sd);
+    return -1;
+  }
+  if ((seq = nl_getlist(sd, seq+1, RTM_GETADDR,
+                       &nlmsg_list, &nlmsg_end)) < 0){
+    free_nlmsglist(nlmsg_list);
+    nl_close(sd);
+    return -1;
+  }
+
+/* ---------------------------------- */
+  /* Estimate size of result buffer and fill it */
+  for (build=0; build<=1; build++){
+    struct ifaddrs *ifl = NULL, *ifa = NULL;
+    struct nlmsghdr *nlh, *nlh0;
+    char *data = NULL, *xdata = NULL;
+    void *ifdata = NULL;
+    char *ifname = NULL, **iflist = NULL;
+    uint16_t *ifflist = NULL;
+    struct rtmaddr_ifamap ifamap;
+
+    if (build){
+      data = calloc(1,
+                   NLMSG_ALIGN(sizeof(struct ifaddrs[icnt]))
+                   + dlen + xlen + nlen);
+      ifa = (struct ifaddrs *)data;
+      ifdata = calloc(1, 
+                     NLMSG_ALIGN(sizeof(char *[max_ifindex+1]))
+                     + NLMSG_ALIGN(sizeof(uint16_t [max_ifindex+1])));
+      if (ifap != NULL)
+       *ifap = (ifdata != NULL) ? ifa : NULL;
+      else{
+       free_data(data, ifdata);
+       result = 0;
+       break;
+      }
+      if (data == NULL || ifdata == NULL){
+       free_data(data, ifdata);
+       result = -1;
+       break;
+      }
+      ifl = NULL;
+      data += NLMSG_ALIGN(sizeof(struct ifaddrs)) * icnt;
+      xdata = data + dlen;
+      ifname = xdata + xlen;
+      iflist = ifdata;
+      ifflist = (uint16_t *)(((char *)iflist) + NLMSG_ALIGN(sizeof(char *[max_ifindex+1])));
+    }
+
+    for (nlm=nlmsg_list; nlm; nlm=nlm->nlm_next){
+      int nlmlen = nlm->size;
+      if (!(nlh0 = nlm->nlh))
+       continue;
+      for (nlh = nlh0; 
+          NLMSG_OK(nlh, nlmlen); 
+          nlh=NLMSG_NEXT(nlh,nlmlen)){
+       struct ifinfomsg *ifim = NULL;
+       struct ifaddrmsg *ifam = NULL;
+       struct rtattr *rta;
+
+       size_t nlm_struct_size = 0;
+       sa_family_t nlm_family = 0;
+       uint32_t nlm_scope = 0, nlm_index = 0;
+       size_t sockaddr_size = 0;
+       uint32_t nlm_prefixlen = 0;
+       size_t rtasize;
+
+       memset(&ifamap, 0, sizeof(ifamap));
+
+       /* check if the message is what we want */
+       if (nlh->nlmsg_pid != pid ||
+           nlh->nlmsg_seq != nlm->seq)
+         continue;
+       if (nlh->nlmsg_type == NLMSG_DONE){
+         break; /* ok */
+       }
+       switch (nlh->nlmsg_type){
+       case RTM_NEWLINK:
+         ifim = (struct ifinfomsg *)NLMSG_DATA(nlh);
+         nlm_struct_size = sizeof(*ifim);
+         nlm_family = ifim->ifi_family;
+         nlm_scope = 0;
+         nlm_index = ifim->ifi_index;
+         nlm_prefixlen = 0;
+         if (build)
+           ifflist[nlm_index] = ifa->ifa_flags = ifim->ifi_flags;
+         break;
+       case RTM_NEWADDR:
+         ifam = (struct ifaddrmsg *)NLMSG_DATA(nlh);
+         nlm_struct_size = sizeof(*ifam);
+         nlm_family = ifam->ifa_family;
+         nlm_scope = ifam->ifa_scope;
+         nlm_index = ifam->ifa_index;
+         nlm_prefixlen = ifam->ifa_prefixlen;
+         if (build)
+           ifa->ifa_flags = ifflist[nlm_index];
+         break;
+       default:
+         continue;
+       }
+       
+       if (!build){
+         if (max_ifindex < nlm_index)
+           max_ifindex = nlm_index;
+       } else {
+         if (ifl != NULL)
+           ifl->ifa_next = ifa;
+       }
+
+       rtasize = NLMSG_PAYLOAD(nlh, nlmlen) - NLMSG_ALIGN(nlm_struct_size);
+       for (rta = (struct rtattr *)(((char *)NLMSG_DATA(nlh)) + NLMSG_ALIGN(nlm_struct_size));
+            RTA_OK(rta, rtasize);
+            rta = RTA_NEXT(rta, rtasize)){
+         struct sockaddr **sap = NULL;
+         void *rtadata = RTA_DATA(rta);
+         size_t rtapayload = RTA_PAYLOAD(rta);
+         socklen_t sa_len;
+
+         switch(nlh->nlmsg_type){
+         case RTM_NEWLINK:
+           switch(rta->rta_type){
+           case IFLA_ADDRESS:
+           case IFLA_BROADCAST:
+             if (build){
+               sap = (rta->rta_type == IFLA_ADDRESS) ? &ifa->ifa_addr : &ifa->ifa_broadaddr;
+               *sap = (struct sockaddr *)data;
+             }
+             sa_len = ifa_sa_len(AF_PACKET, rtapayload);
+             if (rta->rta_type == IFLA_ADDRESS)
+               sockaddr_size = NLMSG_ALIGN(sa_len);
+             if (!build){
+               dlen += NLMSG_ALIGN(sa_len);
+             } else {
+               memset(*sap, 0, sa_len);
+               ifa_make_sockaddr(AF_PACKET, *sap, rtadata,rtapayload, 0,0);
+               ((struct sockaddr_ll *)*sap)->sll_ifindex = nlm_index;
+               ((struct sockaddr_ll *)*sap)->sll_hatype = ifim->ifi_type;
+               data += NLMSG_ALIGN(sa_len);
+             }
+             break;
+           case IFLA_IFNAME:/* Name of Interface */
+             if (!build)
+               nlen += NLMSG_ALIGN(rtapayload + 1);
+             else{
+               ifa->ifa_name = ifname;
+               if (iflist[nlm_index] == NULL)
+                 iflist[nlm_index] = ifa->ifa_name;
+               strncpy(ifa->ifa_name, rtadata, rtapayload);
+               ifa->ifa_name[rtapayload] = '\0';
+               ifname += NLMSG_ALIGN(rtapayload + 1);
+             }
+             break;
+           case IFLA_STATS:/* Statistics of Interface */
+             if (!build)
+               xlen += NLMSG_ALIGN(rtapayload);
+             else{
+               ifa->ifa_data = xdata;
+               memcpy(ifa->ifa_data, rtadata, rtapayload);
+               xdata += NLMSG_ALIGN(rtapayload);
+             }
+             break;
+           case IFLA_UNSPEC:
+             break;
+           case IFLA_MTU:
+             break;
+           case IFLA_LINK:
+             break;
+           case IFLA_QDISC:
+             break;
+           default:
+             break;
+           }
+           break;
+         case RTM_NEWADDR:
+           if (nlm_family == AF_PACKET) break;
+           switch(rta->rta_type){
+           case IFA_ADDRESS:
+               ifamap.address = rtadata;
+               ifamap.address_len = rtapayload;
+               break;
+           case IFA_LOCAL:
+               ifamap.local = rtadata;
+               ifamap.local_len = rtapayload;
+               break;
+           case IFA_BROADCAST:
+               ifamap.broadcast = rtadata;
+               ifamap.broadcast_len = rtapayload;
+               break;
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+           case IFA_ANYCAST:
+               ifamap.anycast = rtadata;
+               ifamap.anycast_len = rtapayload;
+               break;
+#endif
+           case IFA_LABEL:
+             if (!build)
+               nlen += NLMSG_ALIGN(rtapayload + 1);
+             else{
+               ifa->ifa_name = ifname;
+               if (iflist[nlm_index] == NULL)
+                 iflist[nlm_index] = ifname;
+               strncpy(ifa->ifa_name, rtadata, rtapayload);
+               ifa->ifa_name[rtapayload] = '\0';
+               ifname += NLMSG_ALIGN(rtapayload + 1);
+             }
+             break;
+           case IFA_UNSPEC:
+             break;
+           case IFA_CACHEINFO:
+             break;
+           default:
+             break;
+           }
+         }
+       }
+       if (nlh->nlmsg_type == RTM_NEWADDR &&
+           nlm_family != AF_PACKET) {
+         if (!ifamap.local) {
+           ifamap.local = ifamap.address;
+           ifamap.local_len = ifamap.address_len;
+         }
+         if (!ifamap.address) {
+           ifamap.address = ifamap.local;
+           ifamap.address_len = ifamap.local_len;
+         }
+         if (ifamap.address_len != ifamap.local_len ||
+             (ifamap.address != NULL &&
+              memcmp(ifamap.address, ifamap.local, ifamap.address_len))) {
+           /* p2p; address is peer and local is ours */
+           ifamap.broadcast = ifamap.address;
+           ifamap.broadcast_len = ifamap.address_len;
+           ifamap.address = ifamap.local;
+           ifamap.address_len = ifamap.local_len;
+         }
+         if (ifamap.address) {
+#ifndef IFA_NETMASK
+           sockaddr_size = NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.address_len));
+#endif
+           if (!build)
+             dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.address_len));
+           else {
+             ifa->ifa_addr = (struct sockaddr *)data;
+             ifa_make_sockaddr(nlm_family, ifa->ifa_addr, ifamap.address, ifamap.address_len,
+                               nlm_scope, nlm_index);
+             data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.address_len));
+           }
+         }
+#ifdef IFA_NETMASK
+         if (ifamap.netmask) {
+           if (!build)
+             dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.netmask_len));
+           else {
+             ifa->ifa_netmask = (struct sockaddr *)data;
+             ifa_make_sockaddr(nlm_family, ifa->ifa_netmask, ifamap.netmask, ifamap.netmask_len,
+                               nlm_scope, nlm_index);
+             data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.netmask_len));
+           }
+         }
+#endif
+         if (ifamap.broadcast) {
+           if (!build)
+             dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.broadcast_len));
+           else {
+             ifa->ifa_broadaddr = (struct sockaddr *)data;
+             ifa_make_sockaddr(nlm_family, ifa->ifa_broadaddr, ifamap.broadcast, ifamap.broadcast_len,
+                               nlm_scope, nlm_index);
+             data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.broadcast_len));
+           }
+         }
+#ifdef HAVE_IFADDRS_IFA_ANYCAST
+         if (ifamap.anycast) {
+           if (!build)
+             dlen += NLMSG_ALIGN(ifa_sa_len(nlm_family,ifamap.anycast_len));
+           else {
+             ifa->ifa_anycast = (struct sockaddr *)data;
+             ifa_make_sockaddr(nlm_family, ifa->ifa_anyaddr, ifamap.anycast, ifamap.anycast_len,
+                               nlm_scope, nlm_index);
+             data += NLMSG_ALIGN(ifa_sa_len(nlm_family, ifamap.anycast_len));
+           }
+         }
+#endif
+       }
+       if (!build){
+#ifndef IFA_NETMASK
+         dlen += sockaddr_size;
+#endif
+         icnt++;
+       } else {
+         if (ifa->ifa_name == NULL)
+           ifa->ifa_name = iflist[nlm_index];
+#ifndef IFA_NETMASK
+         if (ifa->ifa_addr && 
+             ifa->ifa_addr->sa_family != AF_UNSPEC && 
+             ifa->ifa_addr->sa_family != AF_PACKET){
+           ifa->ifa_netmask = (struct sockaddr *)data;
+           ifa_make_sockaddr_mask(ifa->ifa_addr->sa_family, ifa->ifa_netmask, nlm_prefixlen);
+         }
+         data += sockaddr_size;
+#endif
+         ifl = ifa++;
+       }
+      }
+    }
+    if (!build){
+      if (icnt == 0 && (dlen + nlen + xlen == 0)){
+       if (ifap != NULL)
+         *ifap = NULL;
+       break; /* cannot found any addresses */
+      }
+    }
+    else
+      free_data(NULL, ifdata);
+  }
+
+/* ---------------------------------- */
+  /* Finalize */
+  free_nlmsglist(nlmsg_list);
+  nl_close(sd);
+  return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+void ROKEN_LIB_FUNCTION
+freeifaddrs(struct ifaddrs *ifa)
+{
+  free(ifa);
+}
+
+
+#else /* !AF_NETLINK */
+
+/*
+ * The generic SIOCGIFCONF version.
+ */
+
+static int
+getifaddrs2(struct ifaddrs **ifap, 
+           int af, int siocgifconf, int siocgifflags,
+           size_t ifreq_sz)
+{
+    int ret;
+    int fd;
+    size_t buf_size;
+    char *buf;
+    struct ifconf ifconf;
+    char *p;
+    size_t sz;
+    struct sockaddr sa_zero;
+    struct ifreq *ifr;
+    struct ifaddrs *start = NULL, **end = &start;
+
+    buf = NULL;
+
+    memset (&sa_zero, 0, sizeof(sa_zero));
+    fd = socket(af, SOCK_DGRAM, 0);
+    if (fd < 0)
+       return -1;
+
+    buf_size = 8192;
+    for (;;) {
+       buf = calloc(1, buf_size);
+       if (buf == NULL) {
+           ret = ENOMEM;
+           goto error_out;
+       }
+       ifconf.ifc_len = buf_size;
+       ifconf.ifc_buf = buf;
+
+       /*
+        * Solaris returns EINVAL when the buffer is too small.
+        */
+       if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
+           ret = errno;
+           goto error_out;
+       }
+       /*
+        * Can the difference between a full and a overfull buf
+        * be determined?
+        */
+
+       if (ifconf.ifc_len < buf_size)
+           break;
+       free (buf);
+       buf_size *= 2;
+    }
+
+    for (p = ifconf.ifc_buf;
+        p < ifconf.ifc_buf + ifconf.ifc_len;
+        p += sz) {
+       struct ifreq ifreq;
+       struct sockaddr *sa;
+       size_t salen;
+
+       ifr = (struct ifreq *)p;
+       sa  = &ifr->ifr_addr;
+
+       sz = ifreq_sz;
+       salen = sizeof(struct sockaddr);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+       salen = sa->sa_len;
+       sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
+#endif
+#ifdef SA_LEN
+       salen = SA_LEN(sa);
+       sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
+#endif
+       memset (&ifreq, 0, sizeof(ifreq));
+       memcpy (ifreq.ifr_name, ifr->ifr_name, sizeof(ifr->ifr_name));
+
+       if (ioctl(fd, siocgifflags, &ifreq) < 0) {
+           ret = errno;
+           goto error_out;
+       }
+
+       *end = malloc(sizeof(**end));
+       if (*end == NULL) {
+           ret = ENOMEM;
+           goto error_out;
+       }
+
+       (*end)->ifa_next = NULL;
+       (*end)->ifa_name = strdup(ifr->ifr_name);
+       (*end)->ifa_flags = ifreq.ifr_flags;
+       (*end)->ifa_addr = malloc(salen);
+       memcpy((*end)->ifa_addr, sa, salen);
+       (*end)->ifa_netmask = NULL;
+
+#if 0
+       /* fix these when we actually need them */
+       if(ifreq.ifr_flags & IFF_BROADCAST) {
+           (*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr));
+           memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr, 
+                  sizeof(ifr->ifr_broadaddr));
+       } else if(ifreq.ifr_flags & IFF_POINTOPOINT) {
+           (*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
+           memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr, 
+                  sizeof(ifr->ifr_dstaddr));
+       } else
+           (*end)->ifa_dstaddr = NULL;
+#else
+           (*end)->ifa_dstaddr = NULL;
+#endif
+
+       (*end)->ifa_data = NULL;
+
+       end = &(*end)->ifa_next;
+       
+    }
+    *ifap = start;
+    close(fd);
+    free(buf);
+    return 0;
+  error_out:
+    freeifaddrs(start);
+    close(fd);
+    free(buf);
+    errno = ret;
+    return -1;
+}
+
+#if defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
+static int
+getlifaddrs2(struct ifaddrs **ifap, 
+            int af, int siocgifconf, int siocgifflags,
+            size_t ifreq_sz)
+{
+    int ret;
+    int fd;
+    size_t buf_size;
+    char *buf;
+    struct lifconf ifconf;
+    char *p;
+    size_t sz;
+    struct sockaddr sa_zero;
+    struct lifreq *ifr;
+    struct ifaddrs *start = NULL, **end = &start;
+
+    buf = NULL;
+
+    memset (&sa_zero, 0, sizeof(sa_zero));
+    fd = socket(af, SOCK_DGRAM, 0);
+    if (fd < 0)
+       return -1;
+
+    buf_size = 8192;
+    for (;;) {
+       buf = calloc(1, buf_size);
+       if (buf == NULL) {
+           ret = ENOMEM;
+           goto error_out;
+       }
+       ifconf.lifc_family = AF_UNSPEC;
+       ifconf.lifc_flags  = 0;
+       ifconf.lifc_len    = buf_size;
+       ifconf.lifc_buf    = buf;
+
+       /*
+        * Solaris returns EINVAL when the buffer is too small.
+        */
+       if (ioctl (fd, siocgifconf, &ifconf) < 0 && errno != EINVAL) {
+           ret = errno;
+           goto error_out;
+       }
+       /*
+        * Can the difference between a full and a overfull buf
+        * be determined?
+        */
+
+       if (ifconf.lifc_len < buf_size)
+           break;
+       free (buf);
+       buf_size *= 2;
+    }
+
+    for (p = ifconf.lifc_buf;
+        p < ifconf.lifc_buf + ifconf.lifc_len;
+        p += sz) {
+       struct lifreq ifreq;
+       struct sockaddr_storage *sa;
+       size_t salen;
+
+       ifr = (struct lifreq *)p;
+       sa  = &ifr->lifr_addr;
+
+       sz = ifreq_sz;
+       salen = sizeof(struct sockaddr_storage);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+       salen = sa->sa_len;
+       sz = max(sz, sizeof(ifr->ifr_name) + sa->sa_len);
+#endif
+#ifdef SA_LEN
+       salen = SA_LEN(sa);
+       sz = max(sz, sizeof(ifr->ifr_name) + SA_LEN(sa));
+#endif
+       memset (&ifreq, 0, sizeof(ifreq));
+       memcpy (ifreq.lifr_name, ifr->lifr_name, sizeof(ifr->lifr_name));
+
+       if (ioctl(fd, siocgifflags, &ifreq) < 0) {
+           ret = errno;
+           goto error_out;
+       }
+
+       *end = malloc(sizeof(**end));
+
+       (*end)->ifa_next = NULL;
+       (*end)->ifa_name = strdup(ifr->lifr_name);
+       (*end)->ifa_flags = ifreq.lifr_flags;
+       (*end)->ifa_addr = malloc(salen);
+       memcpy((*end)->ifa_addr, sa, salen);
+       (*end)->ifa_netmask = NULL;
+
+#if 0
+       /* fix these when we actually need them */
+       if(ifreq.ifr_flags & IFF_BROADCAST) {
+           (*end)->ifa_broadaddr = malloc(sizeof(ifr->ifr_broadaddr));
+           memcpy((*end)->ifa_broadaddr, &ifr->ifr_broadaddr, 
+                  sizeof(ifr->ifr_broadaddr));
+       } else if(ifreq.ifr_flags & IFF_POINTOPOINT) {
+           (*end)->ifa_dstaddr = malloc(sizeof(ifr->ifr_dstaddr));
+           memcpy((*end)->ifa_dstaddr, &ifr->ifr_dstaddr, 
+                  sizeof(ifr->ifr_dstaddr));
+       } else
+           (*end)->ifa_dstaddr = NULL;
+#else
+           (*end)->ifa_dstaddr = NULL;
+#endif
+
+       (*end)->ifa_data = NULL;
+
+       end = &(*end)->ifa_next;
+       
+    }
+    *ifap = start;
+    close(fd);
+    free(buf);
+    return 0;
+  error_out:
+    freeifaddrs(start);
+    close(fd);
+    free(buf);
+    errno = ret;
+    return -1;
+}
+#endif /* defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS) */
+
+int ROKEN_LIB_FUNCTION
+getifaddrs(struct ifaddrs **ifap) 
+{
+    int ret = -1;
+    errno = ENXIO;
+#if defined(AF_INET6) && defined(SIOCGIF6CONF) && defined(SIOCGIF6FLAGS)
+    if (ret)
+       ret = getifaddrs2 (ifap, AF_INET6, SIOCGIF6CONF, SIOCGIF6FLAGS,
+                          sizeof(struct in6_ifreq));
+#endif
+#if defined(HAVE_IPV6) && defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
+    if (ret)
+       ret = getlifaddrs2 (ifap, AF_INET6, SIOCGLIFCONF, SIOCGLIFFLAGS,
+                           sizeof(struct lifreq));
+#endif
+#if defined(HAVE_IPV6) && defined(SIOCGIFCONF)
+    if (ret)
+       ret = getifaddrs2 (ifap, AF_INET6, SIOCGIFCONF, SIOCGIFFLAGS,
+                          sizeof(struct ifreq));
+#endif
+#if defined(AF_INET) && defined(SIOCGIFCONF) && defined(SIOCGIFFLAGS)
+    if (ret)
+       ret = getifaddrs2 (ifap, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS,
+                          sizeof(struct ifreq));
+#endif
+    return ret;
+}
+
+void ROKEN_LIB_FUNCTION
+freeifaddrs(struct ifaddrs *ifp)
+{
+    struct ifaddrs *p, *q;
+    
+    for(p = ifp; p; ) {
+       free(p->ifa_name);
+       if(p->ifa_addr)
+           free(p->ifa_addr);
+       if(p->ifa_dstaddr) 
+           free(p->ifa_dstaddr);
+       if(p->ifa_netmask) 
+           free(p->ifa_netmask);
+       if(p->ifa_data)
+           free(p->ifa_data);
+       q = p;
+       p = p->ifa_next;
+       free(q);
+    }
+}
+
+#endif /* !AF_NETLINK */
+
+#ifdef TEST
+
+void
+print_addr(const char *s, struct sockaddr *sa)
+{
+    int i;
+    printf("  %s=%d/", s, sa->sa_family);
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+    for(i = 0; i < sa->sa_len - ((long)sa->sa_data - (long)&sa->sa_family); i++)
+       printf("%02x", ((unsigned char*)sa->sa_data)[i]);
+#else
+    for(i = 0; i < sizeof(sa->sa_data); i++) 
+       printf("%02x", ((unsigned char*)sa->sa_data)[i]);
+#endif
+    printf("\n");
+}
+
+void 
+print_ifaddrs(struct ifaddrs *x)
+{
+    struct ifaddrs *p;
+    
+    for(p = x; p; p = p->ifa_next) {
+       printf("%s\n", p->ifa_name);
+       printf("  flags=%x\n", p->ifa_flags);
+       if(p->ifa_addr)
+           print_addr("addr", p->ifa_addr);
+       if(p->ifa_dstaddr) 
+           print_addr("dstaddr", p->ifa_dstaddr);
+       if(p->ifa_netmask) 
+           print_addr("netmask", p->ifa_netmask);
+       printf("  %p\n", p->ifa_data);
+    }
+}
+
+int
+main()
+{
+    struct ifaddrs *a = NULL, *b;
+    getifaddrs2(&a, AF_INET, SIOCGIFCONF, SIOCGIFFLAGS, sizeof(struct ifreq));
+    print_ifaddrs(a);
+    printf("---\n");
+    getifaddrs(&b);
+    print_ifaddrs(b);
+    return 0;
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/getipnodebyaddr.c b/src/kerberosV/src/lib/roken/getipnodebyaddr.c
new file mode 100644 (file)
index 0000000..f921de8
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getipnodebyaddr.c,v 1.3 2005/04/12 11:28:47 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * lookup `src, len' (address family `af') in DNS and return a pointer
+ * to a malloced struct hostent or NULL.
+ */
+
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyaddr (const void *src, size_t len, int af, int *error_num)
+{
+    struct hostent *tmp;
+
+    tmp = gethostbyaddr (src, len, af);
+    if (tmp == NULL) {
+       switch (h_errno) {
+       case HOST_NOT_FOUND :
+       case TRY_AGAIN :
+       case NO_RECOVERY :
+           *error_num = h_errno;
+           break;
+       case NO_DATA :
+           *error_num = NO_ADDRESS;
+           break;
+       default :
+           *error_num = NO_RECOVERY;
+           break;
+       }
+       return NULL;
+    }
+    tmp = copyhostent (tmp);
+    if (tmp == NULL) {
+       *error_num = TRY_AGAIN;
+       return NULL;
+    }
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/roken/getipnodebyname.c b/src/kerberosV/src/lib/roken/getipnodebyname.c
new file mode 100644 (file)
index 0000000..2233a8e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getipnodebyname.c,v 1.4 2005/04/12 11:28:47 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#ifndef HAVE_H_ERRNO
+static int h_errno = NO_RECOVERY;
+#endif
+
+/*
+ * lookup `name' (address family `af') in DNS and return a pointer
+ * to a malloced struct hostent or NULL.
+ */
+
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyname (const char *name, int af, int flags, int *error_num)
+{
+    struct hostent *tmp;
+
+#ifdef HAVE_GETHOSTBYNAME2
+    tmp = gethostbyname2 (name, af);
+#else
+    if (af != AF_INET) {
+       *error_num = NO_ADDRESS;
+       return NULL;
+    }
+    tmp = gethostbyname (name);
+#endif
+    if (tmp == NULL) {
+       switch (h_errno) {
+       case HOST_NOT_FOUND :
+       case TRY_AGAIN :
+       case NO_RECOVERY :
+           *error_num = h_errno;
+           break;
+       case NO_DATA :
+           *error_num = NO_ADDRESS;
+           break;
+       default :
+           *error_num = NO_RECOVERY;
+           break;
+       }
+       return NULL;
+    }
+    tmp = copyhostent (tmp);
+    if (tmp == NULL) {
+       *error_num = TRY_AGAIN;
+       return NULL;
+    }
+    return tmp;
+}
diff --git a/src/kerberosV/src/lib/roken/getnameinfo.c b/src/kerberosV/src/lib/roken/getnameinfo.c
new file mode 100644 (file)
index 0000000..30b845e
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getnameinfo.c,v 1.5 2005/04/12 11:28:47 lha Exp $");
+#endif
+
+#include "roken.h"
+
+static int
+doit (int af,
+      const void *addr,
+      size_t addrlen,
+      int port,
+      char *host, size_t hostlen,
+      char *serv, size_t servlen,
+      int flags)
+{
+    if (host != NULL) {
+       if (flags & NI_NUMERICHOST) {
+           if (inet_ntop (af, addr, host, hostlen) == NULL)
+               return EAI_SYSTEM;
+       } else {
+           struct hostent *he = gethostbyaddr (addr,
+                                               addrlen,
+                                               af);
+           if (he != NULL) {
+               strlcpy (host, hostent_find_fqdn(he), hostlen);
+               if (flags & NI_NOFQDN) {
+                   char *dot = strchr (host, '.');
+                   if (dot != NULL)
+                       *dot = '\0';
+               }
+           } else if (flags & NI_NAMEREQD) {
+               return EAI_NONAME;
+           } else if (inet_ntop (af, addr, host, hostlen) == NULL)
+               return EAI_SYSTEM;
+       }
+    }
+
+    if (serv != NULL) {
+       if (flags & NI_NUMERICSERV) {
+           snprintf (serv, servlen, "%u", ntohs(port));
+       } else {
+           const char *proto = "tcp";
+           struct servent *se;
+
+           if (flags & NI_DGRAM)
+               proto = "udp";
+
+           se = getservbyport (port, proto);
+           if (se == NULL) {
+               snprintf (serv, servlen, "%u", ntohs(port));
+           } else {
+               strlcpy (serv, se->s_name, servlen);
+           }
+       }
+    }
+    return 0;
+}
+
+/*
+ *
+ */
+
+int ROKEN_LIB_FUNCTION
+getnameinfo(const struct sockaddr *sa, socklen_t salen,
+           char *host, size_t hostlen,
+           char *serv, size_t servlen,
+           int flags)
+{
+    switch (sa->sa_family) {
+#ifdef HAVE_IPV6
+    case AF_INET6 : {
+       const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+
+       return doit (AF_INET6, &sin6->sin6_addr, sizeof(sin6->sin6_addr),
+                    sin6->sin6_port,
+                    host, hostlen,
+                    serv, servlen,
+                    flags);
+    }
+#endif
+    case AF_INET : {
+       const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
+
+       return doit (AF_INET, &sin->sin_addr, sizeof(sin->sin_addr),
+                    sin->sin_port,
+                    host, hostlen,
+                    serv, servlen,
+                    flags);
+    }
+    default :
+       return EAI_FAMILY;
+    }
+}
diff --git a/src/kerberosV/src/lib/roken/getnameinfo_verified.c b/src/kerberosV/src/lib/roken/getnameinfo_verified.c
new file mode 100644 (file)
index 0000000..06a000d
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1999 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getnameinfo_verified.c,v 1.7 2005/04/12 11:28:48 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * Try to obtain a verified name for the address in `sa, salen' (much
+ * similar to getnameinfo).
+ * Verified in this context means that forwards and backwards lookups
+ * in DNS are consistent.  If that fails, return an error if the
+ * NI_NAMEREQD flag is set or return the numeric address as a string.
+ */
+
+int ROKEN_LIB_FUNCTION
+getnameinfo_verified(const struct sockaddr *sa, socklen_t salen,
+                    char *host, size_t hostlen,
+                    char *serv, size_t servlen,
+                    int flags)
+{
+    int ret;
+    struct addrinfo *ai, *a;
+    char servbuf[NI_MAXSERV];
+    struct addrinfo hints;
+
+    if (host == NULL)
+       return EAI_NONAME;
+
+    if (serv == NULL) {
+       serv = servbuf;
+       servlen = sizeof(servbuf);
+    }
+
+    ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
+                      flags | NI_NUMERICSERV);
+    if (ret)
+       goto fail;
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_socktype = SOCK_STREAM;
+    ret = getaddrinfo (host, serv, &hints, &ai);
+    if (ret)
+       goto fail;
+    for (a = ai; a != NULL; a = a->ai_next) {
+       if (a->ai_addrlen == salen
+           && memcmp (a->ai_addr, sa, salen) == 0) {
+           freeaddrinfo (ai);
+           return 0;
+       }
+    }
+    freeaddrinfo (ai);
+ fail:
+    if (flags & NI_NAMEREQD)
+       return EAI_NONAME;
+    ret = getnameinfo (sa, salen, host, hostlen, serv, servlen,
+                      flags | NI_NUMERICSERV | NI_NUMERICHOST);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/getopt.c b/src/kerberosV/src/lib/roken/getopt.c
new file mode 100644 (file)
index 0000000..12bf138
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * 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. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#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 ROKEN_LIB_FUNCTION
+getopt(nargc, nargv, ostr)
+       int nargc;
+       char * const *nargv;
+       const char *ostr;
+{
+       static char *place = EMSG;              /* option letter processing */
+       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 = strchr(ostr, optopt))) {
+               /*
+                * if the user didn't specify '-' as an option,
+                * assume it means -1 (EOF).
+                */
+               if (optopt == (int)'-')
+                       return(-1);
+               if (!*place)
+                       ++optind;
+               if (opterr && *ostr != ':') {
+                       if (!(p = strrchr(*nargv, '/')))
+                               p = *nargv;
+                       else
+                               ++p;
+                       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 = strrchr(*nargv, '/')))
+                               p = *nargv;
+                       else
+                               ++p;
+                       if (*ostr == ':')
+                               return(BADARG);
+                       if (opterr)
+                               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/src/kerberosV/src/lib/roken/getprogname.c b/src/kerberosV/src/lib/roken/getprogname.c
new file mode 100644 (file)
index 0000000..547c9f3
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: getprogname.c,v 1.3 2005/04/12 11:28:48 lha Exp $");
+#endif
+
+#include "roken.h"
+
+extern char *__progname;
+
+#ifndef HAVE_GETPROGNAME
+const char * ROKEN_LIB_FUNCTION
+getprogname(void)
+{
+    return __progname;
+}
+#endif /* HAVE_GETPROGNAME */
diff --git a/src/kerberosV/src/lib/roken/gettimeofday.c b/src/kerberosV/src/lib/roken/gettimeofday.c
new file mode 100644 (file)
index 0000000..ab368e6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#ifndef HAVE_GETTIMEOFDAY
+
+RCSID("$KTH: gettimeofday.c,v 1.9 2005/04/12 11:28:49 lha Exp $");
+
+/*
+ * Simple gettimeofday that only returns seconds.
+ */
+int ROKEN_LIB_FUNCTION
+gettimeofday (struct timeval *tp, void *ignore)
+{
+     time_t t;
+
+     t = time(NULL);
+     tp->tv_sec  = t;
+     tp->tv_usec = 0;
+     return 0;
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/getuid.c b/src/kerberosV/src/lib/roken/getuid.c
new file mode 100644 (file)
index 0000000..ba49895
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_GETUID
+
+RCSID("$KTH: getuid.c,v 1.4 2005/04/12 11:28:49 lha Exp $");
+
+int ROKEN_LIB_FUNCTION
+getuid(void)
+{
+    return 17;
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/getusershell.c b/src/kerberosV/src/lib/roken/getusershell.c
new file mode 100644 (file)
index 0000000..aed746c
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1985, 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. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$KTH: getusershell.c,v 1.14 2005/04/27 08:05:00 lha Exp $");
+
+#ifndef HAVE_GETUSERSHELL
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#ifdef HAVE_USERSEC_H
+struct aud_rec;
+#include <usersec.h>
+#endif
+#ifdef HAVE_USERCONF_H
+#include <userconf.h>
+#endif
+#include <roken.h>
+
+#ifndef _PATH_SHELLS
+#define _PATH_SHELLS "/etc/shells"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#ifndef _PATH_CSHELL
+#define _PATH_CSHELL "/bin/csh"
+#endif
+
+/*
+ * Local shells should NOT be added here.  They should be added in
+ * /etc/shells.
+ */
+
+static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
+static char **curshell, **shells, *strings;
+static char **initshells (void);
+
+/*
+ * Get a list of shells from _PATH_SHELLS, if it exists.
+ */
+char * ROKEN_LIB_FUNCTION
+getusershell()
+{
+    char *ret;
+
+    if (curshell == NULL)
+       curshell = initshells();
+    ret = *curshell;
+    if (ret != NULL)
+       curshell++;
+    return (ret);
+}
+
+void ROKEN_LIB_FUNCTION
+endusershell()
+{
+    if (shells != NULL)
+       free(shells);
+    shells = NULL;
+    if (strings != NULL)
+       free(strings);
+    strings = NULL;
+    curshell = NULL;
+}
+
+void ROKEN_LIB_FUNCTION
+setusershell()
+{
+    curshell = initshells();
+}
+
+static char **
+initshells()
+{
+    char **sp, *cp;
+#ifdef HAVE_GETCONFATTR
+    char *tmp;
+    int nsh;
+#else
+    FILE *fp;
+#endif
+    struct stat statb;
+
+    free(shells);
+    shells = NULL;
+    free(strings);
+    strings = NULL;
+#ifdef HAVE_GETCONFATTR
+    if(getconfattr(SC_SYS_LOGIN, SC_SHELLS, &tmp, SEC_LIST) != 0)
+       return okshells;
+
+    for(cp = tmp, nsh = 0; *cp; cp += strlen(cp) + 1, nsh++);
+
+    shells = calloc(nsh + 1, sizeof(*shells));
+    if(shells == NULL)
+       return okshells;
+
+    strings = malloc(cp - tmp);
+    if(strings == NULL) {
+       free(shells);
+       shells = NULL;
+       return okshells;
+    }
+    memcpy(strings, tmp, cp - tmp);
+    for(sp = shells, cp = strings; *cp; cp += strlen(cp) + 1, sp++)
+       *sp = cp;
+#else
+    if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
+       return (okshells);
+    if (fstat(fileno(fp), &statb) == -1) {
+       fclose(fp);
+       return (okshells);
+    }
+    if ((strings = malloc((u_int)statb.st_size)) == NULL) {
+       fclose(fp);
+       return (okshells);
+    }
+    shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
+    if (shells == NULL) {
+       fclose(fp);
+       free(strings);
+       strings = NULL;
+       return (okshells);
+    }
+    sp = shells;
+    cp = strings;
+    while (fgets(cp, MaxPathLen + 1, fp) != NULL) {
+       while (*cp != '#' && *cp != '/' && *cp != '\0')
+           cp++;
+       if (*cp == '#' || *cp == '\0')
+           continue;
+       *sp++ = cp;
+       while (!isspace((unsigned char)*cp) && *cp != '#' && *cp != '\0')
+           cp++;
+       *cp++ = '\0';
+    }
+    fclose(fp);
+#endif
+    *sp = NULL;
+    return (shells);
+}
+#endif /* HAVE_GETUSERSHELL */
diff --git a/src/kerberosV/src/lib/roken/glob.c b/src/kerberosV/src/lib/roken/glob.c
new file mode 100644 (file)
index 0000000..803eda1
--- /dev/null
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ */
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ *     Escaping convention: \ inhibits any special meaning the following
+ *     character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ *     Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ *     Same as GLOB_NOCHECK, but it will only append pattern if it did
+ *     not contain any magic characters.  [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ *     Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ *     expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ *     expand {1,2}{a,b} to 1a 1b 2a 2b 
+ * gl_matchc:
+ *     Number of matches in the current invocation of glob.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <errno.h>
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include "glob.h"
+#include "roken.h"
+
+#ifndef ARG_MAX
+#define ARG_MAX _POSIX_ARG_MAX
+#endif
+
+#define        CHAR_DOLLAR             '$'
+#define        CHAR_DOT                '.'
+#define        CHAR_EOS                '\0'
+#define        CHAR_LBRACKET           '['
+#define        CHAR_NOT                '!'
+#define        CHAR_QUESTION           '?'
+#define        CHAR_QUOTE              '\\'
+#define        CHAR_RANGE              '-'
+#define        CHAR_RBRACKET           ']'
+#define        CHAR_SEP                '/'
+#define        CHAR_STAR               '*'
+#define        CHAR_TILDE              '~'
+#define        CHAR_UNDERSCORE         '_'
+#define        CHAR_LBRACE             '{'
+#define        CHAR_RBRACE             '}'
+#define        CHAR_SLASH              '/'
+#define        CHAR_COMMA              ','
+
+#ifndef DEBUG
+
+#define        M_QUOTE         0x8000
+#define        M_PROTECT       0x4000
+#define        M_MASK          0xffff
+#define        M_ASCII         0x00ff
+
+typedef u_short Char;
+
+#else
+
+#define        M_QUOTE         0x80
+#define        M_PROTECT       0x40
+#define        M_MASK          0xff
+#define        M_ASCII         0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define        CHAR(c)         ((Char)((c)&M_ASCII))
+#define        META(c)         ((Char)((c)|M_QUOTE))
+#define        M_ALL           META('*')
+#define        M_END           META(']')
+#define        M_NOT           META('!')
+#define        M_ONE           META('?')
+#define        M_RNG           META('-')
+#define        M_SET           META('[')
+#define        ismeta(c)       (((c)&M_QUOTE) != 0)
+
+
+static int      compare (const void *, const void *);
+static void     g_Ctoc (const Char *, char *);
+static int      g_lstat (Char *, struct stat *, glob_t *);
+static DIR     *g_opendir (Char *, glob_t *);
+static Char    *g_strchr (const Char *, int);
+#ifdef notdef
+static Char    *g_strcat (Char *, const Char *);
+#endif
+static int      g_stat (Char *, struct stat *, glob_t *);
+static int      glob0 (const Char *, glob_t *);
+static int      glob1 (Char *, glob_t *, size_t *);
+static int      glob2 (Char *, Char *, Char *, glob_t *, size_t *);
+static int      glob3 (Char *, Char *, Char *, Char *, glob_t *, size_t *);
+static int      globextend (const Char *, glob_t *, size_t *);
+static const Char *     globtilde (const Char *, Char *, glob_t *);
+static int      globexp1 (const Char *, glob_t *);
+static int      globexp2 (const Char *, const Char *, glob_t *, int *);
+static int      match (Char *, Char *, Char *);
+#ifdef DEBUG
+static void     qprintf (const char *, Char *);
+#endif
+
+int ROKEN_LIB_FUNCTION
+glob(const char *pattern, 
+     int flags, 
+     int (*errfunc)(const char *, int), 
+     glob_t *pglob)
+{
+       const u_char *patnext;
+       int c;
+       Char *bufnext, *bufend, patbuf[MaxPathLen+1];
+
+       patnext = (const u_char *) pattern;
+       if (!(flags & GLOB_APPEND)) {
+               pglob->gl_pathc = 0;
+               pglob->gl_pathv = NULL;
+               if (!(flags & GLOB_DOOFFS))
+                       pglob->gl_offs = 0;
+       }
+       pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+       pglob->gl_errfunc = errfunc;
+       pglob->gl_matchc = 0;
+
+       bufnext = patbuf;
+       bufend = bufnext + MaxPathLen;
+       if (flags & GLOB_QUOTE) {
+               /* Protect the quoted characters. */
+               while (bufnext < bufend && (c = *patnext++) != CHAR_EOS) 
+                       if (c == CHAR_QUOTE) {
+                               if ((c = *patnext++) == CHAR_EOS) {
+                                       c = CHAR_QUOTE;
+                                       --patnext;
+                               }
+                               *bufnext++ = c | M_PROTECT;
+                       }
+                       else
+                               *bufnext++ = c;
+       }
+       else 
+           while (bufnext < bufend && (c = *patnext++) != CHAR_EOS) 
+                   *bufnext++ = c;
+       *bufnext = CHAR_EOS;
+
+       if (flags & GLOB_BRACE)
+           return globexp1(patbuf, pglob);
+       else
+           return glob0(patbuf, pglob);
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int globexp1(const Char *pattern, glob_t *pglob)
+{
+       const Char* ptr = pattern;
+       int rv;
+
+       /* Protect a single {}, for find(1), like csh */
+       if (pattern[0] == CHAR_LBRACE && pattern[1] == CHAR_RBRACE && pattern[2] == CHAR_EOS)
+               return glob0(pattern, pglob);
+
+       while ((ptr = (const Char *) g_strchr(ptr, CHAR_LBRACE)) != NULL)
+               if (!globexp2(ptr, pattern, pglob, &rv))
+                       return rv;
+
+       return glob0(pattern, pglob);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int globexp2(const Char *ptr, const Char *pattern, 
+                   glob_t *pglob, int *rv)
+{
+       int     i;
+       Char   *lm, *ls;
+       const Char *pe, *pm, *pl;
+       Char    patbuf[MaxPathLen + 1];
+
+       /* copy part up to the brace */
+       for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+               continue;
+       ls = lm;
+
+       /* Find the balanced brace */
+       for (i = 0, pe = ++ptr; *pe; pe++)
+               if (*pe == CHAR_LBRACKET) {
+                       /* Ignore everything between [] */
+                       for (pm = pe++; *pe != CHAR_RBRACKET && *pe != CHAR_EOS; pe++)
+                               continue;
+                       if (*pe == CHAR_EOS) {
+                               /* 
+                                * We could not find a matching CHAR_RBRACKET.
+                                * Ignore and just look for CHAR_RBRACE
+                                */
+                               pe = pm;
+                       }
+               }
+               else if (*pe == CHAR_LBRACE)
+                       i++;
+               else if (*pe == CHAR_RBRACE) {
+                       if (i == 0)
+                               break;
+                       i--;
+               }
+
+       /* Non matching braces; just glob the pattern */
+       if (i != 0 || *pe == CHAR_EOS) {
+               *rv = glob0(patbuf, pglob);
+               return 0;
+       }
+
+       for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+               switch (*pm) {
+               case CHAR_LBRACKET:
+                       /* Ignore everything between [] */
+                       for (pl = pm++; *pm != CHAR_RBRACKET && *pm != CHAR_EOS; pm++)
+                               continue;
+                       if (*pm == CHAR_EOS) {
+                               /* 
+                                * We could not find a matching CHAR_RBRACKET.
+                                * Ignore and just look for CHAR_RBRACE
+                                */
+                               pm = pl;
+                       }
+                       break;
+
+               case CHAR_LBRACE:
+                       i++;
+                       break;
+
+               case CHAR_RBRACE:
+                       if (i) {
+                           i--;
+                           break;
+                       }
+                       /* FALLTHROUGH */
+               case CHAR_COMMA:
+                       if (i && *pm == CHAR_COMMA)
+                               break;
+                       else {
+                               /* Append the current string */
+                               for (lm = ls; (pl < pm); *lm++ = *pl++)
+                                       continue;
+                               /* 
+                                * Append the rest of the pattern after the
+                                * closing brace
+                                */
+                               for (pl = pe + 1; (*lm++ = *pl++) != CHAR_EOS;)
+                                       continue;
+
+                               /* Expand the current pattern */
+#ifdef DEBUG
+                               qprintf("globexp2:", patbuf);
+#endif
+                               *rv = globexp1(patbuf, pglob);
+
+                               /* move after the comma, to the next string */
+                               pl = pm + 1;
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+       *rv = 0;
+       return 0;
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, glob_t *pglob)
+{
+       struct passwd *pwd;
+       char *h;
+       const Char *p;
+       Char *b;
+
+       if (*pattern != CHAR_TILDE || !(pglob->gl_flags & GLOB_TILDE))
+               return pattern;
+
+       /* Copy up to the end of the string or / */
+       for (p = pattern + 1, h = (char *) patbuf; *p && *p != CHAR_SLASH; 
+            *h++ = *p++)
+               continue;
+
+       *h = CHAR_EOS;
+
+       if (((char *) patbuf)[0] == CHAR_EOS) {
+               /* 
+                * handle a plain ~ or ~/ by expanding $HOME 
+                * first and then trying the password file
+                */
+               if ((h = getenv("HOME")) == NULL) {
+                       if ((pwd = k_getpwuid(getuid())) == NULL)
+                               return pattern;
+                       else
+                               h = pwd->pw_dir;
+               }
+       }
+       else {
+               /*
+                * Expand a ~user
+                */
+               if ((pwd = k_getpwnam((char*) patbuf)) == NULL)
+                       return pattern;
+               else
+                       h = pwd->pw_dir;
+       }
+
+       /* Copy the home directory */
+       for (b = patbuf; *h; *b++ = *h++)
+               continue;
+       
+       /* Append the rest of the pattern */
+       while ((*b++ = *p++) != CHAR_EOS)
+               continue;
+
+       return patbuf;
+}
+       
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested).  Returns 0
+ * if things went well, nonzero if errors occurred.  It is not an error
+ * to find no matches.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob)
+{
+       const Char *qpatnext;
+       int c, err, oldpathc;
+       Char *bufnext, patbuf[MaxPathLen+1];
+       size_t limit = 0;
+
+       qpatnext = globtilde(pattern, patbuf, pglob);
+       oldpathc = pglob->gl_pathc;
+       bufnext = patbuf;
+
+       /* We don't need to check for buffer overflow any more. */
+       while ((c = *qpatnext++) != CHAR_EOS) {
+               switch (c) {
+               case CHAR_LBRACKET:
+                       c = *qpatnext;
+                       if (c == CHAR_NOT)
+                               ++qpatnext;
+                       if (*qpatnext == CHAR_EOS ||
+                           g_strchr(qpatnext+1, CHAR_RBRACKET) == NULL) {
+                               *bufnext++ = CHAR_LBRACKET;
+                               if (c == CHAR_NOT)
+                                       --qpatnext;
+                               break;
+                       }
+                       *bufnext++ = M_SET;
+                       if (c == CHAR_NOT)
+                               *bufnext++ = M_NOT;
+                       c = *qpatnext++;
+                       do {
+                               *bufnext++ = CHAR(c);
+                               if (*qpatnext == CHAR_RANGE &&
+                                   (c = qpatnext[1]) != CHAR_RBRACKET) {
+                                       *bufnext++ = M_RNG;
+                                       *bufnext++ = CHAR(c);
+                                       qpatnext += 2;
+                               }
+                       } while ((c = *qpatnext++) != CHAR_RBRACKET);
+                       pglob->gl_flags |= GLOB_MAGCHAR;
+                       *bufnext++ = M_END;
+                       break;
+               case CHAR_QUESTION:
+                       pglob->gl_flags |= GLOB_MAGCHAR;
+                       *bufnext++ = M_ONE;
+                       break;
+               case CHAR_STAR:
+                       pglob->gl_flags |= GLOB_MAGCHAR;
+                       /* collapse adjacent stars to one, 
+                        * to avoid exponential behavior
+                        */
+                       if (bufnext == patbuf || bufnext[-1] != M_ALL)
+                           *bufnext++ = M_ALL;
+                       break;
+               default:
+                       *bufnext++ = CHAR(c);
+                       break;
+               }
+       }
+       *bufnext = CHAR_EOS;
+#ifdef DEBUG
+       qprintf("glob0:", patbuf);
+#endif
+
+       if ((err = glob1(patbuf, pglob, &limit)) != 0)
+               return(err);
+
+       /*
+        * If there was no match we are going to append the pattern 
+        * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+        * and the pattern did not contain any magic characters
+        * GLOB_NOMAGIC is there just for compatibility with csh.
+        */
+       if (pglob->gl_pathc == oldpathc && 
+           ((pglob->gl_flags & GLOB_NOCHECK) || 
+             ((pglob->gl_flags & GLOB_NOMAGIC) &&
+              !(pglob->gl_flags & GLOB_MAGCHAR))))
+               return(globextend(pattern, pglob, &limit));
+       else if (!(pglob->gl_flags & GLOB_NOSORT)) 
+               qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+                   pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+       return(0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+       return(strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(Char *pattern, glob_t *pglob, size_t *limit)
+{
+       Char pathbuf[MaxPathLen+1];
+
+       /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+       if (*pattern == CHAR_EOS)
+               return(0);
+       return(glob2(pathbuf, pathbuf, pattern, pglob, limit));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+
+#ifndef S_ISLNK
+#if defined(S_IFLNK) && defined(S_IFMT)
+#define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
+#else
+#define S_ISLNK(mode) 0
+#endif
+#endif
+
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pattern, glob_t *pglob,
+      size_t *limit)
+{
+       struct stat sb;
+       Char *p, *q;
+       int anymeta;
+
+       /*
+        * Loop over pattern segments until end of pattern or until
+        * segment with meta character found.
+        */
+       for (anymeta = 0;;) {
+               if (*pattern == CHAR_EOS) {             /* End of pattern? */
+                       *pathend = CHAR_EOS;
+                       if (g_lstat(pathbuf, &sb, pglob))
+                               return(0);
+               
+                       if (((pglob->gl_flags & GLOB_MARK) &&
+                           pathend[-1] != CHAR_SEP) && (S_ISDIR(sb.st_mode)
+                           || (S_ISLNK(sb.st_mode) &&
+                           (g_stat(pathbuf, &sb, pglob) == 0) &&
+                           S_ISDIR(sb.st_mode)))) {
+                               *pathend++ = CHAR_SEP;
+                               *pathend = CHAR_EOS;
+                       }
+                       ++pglob->gl_matchc;
+                       return(globextend(pathbuf, pglob, limit));
+               }
+
+               /* Find end of next segment, copy tentatively to pathend. */
+               q = pathend;
+               p = pattern;
+               while (*p != CHAR_EOS && *p != CHAR_SEP) {
+                       if (ismeta(*p))
+                               anymeta = 1;
+                       *q++ = *p++;
+               }
+
+               if (!anymeta) {         /* No expansion, do next segment. */
+                       pathend = q;
+                       pattern = p;
+                       while (*pattern == CHAR_SEP)
+                               *pathend++ = *pattern++;
+               } else                  /* Need expansion, recurse. */
+                       return(glob3(pathbuf, pathend, pattern, p, pglob,
+                           limit));
+       }
+       /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pattern, Char *restpattern, 
+      glob_t *pglob, size_t *limit)
+{
+       struct dirent *dp;
+       DIR *dirp;
+       int err;
+       char buf[MaxPathLen];
+
+       /*
+        * The readdirfunc declaration can't be prototyped, because it is
+        * assigned, below, to two functions which are prototyped in glob.h
+        * and dirent.h as taking pointers to differently typed opaque
+        * structures.
+        */
+       struct dirent *(*readdirfunc)(void *);
+
+       *pathend = CHAR_EOS;
+       errno = 0;
+           
+       if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+               /* TODO: don't call for ENOENT or ENOTDIR? */
+               if (pglob->gl_errfunc) {
+                       g_Ctoc(pathbuf, buf);
+                       if (pglob->gl_errfunc(buf, errno) ||
+                           pglob->gl_flags & GLOB_ERR)
+                               return (GLOB_ABEND);
+               }
+               return(0);
+       }
+
+       err = 0;
+
+       /* Search directory for matching names. */
+       if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+               readdirfunc = pglob->gl_readdir;
+       else
+               readdirfunc = (struct dirent *(*)(void *))readdir;
+       while ((dp = (*readdirfunc)(dirp))) {
+               u_char *sc;
+               Char *dc;
+
+               /* Initial CHAR_DOT must be matched literally. */
+               if (dp->d_name[0] == CHAR_DOT && *pattern != CHAR_DOT)
+                       continue;
+               for (sc = (u_char *) dp->d_name, dc = pathend; 
+                    (*dc++ = *sc++) != CHAR_EOS;)
+                       continue;
+               if (!match(pathend, pattern, restpattern)) {
+                       *pathend = CHAR_EOS;
+                       continue;
+               }
+               err = glob2(pathbuf, --dc, restpattern, pglob, limit);
+               if (err)
+                       break;
+       }
+
+       if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+               (*pglob->gl_closedir)(dirp);
+       else
+               closedir(dirp);
+       return(err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ *     Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ *     gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob, size_t *limit)
+{
+       char **pathv;
+       int i;
+       size_t newsize, len;
+       char *copy;
+       const Char *p;
+
+       newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+       pathv = pglob->gl_pathv ? 
+                   realloc(pglob->gl_pathv, newsize) :
+                   malloc(newsize);
+       if (pathv == NULL)
+               return(GLOB_NOSPACE);
+
+       if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+               /* first time around -- clear initial gl_offs items */
+               pathv += pglob->gl_offs;
+               for (i = pglob->gl_offs; --i >= 0; )
+                       *--pathv = NULL;
+       }
+       pglob->gl_pathv = pathv;
+
+       for (p = path; *p++;)
+               continue;
+       len = (size_t)(p - path);
+       *limit += len;
+       if ((copy = malloc(len)) != NULL) {
+               g_Ctoc(path, copy);
+               pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+       }
+       pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+
+       if ((pglob->gl_flags & GLOB_LIMIT) && (newsize + *limit) >= ARG_MAX) {
+               errno = 0;
+               return(GLOB_NOSPACE);
+       }
+
+       return(copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+
+/*
+ * pattern matching function for filenames.  Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+       int ok, negate_range;
+       Char c, k;
+
+       while (pat < patend) {
+               c = *pat++;
+               switch (c & M_MASK) {
+               case M_ALL:
+                       if (pat == patend)
+                               return(1);
+                       do 
+                           if (match(name, pat, patend))
+                                   return(1);
+                       while (*name++ != CHAR_EOS);
+                       return(0);
+               case M_ONE:
+                       if (*name++ == CHAR_EOS)
+                               return(0);
+                       break;
+               case M_SET:
+                       ok = 0;
+                       if ((k = *name++) == CHAR_EOS)
+                               return(0);
+                       if ((negate_range = ((*pat & M_MASK) == M_NOT)) != CHAR_EOS)
+                               ++pat;
+                       while (((c = *pat++) & M_MASK) != M_END)
+                               if ((*pat & M_MASK) == M_RNG) {
+                                       if (c <= k && k <= pat[1])
+                                               ok = 1;
+                                       pat += 2;
+                               } else if (c == k)
+                                       ok = 1;
+                       if (ok == negate_range)
+                               return(0);
+                       break;
+               default:
+                       if (*name++ != c)
+                               return(0);
+                       break;
+               }
+       }
+       return(*name == CHAR_EOS);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void ROKEN_LIB_FUNCTION
+globfree(glob_t *pglob)
+{
+       int i;
+       char **pp;
+
+       if (pglob->gl_pathv != NULL) {
+               pp = pglob->gl_pathv + pglob->gl_offs;
+               for (i = pglob->gl_pathc; i--; ++pp)
+                       if (*pp)
+                               free(*pp);
+               free(pglob->gl_pathv);
+               pglob->gl_pathv = NULL;
+       }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+       char buf[MaxPathLen];
+
+       if (!*str)
+               strlcpy(buf, ".", sizeof(buf));
+       else
+               g_Ctoc(str, buf);
+
+       if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+               return((*pglob->gl_opendir)(buf));
+
+       return(opendir(buf));
+}
+
+static int
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+       char buf[MaxPathLen];
+
+       g_Ctoc(fn, buf);
+       if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+               return((*pglob->gl_lstat)(buf, sb));
+       return(lstat(buf, sb));
+}
+
+static int
+g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+       char buf[MaxPathLen];
+
+       g_Ctoc(fn, buf);
+       if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+               return((*pglob->gl_stat)(buf, sb));
+       return(stat(buf, sb));
+}
+
+static Char *
+g_strchr(const Char *str, int ch)
+{
+       do {
+               if (*str == ch)
+                       return (Char *)str;
+       } while (*str++);
+       return (NULL);
+}
+
+#ifdef notdef
+static Char *
+g_strcat(Char *dst, const Char *src)
+{
+       Char *sdst = dst;
+
+       while (*dst++)
+               continue;
+       --dst;
+       while((*dst++ = *src++) != CHAR_EOS)
+           continue;
+
+       return (sdst);
+}
+#endif
+
+static void
+g_Ctoc(const Char *str, char *buf)
+{
+       char *dc;
+
+       for (dc = buf; (*dc++ = *str++) != CHAR_EOS;)
+               continue;
+}
+
+#ifdef DEBUG
+static void 
+qprintf(const Char *str, Char *s)
+{
+       Char *p;
+
+       printf("%s:\n", str);
+       for (p = s; *p; p++)
+               printf("%c", CHAR(*p));
+       printf("\n");
+       for (p = s; *p; p++)
+               printf("%c", *p & M_PROTECT ? '"' : ' ');
+       printf("\n");
+       for (p = s; *p; p++)
+               printf("%c", ismeta(*p) ? '_' : ' ');
+       printf("\n");
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/glob.hin b/src/kerberosV/src/lib/roken/glob.hin
new file mode 100644 (file)
index 0000000..fb6b539
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1989, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * 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.
+ *
+ *     @(#)glob.h      8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _GLOB_H_
+#define        _GLOB_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#define glob_t rk_glob_t
+#define        glob rk_glob
+#define        globfree rk_globfree
+
+struct stat;
+typedef struct {
+       int gl_pathc;           /* Count of total paths so far. */
+       int gl_matchc;          /* Count of paths matching pattern. */
+       int gl_offs;            /* Reserved at beginning of gl_pathv. */
+       int gl_flags;           /* Copy of flags parameter to glob. */
+       char **gl_pathv;        /* List of paths matching pattern. */
+                               /* Copy of errfunc parameter to glob. */
+       int (*gl_errfunc) (const char *, int);
+
+       /*
+        * Alternate filesystem access methods for glob; replacement
+        * versions of closedir(3), readdir(3), opendir(3), stat(2)
+        * and lstat(2).
+        */
+       void (*gl_closedir) (void *);
+       struct dirent *(*gl_readdir) (void *);  
+       void *(*gl_opendir) (const char *);
+       int (*gl_lstat) (const char *, struct stat *);
+       int (*gl_stat) (const char *, struct stat *);
+} glob_t;
+
+#define        GLOB_APPEND     0x0001  /* Append to output from previous call. */
+#define        GLOB_DOOFFS     0x0002  /* Use gl_offs. */
+#define        GLOB_ERR        0x0004  /* Return on error. */
+#define        GLOB_MARK       0x0008  /* Append / to matching directories. */
+#define        GLOB_NOCHECK    0x0010  /* Return pattern itself if nothing matches. */
+#define        GLOB_NOSORT     0x0020  /* Don't sort. */
+
+#define        GLOB_ALTDIRFUNC 0x0040  /* Use alternately specified directory funcs. */
+#define        GLOB_BRACE      0x0080  /* Expand braces ala csh. */
+#define        GLOB_MAGCHAR    0x0100  /* Pattern had globbing characters. */
+#define        GLOB_NOMAGIC    0x0200  /* GLOB_NOCHECK without magic chars (csh). */
+#define        GLOB_QUOTE      0x0400  /* Quote special chars with \. */
+#define        GLOB_TILDE      0x0800  /* Expand tilde names from the passwd file. */
+#define GLOB_LIMIT     0x1000  /* Limit memory used by matches to ARG_MAX */
+
+#define        GLOB_NOSPACE    (-1)    /* Malloc call failed. */
+#define        GLOB_ABEND      (-2)    /* Unignored error. */
+
+int ROKEN_LIB_FUNCTION
+glob (const char *, int, int (*)(const char *, int), glob_t *);
+
+void ROKEN_LIB_FUNCTION
+globfree (glob_t *);
+
+#endif /* !_GLOB_H_ */
diff --git a/src/kerberosV/src/lib/roken/h_errno.c b/src/kerberosV/src/lib/roken/h_errno.c
new file mode 100644 (file)
index 0000000..eb89cb3
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: h_errno.c,v 1.1 2001/08/08 03:47:23 assar Exp $");
+#endif
+
+#ifndef HAVE_H_ERRNO
+int h_errno = -17; /* Some magic number */
+#endif
diff --git a/src/kerberosV/src/lib/roken/hex-test.c b/src/kerberosV/src/lib/roken/hex-test.c
new file mode 100644 (file)
index 0000000..7d00ec4
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1999 - 2001, 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+
+RCSID("$KTH: hex-test.c,v 1.2 2005/04/04 19:23:37 lha Exp $");
+#endif
+
+#include <roken.h>
+#include <hex.h>
+
+int
+main(int argc, char **argv)
+{
+    int numerr = 0;
+    int numtest = 1;
+    struct test {
+       void *data;
+       size_t len;
+       const char *result;
+    } *t, tests[] = {
+       { "", 0 , "" },
+       { "a", 1, "61" },
+       { "ab", 2, "6162" },
+       { "abc", 3, "616263" },
+       { "abcd", 4, "61626364" },
+       { "abcde", 5, "6162636465" },
+       { "abcdef", 6, "616263646566" },
+       { "abcdefg", 7, "61626364656667" },
+       { "=", 1, "3D" },
+       { NULL }
+    };
+    for(t = tests; t->data; t++) {
+       char *str;
+       int len;
+       len = hex_encode(t->data, t->len, &str);
+       if(strcmp(str, t->result) != 0) {
+           fprintf(stderr, "failed test %d: %s != %s\n", numtest, 
+                   str, t->result);
+           numerr++;
+       }
+       free(str);
+       str = strdup(t->result);
+       len = strlen(str);
+       len = hex_decode(t->result, str, len);
+       if(len != t->len) {
+           fprintf(stderr, "failed test %d: len %lu != %lu\n", numtest,
+                   (unsigned long)len, (unsigned long)t->len);
+           numerr++;
+       } else if(memcmp(str, t->data, t->len) != 0) {
+           fprintf(stderr, "failed test %d: data\n", numtest);
+           numerr++;
+       }
+       free(str);
+       numtest++;
+    }
+
+    return numerr;
+}
diff --git a/src/kerberosV/src/lib/roken/hex.c b/src/kerberosV/src/lib/roken/hex.c
new file mode 100644 (file)
index 0000000..6d3509d
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2004-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: hex.c,v 1.7 2005/05/27 13:37:47 lha Exp $");
+#endif
+#include "roken.h"
+#include <ctype.h>
+#include "hex.h"
+
+const static char hexchar[] = "0123456789ABCDEF";
+
+static int 
+pos(char c)
+{
+    const char *p;
+    c = toupper((unsigned char)c);
+    for (p = hexchar; *p; p++)
+       if (*p == c)
+           return p - hexchar;
+    return -1;
+}
+
+ssize_t ROKEN_LIB_FUNCTION
+hex_encode(const void *data, size_t size, char **str)
+{
+    const unsigned char *q = data;
+    size_t i;
+    char *p;
+
+    /* check for overflow */
+    if (size * 2 < size)
+       return -1;
+
+    p = malloc(size * 2 + 1);
+    if (p == NULL)
+       return -1;
+    
+    for (i = 0; i < size; i++) {
+       p[i * 2] = hexchar[(*q >> 4) & 0xf];
+       p[i * 2 + 1] = hexchar[*q & 0xf];
+       q++;
+    }
+    p[i * 2] = '\0';
+    *str = p;
+
+    return i * 2;
+}
+
+ssize_t ROKEN_LIB_FUNCTION
+hex_decode(const char *str, void *data, size_t len)
+{
+    size_t l;
+    unsigned char *p = data;
+    size_t i;
+       
+    l = strlen(str);
+    
+    /* check for overflow, same as (l+1)/2 but overflow safe */
+    if ((l/2) + (l&1) > len)
+       return -1;
+
+    for (i = 0; i < l / 2; i++)
+       p[i] = pos(str[i * 2]) << 4 | pos(str[(i * 2) + 1]);
+    return i;
+}
diff --git a/src/kerberosV/src/lib/roken/hex.h b/src/kerberosV/src/lib/roken/hex.h
new file mode 100644 (file)
index 0000000..27409cc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: hex.h,v 1.3 2005/04/12 11:28:50 lha Exp $ */
+
+#ifndef _rk_HEX_H_
+#define _rk_HEX_H_ 1
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#define hex_encode rk_hex_encode
+#define hex_decode rk_hex_decode
+
+ssize_t        ROKEN_LIB_FUNCTION
+       hex_encode(const void *, size_t, char **);
+ssize_t ROKEN_LIB_FUNCTION
+       hex_decode(const char *, void *, size_t);
+
+#endif /* _rk_HEX_H_ */
diff --git a/src/kerberosV/src/lib/roken/hostent_find_fqdn.c b/src/kerberosV/src/lib/roken/hostent_find_fqdn.c
new file mode 100644 (file)
index 0000000..7df28aa
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: hostent_find_fqdn.c,v 1.3 2005/04/12 11:28:51 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * Try to find a fqdn (with `.') in he if possible, else return h_name
+ */
+
+const char * ROKEN_LIB_FUNCTION
+hostent_find_fqdn (const struct hostent *he)
+{
+    const char *ret = he->h_name;
+    const char **h;
+
+    if (strchr (ret, '.') == NULL)
+       for (h = (const char **)he->h_aliases; *h != NULL; ++h) {
+           if (strchr (*h, '.') != NULL) {
+               ret = *h;
+               break;
+           }
+       }
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/hstrerror.c b/src/kerberosV/src/lib/roken/hstrerror.c
new file mode 100644 (file)
index 0000000..ec60097
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1995 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: hstrerror.c,v 1.26 2005/04/12 11:28:51 lha Exp $");
+#endif
+
+#ifndef HAVE_HSTRERROR
+
+#if (defined(SunOS) && (SunOS >= 50))
+#define hstrerror broken_proto
+#endif
+#include "roken.h"
+#if (defined(SunOS) && (SunOS >= 50))
+#undef hstrerror
+#endif
+
+#if !(defined(HAVE_H_ERRLIST) && defined(HAVE_H_NERR))
+static const char *const h_errlist[] = {
+    "Resolver Error 0 (no error)",
+    "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 */
+};
+
+static
+const
+int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+#else
+
+#if !HAVE_DECL_H_ERRLIST
+extern const char *h_errlist[];
+extern int h_nerr;
+#endif
+
+#endif
+
+const char * ROKEN_LIB_FUNCTION
+hstrerror(int herr)
+{
+    if (0 <= herr && herr < h_nerr)
+       return h_errlist[herr];
+    else if(herr == -17)
+       return "unknown error";
+    else
+       return "Error number out of range (hstrerror)";
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/ifaddrs.hin b/src/kerberosV/src/lib/roken/ifaddrs.hin
new file mode 100644 (file)
index 0000000..c4798bc
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: ifaddrs.hin,v 1.4 2005/04/12 11:28:51 lha Exp $ */
+
+#ifndef __ifaddrs_h__
+#define __ifaddrs_h__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+/*
+ * the interface is defined in terms of the fields below, and this is
+ * sometimes #define'd, so there seems to be no simple way of solving
+ * this and this seemed the best. */
+
+#undef ifa_dstaddr
+
+struct ifaddrs {
+    struct ifaddrs *ifa_next;
+    char *ifa_name;
+    unsigned int ifa_flags;
+    struct sockaddr *ifa_addr;
+    struct sockaddr *ifa_netmask;
+    struct sockaddr *ifa_dstaddr;
+    void *ifa_data;
+};
+
+#ifndef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr
+#endif
+
+int ROKEN_LIB_FUNCTION
+getifaddrs(struct ifaddrs**);
+
+void ROKEN_LIB_FUNCTION
+freeifaddrs(struct ifaddrs*);
+
+#endif /* __ifaddrs_h__ */
diff --git a/src/kerberosV/src/lib/roken/inet_aton.c b/src/kerberosV/src/lib/roken/inet_aton.c
new file mode 100644 (file)
index 0000000..4d3e264
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: inet_aton.c,v 1.14 2005/04/12 11:28:52 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/* Minimal implementation of inet_aton.
+ * Cannot distinguish between failure and a local broadcast address. */
+
+int ROKEN_LIB_FUNCTION
+inet_aton(const char *cp, struct in_addr *addr)
+{
+  addr->s_addr = inet_addr(cp);
+  return (addr->s_addr == INADDR_NONE) ? 0 : 1;
+}
diff --git a/src/kerberosV/src/lib/roken/inet_ntop.c b/src/kerberosV/src/lib/roken/inet_ntop.c
new file mode 100644 (file)
index 0000000..c598f72
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: inet_ntop.c,v 1.6 2005/04/12 11:28:52 lha Exp $");
+#endif
+
+#include <roken.h>
+
+/*
+ *
+ */
+
+static const char *
+inet_ntop_v4 (const void *src, char *dst, size_t size)
+{
+    const char digits[] = "0123456789";
+    int i;
+    struct in_addr *addr = (struct in_addr *)src;
+    u_long a = ntohl(addr->s_addr);
+    const char *orig_dst = dst;
+
+    if (size < INET_ADDRSTRLEN) {
+       errno = ENOSPC;
+       return NULL;
+    }
+    for (i = 0; i < 4; ++i) {
+       int n = (a >> (24 - i * 8)) & 0xFF;
+       int non_zerop = 0;
+
+       if (non_zerop || n / 100 > 0) {
+           *dst++ = digits[n / 100];
+           n %= 100;
+           non_zerop = 1;
+       }
+       if (non_zerop || n / 10 > 0) {
+           *dst++ = digits[n / 10];
+           n %= 10;
+           non_zerop = 1;
+       }
+       *dst++ = digits[n];
+       if (i != 3)
+           *dst++ = '.';
+    }
+    *dst++ = '\0';
+    return orig_dst;
+}
+
+#ifdef HAVE_IPV6
+static const char *
+inet_ntop_v6 (const void *src, char *dst, size_t size)
+{
+    const char xdigits[] = "0123456789abcdef";
+    int i;
+    const struct in6_addr *addr = (struct in6_addr *)src;
+    const u_char *ptr = addr->s6_addr;
+    const char *orig_dst = dst;
+
+    if (size < INET6_ADDRSTRLEN) {
+       errno = ENOSPC;
+       return NULL;
+    }
+    for (i = 0; i < 8; ++i) {
+       int non_zerop = 0;
+
+       if (non_zerop || (ptr[0] >> 4)) {
+           *dst++ = xdigits[ptr[0] >> 4];
+           non_zerop = 1;
+       }
+       if (non_zerop || (ptr[0] & 0x0F)) {
+           *dst++ = xdigits[ptr[0] & 0x0F];
+           non_zerop = 1;
+       }
+       if (non_zerop || (ptr[1] >> 4)) {
+           *dst++ = xdigits[ptr[1] >> 4];
+           non_zerop = 1;
+       }
+       *dst++ = xdigits[ptr[1] & 0x0F];
+       if (i != 7)
+           *dst++ = ':';
+       ptr += 2;
+    }
+    *dst++ = '\0';
+    return orig_dst;
+}
+#endif /* HAVE_IPV6 */
+
+const char * ROKEN_LIB_FUNCTION
+inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+    switch (af) {
+    case AF_INET :
+       return inet_ntop_v4 (src, dst, size);
+#ifdef HAVE_IPV6
+    case AF_INET6 :
+       return inet_ntop_v6 (src, dst, size);
+#endif
+    default :
+       errno = EAFNOSUPPORT;
+       return NULL;
+    }
+}
diff --git a/src/kerberosV/src/lib/roken/inet_pton.c b/src/kerberosV/src/lib/roken/inet_pton.c
new file mode 100644 (file)
index 0000000..cea6a55
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: inet_pton.c,v 1.4 2005/04/12 11:28:52 lha Exp $");
+#endif
+
+#include <roken.h>
+
+int ROKEN_LIB_FUNCTION
+inet_pton(int af, const char *src, void *dst)
+{
+    if (af != AF_INET) {
+       errno = EAFNOSUPPORT;
+       return -1;
+    }
+    return inet_aton (src, dst);
+}
diff --git a/src/kerberosV/src/lib/roken/initgroups.c b/src/kerberosV/src/lib/roken/initgroups.c
new file mode 100644 (file)
index 0000000..e441ce6
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: initgroups.c,v 1.4 2005/04/12 11:28:53 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+initgroups(const char *name, gid_t basegid)
+{
+  return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/innetgr.c b/src/kerberosV/src/lib/roken/innetgr.c
new file mode 100644 (file)
index 0000000..ba93083
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_INNETGR
+
+RCSID("$KTH: innetgr.c,v 1.2 2005/04/12 11:28:53 lha Exp $");
+
+int ROKEN_LIB_FUNCTION
+innetgr(const char *netgroup, const char *machine, 
+       const char *user, const char *domain)
+{
+    return 0;
+}
+#endif
+
diff --git a/src/kerberosV/src/lib/roken/install-sh b/src/kerberosV/src/lib/roken/install-sh
new file mode 100644 (file)
index 0000000..e9de238
--- /dev/null
@@ -0,0 +1,251 @@
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# 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 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.
+#
+# 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=""
+
+while [ x"$1" != x ]; do
+    case $1 in
+       -c) instcmd="$cpprog"
+           shift
+           continue;;
+
+       -d) dir_arg=true
+           shift
+           continue;;
+
+       -m) chmodcmd="$chmodprog $2"
+           shift
+           shift
+           continue;;
+
+       -o) chowncmd="$chownprog $2"
+           shift
+           shift
+           continue;;
+
+       -g) chgrpcmd="$chgrpprog $2"
+           shift
+           shift
+           continue;;
+
+       -s) stripcmd="$stripprog"
+           shift
+           continue;;
+
+       -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+           shift
+           continue;;
+
+       -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+           shift
+           continue;;
+
+       *)  if [ x"$src" = x ]
+           then
+               src=$1
+           else
+               # this colon is to work around a 386BSD /bin/sh bug
+               :
+               dst=$1
+           fi
+           shift
+           continue;;
+    esac
+done
+
+if [ x"$src" = x ]
+then
+       echo "install:  no input file specified"
+       exit 1
+else
+       true
+fi
+
+if [ x"$dir_arg" != x ]; then
+       dst=$src
+       src=""
+       
+       if [ -d $dst ]; then
+               instcmd=:
+               chmodcmd=""
+       else
+               instcmd=mkdir
+       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 [ -f $src -o -d $src ]
+       then
+               true
+       else
+               echo "install:  $src does not exist"
+               exit 1
+       fi
+       
+       if [ x"$dst" = x ]
+       then
+               echo "install:  no destination specified"
+               exit 1
+       else
+               true
+       fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+       if [ -d $dst ]
+       then
+               dst="$dst"/`basename $src`
+       else
+               true
+       fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+#  this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -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 [ $# -ne 0 ] ; do
+       pathcomp="${pathcomp}${1}"
+       shift
+
+       if [ ! -d "${pathcomp}" ] ;
+        then
+               $mkdirprog "${pathcomp}"
+       else
+               true
+       fi
+
+       pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+       $doit $instcmd $dst &&
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+       if [ x"$transformarg" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               dstfile=`basename $dst $transformbasename | 
+                       sed $transformarg`$transformbasename
+       fi
+
+# don't allow the sed command to completely eliminate the filename
+
+       if [ x"$dstfile" = x ] 
+       then
+               dstfile=`basename $dst`
+       else
+               true
+       fi
+
+# Make a temp file name in the proper directory.
+
+       dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+       $doit $instcmd $src $dsttmp &&
+
+       trap "rm -f ${dsttmp}" 0 &&
+
+# 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.
+
+       if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+       if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+       if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+       if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+       $doit $rmcmd -f $dstdir/$dstfile &&
+       $doit $mvcmd $dsttmp $dstdir/$dstfile 
+
+fi &&
+
+
+exit 0
diff --git a/src/kerberosV/src/lib/roken/iruserok.c b/src/kerberosV/src/lib/roken/iruserok.c
new file mode 100644 (file)
index 0000000..395b3b9
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: iruserok.c,v 1.25 2005/04/12 11:28:54 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+#ifdef HAVE_RPCSVC_YPCLNT_H
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#include "roken.h"
+
+int     __check_rhosts_file = 1;
+char    *__rcmd_errstr = 0;
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static
+int
+__icheckhost(unsigned raddr, const char *lhost)
+{
+       struct hostent *hp;
+       u_long laddr;
+       char **pp;
+
+       /* Try for raw ip address first. */
+       if (isdigit((unsigned char)*lhost)
+           && (long)(laddr = inet_addr(lhost)) != -1)
+               return (raddr == laddr);
+
+       /* Better be a hostname. */
+       if ((hp = gethostbyname(lhost)) == NULL)
+               return (0);
+
+       /* Spin through ip addresses. */
+       for (pp = hp->h_addr_list; *pp; ++pp)
+               if (memcmp(&raddr, *pp, sizeof(u_long)) == 0)
+                       return (1);
+
+       /* No match. */
+       return (0);
+}
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ */
+static
+int
+__ivaliduser(FILE *hostf, unsigned raddr, const char *luser,
+            const char *ruser)
+{
+       char *user, *p;
+       int ch;
+       char buf[MaxHostNameLen + 128];         /* host + login */
+       char hname[MaxHostNameLen];
+       struct hostent *hp;
+       /* Presumed guilty until proven innocent. */
+       int userok = 0, hostok = 0;
+#ifdef HAVE_YP_GET_DEFAULT_DOMAIN
+       char *ypdomain;
+
+       if (yp_get_default_domain(&ypdomain))
+               ypdomain = NULL;
+#else
+#define        ypdomain NULL
+#endif
+       /* We need to get the damn hostname back for netgroup matching. */
+       if ((hp = gethostbyaddr((char *)&raddr,
+                               sizeof(u_long),
+                               AF_INET)) == NULL)
+               return (-1);
+       strlcpy(hname, hp->h_name, sizeof(hname));
+
+       while (fgets(buf, sizeof(buf), hostf)) {
+               p = buf;
+               /* Skip lines that are too long. */
+               if (strchr(p, '\n') == NULL) {
+                       while ((ch = getc(hostf)) != '\n' && ch != EOF);
+                       continue;
+               }
+               if (*p == '\n' || *p == '#') {
+                       /* comment... */
+                       continue;
+               }
+               while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+                       if (isupper((unsigned char)*p))
+                           *p = tolower((unsigned char)*p);
+                       p++;
+               }
+               if (*p == ' ' || *p == '\t') {
+                       *p++ = '\0';
+                       while (*p == ' ' || *p == '\t')
+                               p++;
+                       user = p;
+                       while (*p != '\n' && *p != ' ' &&
+                           *p != '\t' && *p != '\0')
+                               p++;
+               } else
+                       user = p;
+               *p = '\0';
+               /*
+                * Do +/- and +@/-@ checking. This looks really nasty,
+                * but it matches SunOS's behavior so far as I can tell.
+                */
+               switch(buf[0]) {
+               case '+':
+                       if (!buf[1]) {     /* '+' matches all hosts */
+                               hostok = 1;
+                               break;
+                       }
+                       if (buf[1] == '@')  /* match a host by netgroup */
+                               hostok = innetgr((char *)&buf[2],
+                                       (char *)&hname, NULL, ypdomain);
+                       else            /* match a host by addr */
+                               hostok = __icheckhost(raddr,(char *)&buf[1]);
+                       break;
+               case '-':     /* reject '-' hosts and all their users */
+                       if (buf[1] == '@') {
+                               if (innetgr((char *)&buf[2],
+                                             (char *)&hname, NULL, ypdomain))
+                                       return(-1);
+                       } else {
+                               if (__icheckhost(raddr,(char *)&buf[1]))
+                                       return(-1);
+                       }
+                       break;
+               default:  /* if no '+' or '-', do a simple match */
+                       hostok = __icheckhost(raddr, buf);
+                       break;
+               }
+               switch(*user) {
+               case '+':
+                       if (!*(user+1)) {      /* '+' matches all users */
+                               userok = 1;
+                               break;
+                       }
+                       if (*(user+1) == '@')  /* match a user by netgroup */
+                               userok = innetgr(user+2, NULL, (char *)ruser,
+                                                ypdomain);
+                       else       /* match a user by direct specification */
+                               userok = !(strcmp(ruser, user+1));
+                       break;
+               case '-':               /* if we matched a hostname, */
+                       if (hostok) {   /* check for user field rejections */
+                               if (!*(user+1))
+                                       return(-1);
+                               if (*(user+1) == '@') {
+                                       if (innetgr(user+2, NULL,
+                                                   (char *)ruser, ypdomain))
+                                               return(-1);
+                               } else {
+                                       if (!strcmp(ruser, user+1))
+                                               return(-1);
+                               }
+                       }
+                       break;
+               default:        /* no rejections: try to match the user */
+                       if (hostok)
+                               userok = !(strcmp(ruser,*user ? user : luser));
+                       break;
+               }
+               if (hostok && userok)
+                       return(0);
+       }
+       return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver.  When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int ROKEN_LIB_FUNCTION
+iruserok(unsigned raddr, int superuser, const char *ruser, const char *luser)
+{
+       char *cp;
+       struct stat sbuf;
+       struct passwd *pwd;
+       FILE *hostf;
+       uid_t uid;
+       int first;
+       char pbuf[MaxPathLen];
+
+       first = 1;
+       hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+       if (hostf) {
+               if (__ivaliduser(hostf, raddr, luser, ruser) == 0) {
+                       fclose(hostf);
+                       return (0);
+               }
+               fclose(hostf);
+       }
+       if (first == 1 && (__check_rhosts_file || superuser)) {
+               first = 0;
+               if ((pwd = k_getpwnam((char*)luser)) == NULL)
+                       return (-1);
+               snprintf (pbuf, sizeof(pbuf), "%s/.rhosts", pwd->pw_dir);
+
+               /*
+                * Change effective uid while opening .rhosts.  If root and
+                * reading an NFS mounted file system, can't read files that
+                * are protected read/write owner only.
+                */
+               uid = geteuid();
+               seteuid(pwd->pw_uid);
+               hostf = fopen(pbuf, "r");
+               seteuid(uid);
+
+               if (hostf == NULL)
+                       return (-1);
+               /*
+                * If not a regular file, or is owned by someone other than
+                * user or root or if writeable by anyone but the owner, quit.
+                */
+               cp = NULL;
+               if (lstat(pbuf, &sbuf) < 0)
+                       cp = ".rhosts lstat failed";
+               else if (!S_ISREG(sbuf.st_mode))
+                       cp = ".rhosts not regular file";
+               else if (fstat(fileno(hostf), &sbuf) < 0)
+                       cp = ".rhosts fstat failed";
+               else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+                       cp = "bad .rhosts owner";
+               else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+                       cp = ".rhosts writeable by other than owner";
+               /* If there were any problems, quit. */
+               if (cp) {
+                       __rcmd_errstr = cp;
+                       fclose(hostf);
+                       return (-1);
+               }
+               goto again;
+       }
+       return (-1);
+}
diff --git a/src/kerberosV/src/lib/roken/issuid.c b/src/kerberosV/src/lib/roken/issuid.c
new file mode 100644 (file)
index 0000000..aae4198
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1998 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: issuid.c,v 1.6 2005/05/13 07:42:03 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+issuid(void)
+{
+#if defined(HAVE_ISSETUGID)
+    return issetugid();
+#else /* !HAVE_ISSETUGID */
+
+#if defined(HAVE_GETUID) && defined(HAVE_GETEUID)
+    if(getuid() != geteuid())
+       return 1;
+#endif
+#if defined(HAVE_GETGID) && defined(HAVE_GETEGID)
+    if(getgid() != getegid())
+       return 2;
+#endif
+
+    return 0;
+#endif /* HAVE_ISSETUGID */
+}
diff --git a/src/kerberosV/src/lib/roken/k_getpwnam.c b/src/kerberosV/src/lib/roken/k_getpwnam.c
new file mode 100644 (file)
index 0000000..6f159f3
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: k_getpwnam.c,v 1.10 2005/04/12 11:28:54 lha Exp $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+struct passwd * ROKEN_LIB_FUNCTION
+k_getpwnam (const char *user)
+{
+     struct passwd *p;
+
+     p = getpwnam (user);
+#if defined(HAVE_GETSPNAM) && defined(HAVE_STRUCT_SPWD)
+     if(p)
+     {
+         struct spwd *spwd;
+
+         spwd = getspnam (user);
+         if (spwd)
+              p->pw_passwd = spwd->sp_pwdp;
+         endspent ();
+     }
+#else
+     endpwent ();
+#endif
+     return p;
+}
diff --git a/src/kerberosV/src/lib/roken/k_getpwuid.c b/src/kerberosV/src/lib/roken/k_getpwuid.c
new file mode 100644 (file)
index 0000000..10196d5
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: k_getpwuid.c,v 1.10 2005/04/12 11:28:55 lha Exp $");
+#endif /* HAVE_CONFIG_H */
+
+#include "roken.h"
+#ifdef HAVE_SHADOW_H
+#include <shadow.h>
+#endif
+
+struct passwd * ROKEN_LIB_FUNCTION
+k_getpwuid (uid_t uid)
+{
+     struct passwd *p;
+
+     p = getpwuid (uid);
+#if defined(HAVE_GETSPNAM) && defined(HAVE_STRUCT_SPWD)
+     if (p)
+     {
+         struct spwd *spwd;
+
+         spwd = getspnam (p->pw_name);
+         if (spwd)
+              p->pw_passwd = spwd->sp_pwdp;
+         endspent ();
+     }
+#else
+     endpwent ();
+#endif
+     return p;
+}
diff --git a/src/kerberosV/src/lib/roken/localtime_r.c b/src/kerberosV/src/lib/roken/localtime_r.c
new file mode 100644 (file)
index 0000000..c50880c
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: localtime_r.c,v 1.3 2005/04/12 11:28:55 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <time.h>
+#include "roken.h"
+
+#ifndef HAVE_LOCALTIME_R
+
+struct tm * ROKEN_LIB_FUNCTION
+localtime_r(const time_t *timer, struct tm *result)
+{
+    struct tm *tm;
+    
+    tm = localtime((time_t *)timer);
+    if (tm == NULL)
+       return NULL;
+    *result = *tm;
+    return result;
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/lstat.c b/src/kerberosV/src/lib/roken/lstat.c
new file mode 100644 (file)
index 0000000..b3e36eb
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: lstat.c,v 1.5 2005/04/12 11:28:55 lha Exp $");
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+lstat(const char *path, struct stat *buf)
+{
+  return stat(path, buf);
+}
diff --git a/src/kerberosV/src/lib/roken/make-print-version.c b/src/kerberosV/src/lib/roken/make-print-version.c
new file mode 100644 (file)
index 0000000..0e8b27c
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1998 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: make-print-version.c,v 1.3 2000/08/16 11:30:04 assar Exp $");
+#endif
+
+#include <stdio.h>
+
+#ifdef KRB5
+extern const char *heimdal_version;
+#endif
+#ifdef KRB4
+extern char *krb4_version;
+#endif
+#include <version.h>
+
+int
+main(int argc, char **argv)
+{
+    FILE *f;
+    if(argc != 2)
+       return 1;
+    f = fopen(argv[1], "w");
+    if(f == NULL)
+       return 1;
+    fprintf(f, "#define VERSIONLIST { ");
+#ifdef KRB5
+    fprintf(f, "\"%s\", ", heimdal_version);
+#endif
+#ifdef KRB4
+    fprintf(f, "\"%s\", ", krb4_version);
+#endif
+    fprintf(f, "}\n");
+    fclose(f);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/memmove.c b/src/kerberosV/src/lib/roken/memmove.c
new file mode 100644 (file)
index 0000000..b172c8e
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: memmove.c,v 1.8 2005/04/12 11:28:56 lha Exp $");
+#endif
+
+/* 
+ * memmove for systems that doesn't have it 
+ */
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+void* ROKEN_LIB_FUNCTION
+memmove(void *s1, const void *s2, size_t n)
+{
+  char *s=(char*)s2, *d=(char*)s1;
+
+  if(d > s){
+    s+=n-1;
+    d+=n-1;
+    while(n){
+      *d--=*s--;
+      n--;
+    }
+  }else if(d < s)
+    while(n){
+      *d++=*s++;
+      n--;
+    }
+  return s1;
+}
diff --git a/src/kerberosV/src/lib/roken/mini_inetd.c b/src/kerberosV/src/lib/roken/mini_inetd.c
new file mode 100644 (file)
index 0000000..456bf71
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: mini_inetd.c,v 1.31 2005/04/12 11:28:56 lha Exp $");
+#endif
+
+#include <err.h>
+#include "roken.h"
+
+/*
+ * accept a connection on `s' and pretend it's served by inetd.
+ */
+
+static void
+accept_it (int s)
+{
+    int s2;
+
+    s2 = accept(s, NULL, NULL);
+    if(s2 < 0)
+       err (1, "accept");
+    close(s);
+    dup2(s2, STDIN_FILENO);
+    dup2(s2, STDOUT_FILENO);
+    /* dup2(s2, STDERR_FILENO); */
+    close(s2);
+}
+
+/*
+ * Listen on a specified port, emulating inetd.
+ */
+
+void ROKEN_LIB_FUNCTION
+mini_inetd_addrinfo (struct addrinfo *ai)
+{
+    int ret;
+    struct addrinfo *a;
+    int n, nalloc, i;
+    int *fds;
+    fd_set orig_read_set, read_set;
+    int max_fd = -1;
+
+    for (nalloc = 0, a = ai; a != NULL; a = a->ai_next)
+       ++nalloc;
+
+    fds = malloc (nalloc * sizeof(*fds));
+    if (fds == NULL)
+       errx (1, "mini_inetd: out of memory");
+
+    FD_ZERO(&orig_read_set);
+
+    for (i = 0, a = ai; a != NULL; a = a->ai_next) {
+       fds[i] = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
+       if (fds[i] < 0) {
+           warn ("socket af = %d", a->ai_family);
+           continue;
+       }
+       socket_set_reuseaddr (fds[i], 1);
+       if (bind (fds[i], a->ai_addr, a->ai_addrlen) < 0) {
+           warn ("bind af = %d", a->ai_family);
+           close(fds[i]);
+           continue;
+       }
+       if (listen (fds[i], SOMAXCONN) < 0) {
+           warn ("listen af = %d", a->ai_family);
+           close(fds[i]);
+           continue;
+       }
+       if (fds[i] >= FD_SETSIZE)
+           errx (1, "fd too large");
+       FD_SET(fds[i], &orig_read_set);
+       max_fd = max(max_fd, fds[i]);
+       ++i;
+    }
+    if (i == 0)
+       errx (1, "no sockets");
+    n = i;
+
+    do {
+       read_set = orig_read_set;
+
+       ret = select (max_fd + 1, &read_set, NULL, NULL, NULL);
+       if (ret < 0 && errno != EINTR)
+           err (1, "select");
+    } while (ret <= 0);
+
+    for (i = 0; i < n; ++i)
+       if (FD_ISSET (fds[i], &read_set)) {
+           accept_it (fds[i]);
+           free(fds);
+           return;
+       }
+    free(fds);
+    abort ();
+}
+
+void ROKEN_LIB_FUNCTION
+mini_inetd (int port)
+{
+    int error;
+    struct addrinfo *ai, hints;
+    char portstr[NI_MAXSERV];
+
+    memset (&hints, 0, sizeof(hints));
+    hints.ai_flags    = AI_PASSIVE;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_family   = PF_UNSPEC;
+
+    snprintf (portstr, sizeof(portstr), "%d", ntohs(port));
+
+    error = getaddrinfo (NULL, portstr, &hints, &ai);
+    if (error)
+       errx (1, "getaddrinfo: %s", gai_strerror (error));
+
+    mini_inetd_addrinfo(ai);
+    
+    freeaddrinfo(ai);
+}
diff --git a/src/kerberosV/src/lib/roken/missing b/src/kerberosV/src/lib/roken/missing
new file mode 100644 (file)
index 0000000..7789652
--- /dev/null
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# 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.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+case "$1" in
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]"
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing - GNU libit 0.0"
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+  aclocal)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acinclude.m4' or \`configure.in'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`configure.in'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`acconfig.h' or \`configure.in'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case "$f" in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  bison|yacc)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f y.tab.h ]; then
+       echo >y.tab.h
+    fi
+    if [ ! -f y.tab.c ]; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex|flex)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if [ $# -ne 1 ]; then
+        eval LASTARG="\${$#}"
+       case "$LASTARG" in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if [ -f "$SRCFILE" ]; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if [ ! -f lex.yy.c ]; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  makeinfo)
+    echo 1>&2 "\
+WARNING: \`$1' is missing on your system.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+    if test -z "$file"; then
+      file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+    fi
+    touch $file
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+         system.  You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequirements for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
diff --git a/src/kerberosV/src/lib/roken/mkinstalldirs b/src/kerberosV/src/lib/roken/mkinstalldirs
new file mode 100644 (file)
index 0000000..cd937fd
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id: mkinstalldirs,v 1.1.1.1 2001/05/25 07:51:15 hin Exp $
+
+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/src/kerberosV/src/lib/roken/mkstemp.c b/src/kerberosV/src/lib/roken/mkstemp.c
new file mode 100644 (file)
index 0000000..3daf240
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#include <errno.h>
+
+RCSID("$KTH: mkstemp.c,v 1.4 2005/04/12 11:28:56 lha Exp $");
+
+#ifndef HAVE_MKSTEMP
+
+int ROKEN_LIB_FUNCTION
+mkstemp(char *template)
+{
+    int start, i;
+    pid_t val;
+    val = getpid();
+    start = strlen(template) - 1;
+    while(template[start] == 'X') {
+       template[start] = '0' + val % 10;
+       val /= 10;
+       start--;
+    }
+    
+    do{
+       int fd;
+       fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600);
+       if(fd >= 0 || errno != EEXIST)
+           return fd;
+       i = start + 1;
+       do{
+           if(template[i] == 0)
+               return -1;
+           template[i]++;
+           if(template[i] == '9' + 1)
+               template[i] = 'a';
+           if(template[i] <= 'z')
+               break;
+           template[i] = 'a';
+           i++;
+       }while(1);
+    }while(1);
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/ndbm_wrap.c b/src/kerberosV/src/lib/roken/ndbm_wrap.c
new file mode 100644 (file)
index 0000000..2335407
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: ndbm_wrap.c,v 1.4 2005/04/12 11:28:57 lha Exp $");
+#endif
+
+#include "ndbm_wrap.h"
+#if defined(HAVE_DB4_DB_H)
+#include <db4/db.h>
+#elif defined(HAVE_DB3_DB_H)
+#include <db3/db.h>
+#else
+#include <db.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+
+/* XXX undefine open so this works on Solaris with large file support */
+#undef open
+
+#define DBT2DATUM(DBT, DATUM) do { (DATUM)->dptr = (DBT)->data; (DATUM)->dsize = (DBT)->size; } while(0)
+#define DATUM2DBT(DATUM, DBT) do { (DBT)->data = (DATUM)->dptr; (DBT)->size = (DATUM)->dsize; } while(0)
+#define RETURN(X) return ((X) == 0) ? 0 : -1
+
+#ifdef HAVE_DB3
+static DBC *cursor;
+#endif
+
+#define D(X) ((DB*)(X))
+
+void ROKEN_LIB_FUNCTION
+dbm_close (DBM *db)
+{
+#ifdef HAVE_DB3
+    D(db)->close(D(db), 0);
+    cursor = NULL;
+#else
+    D(db)->close(D(db));
+#endif
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_delete (DBM *db, datum dkey)
+{
+    DBT key;
+    DATUM2DBT(&dkey, &key);
+#ifdef HAVE_DB3
+    RETURN(D(db)->del(D(db), NULL, &key, 0));
+#else
+    RETURN(D(db)->del(D(db), &key, 0));
+#endif
+}
+
+datum
+dbm_fetch (DBM *db, datum dkey)
+{
+    datum dvalue;
+    DBT key, value;
+    DATUM2DBT(&dkey, &key);
+    if(D(db)->get(D(db), 
+#ifdef HAVE_DB3
+              NULL, 
+#endif
+              &key, &value, 0) != 0) 
+       dvalue.dptr = NULL;
+    else
+       DBT2DATUM(&value, &dvalue);
+
+    return dvalue;
+}
+
+static datum
+dbm_get (DB *db, int flags)
+{
+    DBT key, value;
+    datum datum;
+#ifdef HAVE_DB3
+    if(cursor == NULL) 
+       db->cursor(db, NULL, &cursor, 0);
+    if(cursor->c_get(cursor, &key, &value, flags) != 0) 
+       datum.dptr = NULL;
+    else 
+       DBT2DATUM(&value, &datum);
+#else
+    db->seq(db, &key, &value, flags);
+#endif
+    return datum;
+}
+
+#ifndef DB_FIRST
+#define DB_FIRST       R_FIRST
+#define DB_NEXT                R_NEXT
+#define DB_NOOVERWRITE R_NOOVERWRITE
+#define DB_KEYEXIST    1
+#endif
+
+datum ROKEN_LIB_FUNCTION
+dbm_firstkey (DBM *db)
+{
+    return dbm_get(D(db), DB_FIRST);
+}
+
+datum ROKEN_LIB_FUNCTION
+dbm_nextkey (DBM *db)
+{
+    return dbm_get(D(db), DB_NEXT);
+}
+
+DBM* ROKEN_LIB_FUNCTION
+dbm_open (const char *file, int flags, mode_t mode)
+{
+    DB *db;
+    int myflags = 0;
+    char *fn;
+    if(asprintf(&fn, "%s.db", file) == -1)
+       return NULL;
+#ifdef HAVE_DB3
+    if (flags & O_CREAT)
+       myflags |= DB_CREATE;
+
+    if (flags & O_EXCL)
+       myflags |= DB_EXCL;
+
+    if (flags & O_RDONLY)
+       myflags |= DB_RDONLY;
+
+    if (flags & O_TRUNC)
+       myflags |= DB_TRUNCATE;
+    if(db_create(&db, NULL, 0) != 0) {
+       free(fn);
+       return NULL;
+    }
+
+#if (DB_VERSION_MAJOR > 3) && (DB_VERSION_MINOR > 0)
+    if(db->open(db, NULL, fn, NULL, DB_BTREE, myflags, mode) != 0) {
+#else
+    if(db->open(db, fn, NULL, DB_BTREE, myflags, mode) != 0) {
+#endif
+       free(fn);
+       db->close(db, 0);
+       return NULL;
+    }
+#else
+    db = dbopen(fn, flags, mode, DB_BTREE, NULL);
+#endif
+    free(fn);
+    return (DBM*)db;
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_store (DBM *db, datum dkey, datum dvalue, int flags)
+{
+    int ret;
+    DBT key, value;
+    int myflags = 0;
+    if((flags & DBM_REPLACE) == 0)
+       myflags |= DB_NOOVERWRITE;
+    DATUM2DBT(&dkey, &key);
+    DATUM2DBT(&dvalue, &value);    
+    ret = D(db)->put(D(db), 
+#ifdef HAVE_DB3
+                    NULL, 
+#endif
+&key, &value, myflags);
+    if(ret == DB_KEYEXIST)
+       return 1;
+    RETURN(ret);
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_error (DBM *db)
+{
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+dbm_clearerr (DBM *db)
+{
+    return 0;
+}
+
diff --git a/src/kerberosV/src/lib/roken/ndbm_wrap.h b/src/kerberosV/src/lib/roken/ndbm_wrap.h
new file mode 100644 (file)
index 0000000..c55f44c
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: ndbm_wrap.h,v 1.2 2005/04/12 11:28:57 lha Exp $ */
+
+#ifndef __ndbm_wrap_h__
+#define __ndbm_wrap_h__
+
+#include <stdio.h>
+#include <sys/types.h>
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#ifndef dbm_rename
+#define dbm_rename(X)  __roken_ ## X
+#endif
+
+#define dbm_open       dbm_rename(dbm_open)
+#define dbm_close      dbm_rename(dbm_close)
+#define dbm_delete     dbm_rename(dbm_delete)
+#define dbm_fetch      dbm_rename(dbm_fetch)
+#define dbm_get                dbm_rename(dbm_get)
+#define dbm_firstkey   dbm_rename(dbm_firstkey)
+#define dbm_nextkey    dbm_rename(dbm_nextkey)
+#define dbm_store      dbm_rename(dbm_store)
+#define dbm_error      dbm_rename(dbm_error)
+#define dbm_clearerr   dbm_rename(dbm_clearerr)
+
+#define datum          dbm_rename(datum)
+
+typedef struct {
+    void *dptr;
+    size_t dsize;
+} datum;
+
+#define DBM_REPLACE 1
+typedef struct DBM DBM;
+
+#if 0
+typedef struct {
+    int dummy;
+} DBM;
+#endif
+
+int ROKEN_LIB_FUNCTION dbm_clearerr (DBM*);
+void ROKEN_LIB_FUNCTION dbm_close (DBM*);
+int ROKEN_LIB_FUNCTION dbm_delete (DBM*, datum);
+int ROKEN_LIB_FUNCTION dbm_error (DBM*);
+datum ROKEN_LIB_FUNCTION dbm_fetch (DBM*, datum);
+datum ROKEN_LIB_FUNCTION dbm_firstkey (DBM*);
+datum ROKEN_LIB_FUNCTION dbm_nextkey (DBM*);
+DBM* ROKEN_LIB_FUNCTION dbm_open (const char*, int, mode_t);
+int ROKEN_LIB_FUNCTION dbm_store (DBM*, datum, datum, int);
+
+#endif /* __ndbm_wrap_h__ */
diff --git a/src/kerberosV/src/lib/roken/net_read.c b/src/kerberosV/src/lib/roken/net_read.c
new file mode 100644 (file)
index 0000000..aa400b5
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: net_read.c,v 1.4 2005/04/12 11:28:57 lha Exp $");
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <roken.h>
+
+/*
+ * Like read but never return partial data.
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+net_read (int fd, void *buf, size_t nbytes)
+{
+    char *cbuf = (char *)buf;
+    ssize_t count;
+    size_t rem = nbytes;
+
+    while (rem > 0) {
+#ifdef WIN32
+       count = recv (fd, cbuf, rem, 0);
+#else
+       count = read (fd, cbuf, rem);
+#endif
+       if (count < 0) {
+           if (errno == EINTR)
+               continue;
+           else
+               return count;
+       } else if (count == 0) {
+           return count;
+       }
+       cbuf += count;
+       rem -= count;
+    }
+    return nbytes;
+}
diff --git a/src/kerberosV/src/lib/roken/net_write.c b/src/kerberosV/src/lib/roken/net_write.c
new file mode 100644 (file)
index 0000000..ac9f9cf
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: net_write.c,v 1.5 2005/04/12 11:28:58 lha Exp $");
+#endif
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <roken.h>
+
+/*
+ * Like write but never return partial data.
+ */
+
+ssize_t ROKEN_LIB_FUNCTION
+net_write (int fd, const void *buf, size_t nbytes)
+{
+    const char *cbuf = (const char *)buf;
+    ssize_t count;
+    size_t rem = nbytes;
+
+    while (rem > 0) {
+#ifdef WIN32
+       count = send (fd, cbuf, rem, 0);
+#else
+       count = write (fd, cbuf, rem);
+#endif
+       if (count < 0) {
+           if (errno == EINTR)
+               continue;
+           else
+               return count;
+       }
+       cbuf += count;
+       rem -= count;
+    }
+    return nbytes;
+}
diff --git a/src/kerberosV/src/lib/roken/parse_bytes-test.c b/src/kerberosV/src/lib/roken/parse_bytes-test.c
new file mode 100644 (file)
index 0000000..db119bc
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_bytes-test.c,v 1.3 2001/09/04 09:56:00 assar Exp $");
+#endif
+
+#include "roken.h"
+#include "parse_bytes.h"
+
+static struct testcase {
+    int canonicalp;
+    int val;
+    const char *def_unit;
+    const char *str;
+} tests[] = {
+    {0, 0, NULL, "0 bytes"},
+    {1, 0, NULL, "0"},
+    {0, 1, NULL, "1"},
+    {1, 1, NULL, "1 byte"},
+    {0, 0, "kilobyte", "0"},
+    {0, 1024, "kilobyte", "1"},
+    {1, 1024, "kilobyte", "1 kilobyte"},
+    {1, 1024 * 1024, NULL, "1 megabyte"},
+    {0, 1025, NULL, "1 kilobyte 1"},
+    {1, 1025, NULL, "1 kilobyte 1 byte"},
+};
+
+int
+main(int argc, char **argv)
+{
+    int i;
+    int ret = 0;
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
+       char buf[256];
+       int val = parse_bytes (tests[i].str, tests[i].def_unit);
+       int len;
+
+       if (val != tests[i].val) {
+           printf ("parse_bytes (%s, %s) = %d != %d\n",
+                   tests[i].str,
+                   tests[i].def_unit ? tests[i].def_unit : "none",
+                   val, tests[i].val);
+           ++ret;
+       }
+       if (tests[i].canonicalp) {
+           len = unparse_bytes (tests[i].val, buf, sizeof(buf));
+           if (strcmp (tests[i].str, buf) != 0) {
+               printf ("unparse_bytes (%d) = \"%s\" != \"%s\"\n",
+                       tests[i].val, buf, tests[i].str);
+               ++ret;
+           }
+       }    
+    }
+    if (ret) {
+       printf ("%d errors\n", ret);
+       return 1;
+    } else
+       return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/parse_bytes.c b/src/kerberosV/src/lib/roken/parse_bytes.c
new file mode 100644 (file)
index 0000000..75a7ebd
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_bytes.c,v 1.5 2005/04/12 11:28:58 lha Exp $");
+#endif
+
+#include <parse_units.h>
+#include "parse_bytes.h"
+
+static struct units bytes_units[] = {
+    { "gigabyte", 1024 * 1024 * 1024 },
+    { "gbyte", 1024 * 1024 * 1024 },
+    { "GB", 1024 * 1024 * 1024 },
+    { "megabyte", 1024 * 1024 },
+    { "mbyte", 1024 * 1024 },
+    { "MB", 1024 * 1024 },
+    { "kilobyte", 1024 },
+    { "KB", 1024 },
+    { "byte", 1 },
+    { NULL, 0 }
+};
+
+static struct units bytes_short_units[] = {
+    { "GB", 1024 * 1024 * 1024 },
+    { "MB", 1024 * 1024 },
+    { "KB", 1024 },
+    { NULL, 0 }
+};
+
+int ROKEN_LIB_FUNCTION
+parse_bytes (const char *s, const char *def_unit)
+{
+    return parse_units (s, bytes_units, def_unit);
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes (int t, char *s, size_t len)
+{
+    return unparse_units (t, bytes_units, s, len);
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes_short (int t, char *s, size_t len)
+{
+    return unparse_units_approx (t, bytes_short_units, s, len);
+}
diff --git a/src/kerberosV/src/lib/roken/parse_bytes.h b/src/kerberosV/src/lib/roken/parse_bytes.h
new file mode 100644 (file)
index 0000000..c30eeb9
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: parse_bytes.h,v 1.4 2005/04/13 13:19:07 lha Exp $ */
+
+#ifndef __PARSE_BYTES_H__
+#define __PARSE_BYTES_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+int ROKEN_LIB_FUNCTION
+parse_bytes (const char *s, const char *def_unit);
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes (int t, char *s, size_t len);
+
+int ROKEN_LIB_FUNCTION
+unparse_bytes_short (int t, char *s, size_t len);
+
+#endif /* __PARSE_BYTES_H__ */
diff --git a/src/kerberosV/src/lib/roken/parse_reply-test.c b/src/kerberosV/src/lib/roken/parse_reply-test.c
new file mode 100644 (file)
index 0000000..8967d49
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_reply-test.c,v 1.3 2005/05/29 21:21:12 lha Exp $");
+#endif
+
+#include <sys/types.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <fcntl.h>
+
+#include "roken.h"
+#include "resolve.h"
+
+struct dns_reply*
+parse_reply(const unsigned char *, size_t);
+
+enum { MAX_BUF = 36};
+
+static struct testcase {
+    unsigned char buf[MAX_BUF];
+    size_t buf_len;
+} tests[] = {
+    {{0x12, 0x67, 0x84, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+     0x03, 'f', 'o', 'o', 0x00,
+     0x00, 0x10, 0x00, 0x01,
+     0x03, 'f', 'o', 'o', 0x00,
+     0x00, 0x10, 0x00, 0x01,
+      0x00, 0x00, 0x12, 0x67, 0xff, 0xff}, 36}
+};
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (-1)
+#endif
+
+static sig_atomic_t val = 0;
+
+static RETSIGTYPE
+segv_handler(int sig)
+{
+    val = 1;
+}
+
+int
+main(int argc, char **argv)
+{
+#ifndef HAVE_MMAP
+    return 77;                 /* signal to automake that this test
+                                   cannot be run */
+#else /* HAVE_MMAP */
+    int ret;
+    int i;
+    struct sigaction sa;
+
+    sigemptyset (&sa.sa_mask);
+    sa.sa_flags = 0;
+    sa.sa_handler = segv_handler;
+    sigaction (SIGSEGV, &sa, NULL);
+
+    for (i = 0; val == 0 && i < sizeof(tests)/sizeof(tests[0]); ++i) {
+       const struct testcase *t = &tests[i];
+       unsigned char *p1, *p2;
+       int flags;
+       int fd;
+       size_t pagesize = getpagesize();
+       unsigned char *buf;
+
+#ifdef MAP_ANON
+       flags = MAP_ANON;
+       fd = -1;
+#else
+       flags = 0;
+       fd = open ("/dev/zero", O_RDONLY);
+       if(fd < 0)
+           err (1, "open /dev/zero");
+#endif
+       flags |= MAP_PRIVATE;
+
+       p1 = (unsigned char *)mmap(0, 2 * pagesize, PROT_READ | PROT_WRITE,
+                 flags, fd, 0);
+       if (p1 == (unsigned char *)MAP_FAILED)
+           err (1, "mmap");
+       p2 = p1 + pagesize;
+       ret = mprotect ((void *)p2, pagesize, 0);
+       if (ret < 0)
+           err (1, "mprotect");
+       buf = p2 - t->buf_len;
+       memcpy (buf, t->buf, t->buf_len);
+       parse_reply (buf, t->buf_len);
+       ret = munmap ((void *)p1, 2 * pagesize);
+       if (ret < 0)
+           err (1, "munmap");
+    }
+    return val;
+#endif /* HAVE_MMAP */
+}
diff --git a/src/kerberosV/src/lib/roken/parse_time-test.c b/src/kerberosV/src/lib/roken/parse_time-test.c
new file mode 100644 (file)
index 0000000..7e19165
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_time-test.c,v 1.7 2005/04/30 14:48:29 lha Exp $");
+#endif
+
+#include "roken.h"
+#include "parse_time.h"
+#include "test-mem.h"
+#include "err.h"
+
+static struct testcase {
+    size_t size;
+    time_t val;
+    char *str;
+} tests[] = {
+    { 8, 1,            "1 second" },
+    { 17, 61,          "1 minute 1 second" },
+    { 18, 62,          "1 minute 2 seconds" },
+    { 8, 60,           "1 minute" },
+    { 6, 3600,         "1 hour" },
+    { 15, 3601,                "1 hour 1 second" },
+    { 16, 3602,                "1 hour 2 seconds" }
+};
+
+int
+main(int argc, char **argv)
+{
+    size_t sz;
+    size_t buf_sz;
+    int i, j;
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
+       char *buf;
+
+       sz = unparse_time(tests[i].val, NULL, 0);
+       if  (sz != tests[i].size)
+           errx(1, "sz (%lu) != tests[%d].size (%lu)",
+                (unsigned long)sz, i, (unsigned long)tests[i].size);
+       
+       for (buf_sz = 0; buf_sz < tests[i].size + 2; buf_sz++) {
+
+           buf = rk_test_mem_alloc(RK_TM_OVERRUN, "overrun",
+                                   NULL, buf_sz);
+           sz = unparse_time(tests[i].val, buf, buf_sz);
+           if (sz != tests[i].size)
+               errx(1, "sz (%lu) != tests[%d].size (%lu) with in size %lu",
+                    (unsigned long)sz, i, 
+                    (unsigned long)tests[i].size,
+                    (unsigned long)buf_sz);
+           if (buf_sz > 0 && memcmp(buf, tests[i].str, buf_sz - 1) != 0)
+               errx(1, "test %i wrong result %s vs %s", i, buf, tests[i].str);
+           if (buf_sz > 0 && buf[buf_sz - 1] != '\0')
+               errx(1, "test %i not zero terminated", i);
+           rk_test_mem_free("overrun");
+
+           buf = rk_test_mem_alloc(RK_TM_UNDERRUN, "underrun", 
+                                   NULL, tests[i].size);
+           sz = unparse_time(tests[i].val, buf, buf_sz);
+           if (sz != tests[i].size)
+               errx(1, "sz (%lu) != tests[%d].size (%lu) with insize %lu",
+                    (unsigned long)sz, i,
+                    (unsigned long)tests[i].size,
+                    (unsigned long)buf_sz);
+           if (buf_sz > 0 && strncmp(buf, tests[i].str, buf_sz - 1) != 0)
+               errx(1, "test %i wrong result %s vs %s", i, buf, tests[i].str);
+           if (buf_sz > 0 && buf[buf_sz - 1] != '\0')
+               errx(1, "test %i not zero terminated", i);
+           rk_test_mem_free("underrun");
+       }
+       buf = rk_test_mem_alloc(RK_TM_OVERRUN, "overrun",
+                               tests[i].str, tests[i].size + 1);
+       j = parse_time(buf, "s");
+       if (j != tests[i].val)
+           errx(1, "parse_time failed for test %d", i);
+       rk_test_mem_free("overrun");
+
+       buf = rk_test_mem_alloc(RK_TM_UNDERRUN, "underrun",
+                               tests[i].str, tests[i].size + 1);
+       j = parse_time(buf, "s");
+       if (j != tests[i].val)
+           errx(1, "parse_time failed for test %d", i);
+       rk_test_mem_free("underrun");
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/parse_time.3 b/src/kerberosV/src/lib/roken/parse_time.3
new file mode 100644 (file)
index 0000000..d0d5d38
--- /dev/null
@@ -0,0 +1,173 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" $KTH: parse_time.3,v 1.3 2004/10/30 22:34:28 lha Exp $
+.\"
+.Dd October 31, 2004
+.Dt PARSE_TIME 3
+.Os HEIMDAL
+.Sh NAME
+.Nm parse_time ,
+.Nm print_time_table ,
+.Nm unparse_time ,
+.Nm unparse_time_approx
+.Nd parse and unparse time intervals
+.Sh LIBRARY
+The roken library (libroken, -lroken)
+.Sh SYNOPSIS
+.Fd #include <parse_time.h>
+.Ft int
+.Fn parse_time "const char *timespec" "const char *def_unit"
+.Ft void
+.Fn print_time_table "FILE *f"
+.Ft size_t
+.Fn unparse_time "int seconds" "char *buf" "size_t len"
+.Ft size_t
+.Fn unparse_time_approx "int seconds" "char *buf" "size_t len"
+.Sh DESCRIPTION
+The 
+.Fn parse_time
+function converts a the period of time specified in
+into a number of seconds.
+The 
+.Fa timespec
+can be any number of 
+.Aq number unit
+pairs separated by comma and whitespace. The number can be
+negative. Number without explicit units are taken as being
+.Fa def_unit .
+.Pp
+The
+.Fn unparse_time
+and
+.Fn unparse_time_approx
+does the opposite of 
+.Fn parse_time ,
+that is they take a number of seconds and express that as human
+readable string. 
+.Fa unparse_time
+produces an exact time, while 
+.Fa unparse_time_approx
+restricts the result to only include one units.
+.Pp
+.Fn print_time_table
+prints a descriptive list of available units on the passed file
+descriptor.
+.Pp
+The possible units include:
+.Bl -tag -width "month" -compact -offset indent
+.It Li second , s
+.It Li minute , m
+.It Li hour , h
+.It day
+.It week
+seven days
+.It month
+30 days
+.It year
+365 days
+.El
+.Pp
+Units names can be arbitrarily abbreviated (as long as they are
+unique).
+.Sh RETURN VALUES
+.Fn parse_time
+returns the number of seconds that represents the expression in 
+.Fa timespec
+or -1 on error.
+.Fn unparse_time
+and 
+.Fn unparse_time_approx 
+return the number of characters written to 
+.Fa buf .
+if the return value is greater than or equal to the
+.Fa len
+argument, the string was too short and some of the printed characters
+were discarded.
+.Sh EXAMPLES
+.Bd -literal
+#include <stdio.h>
+#include <parse_time.h>
+
+int
+main(int argc, char **argv)
+{
+    int i;
+    int result;
+    char buf[128];
+    print_time_table(stdout);
+    for (i = 1; i < argc; i++) {
+       result = parse_time(argv[i], "second");
+       if(result == -1) {
+           fprintf(stderr, "%s: parse error\\n", argv[i]);
+           continue;
+       }
+       printf("--\\n");
+       printf("parse_time = %d\\n", result);
+       unparse_time(result, buf, sizeof(buf));
+       printf("unparse_time = %s\\n", buf);
+       unparse_time_approx(result, buf, sizeof(buf));
+       printf("unparse_time_approx = %s\\n", buf);
+    }
+    return 0;
+}
+.Ed
+.Bd -literal
+$ ./a.out "1 minute 30 seconds" "90 s" "1 y -1 s"     
+1   year = 365 days
+1  month = 30 days
+1   week = 7 days
+1    day = 24 hours
+1   hour = 60 minutes
+1 minute = 60 seconds
+1 second
+--
+parse_time = 90
+unparse_time = 1 minute 30 seconds
+unparse_time_approx = 1 minute
+--
+parse_time = 90
+unparse_time = 1 minute 30 seconds
+unparse_time_approx = 1 minute
+--
+parse_time = 31535999
+unparse_time = 12 months 4 days 23 hours 59 minutes 59 seconds
+unparse_time_approx = 12 months
+.Ed
+.Sh BUGS
+Since
+.Fn parse_time
+returns -1 on error there is no way to parse "minus one second".
+Currently "s" at the end of units is ignored. This is a hack for
+English plural forms. If these functions are ever localised, this
+scheme will have to change.
+.\".Sh SEE ALSO
+.\".Xr parse_bytes 3
+.\".Xr parse_units 3
diff --git a/src/kerberosV/src/lib/roken/parse_time.c b/src/kerberosV/src/lib/roken/parse_time.c
new file mode 100644 (file)
index 0000000..2923945
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_time.c,v 1.7 2005/04/12 11:28:58 lha Exp $");
+#endif
+
+#include <parse_units.h>
+#include "parse_time.h"
+
+static struct units time_units[] = {
+    {"year",   365 * 24 * 60 * 60},
+    {"month",  30 * 24 * 60 * 60},
+    {"week",   7 * 24 * 60 * 60},
+    {"day",    24 * 60 * 60},
+    {"hour",   60 * 60},
+    {"h",      60 * 60},
+    {"minute", 60},
+    {"m",      60},
+    {"second", 1},
+    {"s",      1},
+    {NULL, 0},
+};
+
+int ROKEN_LIB_FUNCTION
+parse_time (const char *s, const char *def_unit)
+{
+    return parse_units (s, time_units, def_unit);
+}
+
+size_t ROKEN_LIB_FUNCTION
+unparse_time (int t, char *s, size_t len)
+{
+    return unparse_units (t, time_units, s, len);
+}
+
+size_t ROKEN_LIB_FUNCTION
+unparse_time_approx (int t, char *s, size_t len)
+{
+    return unparse_units_approx (t, time_units, s, len);
+}
+
+void ROKEN_LIB_FUNCTION
+print_time_table (FILE *f)
+{
+    print_units_table (time_units, f);
+}
diff --git a/src/kerberosV/src/lib/roken/parse_time.h b/src/kerberosV/src/lib/roken/parse_time.h
new file mode 100644 (file)
index 0000000..281d33c
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: parse_time.h,v 1.5 2005/04/12 11:28:59 lha Exp $ */
+
+#ifndef __PARSE_TIME_H__
+#define __PARSE_TIME_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+int
+parse_time (const char *s, const char *def_unit);
+
+size_t
+unparse_time (int t, char *s, size_t len);
+
+size_t
+unparse_time_approx (int t, char *s, size_t len);
+
+void
+print_time_table (FILE *f);
+
+#endif /* __PARSE_TIME_H__ */
diff --git a/src/kerberosV/src/lib/roken/parse_units.c b/src/kerberosV/src/lib/roken/parse_units.c
new file mode 100644 (file)
index 0000000..3444c7e
--- /dev/null
@@ -0,0 +1,340 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: parse_units.c,v 1.18 2005/04/12 11:28:59 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <roken.h>
+#include "parse_units.h"
+
+/*
+ * Parse string in `s' according to `units' and return value.
+ * def_unit defines the default unit.
+ */
+
+static int
+parse_something (const char *s, const struct units *units,
+                const char *def_unit,
+                int (*func)(int res, int val, unsigned mult),
+                int init,
+                int accept_no_val_p)
+{
+    const char *p;
+    int res = init;
+    unsigned def_mult = 1;
+
+    if (def_unit != NULL) {
+       const struct units *u;
+
+       for (u = units; u->name; ++u) {
+           if (strcasecmp (u->name, def_unit) == 0) {
+               def_mult = u->mult;
+               break;
+           }
+       }
+       if (u->name == NULL)
+           return -1;
+    }
+
+    p = s;
+    while (*p) {
+       double val;
+       char *next;
+       const struct units *u, *partial_unit;
+       size_t u_len;
+       unsigned partial;
+       int no_val_p = 0;
+
+       while(isspace((unsigned char)*p) || *p == ',')
+           ++p;
+
+       val = strtod (p, &next); /* strtol(p, &next, 0); */
+       if (p == next) {
+           val = 0;
+           if(!accept_no_val_p)
+               return -1;
+           no_val_p = 1;
+       }
+       p = next;
+       while (isspace((unsigned char)*p))
+           ++p;
+       if (*p == '\0') {
+           res = (*func)(res, val, def_mult);
+           if (res < 0)
+               return res;
+           break;
+       } else if (*p == '+') {
+           ++p;
+           val = 1;
+       } else if (*p == '-') {
+           ++p;
+           val = -1;
+       }
+       if (no_val_p && val == 0)
+           val = 1;
+       u_len = strcspn (p, ", \t");
+       partial = 0;
+       partial_unit = NULL;
+       if (u_len > 1 && p[u_len - 1] == 's')
+           --u_len;
+       for (u = units; u->name; ++u) {
+           if (strncasecmp (p, u->name, u_len) == 0) {
+               if (u_len == strlen (u->name)) {
+                   p += u_len;
+                   res = (*func)(res, val, u->mult);
+                   if (res < 0)
+                       return res;
+                   break;
+               } else {
+                   ++partial;
+                   partial_unit = u;
+               }
+           }
+       }
+       if (u->name == NULL) {
+           if (partial == 1) {
+               p += u_len;
+               res = (*func)(res, val, partial_unit->mult);
+               if (res < 0)
+                   return res;
+           } else {
+               return -1;
+           }
+       }
+       if (*p == 's')
+           ++p;
+    }
+    return res;
+}
+
+/*
+ * The string consists of a sequence of `n unit'
+ */
+
+static int
+acc_units(int res, int val, unsigned mult)
+{
+    return res + val * mult;
+}
+
+int ROKEN_LIB_FUNCTION
+parse_units (const char *s, const struct units *units,
+            const char *def_unit)
+{
+    return parse_something (s, units, def_unit, acc_units, 0, 0);
+}
+
+/*
+ * The string consists of a sequence of `[+-]flag'.  `orig' consists
+ * the original set of flags, those are then modified and returned as
+ * the function value.
+ */
+
+static int
+acc_flags(int res, int val, unsigned mult)
+{
+    if(val == 1)
+       return res | mult;
+    else if(val == -1)
+       return res & ~mult;
+    else if (val == 0)
+       return mult;
+    else
+       return -1;
+}
+
+int ROKEN_LIB_FUNCTION
+parse_flags (const char *s, const struct units *units,
+            int orig)
+{
+    return parse_something (s, units, NULL, acc_flags, orig, 1);
+}
+
+/*
+ * Return a string representation according to `units' of `num' in `s'
+ * with maximum length `len'.  The actual length of the returned string
+ * is the returned value.
+ */
+
+static int
+unparse_something (int num, const struct units *units, char *s, size_t len,
+                  int (*print) (char *, size_t, int, const char *, int),
+                  int (*update) (int, unsigned),
+                  const char *zero_string)
+{
+    const struct units *u;
+    int ret = 0, tmp;
+
+    /* snprintf doesn't nul terminate on 0 length */   
+    if (len == 0)
+       return(0);
+
+    if (num == 0) {
+       (void) snprintf (s, len, "%s", zero_string);
+       return(strlen(s));
+    }
+
+    for (u = units; num > 0 && u->name; ++u) {
+       int divisor;
+
+       divisor = num / u->mult;
+       if (divisor) {
+           num = (*update) (num, u->mult);
+           tmp = (*print) (s, len, divisor, u->name, num);
+           if (tmp < 0)
+               return tmp;
+           if (tmp > len) {
+               len = 0;
+               s = NULL;
+           } else {
+               len -= tmp;
+               s += tmp;
+           }
+           ret += tmp;
+       }
+    }
+    return ret;
+}
+
+static int
+print_unit (char *s, size_t len, int divisor, const char *name, int rem)
+{
+    return snprintf (s, len, "%u %s%s%s",
+                    divisor, name,
+                    divisor == 1 ? "" : "s",
+                    rem > 0 ? " " : "");
+}
+
+static int
+update_unit (int in, unsigned mult)
+{
+    return in % mult;
+}
+
+static int
+update_unit_approx (int in, unsigned mult)
+{
+    if (in / mult > 0)
+       return 0;
+    else
+       return update_unit (in, mult);
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_units (int num, const struct units *units, char *s, size_t len)
+{
+    return unparse_something (num, units, s, len,
+                             print_unit,
+                             update_unit,
+                             "0");
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_units_approx (int num, const struct units *units, char *s, size_t len)
+{
+    return unparse_something (num, units, s, len,
+                             print_unit,
+                             update_unit_approx,
+                             "0");
+}
+
+void ROKEN_LIB_FUNCTION
+print_units_table (const struct units *units, FILE *f)
+{
+    const struct units *u, *u2;
+    unsigned max_sz = 0;
+
+    for (u = units; u->name; ++u) {
+       max_sz = max(max_sz, strlen(u->name));
+    }
+
+    for (u = units; u->name;) {
+       char buf[1024];
+       const struct units *next;
+
+       for (next = u + 1; next->name && next->mult == u->mult; ++next)
+           ;
+
+       if (next->name) {
+           for (u2 = next;
+                u2->name && u->mult % u2->mult != 0;
+                ++u2)
+               ;
+           if (u2->name == NULL)
+               --u2;
+           unparse_units (u->mult, u2, buf, sizeof(buf));
+           fprintf (f, "1 %*s = %s\n", max_sz, u->name, buf);
+       } else {
+           fprintf (f, "1 %s\n", u->name);
+       }
+       u = next;
+    }
+}
+
+static int
+print_flag (char *s, size_t len, int divisor, const char *name, int rem)
+{
+    if (len == 0)
+       return(0);      
+    (void) snprintf (s, len, "%s%s", name, rem > 0 ? ", " : "");
+    return(strlen(s));
+}
+
+static int
+update_flag (int in, unsigned mult)
+{
+    return in - mult;
+}
+
+int ROKEN_LIB_FUNCTION
+unparse_flags (int num, const struct units *units, char *s, size_t len)
+{
+    return unparse_something (num, units, s, len,
+                             print_flag,
+                             update_flag,
+                             "");
+}
+
+void ROKEN_LIB_FUNCTION
+print_flags_table (const struct units *units, FILE *f)
+{
+    const struct units *u;
+
+    for(u = units; u->name; ++u)
+       fprintf(f, "%s%s", u->name, (u+1)->name ? ", " : "\n");
+}
diff --git a/src/kerberosV/src/lib/roken/parse_units.h b/src/kerberosV/src/lib/roken/parse_units.h
new file mode 100644 (file)
index 0000000..957782d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1997 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: parse_units.h,v 1.9 2005/04/12 11:28:59 lha Exp $ */
+
+#ifndef __PARSE_UNITS_H__
+#define __PARSE_UNITS_H__
+
+#include <stdio.h>
+#include <stddef.h>
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+struct units {
+    const char *name;
+    unsigned mult;
+};
+
+int ROKEN_LIB_FUNCTION
+parse_units (const char *s, const struct units *units,
+            const char *def_unit);
+
+void ROKEN_LIB_FUNCTION
+print_units_table (const struct units *units, FILE *f);
+
+int ROKEN_LIB_FUNCTION
+parse_flags (const char *s, const struct units *units,
+            int orig);
+
+int ROKEN_LIB_FUNCTION
+unparse_units (int num, const struct units *units, char *s, size_t len);
+
+int ROKEN_LIB_FUNCTION
+unparse_units_approx (int num, const struct units *units, char *s,
+                     size_t len);
+
+int ROKEN_LIB_FUNCTION
+unparse_flags (int num, const struct units *units, char *s, size_t len);
+
+void ROKEN_LIB_FUNCTION
+print_flags_table (const struct units *units, FILE *f);
+
+#endif /* __PARSE_UNITS_H__ */
diff --git a/src/kerberosV/src/lib/roken/print_version.c b/src/kerberosV/src/lib/roken/print_version.c
new file mode 100644 (file)
index 0000000..ffe7f58
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1998 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: print_version.c,v 1.9 2005/04/12 11:29:00 lha Exp $");
+#endif
+#include "roken.h"
+
+#include "print_version.h"
+
+extern char *__progname;
+
+void ROKEN_LIB_FUNCTION
+print_version(const char *progname)
+{
+    const char *arg[] = VERSIONLIST;
+    const int num_args = sizeof(arg) / sizeof(arg[0]);
+    char *msg;
+    size_t len = 0;
+    int i;
+    
+    if(progname == NULL)
+       progname = __progname;
+    
+    if(num_args == 0)
+       msg = "no version information";
+    else {
+       for(i = 0; i < num_args; i++) {
+           if(i > 0)
+               len += 2;
+           len += strlen(arg[i]);
+       }
+       msg = malloc(len + 1);
+       if(msg == NULL) {
+           fprintf(stderr, "%s: out of memory\n", progname);
+           return;
+       }
+       msg[0] = '\0';
+       for(i = 0; i < num_args; i++) {
+           if(i > 0)
+               strlcat(msg, ", ", len+1);
+           strlcat(msg, arg[i], len+1);
+       }
+    }
+    fprintf(stderr, "%s (%s)\n", progname, msg);
+    fprintf(stderr, "Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan\n");
+    if(num_args != 0)
+       free(msg);
+}
diff --git a/src/kerberosV/src/lib/roken/putenv.c b/src/kerberosV/src/lib/roken/putenv.c
new file mode 100644 (file)
index 0000000..c9f4027
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: putenv.c,v 1.8 2005/04/12 11:29:00 lha Exp $");
+#endif
+
+#include <stdlib.h>
+
+extern char **environ;
+
+/*
+ * putenv --
+ *     String points to a string of the form name=value.
+ *
+ *      Makes the value of the environment variable name equal to
+ *      value by altering an existing variable or creating a new one.
+ */
+
+int ROKEN_LIB_FUNCTION
+putenv(const char *string)
+{
+    int i;
+    const char *eq = (const char *)strchr(string, '=');
+    int len;
+    
+    if (eq == NULL)
+       return 1;
+    len = eq - string;
+
+    if(environ == NULL) {
+       environ = malloc(sizeof(char*));
+       if(environ == NULL)
+           return 1;
+       environ[0] = NULL;
+    }
+
+    for(i = 0; environ[i] != NULL; i++)
+       if(strncmp(string, environ[i], len) == 0) {
+           environ[i] = string;
+           return 0;
+       }
+    environ = realloc(environ, sizeof(char*) * (i + 2));
+    if(environ == NULL)
+       return 1;
+    environ[i]   = string;
+    environ[i+1] = NULL;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/rcmd.c b/src/kerberosV/src/lib/roken/rcmd.c
new file mode 100644 (file)
index 0000000..735029a
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: rcmd.c,v 1.4 2005/04/12 11:29:00 lha Exp $");
+#endif
+
+#include "roken.h"
+#include <stdio.h>
+
+int ROKEN_LIB_FUNCTION
+rcmd(char **ahost,
+     unsigned short inport,
+     const char *locuser,
+     const char *remuser,
+     const char *cmd,
+     int *fd2p)
+{
+  fprintf(stderr, "Only kerberized services are implemented\n");
+  return -1;
+}
diff --git a/src/kerberosV/src/lib/roken/readv.c b/src/kerberosV/src/lib/roken/readv.c
new file mode 100644 (file)
index 0000000..320eca4
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: readv.c,v 1.6 2005/04/12 11:29:01 lha Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+readv(int d, const struct iovec *iov, int iovcnt)
+{
+    ssize_t ret, nb;
+    size_t tot = 0;
+    int i;
+    char *buf, *p;
+
+    for(i = 0; i < iovcnt; ++i)
+       tot += iov[i].iov_len;
+    buf = malloc(tot);
+    if (tot != 0 && buf == NULL) {
+       errno = ENOMEM;
+       return -1;
+    }
+    nb = ret = read (d, buf, tot);
+    p = buf;
+    while (nb > 0) {
+       ssize_t cnt = min(nb, iov->iov_len);
+
+       memcpy (iov->iov_base, p, cnt);
+       p += cnt;
+       nb -= cnt;
+    }
+    free(buf);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/realloc.c b/src/kerberosV/src/lib/roken/realloc.c
new file mode 100644 (file)
index 0000000..33e898c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#undef realloc
+#endif
+#include <stdlib.h>
+#include "roken.h"
+
+RCSID("$Id");
+
+
+void * ROKEN_LIB_FUNCTION
+rk_realloc(void *ptr, size_t size)
+{
+    if (ptr == NULL)
+       return malloc(size);
+    return realloc(ptr, size);
+}
diff --git a/src/kerberosV/src/lib/roken/recvmsg.c b/src/kerberosV/src/lib/roken/recvmsg.c
new file mode 100644 (file)
index 0000000..7ede3e8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: recvmsg.c,v 1.6 2005/04/12 11:29:01 lha Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+recvmsg(int s, struct msghdr *msg, int flags)
+{
+    ssize_t ret, nb;
+    size_t tot = 0;
+    int i;
+    char *buf, *p;
+    struct iovec *iov = msg->msg_iov;
+
+    for(i = 0; i < msg->msg_iovlen; ++i)
+       tot += iov[i].iov_len;
+    buf = malloc(tot);
+    if (tot != 0 && buf == NULL) {
+       errno = ENOMEM;
+       return -1;
+    }
+    nb = ret = recvfrom (s, buf, tot, flags, msg->msg_name, &msg->msg_namelen);
+    p = buf;
+    while (nb > 0) {
+       ssize_t cnt = min(nb, iov->iov_len);
+
+       memcpy (iov->iov_base, p, cnt);
+       p += cnt;
+       nb -= cnt;
+       ++iov;
+    }
+    free(buf);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/resolve-test.c b/src/kerberosV/src/lib/roken/resolve-test.c
new file mode 100644 (file)
index 0000000..87fd9d2
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 1995 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#include "getarg.h"
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#include "resolve.h"
+
+RCSID("$KTH: resolve-test.c,v 1.4 2005/04/10 19:00:02 lha Exp $");
+
+static int version_flag = 0;
+static int help_flag   = 0;
+
+static struct getargs args[] = {
+    {"version",        0,      arg_flag,       &version_flag,
+     "print version", NULL },
+    {"help",   0,      arg_flag,       &help_flag,
+     NULL, NULL }
+};
+
+static void
+usage (int ret)
+{
+    arg_printusage (args,
+                   sizeof(args)/sizeof(*args),
+                   NULL,
+                   "dns-record resource-record-type");
+    exit (ret);
+}
+
+int
+main(int argc, char **argv)
+{
+    struct dns_reply *r;
+    struct resource_record *rr;
+    int optind = 0;
+
+    setprogname (argv[0]);
+
+    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optind))
+       usage(1);
+    
+    if (help_flag)
+       usage (0);
+
+    if(version_flag){
+       printf("some version\n");
+       exit(0);
+    }
+
+    argc -= optind;
+    argv += optind;
+
+    if (argc != 2)
+       usage(1);
+
+    r = dns_lookup(argv[0], argv[1]);
+    if(r == NULL){
+       printf("No reply.\n");
+       return 1;
+    }
+    if(r->q.type == rk_ns_t_srv)
+       dns_srv_order(r);
+
+    for(rr = r->head; rr;rr=rr->next){
+       printf("%-30s %-5s %-6d ", rr->domain, dns_type_to_string(rr->type), rr->ttl);
+       switch(rr->type){
+       case rk_ns_t_ns:
+       case rk_ns_t_cname:
+       case rk_ns_t_ptr:
+           printf("%s\n", (char*)rr->u.data);
+           break;
+       case rk_ns_t_a:
+           printf("%s\n", inet_ntoa(*rr->u.a));
+           break;
+       case rk_ns_t_mx:
+       case rk_ns_t_afsdb:{
+           printf("%d %s\n", rr->u.mx->preference, rr->u.mx->domain);
+           break;
+       }
+       case rk_ns_t_srv:{
+           struct srv_record *srv = rr->u.srv;
+           printf("%d %d %d %s\n", srv->priority, srv->weight, 
+                  srv->port, srv->target);
+           break;
+       }
+       case rk_ns_t_txt: {
+           printf("%s\n", rr->u.txt);
+           break;
+       }
+       case rk_ns_t_sig : {
+           struct sig_record *sig = rr->u.sig;
+           const char *type_string = dns_type_to_string (sig->type);
+
+           printf ("type %u (%s), algorithm %u, labels %u, orig_ttl %u, sig_expiration %u, sig_inception %u, key_tag %u, signer %s\n",
+                   sig->type, type_string ? type_string : "",
+                   sig->algorithm, sig->labels, sig->orig_ttl,
+                   sig->sig_expiration, sig->sig_inception, sig->key_tag,
+                   sig->signer);
+           break;
+       }
+       case rk_ns_t_key : {
+           struct key_record *key = rr->u.key;
+
+           printf ("flags %u, protocol %u, algorithm %u\n",
+                   key->flags, key->protocol, key->algorithm);
+           break;
+       }
+       case rk_ns_t_sshfp : {
+           struct sshfp_record *sshfp = rr->u.sshfp;
+           int i;
+
+           printf ("alg %u type %u length %lu data ", sshfp->algorithm, 
+                   sshfp->type,  (unsigned long)sshfp->sshfp_len);
+           for (i = 0; i < sshfp->sshfp_len; i++)
+               printf("%02X", sshfp->sshfp_data[i]);
+           printf("\n");
+
+           break;
+       }
+       case rk_ns_t_ds : {
+           struct ds_record *ds = rr->u.ds;
+           int i;
+
+           printf ("key tag %u alg %u type %u length %u data ",
+                   ds->key_tag, ds->algorithm, ds->digest_type, 
+                   ds->digest_len);
+           for (i = 0; i < ds->digest_len; i++)
+               printf("%02X", ds->digest_data[i]);
+           printf("\n");
+
+           break;
+       }
+       default:
+           printf("\n");
+           break;
+       }
+    }
+    
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/resolve.c b/src/kerberosV/src/lib/roken/resolve.c
new file mode 100644 (file)
index 0000000..0db6bc3
--- /dev/null
@@ -0,0 +1,690 @@
+/*
+ * Copyright (c) 1995 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#include "resolve.h"
+
+#include <assert.h>
+
+RCSID("$KTH: resolve.c,v 1.50 2005/04/12 11:29:01 lha Exp $");
+
+#ifdef _AIX /* AIX have broken res_nsearch() in 5.1 (5.0 also ?) */
+#undef HAVE_RES_NSEARCH
+#endif
+
+#define DECL(X) {#X, rk_ns_t_##X}
+
+static struct stot{
+    const char *name;
+    int type;
+}stot[] = {
+    DECL(a),
+    DECL(aaaa),
+    DECL(ns),
+    DECL(cname),
+    DECL(soa),
+    DECL(ptr),
+    DECL(mx),
+    DECL(txt),
+    DECL(afsdb),
+    DECL(sig),
+    DECL(key),
+    DECL(srv),
+    DECL(naptr),
+    DECL(sshfp),
+    DECL(ds),
+    {NULL,     0}
+};
+
+int _resolve_debug = 0;
+
+int ROKEN_LIB_FUNCTION
+dns_string_to_type(const char *name)
+{
+    struct stot *p = stot;
+    for(p = stot; p->name; p++)
+       if(strcasecmp(name, p->name) == 0)
+           return p->type;
+    return -1;
+}
+
+const char * ROKEN_LIB_FUNCTION
+dns_type_to_string(int type)
+{
+    struct stot *p = stot;
+    for(p = stot; p->name; p++)
+       if(type == p->type)
+           return p->name;
+    return NULL;
+}
+
+#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)
+
+void ROKEN_LIB_FUNCTION
+dns_free_data(struct dns_reply *r)
+{
+    struct resource_record *rr;
+    if(r->q.domain)
+       free(r->q.domain);
+    for(rr = r->head; rr;){
+       struct resource_record *tmp = rr;
+       if(rr->domain)
+           free(rr->domain);
+       if(rr->u.data)
+           free(rr->u.data);
+       rr = rr->next;
+       free(tmp);
+    }
+    free (r);
+}
+
+static int
+parse_record(const unsigned char *data, const unsigned char *end_data, 
+            const unsigned char **pp, struct resource_record **rr)
+{
+    int type, class, ttl, size;
+    int status;
+    char host[MAXDNAME];
+    const unsigned char *p = *pp;
+    status = dn_expand(data, end_data, p, host, sizeof(host));
+    if(status < 0) 
+       return -1;
+    if (p + status + 10 > end_data)
+       return -1;
+    p += status;
+    type = (p[0] << 8) | p[1];
+    p += 2;
+    class = (p[0] << 8) | p[1];
+    p += 2;
+    ttl = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+    p += 4;
+    size = (p[0] << 8) | p[1];
+    p += 2;
+
+    if (p + size > end_data)
+       return -1;
+
+    *rr = calloc(1, sizeof(**rr));
+    if(*rr == NULL) 
+       return -1;
+    (*rr)->domain = strdup(host);
+    if((*rr)->domain == NULL) {
+       free(*rr);
+       return -1;
+    }
+    (*rr)->type = type;
+    (*rr)->class = class;
+    (*rr)->ttl = ttl;
+    (*rr)->size = size;
+    switch(type){
+    case rk_ns_t_ns:
+    case rk_ns_t_cname:
+    case rk_ns_t_ptr:
+       status = dn_expand(data, end_data, p, host, sizeof(host));
+       if(status < 0) {
+           free(*rr);
+           return -1;
+       }
+       (*rr)->u.txt = strdup(host);
+       if((*rr)->u.txt == NULL) {
+           free(*rr);
+           return -1;
+       }
+       break;
+    case rk_ns_t_mx:
+    case rk_ns_t_afsdb:{
+       size_t hostlen;
+
+       status = dn_expand(data, end_data, p + 2, host, sizeof(host));
+       if(status < 0){
+           free(*rr);
+           return -1;
+       }
+       if (status + 2 > size) {
+           free(*rr);
+           return -1;
+       }
+
+       hostlen = strlen(host);
+       (*rr)->u.mx = (struct mx_record*)malloc(sizeof(struct mx_record) + 
+                                               hostlen);
+       if((*rr)->u.mx == NULL) {
+           free(*rr);
+           return -1;
+       }
+       (*rr)->u.mx->preference = (p[0] << 8) | p[1];
+       strlcpy((*rr)->u.mx->domain, host, hostlen + 1);
+       break;
+    }
+    case rk_ns_t_srv:{
+       size_t hostlen;
+       status = dn_expand(data, end_data, p + 6, host, sizeof(host));
+       if(status < 0){
+           free(*rr);
+           return -1;
+       }
+       if (status + 6 > size) {
+           free(*rr);
+           return -1;
+       }
+
+       hostlen = strlen(host);
+       (*rr)->u.srv = 
+           (struct srv_record*)malloc(sizeof(struct srv_record) + 
+                                      hostlen);
+       if((*rr)->u.srv == NULL) {
+           free(*rr);
+           return -1;
+       }
+       (*rr)->u.srv->priority = (p[0] << 8) | p[1];
+       (*rr)->u.srv->weight = (p[2] << 8) | p[3];
+       (*rr)->u.srv->port = (p[4] << 8) | p[5];
+       strlcpy((*rr)->u.srv->target, host, hostlen + 1);
+       break;
+    }
+    case rk_ns_t_txt:{
+       if(size == 0 || size < *p + 1) {
+           free(*rr);
+           return -1;
+       }
+       (*rr)->u.txt = (char*)malloc(*p + 1);
+       if((*rr)->u.txt == NULL) {
+           free(*rr);
+           return -1;
+       }
+       strncpy((*rr)->u.txt, (char*)p + 1, *p);
+       (*rr)->u.txt[*p] = '\0';
+       break;
+    }
+    case rk_ns_t_key : {
+       size_t key_len;
+
+       if (size < 4) {
+           free(*rr);
+           return -1;
+       }
+
+       key_len = size - 4;
+       (*rr)->u.key = malloc (sizeof(*(*rr)->u.key) + key_len - 1);
+       if ((*rr)->u.key == NULL) {
+           free(*rr);
+           return -1;
+       }
+
+       (*rr)->u.key->flags     = (p[0] << 8) | p[1];
+       (*rr)->u.key->protocol  = p[2];
+       (*rr)->u.key->algorithm = p[3];
+       (*rr)->u.key->key_len   = key_len;
+       memcpy ((*rr)->u.key->key_data, p + 4, key_len);
+       break;
+    }
+    case rk_ns_t_sig : {
+       size_t sig_len, hostlen;
+
+       if(size <= 18) {
+           free(*rr);
+           return -1;
+       }
+       status = dn_expand (data, end_data, p + 18, host, sizeof(host));
+       if (status < 0) {
+           free(*rr);
+           return -1;
+       }
+       if (status + 18 > size) {
+           free(*rr);
+           return -1;
+       }
+
+       /* the signer name is placed after the sig_data, to make it
+           easy to free this struture; the size calculation below
+           includes the zero-termination if the structure itself.
+          don't you just love C?
+       */
+       sig_len = size - 18 - status;
+       hostlen = strlen(host);
+       (*rr)->u.sig = malloc(sizeof(*(*rr)->u.sig)
+                             + hostlen + sig_len);
+       if ((*rr)->u.sig == NULL) {
+           free(*rr);
+           return -1;
+       }
+       (*rr)->u.sig->type           = (p[0] << 8) | p[1];
+       (*rr)->u.sig->algorithm      = p[2];
+       (*rr)->u.sig->labels         = p[3];
+       (*rr)->u.sig->orig_ttl       = (p[4] << 24) | (p[5] << 16)
+           | (p[6] << 8) | p[7];
+       (*rr)->u.sig->sig_expiration = (p[8] << 24) | (p[9] << 16)
+           | (p[10] << 8) | p[11];
+       (*rr)->u.sig->sig_inception  = (p[12] << 24) | (p[13] << 16)
+           | (p[14] << 8) | p[15];
+       (*rr)->u.sig->key_tag        = (p[16] << 8) | p[17];
+       (*rr)->u.sig->sig_len        = sig_len;
+       memcpy ((*rr)->u.sig->sig_data, p + 18 + status, sig_len);
+       (*rr)->u.sig->signer         = &(*rr)->u.sig->sig_data[sig_len];
+       strlcpy((*rr)->u.sig->signer, host, hostlen + 1);
+       break;
+    }
+
+    case rk_ns_t_cert : {
+       size_t cert_len;
+
+       if (size < 5) {
+           free(*rr);
+           return -1;
+       }
+
+       cert_len = size - 5;
+       (*rr)->u.cert = malloc (sizeof(*(*rr)->u.cert) + cert_len - 1);
+       if ((*rr)->u.cert == NULL) {
+           free(*rr);
+           return -1;
+       }
+
+       (*rr)->u.cert->type      = (p[0] << 8) | p[1];
+       (*rr)->u.cert->tag       = (p[2] << 8) | p[3];
+       (*rr)->u.cert->algorithm = p[4];
+       (*rr)->u.cert->cert_len  = cert_len;
+       memcpy ((*rr)->u.cert->cert_data, p + 5, cert_len);
+       break;
+    }
+    case rk_ns_t_sshfp : {
+       size_t sshfp_len;
+
+       if (size < 2) {
+           free(*rr);
+           return -1;
+       }
+
+       sshfp_len = size - 2;
+
+       (*rr)->u.sshfp = malloc (sizeof(*(*rr)->u.sshfp) + sshfp_len - 1);
+       if ((*rr)->u.sshfp == NULL) {
+           free(*rr);
+           return -1;
+       }
+
+       (*rr)->u.sshfp->algorithm = p[0];
+       (*rr)->u.sshfp->type      = p[1];
+       (*rr)->u.sshfp->sshfp_len  = sshfp_len;
+       memcpy ((*rr)->u.sshfp->sshfp_data, p + 2, sshfp_len);
+       break;
+    }
+    case rk_ns_t_ds: {
+       size_t digest_len;
+
+       if (size < 4) {
+           free(*rr);
+           return -1;
+       }
+
+       digest_len = size - 4;
+
+       (*rr)->u.ds = malloc (sizeof(*(*rr)->u.ds) + digest_len - 1);
+       if ((*rr)->u.ds == NULL) {
+           free(*rr);
+           return -1;
+       }
+
+       (*rr)->u.ds->key_tag     = (p[0] << 8) | p[1];
+       (*rr)->u.ds->algorithm   = p[2];
+       (*rr)->u.ds->digest_type = p[3];
+       (*rr)->u.ds->digest_len  = digest_len;
+       memcpy ((*rr)->u.ds->digest_data, p + 4, digest_len);
+       break;
+    }
+    default:
+       (*rr)->u.data = (unsigned char*)malloc(size);
+       if(size != 0 && (*rr)->u.data == NULL) {
+           free(*rr);
+           return -1;
+       }
+       memcpy((*rr)->u.data, p, size);
+    }
+    *pp = p + size;
+    return 0;
+}
+
+#ifndef TEST_RESOLVE
+static
+#endif
+struct dns_reply*
+parse_reply(const unsigned char *data, size_t len)
+{
+    const unsigned char *p;
+    int status;
+    int i;
+    char host[MAXDNAME];
+    const unsigned char *end_data = data + len;
+    struct dns_reply *r;
+    struct resource_record **rr;
+    
+    r = calloc(1, sizeof(*r));
+    if (r == NULL)
+       return NULL;
+
+    p = data;
+
+    r->h.id = (p[0] << 8) | p[1];
+    r->h.flags = 0;
+    if (p[2] & 0x01)
+       r->h.flags |= rk_DNS_HEADER_RESPONSE_FLAG;
+    r->h.opcode = (p[2] >> 1) & 0xf;
+    if (p[2] & 0x20)
+       r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
+    if (p[2] & 0x40)
+       r->h.flags |= rk_DNS_HEADER_TRUNCATED_MESSAGE;
+    if (p[2] & 0x80)
+       r->h.flags |= rk_DNS_HEADER_RECURSION_DESIRED;
+    if (p[3] & 0x01)
+       r->h.flags |= rk_DNS_HEADER_RECURSION_AVAILABLE;
+    if (p[3] & 0x04)
+       r->h.flags |= rk_DNS_HEADER_AUTHORITIVE_ANSWER;
+    if (p[3] & 0x08)
+       r->h.flags |= rk_DNS_HEADER_CHECKING_DISABLED;
+    r->h.response_code = (p[3] >> 4) & 0xf;
+    r->h.qdcount = (p[4] << 8) | p[5];
+    r->h.ancount = (p[6] << 8) | p[7];
+    r->h.nscount = (p[8] << 8) | p[9];
+    r->h.arcount = (p[10] << 8) | p[11];
+
+    p += 12;
+
+    if(r->h.qdcount != 1) {
+       free(r);
+       return NULL;
+    }
+    status = dn_expand(data, end_data, p, host, sizeof(host));
+    if(status < 0){
+       dns_free_data(r);
+       return NULL;
+    }
+    r->q.domain = strdup(host);
+    if(r->q.domain == NULL) {
+       dns_free_data(r);
+       return NULL;
+    }
+    if (p + status + 4 > end_data) {
+       dns_free_data(r);
+       return NULL;
+    }
+    p += status;
+    r->q.type = (p[0] << 8 | p[1]);
+    p += 2;
+    r->q.class = (p[0] << 8 | p[1]);
+    p += 2;
+    
+    rr = &r->head;
+    for(i = 0; i < r->h.ancount; i++) {
+       if(parse_record(data, end_data, &p, rr) != 0) {
+           dns_free_data(r);
+           return NULL;
+       }
+       rr = &(*rr)->next;
+    }
+    for(i = 0; i < r->h.nscount; i++) {
+       if(parse_record(data, end_data, &p, rr) != 0) {
+           dns_free_data(r);
+           return NULL;
+       }
+       rr = &(*rr)->next;
+    }
+    for(i = 0; i < r->h.arcount; i++) {
+       if(parse_record(data, end_data, &p, rr) != 0) {
+           dns_free_data(r);
+           return NULL;
+       }
+       rr = &(*rr)->next;
+    }
+    *rr = NULL;
+    return r;
+}
+
+static struct dns_reply *
+dns_lookup_int(const char *domain, int rr_class, int rr_type)
+{
+    struct dns_reply *r;
+    unsigned char *reply = NULL;
+    int size;
+    int len;
+#ifdef HAVE_RES_NSEARCH
+    struct __res_state state;
+    memset(&state, 0, sizeof(state));
+    if(res_ninit(&state))
+       return NULL; /* is this the best we can do? */
+#elif defined(HAVE__RES)
+    u_long old_options = 0;
+#endif
+    
+    size = 0;
+    len = 1000;
+    do {
+       if (reply) {
+           free(reply);
+           reply = NULL;
+       }
+       if (size <= len)
+           size = len;
+       if (_resolve_debug) {
+#ifdef HAVE_RES_NSEARCH
+           state.options |= RES_DEBUG;
+#elif defined(HAVE__RES)
+           old_options = _res.options;
+           _res.options |= RES_DEBUG;
+#endif
+           fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,
+                   rr_class, dns_type_to_string(rr_type), size);
+       }
+       reply = malloc(size);
+       if (reply == NULL) {
+#ifdef HAVE_RES_NSEARCH
+           res_nclose(&state);
+#endif
+           return NULL;
+       }
+#ifdef HAVE_RES_NSEARCH
+       len = res_nsearch(&state, domain, rr_class, rr_type, reply, size);
+#else
+       len = res_search(domain, rr_class, rr_type, reply, size);
+#endif
+       if (_resolve_debug) {
+#if defined(HAVE__RES) && !defined(HAVE_RES_NSEARCH)
+           _res.options = old_options;
+#endif
+           fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
+                   domain, rr_class, dns_type_to_string(rr_type), len);
+       }
+       if (len < 0) {
+#ifdef HAVE_RES_NSEARCH
+           res_nclose(&state);
+#endif
+           free(reply);
+           return NULL;
+       }
+    } while (size < len && len < rk_DNS_MAX_PACKET_SIZE);
+#ifdef HAVE_RES_NSEARCH
+    res_nclose(&state);
+#endif
+
+    len = min(len, size);
+    r = parse_reply(reply, len);
+    free(reply);
+    return r;
+}
+
+struct dns_reply * ROKEN_LIB_FUNCTION
+dns_lookup(const char *domain, const char *type_name)
+{
+    int type;
+    
+    type = dns_string_to_type(type_name);
+    if(type == -1) {
+       if(_resolve_debug)
+           fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n", 
+                   type_name);
+       return NULL;
+    }
+    return dns_lookup_int(domain, C_IN, type);
+}
+
+static int
+compare_srv(const void *a, const void *b)
+{
+    const struct resource_record *const* aa = a, *const* bb = b;
+
+    if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
+       return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
+    return ((*aa)->u.srv->priority - (*bb)->u.srv->priority);
+}
+
+#ifndef HAVE_RANDOM
+#define random() rand()
+#endif
+
+/* try to rearrange the srv-records by the algorithm in RFC2782 */
+void ROKEN_LIB_FUNCTION
+dns_srv_order(struct dns_reply *r)
+{
+    struct resource_record **srvs, **ss, **headp;
+    struct resource_record *rr;
+    int num_srv = 0;
+
+#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
+    int state[256 / sizeof(int)];
+    char *oldstate;
+#endif
+
+    for(rr = r->head; rr; rr = rr->next) 
+       if(rr->type == rk_ns_t_srv)
+           num_srv++;
+
+    if(num_srv == 0)
+       return;
+
+    srvs = malloc(num_srv * sizeof(*srvs));
+    if(srvs == NULL)
+       return; /* XXX not much to do here */
+    
+    /* unlink all srv-records from the linked list and put them in
+       a vector */
+    for(ss = srvs, headp = &r->head; *headp; )
+       if((*headp)->type == rk_ns_t_srv) {
+           *ss = *headp;
+           *headp = (*headp)->next;
+           (*ss)->next = NULL;
+           ss++;
+       } else
+           headp = &(*headp)->next;
+    
+    /* sort them by priority and weight */
+    qsort(srvs, num_srv, sizeof(*srvs), compare_srv);
+
+#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
+    oldstate = initstate(time(NULL), (char*)state, sizeof(state));
+#endif
+
+    headp = &r->head;
+    
+    for(ss = srvs; ss < srvs + num_srv; ) {
+       int sum, rnd, count;
+       struct resource_record **ee, **tt;
+       /* find the last record with the same priority and count the
+           sum of all weights */
+       for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
+           if(*tt == NULL)
+               continue;
+           if((*tt)->u.srv->priority != (*ss)->u.srv->priority)
+               break;
+           sum += (*tt)->u.srv->weight;
+       }
+       ee = tt;
+       /* ss is now the first record of this priority and ee is the
+           first of the next */
+       while(ss < ee) {
+           rnd = random() % (sum + 1);
+           for(count = 0, tt = ss; ; tt++) {
+               if(*tt == NULL)
+                   continue;
+               count += (*tt)->u.srv->weight;
+               if(count >= rnd)
+                   break;
+           }
+
+           assert(tt < ee);
+
+           /* insert the selected record at the tail (of the head) of
+               the list */
+           (*tt)->next = *headp;
+           *headp = *tt;
+           headp = &(*tt)->next;
+           sum -= (*tt)->u.srv->weight;
+           *tt = NULL;
+           while(ss < ee && *ss == NULL)
+               ss++;
+       }
+    }
+    
+#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
+    setstate(oldstate);
+#endif
+    free(srvs);
+    return;
+}
+
+#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
+
+struct dns_reply * ROKEN_LIB_FUNCTION
+dns_lookup(const char *domain, const char *type_name)
+{
+    return NULL;
+}
+
+void ROKEN_LIB_FUNCTION
+dns_free_data(struct dns_reply *r)
+{
+}
+
+void ROKEN_LIB_FUNCTION
+dns_srv_order(struct dns_reply *r)
+{
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/resolve.h b/src/kerberosV/src/lib/roken/resolve.h
new file mode 100644 (file)
index 0000000..cda489e
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1995 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: resolve.h,v 1.24 2005/04/12 11:29:02 lha Exp $ */
+
+#ifndef __RESOLVE_H__
+#define __RESOLVE_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+typedef enum {
+       rk_ns_t_invalid = 0,    /* Cookie. */
+       rk_ns_t_a = 1,          /* Host address. */
+       rk_ns_t_ns = 2,         /* Authoritative server. */
+       rk_ns_t_md = 3,         /* Mail destination. */
+       rk_ns_t_mf = 4,         /* Mail forwarder. */
+       rk_ns_t_cname = 5,      /* Canonical name. */
+       rk_ns_t_soa = 6,        /* Start of authority zone. */
+       rk_ns_t_mb = 7,         /* Mailbox domain name. */
+       rk_ns_t_mg = 8,         /* Mail group member. */
+       rk_ns_t_mr = 9,         /* Mail rename name. */
+       rk_ns_t_null = 10,      /* Null resource record. */
+       rk_ns_t_wks = 11,       /* Well known service. */
+       rk_ns_t_ptr = 12,       /* Domain name pointer. */
+       rk_ns_t_hinfo = 13,     /* Host information. */
+       rk_ns_t_minfo = 14,     /* Mailbox information. */
+       rk_ns_t_mx = 15,        /* Mail routing information. */
+       rk_ns_t_txt = 16,       /* Text strings. */
+       rk_ns_t_rp = 17,        /* Responsible person. */
+       rk_ns_t_afsdb = 18,     /* AFS cell database. */
+       rk_ns_t_x25 = 19,       /* X_25 calling address. */
+       rk_ns_t_isdn = 20,      /* ISDN calling address. */
+       rk_ns_t_rt = 21,        /* Router. */
+       rk_ns_t_nsap = 22,      /* NSAP address. */
+       rk_ns_t_nsap_ptr = 23,  /* Reverse NSAP lookup (deprecated). */
+       rk_ns_t_sig = 24,       /* Security signature. */
+       rk_ns_t_key = 25,       /* Security key. */
+       rk_ns_t_px = 26,        /* X.400 mail mapping. */
+       rk_ns_t_gpos = 27,      /* Geographical position (withdrawn). */
+       rk_ns_t_aaaa = 28,      /* Ip6 Address. */
+       rk_ns_t_loc = 29,       /* Location Information. */
+       rk_ns_t_nxt = 30,       /* Next domain (security). */
+       rk_ns_t_eid = 31,       /* Endpoint identifier. */
+       rk_ns_t_nimloc = 32,    /* Nimrod Locator. */
+       rk_ns_t_srv = 33,       /* Server Selection. */
+       rk_ns_t_atma = 34,      /* ATM Address */
+       rk_ns_t_naptr = 35,     /* Naming Authority PoinTeR */
+       rk_ns_t_kx = 36,        /* Key Exchange */
+       rk_ns_t_cert = 37,      /* Certification record */
+       rk_ns_t_a6 = 38,        /* IPv6 address (deprecates AAAA) */
+       rk_ns_t_dname = 39,     /* Non-terminal DNAME (for IPv6) */
+       rk_ns_t_sink = 40,      /* Kitchen sink (experimentatl) */
+       rk_ns_t_opt = 41,       /* EDNS0 option (meta-RR) */
+       rk_ns_t_apl = 42,       /* Address prefix list (RFC 3123) */
+       rk_ns_t_ds = 43,        /* Delegation Signer (RFC 3658) */
+       rk_ns_t_sshfp = 44,     /* SSH fingerprint */
+       rk_ns_t_tkey = 249,     /* Transaction key */
+       rk_ns_t_tsig = 250,     /* Transaction signature. */
+       rk_ns_t_ixfr = 251,     /* Incremental zone transfer. */
+       rk_ns_t_axfr = 252,     /* Transfer zone of authority. */
+       rk_ns_t_mailb = 253,    /* Transfer mailbox records. */
+       rk_ns_t_maila = 254,    /* Transfer mail agent records. */
+       rk_ns_t_any = 255,      /* Wildcard match. */
+       rk_ns_t_zxfr = 256,     /* BIND-specific, nonstandard. */
+       rk_ns_t_max = 65536
+} rk_ns_type;
+
+/* We use these, but they are not always present in <arpa/nameser.h> */
+
+#ifndef C_IN
+#define C_IN           1
+#endif
+
+#ifndef T_A
+#define T_A            1
+#endif
+#ifndef T_NS
+#define T_NS           2
+#endif
+#ifndef T_CNAME
+#define T_CNAME                5
+#endif
+#ifndef T_SOA
+#define T_SOA          5
+#endif
+#ifndef T_PTR
+#define T_PTR          12
+#endif
+#ifndef T_MX
+#define T_MX           15
+#endif
+#ifndef T_TXT
+#define T_TXT          16
+#endif
+#ifndef T_AFSDB
+#define T_AFSDB                18
+#endif
+#ifndef T_SIG
+#define T_SIG          24
+#endif
+#ifndef T_KEY
+#define T_KEY          25
+#endif
+#ifndef T_AAAA
+#define T_AAAA         28
+#endif
+#ifndef T_SRV
+#define T_SRV          33
+#endif
+#ifndef T_NAPTR
+#define T_NAPTR                35
+#endif
+#ifndef T_CERT
+#define T_CERT         37
+#endif
+#ifndef T_SSHFP
+#define T_SSHFP                44
+#endif
+
+#ifndef MAXDNAME
+#define MAXDNAME       1025
+#endif
+
+#define dns_query              rk_dns_query
+#define mx_record              rk_mx_record
+#define srv_record             rk_srv_record
+#define key_record             rk_key_record
+#define sig_record             rk_sig_record
+#define cert_record            rk_cert_record
+#define sshfp_record           rk_sshfp_record
+#define resource_record                rk_resource_record
+#define dns_reply              rk_dns_reply
+
+#define dns_lookup             rk_dns_lookup
+#define dns_free_data          rk_dns_free_data
+#define dns_string_to_type     rk_dns_string_to_type
+#define dns_type_to_string     rk_dns_type_to_string
+#define dns_srv_order          rk_dns_srv_order
+
+struct dns_query{
+    char *domain;
+    unsigned type;
+    unsigned class;
+};
+
+struct mx_record{
+    unsigned  preference;
+    char domain[1];
+};
+
+struct srv_record{
+    unsigned priority;
+    unsigned weight;
+    unsigned port;
+    char target[1];
+};
+
+struct key_record {
+    unsigned flags;
+    unsigned protocol;
+    unsigned algorithm;
+    size_t   key_len;
+    u_char   key_data[1];
+};
+
+struct sig_record {
+    unsigned type;
+    unsigned algorithm;
+    unsigned labels;
+    unsigned orig_ttl;
+    unsigned sig_expiration;
+    unsigned sig_inception;
+    unsigned key_tag;
+    char     *signer;
+    unsigned sig_len;
+    char     sig_data[1];      /* also includes signer */
+};
+
+struct cert_record {
+    unsigned type;
+    unsigned tag;
+    unsigned algorithm;
+    size_t   cert_len;
+    u_char   cert_data[1];
+};
+
+struct sshfp_record {
+    unsigned algorithm;
+    unsigned type;
+    size_t   sshfp_len;
+    u_char   sshfp_data[1];
+};
+
+struct ds_record {
+    unsigned key_tag;
+    unsigned algorithm;
+    unsigned digest_type;
+    unsigned digest_len;
+    u_char digest_data[1];
+};
+
+struct resource_record{
+    char *domain;
+    unsigned type;
+    unsigned class;
+    unsigned ttl;
+    unsigned size;
+    union {
+       void *data;
+       struct mx_record *mx;
+       struct mx_record *afsdb; /* mx and afsdb are identical */
+       struct srv_record *srv;
+       struct in_addr *a;
+       char *txt;
+       struct key_record *key;
+       struct cert_record *cert;
+       struct sig_record *sig;
+       struct sshfp_record *sshfp;
+       struct ds_record *ds;
+    }u;
+    struct resource_record *next;
+};
+
+#define rk_DNS_MAX_PACKET_SIZE         0xffff
+
+struct dns_header {
+    unsigned id;
+    unsigned flags;
+#define rk_DNS_HEADER_RESPONSE_FLAG            1
+#define rk_DNS_HEADER_AUTHORITIVE_ANSWER       2
+#define rk_DNS_HEADER_TRUNCATED_MESSAGE                4
+#define rk_DNS_HEADER_RECURSION_DESIRED                8
+#define rk_DNS_HEADER_RECURSION_AVAILABLE      16
+#define rk_DNS_HEADER_AUTHENTIC_DATA           32
+#define rk_DNS_HEADER_CHECKING_DISABLED                64
+    unsigned opcode;
+    unsigned response_code;
+    unsigned qdcount;
+    unsigned ancount;
+    unsigned nscount;
+    unsigned arcount;
+};
+
+struct dns_reply{
+    struct dns_header h;
+    struct dns_query q;
+    struct resource_record *head;
+};
+
+
+struct dns_reply* ROKEN_LIB_FUNCTION
+       dns_lookup(const char *, const char *);
+void ROKEN_LIB_FUNCTION
+       dns_free_data(struct dns_reply *);
+int ROKEN_LIB_FUNCTION
+       dns_string_to_type(const char *name);
+const char *ROKEN_LIB_FUNCTION
+       dns_type_to_string(int type);
+void ROKEN_LIB_FUNCTION
+       dns_srv_order(struct dns_reply*);
+
+#endif /* __RESOLVE_H__ */
diff --git a/src/kerberosV/src/lib/roken/resource.h b/src/kerberosV/src/lib/roken/resource.h
new file mode 100644 (file)
index 0000000..01cd01d
--- /dev/null
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}\r
+// Microsoft Developer Studio generated include file.\r
+// Used by roken.rc\r
+//\r
+\r
+// Next default values for new objects\r
+// \r
+#ifdef APSTUDIO_INVOKED\r
+#ifndef APSTUDIO_READONLY_SYMBOLS\r
+#define _APS_NEXT_RESOURCE_VALUE        101\r
+#define _APS_NEXT_COMMAND_VALUE         40001\r
+#define _APS_NEXT_CONTROL_VALUE         1000\r
+#define _APS_NEXT_SYMED_VALUE           101\r
+#endif\r
+#endif\r
diff --git a/src/kerberosV/src/lib/roken/roken-common.h b/src/kerberosV/src/lib/roken/roken-common.h
new file mode 100644 (file)
index 0000000..0e0bcf1
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 1995 - 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: roken-common.h,v 1.56 2005/04/27 12:17:53 lha Exp $ */
+
+#ifndef __ROKEN_COMMON_H__
+#define __ROKEN_COMMON_H__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+#ifdef __cplusplus
+#define ROKEN_CPP_START        extern "C" {
+#define ROKEN_CPP_END  }
+#else
+#define ROKEN_CPP_START
+#define ROKEN_CPP_END
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK 0x7f000001
+#endif
+
+#ifndef SOMAXCONN
+#define SOMAXCONN 5
+#endif
+
+#ifndef STDIN_FILENO
+#define STDIN_FILENO 0
+#endif
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#ifndef STDERR_FILENO
+#define STDERR_FILENO 2
+#endif
+
+#ifndef max
+#define max(a,b) (((a)>(b))?(a):(b))
+#endif
+
+#ifndef min
+#define min(a,b) (((a)<(b))?(a):(b))
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#ifndef LOG_DAEMON
+#define openlog(id,option,facility) openlog((id),(option))
+#define        LOG_DAEMON      0
+#endif
+#ifndef LOG_ODELAY
+#define LOG_ODELAY 0
+#endif
+#ifndef LOG_NDELAY
+#define LOG_NDELAY 0x08
+#endif
+#ifndef LOG_CONS
+#define LOG_CONS 0
+#endif
+#ifndef LOG_AUTH
+#define LOG_AUTH 0
+#endif
+#ifndef LOG_AUTHPRIV
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+
+#ifndef F_OK
+#define F_OK 0
+#endif
+
+#ifndef O_ACCMODE
+#define O_ACCMODE      003
+#endif
+
+#ifndef _PATH_DEV
+#define _PATH_DEV "/dev/"
+#endif
+
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+
+#ifndef _PATH_HEQUIV
+#define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+
+#ifndef _PATH_VARRUN
+#define _PATH_VARRUN "/var/run/"
+#endif
+
+#ifndef _PATH_BSHELL
+#define _PATH_BSHELL "/bin/sh"
+#endif
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN (1024+4)
+#endif
+
+#ifndef SIG_ERR
+#define SIG_ERR ((RETSIGTYPE (*)(int))-1)
+#endif
+
+/*
+ * error code for getipnodeby{name,addr}
+ */
+
+#ifndef HOST_NOT_FOUND
+#define HOST_NOT_FOUND 1
+#endif
+
+#ifndef TRY_AGAIN
+#define TRY_AGAIN 2
+#endif
+
+#ifndef NO_RECOVERY
+#define NO_RECOVERY 3
+#endif
+
+#ifndef NO_DATA
+#define NO_DATA 4
+#endif
+
+#ifndef NO_ADDRESS
+#define NO_ADDRESS NO_DATA
+#endif
+
+/*
+ * error code for getaddrinfo
+ */
+
+#ifndef EAI_NOERROR
+#define EAI_NOERROR    0       /* no error */
+#endif
+
+#ifndef EAI_NONAME
+
+#define EAI_ADDRFAMILY 1       /* address family for nodename not supported */
+#define EAI_AGAIN      2       /* temporary failure in name resolution */
+#define EAI_BADFLAGS   3       /* invalid value for ai_flags */
+#define EAI_FAIL       4       /* non-recoverable failure in name resolution */
+#define EAI_FAMILY     5       /* ai_family not supported */
+#define EAI_MEMORY     6       /* memory allocation failure */
+#define EAI_NODATA     7       /* no address associated with nodename */
+#define EAI_NONAME     8       /* nodename nor servname provided, or not known */
+#define EAI_SERVICE    9       /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE   10      /* ai_socktype not supported */
+#define EAI_SYSTEM     11      /* system error returned in errno */
+
+#endif /* EAI_NONAME */
+
+/* flags for getaddrinfo() */
+
+#ifndef AI_PASSIVE
+#define AI_PASSIVE     0x01
+#define AI_CANONNAME   0x02
+#endif /* AI_PASSIVE */
+
+#ifndef AI_NUMERICHOST
+#define AI_NUMERICHOST 0x04
+#endif
+
+/* flags for getnameinfo() */
+
+#ifndef NI_DGRAM
+#define NI_DGRAM       0x01
+#define NI_NAMEREQD    0x02
+#define NI_NOFQDN      0x04
+#define NI_NUMERICHOST 0x08
+#define NI_NUMERICSERV 0x10
+#endif
+
+/*
+ * constants for getnameinfo
+ */
+
+#ifndef NI_MAXHOST
+#define NI_MAXHOST  1025
+#define NI_MAXSERV    32
+#endif
+
+/*
+ * constants for inet_ntop
+ */
+
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN    16
+#endif
+
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN   46
+#endif
+
+/*
+ * for shutdown(2)
+ */
+
+#ifndef SHUT_RD
+#define SHUT_RD 0
+#endif
+
+#ifndef SHUT_WR
+#define SHUT_WR 1
+#endif
+
+#ifndef SHUT_RDWR
+#define SHUT_RDWR 2
+#endif
+
+#ifndef HAVE___ATTRIBUTE__
+#define __attribute__(x)
+#endif
+
+ROKEN_CPP_START
+
+#ifndef IRIX4 /* fix for compiler bug */
+#ifdef RETSIGTYPE
+typedef RETSIGTYPE (*SigAction)(int);
+SigAction signal(int iSig, SigAction pAction); /* BSD compatible */
+#endif
+#endif
+
+int ROKEN_LIB_FUNCTION
+simple_execve(const char*, char*const[], char*const[]);
+
+int ROKEN_LIB_FUNCTION
+simple_execve_timed(const char *, char *const[], 
+                   char *const [], time_t (*)(void *), 
+                   void *, time_t);
+int ROKEN_LIB_FUNCTION
+simple_execvp(const char*, char *const[]);
+
+int ROKEN_LIB_FUNCTION
+simple_execvp_timed(const char *, char *const[], 
+                   time_t (*)(void *), void *, time_t);
+int ROKEN_LIB_FUNCTION
+simple_execlp(const char*, ...);
+
+int ROKEN_LIB_FUNCTION
+simple_execle(const char*, ...);
+
+int ROKEN_LIB_FUNCTION
+simple_execl(const char *file, ...);
+
+int ROKEN_LIB_FUNCTION
+wait_for_process(pid_t);
+
+int ROKEN_LIB_FUNCTION
+wait_for_process_timed(pid_t, time_t (*)(void *), 
+                                             void *, time_t);
+int ROKEN_LIB_FUNCTION
+pipe_execv(FILE**, FILE**, FILE**, const char*, ...);
+
+void ROKEN_LIB_FUNCTION
+print_version(const char *);
+
+ssize_t ROKEN_LIB_FUNCTION
+eread (int fd, void *buf, size_t nbytes);
+
+ssize_t ROKEN_LIB_FUNCTION
+ewrite (int fd, const void *buf, size_t nbytes);
+
+struct hostent;
+
+const char * ROKEN_LIB_FUNCTION
+hostent_find_fqdn (const struct hostent *he);
+
+void ROKEN_LIB_FUNCTION
+esetenv(const char *var, const char *val, int rewrite);
+
+void ROKEN_LIB_FUNCTION
+socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port);
+
+size_t ROKEN_LIB_FUNCTION
+socket_addr_size (const struct sockaddr *sa);
+
+void ROKEN_LIB_FUNCTION
+socket_set_any (struct sockaddr *sa, int af);
+
+size_t ROKEN_LIB_FUNCTION
+socket_sockaddr_size (const struct sockaddr *sa);
+
+void * ROKEN_LIB_FUNCTION
+socket_get_address (struct sockaddr *sa);
+
+int ROKEN_LIB_FUNCTION
+socket_get_port (const struct sockaddr *sa);
+
+void ROKEN_LIB_FUNCTION
+socket_set_port (struct sockaddr *sa, int port);
+
+void ROKEN_LIB_FUNCTION
+socket_set_portrange (int sock, int restr, int af);
+
+void ROKEN_LIB_FUNCTION
+socket_set_debug (int sock);
+
+void ROKEN_LIB_FUNCTION
+socket_set_tos (int sock, int tos);
+
+void ROKEN_LIB_FUNCTION
+socket_set_reuseaddr (int sock, int val);
+
+char ** ROKEN_LIB_FUNCTION
+vstrcollect(va_list *ap);
+
+char ** ROKEN_LIB_FUNCTION
+strcollect(char *first, ...);
+
+void ROKEN_LIB_FUNCTION
+timevalfix(struct timeval *t1);
+
+void ROKEN_LIB_FUNCTION
+timevaladd(struct timeval *t1, const struct timeval *t2);
+
+void ROKEN_LIB_FUNCTION
+timevalsub(struct timeval *t1, const struct timeval *t2);
+
+char *ROKEN_LIB_FUNCTION
+pid_file_write (const char *progname);
+
+void ROKEN_LIB_FUNCTION
+pid_file_delete (char **);
+
+int ROKEN_LIB_FUNCTION
+read_environment(const char *file, char ***env);
+
+void ROKEN_LIB_FUNCTION
+warnerr(int doerrno, const char *fmt, va_list ap)
+    __attribute__ ((format (printf, 2, 0)));
+
+void * ROKEN_LIB_FUNCTION
+rk_realloc(void *, size_t);
+
+ROKEN_CPP_END
+
+#endif /* __ROKEN_COMMON_H__ */
diff --git a/src/kerberosV/src/lib/roken/roken.awk b/src/kerberosV/src/lib/roken/roken.awk
new file mode 100644 (file)
index 0000000..1cbd614
--- /dev/null
@@ -0,0 +1,40 @@
+# $KTH: roken.awk,v 1.9 2003/03/04 10:37:26 lha Exp $
+
+BEGIN {
+       print "#ifdef HAVE_CONFIG_H"
+       print "#include <config.h>"
+       print "#endif"
+       print "#include <stdio.h>"
+       print ""
+       print "int main(int argc, char **argv)"
+       print "{"
+           print "puts(\"/* This is an OS dependent, generated file */\");"
+       print "puts(\"\\n\");"
+       print "puts(\"#ifndef __ROKEN_H__\");"
+       print "puts(\"#define __ROKEN_H__\");"
+       print "puts(\"\");"
+}
+
+$1 == "\#ifdef" || $1 == "\#ifndef" || $1 == "\#if" || $1 == "\#else" || $1 == "\#elif" || $1 == "\#endif" || $1 == "#ifdef" || $1 == "#ifndef" || $1 == "#if" || $1 == "#else" || $1 == "#elif" || $1 == "#endif" {
+       print $0;
+       next
+}
+
+{
+       s = ""
+       for(i = 1; i <= length; i++){
+               x = substr($0, i, 1)
+               if(x == "\"" || x == "\\")
+                       s = s "\\";
+               s = s x;
+       }
+       print "puts(\"" s "\");"
+}
+
+END {
+       print "puts(\"#define ROKEN_VERSION \" VERSION );"
+       print "puts(\"\");"
+       print "puts(\"#endif /* __ROKEN_H__ */\");"
+       print "return 0;"
+       print "}"
+}
diff --git a/src/kerberosV/src/lib/roken/roken.h.in b/src/kerberosV/src/lib/roken/roken.h.in
new file mode 100644 (file)
index 0000000..db09a6f
--- /dev/null
@@ -0,0 +1,685 @@
+/* -*- C -*- */
+/*
+ * Copyright (c) 1995-2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: roken.h.in,v 1.174 2005/05/11 13:04:04 lha Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <signal.h>
+
+#ifdef _AIX
+struct ether_addr;
+struct sockaddr_dl;
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_BITYPES_H
+#include <sys/bitypes.h>
+#endif
+#ifdef HAVE_BIND_BITYPES_H
+#include <bind/bitypes.h>
+#endif
+#ifdef HAVE_NETINET_IN6_MACHTYPES_H
+#include <netinet/in6_machtypes.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+#ifdef HAVE_GRP_H
+#include <grp.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_NETINET_IN6_H
+#include <netinet/in6.h>
+#endif
+#ifdef HAVE_NETINET6_IN6_H
+#include <netinet6/in6.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+#ifdef HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#ifdef HAVE_ARPA_NAMESER_H
+#include <arpa/nameser.h>
+#endif
+#ifdef HAVE_RESOLV_H
+#include <resolv.h>
+#endif
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <err.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40
+#include <sys/ioctl.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+
+#ifdef HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef int ssize_t;
+#endif
+
+#include <roken-common.h>
+
+ROKEN_CPP_START
+
+#if !defined(HAVE_SETSID) && defined(HAVE__SETSID)
+#define setsid _setsid
+#endif
+
+#ifndef HAVE_PUTENV
+int ROKEN_LIB_FUNCTION putenv(const char *string);
+#endif
+
+#if !defined(HAVE_SETENV) || defined(NEED_SETENV_PROTO)
+int ROKEN_LIB_FUNCTION setenv(const char *var, const char *val, int rewrite);
+#endif
+
+#if !defined(HAVE_UNSETENV) || defined(NEED_UNSETENV_PROTO)
+void ROKEN_LIB_FUNCTION unsetenv(const char *name);
+#endif
+
+#if !defined(HAVE_GETUSERSHELL) || defined(NEED_GETUSERSHELL_PROTO)
+char * ROKEN_LIB_FUNCTION getusershell(void);
+void ROKEN_LIB_FUNCTION endusershell(void);
+#endif
+
+#if !defined(HAVE_SNPRINTF) || defined(NEED_SNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION snprintf (char *str, size_t sz, const char *format, ...)
+     __attribute__ ((format (printf, 3, 4)));
+#endif
+
+#if !defined(HAVE_VSNPRINTF) || defined(NEED_VSNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION 
+     vsnprintf (char *str, size_t sz, const char *format, va_list ap)
+     __attribute__((format (printf, 3, 0)));
+#endif
+
+#if !defined(HAVE_ASPRINTF) || defined(NEED_ASPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+     asprintf (char **ret, const char *format, ...)
+     __attribute__ ((format (printf, 2, 3)));
+#endif
+
+#if !defined(HAVE_VASPRINTF) || defined(NEED_VASPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+    vasprintf (char **ret, const char *format, va_list ap)
+     __attribute__((format (printf, 2, 0)));
+#endif
+
+#if !defined(HAVE_ASNPRINTF) || defined(NEED_ASNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+    asnprintf (char **ret, size_t max_sz, const char *format, ...)
+     __attribute__ ((format (printf, 3, 4)));
+#endif
+
+#if !defined(HAVE_VASNPRINTF) || defined(NEED_VASNPRINTF_PROTO)
+int ROKEN_LIB_FUNCTION
+    vasnprintf (char **ret, size_t max_sz, const char *format, va_list ap)
+     __attribute__((format (printf, 3, 0)));
+#endif
+
+#ifndef HAVE_STRDUP
+char * ROKEN_LIB_FUNCTION strdup(const char *old);
+#endif
+
+#if !defined(HAVE_STRNDUP) || defined(NEED_STRNDUP_PROTO)
+char * ROKEN_LIB_FUNCTION strndup(const char *old, size_t sz);
+#endif
+
+#ifndef HAVE_STRLWR
+char * ROKEN_LIB_FUNCTION strlwr(char *);
+#endif
+
+#ifndef HAVE_STRNLEN
+size_t ROKEN_LIB_FUNCTION strnlen(const char*, size_t);
+#endif
+
+#if !defined(HAVE_STRSEP) || defined(NEED_STRSEP_PROTO)
+char * ROKEN_LIB_FUNCTION strsep(char**, const char*);
+#endif
+
+#if !defined(HAVE_STRSEP_COPY) || defined(NEED_STRSEP_COPY_PROTO)
+ssize_t ROKEN_LIB_FUNCTION strsep_copy(const char**, const char*, char*, size_t);
+#endif
+
+#ifndef HAVE_STRCASECMP
+int ROKEN_LIB_FUNCTION strcasecmp(const char *s1, const char *s2);
+#endif
+
+#ifdef NEED_FCLOSE_PROTO
+int ROKEN_LIB_FUNCTION fclose(FILE *);
+#endif
+
+#ifdef NEED_STRTOK_R_PROTO
+char * ROKEN_LIB_FUNCTION strtok_r(char *s1, const char *s2, char **lasts);
+#endif
+
+#ifndef HAVE_STRUPR
+char * ROKEN_LIB_FUNCTION strupr(char *);
+#endif
+
+#ifndef HAVE_STRLCPY
+size_t ROKEN_LIB_FUNCTION strlcpy (char *dst, const char *src, size_t dst_sz);
+#endif
+
+#ifndef HAVE_STRLCAT
+size_t ROKEN_LIB_FUNCTION strlcat (char *dst, const char *src, size_t dst_sz);
+#endif
+
+#ifndef HAVE_GETDTABLESIZE
+int ROKEN_LIB_FUNCTION getdtablesize(void);
+#endif
+
+#if !defined(HAVE_STRERROR) && !defined(strerror)
+char * ROKEN_LIB_FUNCTION strerror(int eno);
+#endif
+
+#if !defined(HAVE_HSTRERROR) || defined(NEED_HSTRERROR_PROTO)
+/* This causes a fatal error under Psoriasis */
+#if !(defined(SunOS) && (SunOS >= 50))
+const char * ROKEN_LIB_FUNCTION hstrerror(int herr);
+#endif
+#endif
+
+#if !HAVE_DECL_H_ERRNO
+extern int h_errno;
+#endif
+
+#if !defined(HAVE_INET_ATON) || defined(NEED_INET_ATON_PROTO)
+int ROKEN_LIB_FUNCTION inet_aton(const char *cp, struct in_addr *adr);
+#endif
+
+#ifndef HAVE_INET_NTOP
+const char * ROKEN_LIB_FUNCTION
+inet_ntop(int af, const void *src, char *dst, size_t size);
+#endif
+
+#ifndef HAVE_INET_PTON
+int ROKEN_LIB_FUNCTION
+inet_pton(int af, const char *src, void *dst);
+#endif
+
+#if !defined(HAVE_GETCWD)
+char* ROKEN_LIB_FUNCTION getcwd(char *path, size_t size);
+#endif
+
+#ifdef HAVE_PWD_H
+#include <pwd.h>
+struct passwd * ROKEN_LIB_FUNCTION k_getpwnam (const char *user);
+struct passwd * ROKEN_LIB_FUNCTION k_getpwuid (uid_t uid);
+#endif
+
+const char * ROKEN_LIB_FUNCTION get_default_username (void);
+
+#ifndef HAVE_SETEUID
+int ROKEN_LIB_FUNCTION seteuid(uid_t euid);
+#endif
+
+#ifndef HAVE_SETEGID
+int ROKEN_LIB_FUNCTION setegid(gid_t egid);
+#endif
+
+#ifndef HAVE_LSTAT
+int ROKEN_LIB_FUNCTION lstat(const char *path, struct stat *buf);
+#endif
+
+#if !defined(HAVE_MKSTEMP) || defined(NEED_MKSTEMP_PROTO)
+int ROKEN_LIB_FUNCTION mkstemp(char *);
+#endif
+
+#ifndef HAVE_CGETENT
+int ROKEN_LIB_FUNCTION cgetent(char **buf, char **db_array, const char *name);
+int ROKEN_LIB_FUNCTION cgetstr(char *buf, const char *cap, char **str);
+#endif
+
+#ifndef HAVE_INITGROUPS
+int ROKEN_LIB_FUNCTION initgroups(const char *name, gid_t basegid);
+#endif
+
+#ifndef HAVE_FCHOWN
+int ROKEN_LIB_FUNCTION fchown(int fd, uid_t owner, gid_t group);
+#endif
+
+#if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO)
+int ROKEN_LIB_FUNCTION daemon(int nochdir, int noclose);
+#endif
+
+#ifndef HAVE_INNETGR
+int ROKEN_LIB_FUNCTION innetgr(const char *netgroup, const char *machine, 
+           const char *user, const char *domain);
+#endif
+
+#ifndef HAVE_CHOWN
+int ROKEN_LIB_FUNCTION chown(const char *path, uid_t owner, gid_t group);
+#endif
+
+#ifndef HAVE_RCMD
+int ROKEN_LIB_FUNCTION
+    rcmd(char **ahost, unsigned short inport, const char *locuser,
+        const char *remuser, const char *cmd, int *fd2p);
+#endif
+
+#if !defined(HAVE_INNETGR) || defined(NEED_INNETGR_PROTO)
+int ROKEN_LIB_FUNCTION innetgr(const char*, const char*,
+    const char*, const char*);
+#endif
+
+#ifndef HAVE_IRUSEROK
+int ROKEN_LIB_FUNCTION iruserok(unsigned raddr, int superuser, 
+    const char *ruser, const char *luser);
+#endif
+
+#if !defined(HAVE_GETHOSTNAME) || defined(NEED_GETHOSTNAME_PROTO)
+int ROKEN_LIB_FUNCTION gethostname(char *name, int namelen);
+#endif
+
+#ifndef HAVE_WRITEV
+ssize_t ROKEN_LIB_FUNCTION
+writev(int d, const struct iovec *iov, int iovcnt);
+#endif
+
+#ifndef HAVE_READV
+ssize_t ROKEN_LIB_FUNCTION
+readv(int d, const struct iovec *iov, int iovcnt);
+#endif
+
+#ifndef HAVE_MKSTEMP
+int ROKEN_LIB_FUNCTION
+mkstemp(char *template);
+#endif
+
+#ifndef HAVE_PIDFILE
+void ROKEN_LIB_FUNCTION pidfile (const char*);
+#endif
+
+#ifndef HAVE_BSWAP32
+unsigned int ROKEN_LIB_FUNCTION bswap32(unsigned int);
+#endif
+
+#ifndef HAVE_BSWAP16
+unsigned short ROKEN_LIB_FUNCTION bswap16(unsigned short);
+#endif
+
+#ifndef HAVE_FLOCK
+#ifndef LOCK_SH
+#define LOCK_SH   1            /* Shared lock */
+#endif
+#ifndef        LOCK_EX
+#define LOCK_EX   2            /* Exclusive lock */
+#endif
+#ifndef LOCK_NB
+#define LOCK_NB   4            /* Don't block when locking */
+#endif
+#ifndef LOCK_UN
+#define LOCK_UN   8            /* Unlock */
+#endif
+
+int flock(int fd, int operation);
+#endif /* HAVE_FLOCK */
+
+time_t ROKEN_LIB_FUNCTION tm2time (struct tm tm, int local);
+
+int ROKEN_LIB_FUNCTION unix_verify_user(char *user, char *password);
+
+int ROKEN_LIB_FUNCTION roken_concat (char *s, size_t len, ...);
+
+size_t ROKEN_LIB_FUNCTION roken_mconcat (char **s, size_t max_len, ...);
+
+int ROKEN_LIB_FUNCTION roken_vconcat (char *s, size_t len, va_list args);
+
+size_t ROKEN_LIB_FUNCTION
+    roken_vmconcat (char **s, size_t max_len, va_list args);
+
+ssize_t ROKEN_LIB_FUNCTION net_write (int fd, const void *buf, size_t nbytes);
+
+ssize_t ROKEN_LIB_FUNCTION net_read (int fd, void *buf, size_t nbytes);
+
+int ROKEN_LIB_FUNCTION issuid(void);
+
+#ifndef HAVE_STRUCT_WINSIZE
+struct winsize {
+       unsigned short ws_row, ws_col;
+       unsigned short ws_xpixel, ws_ypixel;
+};
+#endif
+
+int ROKEN_LIB_FUNCTION get_window_size(int fd, struct winsize *);
+
+#ifndef HAVE_VSYSLOG
+void ROKEN_LIB_FUNCTION vsyslog(int pri, const char *fmt, va_list ap);
+#endif
+
+#if !HAVE_DECL_OPTARG
+extern char *optarg;
+#endif
+#if !HAVE_DECL_OPTIND
+extern int optind;
+#endif
+#if !HAVE_DECL_OPTERR
+extern int opterr;
+#endif
+
+#if !HAVE_DECL_ENVIRON
+extern char **environ;
+#endif
+
+#ifndef HAVE_GETIPNODEBYNAME
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyname (const char *name, int af, int flags, int *error_num);
+#endif
+
+#ifndef HAVE_GETIPNODEBYADDR
+struct hostent * ROKEN_LIB_FUNCTION
+getipnodebyaddr (const void *src, size_t len, int af, int *error_num);
+#endif
+
+#ifndef HAVE_FREEHOSTENT
+void ROKEN_LIB_FUNCTION
+freehostent (struct hostent *h);
+#endif
+
+#ifndef HAVE_COPYHOSTENT
+struct hostent * ROKEN_LIB_FUNCTION
+copyhostent (const struct hostent *h);
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
+
+#ifndef HAVE_SA_FAMILY_T
+typedef unsigned short sa_family_t;
+#endif
+
+#ifdef HAVE_IPV6
+#define _SS_MAXSIZE sizeof(struct sockaddr_in6)
+#else
+#define _SS_MAXSIZE sizeof(struct sockaddr_in)
+#endif
+
+#define _SS_ALIGNSIZE  sizeof(unsigned long)
+
+#if HAVE_STRUCT_SOCKADDR_SA_LEN
+
+typedef unsigned char roken_sa_family_t;
+
+#define _SS_PAD1SIZE   ((2 * _SS_ALIGNSIZE - sizeof (roken_sa_family_t) - sizeof(unsigned char)) % _SS_ALIGNSIZE)
+#define _SS_PAD2SIZE   (_SS_MAXSIZE - (sizeof (roken_sa_family_t) + sizeof(unsigned char) + _SS_PAD1SIZE + _SS_ALIGNSIZE))
+
+struct sockaddr_storage {
+    unsigned char      ss_len;
+    roken_sa_family_t  ss_family;
+    char               __ss_pad1[_SS_PAD1SIZE];
+    unsigned long      __ss_align[_SS_PAD2SIZE / sizeof(unsigned long) + 1];
+};
+
+#else /* !HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+typedef unsigned short roken_sa_family_t;
+
+#define _SS_PAD1SIZE   ((2 * _SS_ALIGNSIZE - sizeof (roken_sa_family_t)) % _SS_ALIGNSIZE)
+#define _SS_PAD2SIZE   (_SS_MAXSIZE - (sizeof (roken_sa_family_t) + _SS_PAD1SIZE + _SS_ALIGNSIZE))
+
+struct sockaddr_storage {
+    roken_sa_family_t  ss_family;
+    char               __ss_pad1[_SS_PAD1SIZE];
+    unsigned long      __ss_align[_SS_PAD2SIZE / sizeof(unsigned long) + 1];
+};
+
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+
+#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
+
+#ifndef HAVE_STRUCT_ADDRINFO
+struct addrinfo {
+    int    ai_flags;
+    int    ai_family;
+    int    ai_socktype;
+    int    ai_protocol;
+    size_t ai_addrlen;
+    char  *ai_canonname;
+    struct sockaddr *ai_addr;
+    struct addrinfo *ai_next;
+};
+#endif
+
+#ifndef HAVE_GETADDRINFO
+int ROKEN_LIB_FUNCTION
+getaddrinfo(const char *nodename,
+           const char *servname,
+           const struct addrinfo *hints,
+           struct addrinfo **res);
+#endif
+
+#ifndef HAVE_GETNAMEINFO
+int ROKEN_LIB_FUNCTION
+getnameinfo(const struct sockaddr *sa, socklen_t salen,
+               char *host, size_t hostlen,
+               char *serv, size_t servlen,
+               int flags);
+#endif
+
+#ifndef HAVE_FREEADDRINFO
+void ROKEN_LIB_FUNCTION
+freeaddrinfo(struct addrinfo *ai);
+#endif
+
+#ifndef HAVE_GAI_STRERROR
+char * ROKEN_LIB_FUNCTION
+gai_strerror(int ecode);
+#endif
+
+int ROKEN_LIB_FUNCTION
+getnameinfo_verified(const struct sockaddr *sa, socklen_t salen,
+                    char *host, size_t hostlen,
+                    char *serv, size_t servlen,
+                    int flags);
+
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec(const char *, int, struct addrinfo **); 
+int ROKEN_LIB_FUNCTION
+roken_getaddrinfo_hostspec2(const char *, int, int, struct addrinfo **);
+
+#ifndef HAVE_STRFTIME
+size_t ROKEN_LIB_FUNCTION
+strftime (char *buf, size_t maxsize, const char *format,
+         const struct tm *tm);
+#endif
+
+#ifndef HAVE_STRPTIME
+char * ROKEN_LIB_FUNCTION
+strptime (const char *buf, const char *format, struct tm *timeptr);
+#endif
+
+#ifndef HAVE_EMALLOC
+void * ROKEN_LIB_FUNCTION emalloc (size_t);
+#endif
+#ifndef HAVE_ECALLOC
+void * ROKEN_LIB_FUNCTION ecalloc(size_t num, size_t sz);
+#endif
+#ifndef HAVE_EREALLOC
+void * ROKEN_LIB_FUNCTION erealloc (void *, size_t);
+#endif
+#ifndef HAVE_ESTRDUP
+char * ROKEN_LIB_FUNCTION estrdup (const char *);
+#endif
+
+/*
+ * kludges and such
+ */
+
+#if 1
+int ROKEN_LIB_FUNCTION
+roken_gethostby_setup(const char*, const char*);
+struct hostent* ROKEN_LIB_FUNCTION
+roken_gethostbyname(const char*);
+struct hostent* ROKEN_LIB_FUNCTION 
+roken_gethostbyaddr(const void*, size_t, int);
+#else
+#ifdef GETHOSTBYNAME_PROTO_COMPATIBLE
+#define roken_gethostbyname(x) gethostbyname(x)
+#else
+#define roken_gethostbyname(x) gethostbyname((char *)x)
+#endif
+
+#ifdef GETHOSTBYADDR_PROTO_COMPATIBLE
+#define roken_gethostbyaddr(a, l, t) gethostbyaddr(a, l, t)
+#else
+#define roken_gethostbyaddr(a, l, t) gethostbyaddr((char *)a, l, t)
+#endif
+#endif
+
+#ifdef GETSERVBYNAME_PROTO_COMPATIBLE
+#define roken_getservbyname(x,y) getservbyname(x,y)
+#else
+#define roken_getservbyname(x,y) getservbyname((char *)x, (char *)y)
+#endif
+
+#ifdef OPENLOG_PROTO_COMPATIBLE
+#define roken_openlog(a,b,c) openlog(a,b,c)
+#else
+#define roken_openlog(a,b,c) openlog((char *)a,b,c)
+#endif
+
+#ifdef GETSOCKNAME_PROTO_COMPATIBLE
+#define roken_getsockname(a,b,c) getsockname(a,b,c)
+#else
+#define roken_getsockname(a,b,c) getsockname(a, b, (void*)c)
+#endif
+
+#ifndef HAVE_SETPROGNAME
+void ROKEN_LIB_FUNCTION setprogname(const char *argv0);
+#endif
+
+#ifndef HAVE_GETPROGNAME
+const char * ROKEN_LIB_FUNCTION getprogname(void);
+#endif
+
+#if !defined(HAVE_SETPROGNAME) && !defined(HAVE_GETPROGNAME) && !HAVE_DECL___PROGNAME
+extern const char *__progname;
+#endif
+
+void ROKEN_LIB_FUNCTION mini_inetd_addrinfo (struct addrinfo*);
+void ROKEN_LIB_FUNCTION mini_inetd (int port);
+
+#ifndef HAVE_LOCALTIME_R
+struct tm * ROKEN_LIB_FUNCTION
+localtime_r(const time_t *timer, struct tm *result);
+#endif
+
+#if !defined(HAVE_STRSVIS) || defined(NEED_STRSVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+strsvis(char *dst, const char *src, int flag, const char *extra);
+#endif
+
+#if !defined(HAVE_STRUNVIS) || defined(NEED_STRUNVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+strunvis(char *dst, const char *src);
+#endif
+
+#if !defined(HAVE_STRVIS) || defined(NEED_STRVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+strvis(char *dst, const char *src, int flag);
+#endif
+
+#if !defined(HAVE_STRVISX) || defined(NEED_STRVISX_PROTO)
+int ROKEN_LIB_FUNCTION
+strvisx(char *dst, const char *src, size_t len, int flag);
+#endif
+
+#if !defined(HAVE_SVIS) || defined(NEED_SVIS_PROTO)
+char * ROKEN_LIB_FUNCTION
+svis(char *dst, int c, int flag, int nextc, const char *extra);
+#endif
+
+#if !defined(HAVE_UNVIS) || defined(NEED_UNVIS_PROTO)
+int ROKEN_LIB_FUNCTION
+unvis(char *cp, int c, int *astate, int flag);
+#endif
+
+#if !defined(HAVE_VIS) || defined(NEED_VIS_PROTO)
+char * ROKEN_LIB_FUNCTION
+vis(char *dst, int c, int flag, int nextc);
+#endif
+
+#if !defined(HAVE_CLOSEFROM)
+int ROKEN_LIB_FUNCTION
+closefrom(int);
+#endif
+
+ROKEN_CPP_END
diff --git a/src/kerberosV/src/lib/roken/roken_gethostby.c b/src/kerberosV/src/lib/roken/roken_gethostby.c
new file mode 100644 (file)
index 0000000..5408e88
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: roken_gethostby.c,v 1.7 2005/04/12 11:29:03 lha Exp $");
+#endif
+
+#include <roken.h>
+
+#undef roken_gethostbyname
+#undef roken_gethostbyaddr
+
+static struct sockaddr_in dns_addr;
+static char *dns_req;
+
+static int
+make_address(const char *address, struct in_addr *ip)
+{
+    if(inet_aton(address, ip) == 0){
+       /* try to resolve as hostname, it might work if the address we
+           are trying to lookup is local, for instance a web proxy */
+       struct hostent *he = gethostbyname(address);
+       if(he) {
+           unsigned char *p = (unsigned char*)he->h_addr;
+           ip->s_addr = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
+       } else {
+           return -1;
+       }
+    }
+    return 0;
+}
+
+static int
+setup_int(const char *proxy_host, short proxy_port,
+         const char *dns_host, short dns_port,
+         const char *dns_path)
+{
+    memset(&dns_addr, 0, sizeof(dns_addr));
+    if(dns_req)
+       free(dns_req);
+    if(proxy_host) {
+       if(make_address(proxy_host, &dns_addr.sin_addr) != 0)
+           return -1;
+       dns_addr.sin_port = htons(proxy_port);
+       asprintf(&dns_req, "http://%s:%d%s", dns_host, dns_port, dns_path);
+    } else {
+       if(make_address(dns_host, &dns_addr.sin_addr) != 0)
+           return -1;
+       dns_addr.sin_port = htons(dns_port);
+       asprintf(&dns_req, "%s", dns_path);
+    }
+    dns_addr.sin_family = AF_INET;
+    return 0;
+}
+
+static void
+split_spec(const char *spec, char **host, int *port, char **path, int def_port)
+{
+    char *p;
+    *host = strdup(spec);
+    p = strchr(*host, ':');
+    if(p) {
+       *p++ = '\0';
+       if(sscanf(p, "%d", port) != 1)
+           *port = def_port;
+    } else
+       *port = def_port;
+    p = strchr(p ? p : *host, '/');
+    if(p) {
+       if(path) 
+           *path = strdup(p);
+       *p = '\0';
+    }else
+       if(path) 
+           *path = NULL;
+}
+
+
+int ROKEN_LIB_FUNCTION
+roken_gethostby_setup(const char *proxy_spec, const char *dns_spec)
+{
+    char *proxy_host = NULL;
+    int proxy_port;
+    char *dns_host, *dns_path;
+    int dns_port;
+    
+    int ret = -1;
+    
+    split_spec(dns_spec, &dns_host, &dns_port, &dns_path, 80);
+    if(dns_path == NULL)
+       goto out;
+    if(proxy_spec)
+       split_spec(proxy_spec, &proxy_host, &proxy_port, NULL, 80);
+    ret = setup_int(proxy_host, proxy_port, dns_host, dns_port, dns_path);
+out:
+    free(proxy_host);
+    free(dns_host);
+    free(dns_path);
+    return ret;
+}
+    
+
+/* Try to lookup a name or an ip-address using http as transport
+   mechanism. See the end of this file for an example program. */
+static struct hostent*
+roken_gethostby(const char *hostname)
+{
+    int s;
+    struct sockaddr_in addr;
+    char *request;
+    char buf[1024];
+    int offset = 0;
+    int n;
+    char *p, *foo;
+    
+    if(dns_addr.sin_family == 0)
+       return NULL; /* no configured host */
+    addr = dns_addr;
+    asprintf(&request, "GET %s?%s HTTP/1.0\r\n\r\n", dns_req, hostname);
+    if(request == NULL)
+       return NULL;
+    s  = socket(AF_INET, SOCK_STREAM, 0);
+    if(s < 0) {
+       free(request);
+       return NULL;
+    }
+    if(connect(s, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
+       close(s);
+       free(request);
+       return NULL;
+    }
+    if(write(s, request, strlen(request)) != strlen(request)) {
+       close(s);
+       free(request);
+       return NULL;
+    }
+    free(request);
+    while(1) {
+       n = read(s, buf + offset, sizeof(buf) - offset);
+       if(n <= 0)
+           break;
+       offset += n;
+    }
+    buf[offset] = '\0';
+    close(s);
+    p = strstr(buf, "\r\n\r\n"); /* find end of header */
+    if(p) p += 4;
+    else return NULL;
+    foo = NULL;
+    p = strtok_r(p, " \t\r\n", &foo);
+    if(p == NULL)
+       return NULL;
+    {
+       /* make a hostent to return */
+#define MAX_ADDRS 16
+       static struct hostent he;
+       static char addrs[4 * MAX_ADDRS];
+       static char *addr_list[MAX_ADDRS + 1];
+       int num_addrs = 0;
+       
+       he.h_name = p;
+       he.h_aliases = NULL;
+       he.h_addrtype = AF_INET;
+       he.h_length = 4;
+       
+       while((p = strtok_r(NULL, " \t\r\n", &foo)) && num_addrs < MAX_ADDRS) {
+           struct in_addr ip;
+           inet_aton(p, &ip);
+           ip.s_addr = ntohl(ip.s_addr);
+           addr_list[num_addrs] = &addrs[num_addrs * 4];
+           addrs[num_addrs * 4 + 0] = (ip.s_addr >> 24) & 0xff;
+           addrs[num_addrs * 4 + 1] = (ip.s_addr >> 16) & 0xff;
+           addrs[num_addrs * 4 + 2] = (ip.s_addr >> 8) & 0xff;
+           addrs[num_addrs * 4 + 3] = (ip.s_addr >> 0) & 0xff;
+           addr_list[++num_addrs] = NULL;
+       }
+       he.h_addr_list = addr_list;
+       return &he;
+    }
+}
+
+struct hostent*
+roken_gethostbyname(const char *hostname)
+{
+    struct hostent *he;
+    he = gethostbyname(hostname);
+    if(he)
+       return he;
+    return roken_gethostby(hostname);
+}
+
+struct hostent* ROKEN_LIB_FUNCTION
+roken_gethostbyaddr(const void *addr, size_t len, int type)
+{
+    struct in_addr a;
+    const char *p;
+    struct hostent *he;
+    he = gethostbyaddr(addr, len, type);
+    if(he)
+       return he;
+    if(type != AF_INET || len != 4)
+       return NULL;
+    p = addr;
+    a.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+    return roken_gethostby(inet_ntoa(a));
+}
+
+#if 0
+
+/* this program can be used as a cgi `script' to lookup names and
+   ip-addresses */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <sys/param.h>
+
+int
+main(int argc, char **argv)
+{
+    char *query = getenv("QUERY_STRING");
+    char host[MAXHOSTNAMELEN];
+    int i;
+    struct hostent *he;
+    
+    printf("Content-type: text/plain\n\n");
+    if(query == NULL)
+       exit(0);
+    he = gethostbyname(query);
+    strncpy(host, he->h_name, sizeof(host));
+    host[sizeof(host) - 1] = '\0';
+    he = gethostbyaddr(he->h_addr, he->h_length, AF_INET);
+    printf("%s\n", he->h_name);
+    for(i = 0; he->h_addr_list[i]; i++) {
+       struct in_addr ip;
+       unsigned char *p = (unsigned char*)he->h_addr_list[i];
+       ip.s_addr = htonl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+       printf("%s\n", inet_ntoa(ip));
+    }
+    exit(0);
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/rtbl.3 b/src/kerberosV/src/lib/roken/rtbl.3
new file mode 100644 (file)
index 0000000..acc3669
--- /dev/null
@@ -0,0 +1,201 @@
+.\" Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\" $KTH: rtbl.3,v 1.2 2004/06/26 16:13:05 lha Exp $
+.\"
+.Dd June 26, 2004
+.Dt RTBL 3
+.Os HEIMDAL
+.Sh NAME
+.Nm rtbl_create ,
+.Nm rtbl_destroy ,
+.Nm rtbl_set_flags ,
+.Nm rtbl_get_flags ,
+.Nm rtbl_set_prefix ,
+.Nm rtbl_set_separator ,
+.Nm rtbl_set_column_prefix ,
+.Nm rtbl_set_column_affix_by_id ,
+.Nm rtbl_add_column ,
+.Nm rtbl_add_column_by_id ,
+.Nm rtbl_add_column_entry ,
+.Nm rtbl_add_column_entry_by_id ,
+.Nm rtbl_new_row ,
+.Nm rtbl_format
+.Nd format data in simple tables
+.Sh LIBRARY
+The roken library (libroken, -lroken)
+.Sh SYNOPSIS
+.In rtbl.h
+.Ft int
+.Fn rtbl_add_column "rtbl_t table" "const char *column_name" "unsigned int flags"
+.Ft int
+.Fn rtbl_add_column_by_id "rtbl_t table" "unsigned int column_id" "const char *column_header" "unsigned int flags"
+.Ft int
+.Fn rtbl_add_column_entry "rtbl_t table" "const char *column_name" "const char *cell_entry"
+.Ft int
+.Fn rtbl_add_column_entry_by_id "rtbl_t table" "unsigned int column_id" "const char *cell_entry"
+.Ft rtbl_t
+.Fn rtbl_create "void"
+.Ft void
+.Fn rtbl_destroy "rtbl_t table"
+.Ft int
+.Fn rtbl_new_row "rtbl_t table"
+.Ft int
+.Fn rtbl_set_column_affix_by_id "rtbl_t table" "unsigned int column_id "const char *prefix" "const char *suffix"
+.Ft int
+.Fn rtbl_set_column_prefix "rtbl_t table" "const char *column_name" "const char *prefix"
+.Ft "unsigned int"
+.Fn rtbl_get_flags "rtbl_t table"
+.Ft void
+.Fn rtbl_set_flags "rtbl_t table" "unsigned int flags"
+.Ft int
+.Fn rtbl_set_prefix "rtbl_t table" "const char *prefix"
+.Ft int
+.Fn rtbl_set_separator "rtbl_t table" "const char *separator"
+.Ft int
+.Fn rtbl_format "rtbl_t table "FILE *file"
+.Sh DESCRIPTION
+This set of functions assemble a simple table consisting of rows and
+columns, allowing it to be printed with certain options. Typical use
+would be output from tools such as
+.Xr ls 1
+or
+.Xr netstat 1 ,
+where you have a fixed number of columns, but don't know the column
+widthds before hand.
+.Pp
+A table is created with
+.Fn rtbl_create
+and destroyed with
+.Fn rtbl_destroy .
+.Pp
+Global flags on the table are set with
+.Fa rtbl_set_flags
+and retrieved with
+.Fa rtbl_get_flags .
+At present the only defined flag is
+.Dv RTBL_HEADER_STYLE_NONE
+which supresses printing the header.
+.Pp
+Before adding data to the table, one or more columns need to be
+created. This would normally be done with
+.Fn rtbl_add_column_by_id ,
+.Fa column_id
+is any number of your choice (it's used only to identify columns),
+.Fa column_header
+is the header to print at the top of the column, and
+.Fa flags
+are flags specific to this column. Currently the only defined flag is
+.Dv RTBL_ALIGN_RIGHT ,
+aligning column entries to the right. Columns are printed in the order
+they are added.
+.Pp
+There's also a way to add columns by column name with
+.Fn rtbl_add_column ,
+but this is less flexible (you need unique header names), and is
+considered deprecated.
+.Pp
+To add data to a column you use
+.Fn rtbl_add_column_entry_by_id ,
+where the
+.Fa column_id
+is the same as when the column was added (adding data to a
+non-existant column is undefined), and
+.Fa cell_entry
+is whatever string you wish to include in that cell. It should not
+include newlines.
+For columns added with
+.Fn rtbl_add_column
+you must use
+.Fn rtbl_add_column_entry
+instead.
+.Pp
+.Fn rtbl_new_row
+fills all columns with blank entries until they all have the same
+number of rows.
+.Pp
+Each column can have a separate prefix and suffix, set with
+.Fa rtbl_set_column_affix_by_id ;
+.Fa rtbl_set_column_prefix
+allows setting the prefix only by column name. In addition to this,
+columns may be separated by a string set with
+.Fa rtbl_set_separator ( Ns
+by default columns are not seprated by anything).
+.Pp
+The finished table is printed to
+.Fa file
+with
+.Fa rtbl_format .
+.Sh EXAMPLES
+This program:
+.Bd -literal -offset xxxx
+#include <stdio.h>
+#include <rtbl.h>
+int
+main(int argc, char **argv)
+{
+    rtbl_t table;
+    table = rtbl_create();
+    rtbl_set_separator(table, "  ");
+    rtbl_add_column_by_id(table, 0, "Column A", 0);
+    rtbl_add_column_by_id(table, 1, "Column B", RTBL_ALIGN_RIGHT);
+    rtbl_add_column_by_id(table, 2, "Column C", 0);
+    rtbl_add_column_entry_by_id(table, 0, "A-1");
+    rtbl_add_column_entry_by_id(table, 0, "A-2");
+    rtbl_add_column_entry_by_id(table, 0, "A-3");
+    rtbl_add_column_entry_by_id(table, 1, "B-1");
+    rtbl_add_column_entry_by_id(table, 2, "C-1");
+    rtbl_add_column_entry_by_id(table, 2, "C-2");
+    rtbl_add_column_entry_by_id(table, 1, "B-2");
+    rtbl_add_column_entry_by_id(table, 1, "B-3");
+    rtbl_add_column_entry_by_id(table, 2, "C-3");
+    rtbl_add_column_entry_by_id(table, 0, "A-4");
+    rtbl_new_row(table);
+    rtbl_add_column_entry_by_id(table, 1, "B-4");
+    rtbl_new_row(table);
+    rtbl_add_column_entry_by_id(table, 2, "C-4");
+    rtbl_new_row(table);
+    rtbl_format(table, stdout);
+    rtbl_destroy(table);
+    return 0;
+}
+.Ed
+.Pp
+will output the following:
+.Bd -literal -offset xxxx
+Column A  Column B  Column C
+A-1            B-1  C-1
+A-2            B-2  C-2
+A-3            B-3  C-3
+A-4
+               B-4
+                    C-4
+.Ed
+.\" .Sh SEE ALSO
diff --git a/src/kerberosV/src/lib/roken/rtbl.c b/src/kerberosV/src/lib/roken/rtbl.c
new file mode 100644 (file)
index 0000000..90f730a
--- /dev/null
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2000, 2002, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID ("$KTH: rtbl.c,v 1.7 2005/04/12 11:29:03 lha Exp $");
+#endif
+#include "roken.h"
+#include "rtbl.h"
+
+struct column_entry {
+    char *data;
+};
+
+struct column_data {
+    char *header;
+    char *prefix;
+    int width;
+    unsigned flags;
+    size_t num_rows;
+    struct column_entry *rows;
+    unsigned int column_id;
+    char *suffix;
+};
+
+struct rtbl_data {
+    char *column_prefix;
+    size_t num_columns;
+    struct column_data **columns;
+    unsigned int flags;
+    char *column_separator;
+};
+
+rtbl_t ROKEN_LIB_FUNCTION
+rtbl_create (void)
+{
+    return calloc (1, sizeof (struct rtbl_data));
+}
+
+void ROKEN_LIB_FUNCTION
+rtbl_set_flags (rtbl_t table, unsigned int flags)
+{
+    table->flags = flags;
+}
+
+unsigned int ROKEN_LIB_FUNCTION
+rtbl_get_flags (rtbl_t table)
+{
+    return table->flags;
+}
+
+static struct column_data *
+rtbl_get_column_by_id (rtbl_t table, unsigned int id)
+{
+    int i;
+    for(i = 0; i < table->num_columns; i++)
+       if(table->columns[i]->column_id == id)
+           return table->columns[i];
+    return NULL;
+}
+
+static struct column_data *
+rtbl_get_column (rtbl_t table, const char *column)
+{
+    int i;
+    for(i = 0; i < table->num_columns; i++)
+       if(strcmp(table->columns[i]->header, column) == 0)
+           return table->columns[i];
+    return NULL;
+}
+
+void ROKEN_LIB_FUNCTION
+rtbl_destroy (rtbl_t table)
+{
+    int i, j;
+
+    for (i = 0; i < table->num_columns; i++) {
+       struct column_data *c = table->columns[i];
+
+       for (j = 0; j < c->num_rows; j++)
+           free (c->rows[j].data);
+       free (c->rows);
+       free (c->header);
+       free (c->prefix);
+       free (c->suffix);
+       free (c);
+    }
+    free (table->column_prefix);
+    free (table->column_separator);
+    free (table->columns);
+    free (table);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_by_id (rtbl_t table, unsigned int id, 
+                      const char *header, unsigned int flags)
+{
+    struct column_data *col, **tmp;
+
+    tmp = realloc (table->columns, (table->num_columns + 1) * sizeof (*tmp));
+    if (tmp == NULL)
+       return ENOMEM;
+    table->columns = tmp;
+    col = malloc (sizeof (*col));
+    if (col == NULL)
+       return ENOMEM;
+    col->header = strdup (header);
+    if (col->header == NULL) {
+       free (col);
+       return ENOMEM;
+    }
+    col->prefix = NULL;
+    col->width = 0;
+    col->flags = flags;
+    col->num_rows = 0;
+    col->rows = NULL;
+    col->column_id = id;
+    col->suffix = NULL;
+    table->columns[table->num_columns++] = col;
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column (rtbl_t table, const char *header, unsigned int flags)
+{
+    return rtbl_add_column_by_id(table, 0, header, flags);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_new_row(rtbl_t table)
+{
+    size_t max_rows = 0;
+    size_t c;
+    for (c = 0; c < table->num_columns; c++)
+       if(table->columns[c]->num_rows > max_rows)
+           max_rows = table->columns[c]->num_rows;
+    for (c = 0; c < table->num_columns; c++) {
+       struct column_entry *tmp;
+
+       if(table->columns[c]->num_rows == max_rows)
+           continue;
+       tmp = realloc(table->columns[c]->rows, 
+                     max_rows * sizeof(table->columns[c]->rows));
+       if(tmp == NULL)
+           return ENOMEM;
+       table->columns[c]->rows = tmp;
+       while(table->columns[c]->num_rows < max_rows) {
+           if((tmp[table->columns[c]->num_rows++].data = strdup("")) == NULL)
+               return ENOMEM;
+       }
+    }
+    return 0;
+}
+
+static void
+column_compute_width (rtbl_t table, struct column_data *column)
+{
+    int i;
+
+    if(table->flags & RTBL_HEADER_STYLE_NONE)
+       column->width = 0;
+    else
+       column->width = strlen (column->header);
+    for (i = 0; i < column->num_rows; i++)
+       column->width = max (column->width, strlen (column->rows[i].data));
+}
+
+/* DEPRECATED */
+int ROKEN_LIB_FUNCTION
+rtbl_set_prefix (rtbl_t table, const char *prefix)
+{
+    if (table->column_prefix)
+       free (table->column_prefix);
+    table->column_prefix = strdup (prefix);
+    if (table->column_prefix == NULL)
+       return ENOMEM;
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_separator (rtbl_t table, const char *separator)
+{
+    if (table->column_separator)
+       free (table->column_separator);
+    table->column_separator = strdup (separator);
+    if (table->column_separator == NULL)
+       return ENOMEM;
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_prefix (rtbl_t table, const char *column,
+                       const char *prefix)
+{
+    struct column_data *c = rtbl_get_column (table, column);
+
+    if (c == NULL)
+       return -1;
+    if (c->prefix)
+       free (c->prefix);
+    c->prefix = strdup (prefix);
+    if (c->prefix == NULL)
+       return ENOMEM;
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_affix_by_id(rtbl_t table, unsigned int id,
+                           const char *prefix, const char *suffix)
+{
+    struct column_data *c = rtbl_get_column_by_id (table, id);
+
+    if (c == NULL)
+       return -1;
+    if (c->prefix)
+       free (c->prefix);
+    if(prefix == NULL)
+       c->prefix = NULL;
+    else {
+       c->prefix = strdup (prefix);
+       if (c->prefix == NULL)
+           return ENOMEM;
+    }
+
+    if (c->suffix)
+       free (c->suffix);
+    if(suffix == NULL)
+       c->suffix = NULL;
+    else {
+       c->suffix = strdup (suffix);
+       if (c->suffix == NULL)
+           return ENOMEM;
+    }
+    return 0;
+}
+
+
+static const char *
+get_column_prefix (rtbl_t table, struct column_data *c)
+{
+    if (c == NULL)
+       return "";
+    if (c->prefix)
+       return c->prefix;
+    if (table->column_prefix)
+       return table->column_prefix;
+    return "";
+}
+
+static const char *
+get_column_suffix (rtbl_t table, struct column_data *c)
+{
+    if (c && c->suffix)
+       return c->suffix;
+    return "";
+}
+
+static int
+add_column_entry (struct column_data *c, const char *data)
+{
+    struct column_entry row, *tmp;
+
+    row.data = strdup (data);
+    if (row.data == NULL)
+       return ENOMEM;
+    tmp = realloc (c->rows, (c->num_rows + 1) * sizeof (*tmp));
+    if (tmp == NULL) {
+       free (row.data);
+       return ENOMEM;
+    }
+    c->rows = tmp;
+    c->rows[c->num_rows++] = row;
+    return 0;
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry_by_id (rtbl_t table, unsigned int id, const char *data)
+{
+    struct column_data *c = rtbl_get_column_by_id (table, id);
+
+    if (c == NULL)
+       return -1;
+
+    return add_column_entry(c, data);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry (rtbl_t table, const char *column, const char *data)
+{
+    struct column_data *c = rtbl_get_column (table, column);
+
+    if (c == NULL)
+       return -1;
+
+    return add_column_entry(c, data);
+}
+
+int ROKEN_LIB_FUNCTION
+rtbl_format (rtbl_t table, FILE * f)
+{
+    int i, j;
+
+    for (i = 0; i < table->num_columns; i++)
+       column_compute_width (table, table->columns[i]);
+    if((table->flags & RTBL_HEADER_STYLE_NONE) == 0) {
+       for (i = 0; i < table->num_columns; i++) {
+           struct column_data *c = table->columns[i];
+
+           if(table->column_separator != NULL && i > 0)
+               fprintf (f, "%s", table->column_separator);
+           fprintf (f, "%s", get_column_prefix (table, c));
+           if(i == table->num_columns - 1 && c->suffix == NULL)
+               /* last column, so no need to pad with spaces */
+               fprintf (f, "%-*s", 0, c->header);
+           else
+               fprintf (f, "%-*s", (int)c->width, c->header);
+           fprintf (f, "%s", get_column_suffix (table, c));
+       }
+       fprintf (f, "\n");
+    }
+
+    for (j = 0;; j++) {
+       int flag = 0;
+
+       /* are there any more rows left? */
+       for (i = 0; flag == 0 && i < table->num_columns; ++i) {
+           struct column_data *c = table->columns[i];
+
+           if (c->num_rows > j) {
+               ++flag;
+               break;
+           }
+       }
+       if (flag == 0)
+           break;
+
+       for (i = 0; i < table->num_columns; i++) {
+           int w;
+           struct column_data *c = table->columns[i];
+
+           if(table->column_separator != NULL && i > 0)
+               fprintf (f, "%s", table->column_separator);
+
+           w = c->width;
+
+           if ((c->flags & RTBL_ALIGN_RIGHT) == 0) {
+               if(i == table->num_columns - 1 && c->suffix == NULL)
+                   /* last column, so no need to pad with spaces */
+                   w = 0;
+               else
+                   w = -w;
+           }
+           fprintf (f, "%s", get_column_prefix (table, c));
+           if (c->num_rows <= j)
+               fprintf (f, "%*s", w, "");
+           else
+               fprintf (f, "%*s", w, c->rows[j].data);
+           fprintf (f, "%s", get_column_suffix (table, c));
+       }
+       fprintf (f, "\n");
+    }
+    return 0;
+}
+
+#ifdef TEST
+int
+main (int argc, char **argv)
+{
+    rtbl_t table;
+
+    table = rtbl_create ();
+    rtbl_add_column_by_id (table, 0, "Issued", 0);
+    rtbl_add_column_by_id (table, 1, "Expires", 0);
+    rtbl_add_column_by_id (table, 2, "Foo", RTBL_ALIGN_RIGHT);
+    rtbl_add_column_by_id (table, 3, "Principal", 0);
+
+    rtbl_add_column_entry_by_id (table, 0, "Jul  7 21:19:29");
+    rtbl_add_column_entry_by_id (table, 1, "Jul  8 07:19:29");
+    rtbl_add_column_entry_by_id (table, 2, "73");
+    rtbl_add_column_entry_by_id (table, 2, "0");
+    rtbl_add_column_entry_by_id (table, 2, "-2000");
+    rtbl_add_column_entry_by_id (table, 3, "krbtgt/NADA.KTH.SE@NADA.KTH.SE");
+
+    rtbl_add_column_entry_by_id (table, 0, "Jul  7 21:19:29");
+    rtbl_add_column_entry_by_id (table, 1, "Jul  8 07:19:29");
+    rtbl_add_column_entry_by_id (table, 3, "afs/pdc.kth.se@NADA.KTH.SE");
+
+    rtbl_add_column_entry_by_id (table, 0, "Jul  7 21:19:29");
+    rtbl_add_column_entry_by_id (table, 1, "Jul  8 07:19:29");
+    rtbl_add_column_entry_by_id (table, 3, "afs@NADA.KTH.SE");
+
+    rtbl_set_separator (table, "  ");
+
+    rtbl_format (table, stdout);
+
+    rtbl_destroy (table);
+
+    printf("\n");
+
+    table = rtbl_create ();
+    rtbl_add_column_by_id (table, 0, "Column A", 0);
+    rtbl_set_column_affix_by_id (table, 0, "<", ">");
+    rtbl_add_column_by_id (table, 1, "Column B", 0);
+    rtbl_set_column_affix_by_id (table, 1, "[", "]");
+    rtbl_add_column_by_id (table, 2, "Column C", 0);
+    rtbl_set_column_affix_by_id (table, 2, "(", ")");
+
+    rtbl_add_column_entry_by_id (table, 0, "1");
+    rtbl_new_row(table);
+    rtbl_add_column_entry_by_id (table, 1, "2");
+    rtbl_new_row(table);
+    rtbl_add_column_entry_by_id (table, 2, "3");
+    rtbl_new_row(table);
+
+    rtbl_set_separator (table, "  ");
+    rtbl_format (table, stdout);
+
+    rtbl_destroy (table);
+
+    return 0;
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/rtbl.h b/src/kerberosV/src/lib/roken/rtbl.h
new file mode 100644 (file)
index 0000000..6263f92
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2000,2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $KTH: rtbl.h,v 1.5 2005/04/12 11:29:03 lha Exp $ */
+
+#ifndef __rtbl_h__
+#define __rtbl_h__
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+struct rtbl_data;
+typedef struct rtbl_data *rtbl_t;
+
+#define RTBL_ALIGN_LEFT                0
+#define RTBL_ALIGN_RIGHT       1
+
+/* flags */
+#define RTBL_HEADER_STYLE_NONE 1
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column (rtbl_t, const char*, unsigned int);
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_by_id (rtbl_t, unsigned int, const char*, unsigned int);
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry (rtbl_t, const char*, const char*);
+
+int ROKEN_LIB_FUNCTION
+rtbl_add_column_entry_by_id (rtbl_t, unsigned int, const char*);
+
+rtbl_t ROKEN_LIB_FUNCTION
+rtbl_create (void);
+
+void ROKEN_LIB_FUNCTION
+rtbl_destroy (rtbl_t);
+
+int ROKEN_LIB_FUNCTION
+rtbl_format (rtbl_t, FILE*);
+
+unsigned int ROKEN_LIB_FUNCTION
+rtbl_get_flags (rtbl_t);
+
+int ROKEN_LIB_FUNCTION
+rtbl_new_row (rtbl_t);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_affix_by_id (rtbl_t, unsigned int, const char*, const char*);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_column_prefix (rtbl_t, const char*, const char*);
+
+void ROKEN_LIB_FUNCTION
+rtbl_set_flags (rtbl_t, unsigned int);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_prefix (rtbl_t, const char*);
+
+int ROKEN_LIB_FUNCTION
+rtbl_set_separator (rtbl_t, const char*);
+
+#endif /* __rtbl_h__ */
diff --git a/src/kerberosV/src/lib/roken/sendmsg.c b/src/kerberosV/src/lib/roken/sendmsg.c
new file mode 100644 (file)
index 0000000..984ea48
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: sendmsg.c,v 1.5 2005/04/12 11:29:04 lha Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+sendmsg(int s, const struct msghdr *msg, int flags)
+{
+    ssize_t ret;
+    size_t tot = 0;
+    int i;
+    char *buf, *p;
+    struct iovec *iov = msg->msg_iov;
+
+    for(i = 0; i < msg->msg_iovlen; ++i)
+       tot += iov[i].iov_len;
+    buf = malloc(tot);
+    if (tot != 0 && buf == NULL) {
+       errno = ENOMEM;
+       return -1;
+    }
+    p = buf;
+    for (i = 0; i < msg->msg_iovlen; ++i) {
+       memcpy (p, iov[i].iov_base, iov[i].iov_len);
+       p += iov[i].iov_len;
+    }
+    ret = sendto (s, buf, tot, flags, msg->msg_name, msg->msg_namelen);
+    free (buf);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/setegid.c b/src/kerberosV/src/lib/roken/setegid.c
new file mode 100644 (file)
index 0000000..10e61be
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: setegid.c,v 1.10 2005/04/12 11:29:04 lha Exp $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+setegid(gid_t egid)
+{
+#ifdef HAVE_SETREGID
+    return setregid(-1, egid);
+#endif
+
+#ifdef HAVE_SETRESGID
+    return setresgid(-1, egid, -1);
+#endif
+
+    return -1;
+}
diff --git a/src/kerberosV/src/lib/roken/setenv.c b/src/kerberosV/src/lib/roken/setenv.c
new file mode 100644 (file)
index 0000000..4014a83
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: setenv.c,v 1.10 2005/04/12 11:29:04 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * This is the easy way out, use putenv to implement setenv. We might
+ * leak some memory but that is ok since we are usally about to exec
+ * anyway.
+ */
+
+int ROKEN_LIB_FUNCTION
+setenv(const char *var, const char *val, int rewrite)
+{
+    char *t;
+
+    if (!rewrite && getenv(var) != 0)
+       return 0;
+  
+    asprintf (&t, "%s=%s", var, val);
+    if (t == NULL)
+       return -1;
+
+    if (putenv(t) == 0)
+       return 0;
+    else
+       return -1;
+}
diff --git a/src/kerberosV/src/lib/roken/seteuid.c b/src/kerberosV/src/lib/roken/seteuid.c
new file mode 100644 (file)
index 0000000..08eddac
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: seteuid.c,v 1.11 2005/04/12 11:29:05 lha Exp $");
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+seteuid(uid_t euid)
+{
+#ifdef HAVE_SETREUID
+    return setreuid(-1, euid);
+#endif
+
+#ifdef HAVE_SETRESUID
+    return setresuid(-1, euid, -1);
+#endif
+
+    return -1;
+}
diff --git a/src/kerberosV/src/lib/roken/setprogname.c b/src/kerberosV/src/lib/roken/setprogname.c
new file mode 100644 (file)
index 0000000..6e5f9a7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995-2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: setprogname.c,v 1.3 2005/04/12 11:29:05 lha Exp $");
+#endif
+
+#include "roken.h"
+
+#ifndef HAVE___PROGNAME
+extern const char *__progname;
+#endif
+
+#ifndef HAVE_SETPROGNAME
+void ROKEN_LIB_FUNCTION
+setprogname(const char *argv0)
+{
+#ifndef HAVE___PROGNAME
+    char *p;
+    if(argv0 == NULL)
+       return;
+    p = strrchr(argv0, '/');
+    if(p == NULL)
+       p = (char *)argv0;
+    else
+       p++;
+    __progname = p;
+#endif
+}
+#endif /* HAVE_SETPROGNAME */
diff --git a/src/kerberosV/src/lib/roken/signal.c b/src/kerberosV/src/lib/roken/signal.c
new file mode 100644 (file)
index 0000000..1727303
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 1995 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: signal.c,v 1.13 2005/04/12 11:29:05 lha Exp $");
+#endif
+
+#include <signal.h>
+#include "roken.h"
+
+/*
+ * We would like to always use this signal but there is a link error
+ * on NEXTSTEP
+ */
+#if !defined(NeXT) && !defined(__APPLE__)
+/*
+ * Bugs:
+ *
+ * Do we need any extra hacks for SIGCLD and/or SIGCHLD?
+ */
+
+SigAction ROKEN_LIB_FUNCTION
+signal(int iSig, SigAction pAction)
+{
+    struct sigaction saNew, saOld;
+
+    saNew.sa_handler = pAction;
+    sigemptyset(&saNew.sa_mask);
+    saNew.sa_flags = 0;
+
+    if (iSig == SIGALRM)
+       {
+#ifdef SA_INTERRUPT
+           saNew.sa_flags |= SA_INTERRUPT;
+#endif
+       }
+    else
+       {
+#ifdef SA_RESTART
+           saNew.sa_flags |= SA_RESTART;
+#endif
+       }
+
+    if (sigaction(iSig, &saNew, &saOld) < 0)
+       return(SIG_ERR);
+
+    return(saOld.sa_handler);
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/simple_exec.c b/src/kerberosV/src/lib/roken/simple_exec.c
new file mode 100644 (file)
index 0000000..5e597b4
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 1998 - 2001, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: simple_exec.c,v 1.14 2005/04/13 11:39:00 lha Exp $");
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <errno.h>
+
+#include <roken.h>
+
+#define EX_NOEXEC      126
+#define EX_NOTFOUND    127
+
+/* return values:
+   -1   on `unspecified' system errors
+   -2   on fork failures
+   -3   on waitpid errors
+   -4   exec timeout
+   0-   is return value from subprocess
+   126  if the program couldn't be executed
+   127  if the program couldn't be found
+   128- is 128 + signal that killed subprocess
+
+   possible values `func' can return:
+   ((time_t)-2)                exit loop w/o killing child and return
+                       `exec timeout'/-4 from simple_exec
+   ((time_t)-1)                kill child with SIGTERM and wait for child to exit
+   0                   don't timeout again
+   n                   seconds to next timeout
+   */
+
+static int sig_alarm;
+
+static RETSIGTYPE
+sigtimeout(int sig)
+{
+    sig_alarm = 1;
+    SIGRETURN(0);
+}
+
+int ROKEN_LIB_FUNCTION
+wait_for_process_timed(pid_t pid, time_t (*func)(void *), 
+                      void *ptr, time_t timeout)
+{
+    RETSIGTYPE (*old_func)(int sig) = NULL;
+    unsigned int oldtime = 0;
+    int ret;
+
+    sig_alarm = 0;
+
+    if (func) {
+       old_func = signal(SIGALRM, sigtimeout);
+       oldtime = alarm(timeout);
+    }
+
+    while(1) {
+       int status;
+
+       while(waitpid(pid, &status, 0) < 0) {
+           if (errno != EINTR) {
+               ret = -3;
+               goto out;
+           }
+           if (func == NULL)
+               continue;
+           if (sig_alarm == 0)
+               continue;
+           timeout = (*func)(ptr);
+           if (timeout == (time_t)-1) {
+               kill(pid, SIGTERM);
+               continue;
+           } else if (timeout == (time_t)-2) {
+               ret = -4;
+               goto out;
+           }
+           alarm(timeout);
+       }
+       if(WIFSTOPPED(status))
+           continue;
+       if(WIFEXITED(status)) {
+           ret = WEXITSTATUS(status);
+           break;
+       }
+       if(WIFSIGNALED(status)) {
+           ret = WTERMSIG(status) + 128;
+           break;
+       }
+    }
+ out:
+    if (func) {
+       signal(SIGALRM, old_func);
+       alarm(oldtime);
+    }
+    return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+wait_for_process(pid_t pid)
+{
+    return wait_for_process_timed(pid, NULL, NULL, 0);
+}
+
+int ROKEN_LIB_FUNCTION
+pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd, 
+          const char *file, ...)
+{
+    int in_fd[2], out_fd[2], err_fd[2];
+    pid_t pid;
+    va_list ap;
+    char **argv;
+
+    if(stdin_fd != NULL)
+       pipe(in_fd);
+    if(stdout_fd != NULL)
+       pipe(out_fd);
+    if(stderr_fd != NULL)
+       pipe(err_fd);
+    pid = fork();
+    switch(pid) {
+    case 0:
+       va_start(ap, file);
+       argv = vstrcollect(&ap);
+       va_end(ap);
+       if(argv == NULL)
+           exit(-1);
+
+       /* close pipes we're not interested in */
+       if(stdin_fd != NULL)
+           close(in_fd[1]);
+       if(stdout_fd != NULL)
+           close(out_fd[0]);
+       if(stderr_fd != NULL)
+           close(err_fd[0]);
+
+       /* pipe everything caller doesn't care about to /dev/null */
+       if(stdin_fd == NULL)
+           in_fd[0] = open(_PATH_DEVNULL, O_RDONLY);
+       if(stdout_fd == NULL)
+           out_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
+       if(stderr_fd == NULL)
+           err_fd[1] = open(_PATH_DEVNULL, O_WRONLY);
+
+       /* move to proper descriptors */
+       if(in_fd[0] != STDIN_FILENO) {
+           dup2(in_fd[0], STDIN_FILENO);
+           close(in_fd[0]);
+       }
+       if(out_fd[1] != STDOUT_FILENO) {
+           dup2(out_fd[1], STDOUT_FILENO);
+           close(out_fd[1]);
+       }
+       if(err_fd[1] != STDERR_FILENO) {
+           dup2(err_fd[1], STDERR_FILENO);
+           close(err_fd[1]);
+       }
+
+       closefrom(3);
+
+       execv(file, argv);
+       exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
+    case -1:
+       if(stdin_fd != NULL) {
+           close(in_fd[0]);
+           close(in_fd[1]);
+       }
+       if(stdout_fd != NULL) {
+           close(out_fd[0]);
+           close(out_fd[1]);
+       }
+       if(stderr_fd != NULL) {
+           close(err_fd[0]);
+           close(err_fd[1]);
+       }
+       return -2;
+    default:
+       if(stdin_fd != NULL) {
+           close(in_fd[0]);
+           *stdin_fd = fdopen(in_fd[1], "w");
+       }
+       if(stdout_fd != NULL) {
+           close(out_fd[1]);
+           *stdout_fd = fdopen(out_fd[0], "r");
+       }
+       if(stderr_fd != NULL) {
+           close(err_fd[1]);
+           *stderr_fd = fdopen(err_fd[0], "r");
+       }
+    }
+    return pid;
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execvp_timed(const char *file, char *const args[], 
+                   time_t (*func)(void *), void *ptr, time_t timeout)
+{
+    pid_t pid = fork();
+    switch(pid){
+    case -1:
+       return -2;
+    case 0:
+       execvp(file, args);
+       exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
+    default: 
+       return wait_for_process_timed(pid, func, ptr, timeout);
+    }
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execvp(const char *file, char *const args[])
+{
+    return simple_execvp_timed(file, args, NULL, NULL, 0);
+}
+
+/* gee, I'd like a execvpe */
+int ROKEN_LIB_FUNCTION
+simple_execve_timed(const char *file, char *const args[], char *const envp[],
+                   time_t (*func)(void *), void *ptr, time_t timeout)
+{
+    pid_t pid = fork();
+    switch(pid){
+    case -1:
+       return -2;
+    case 0:
+       execve(file, args, envp);
+       exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);
+    default: 
+       return wait_for_process_timed(pid, func, ptr, timeout);
+    }
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execve(const char *file, char *const args[], char *const envp[])
+{
+    return simple_execve_timed(file, args, envp, NULL, NULL, 0);
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execlp(const char *file, ...)
+{
+    va_list ap;
+    char **argv;
+    int ret;
+
+    va_start(ap, file);
+    argv = vstrcollect(&ap);
+    va_end(ap);
+    if(argv == NULL)
+       return -1;
+    ret = simple_execvp(file, argv);
+    free(argv);
+    return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execle(const char *file, ... /* ,char *const envp[] */)
+{
+    va_list ap;
+    char **argv;
+    char *const* envp;
+    int ret;
+
+    va_start(ap, file);
+    argv = vstrcollect(&ap);
+    envp = va_arg(ap, char **);
+    va_end(ap);
+    if(argv == NULL)
+       return -1;
+    ret = simple_execve(file, argv, envp);
+    free(argv);
+    return ret;
+}
+
+int ROKEN_LIB_FUNCTION
+simple_execl(const char *file, ...) 
+{
+    va_list ap;
+    char **argv;
+    int ret;
+
+    va_start(ap, file);
+    argv = vstrcollect(&ap);
+    va_end(ap);
+    if(argv == NULL)
+       return -1;
+    ret = simple_execve(file, argv, environ);
+    free(argv);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/socket.c b/src/kerberosV/src/lib/roken/socket.c
new file mode 100644 (file)
index 0000000..21d821f
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 1999 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: socket.c,v 1.9 2005/04/12 11:29:06 lha Exp $");
+#endif
+
+#include <roken.h>
+#include <err.h>
+
+/*
+ * Set `sa' to the unitialized address of address family `af'
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_any (struct sockaddr *sa, int af)
+{
+    switch (af) {
+    case AF_INET : {
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+       memset (sin, 0, sizeof(*sin));
+       sin->sin_family = AF_INET;
+       sin->sin_port   = 0;
+       sin->sin_addr.s_addr = INADDR_ANY;
+       break;
+    }
+#ifdef HAVE_IPV6
+    case AF_INET6 : {
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+       memset (sin6, 0, sizeof(*sin6));
+       sin6->sin6_family = AF_INET6;
+       sin6->sin6_port   = 0;
+       sin6->sin6_addr   = in6addr_any;
+       break;
+    }
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * set `sa' to (`ptr', `port')
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_address_and_port (struct sockaddr *sa, const void *ptr, int port)
+{
+    switch (sa->sa_family) {
+    case AF_INET : {
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+
+       memset (sin, 0, sizeof(*sin));
+       sin->sin_family = AF_INET;
+       sin->sin_port   = port;
+       memcpy (&sin->sin_addr, ptr, sizeof(struct in_addr));
+       break;
+    }
+#ifdef HAVE_IPV6
+    case AF_INET6 : {
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+
+       memset (sin6, 0, sizeof(*sin6));
+       sin6->sin6_family = AF_INET6;
+       sin6->sin6_port   = port;
+       memcpy (&sin6->sin6_addr, ptr, sizeof(struct in6_addr));
+       break;
+    }
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * Return the size of an address of the type in `sa'
+ */
+
+size_t ROKEN_LIB_FUNCTION
+socket_addr_size (const struct sockaddr *sa)
+{
+    switch (sa->sa_family) {
+    case AF_INET :
+       return sizeof(struct in_addr);
+#ifdef HAVE_IPV6
+    case AF_INET6 :
+       return sizeof(struct in6_addr);
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * Return the size of a `struct sockaddr' in `sa'.
+ */
+
+size_t ROKEN_LIB_FUNCTION
+socket_sockaddr_size (const struct sockaddr *sa)
+{
+    switch (sa->sa_family) {
+    case AF_INET :
+       return sizeof(struct sockaddr_in);
+#ifdef HAVE_IPV6
+    case AF_INET6 :
+       return sizeof(struct sockaddr_in6);
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * Return the binary address of `sa'.
+ */
+
+void * ROKEN_LIB_FUNCTION
+socket_get_address (struct sockaddr *sa)
+{
+    switch (sa->sa_family) {
+    case AF_INET : {
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+       return &sin->sin_addr;
+    }
+#ifdef HAVE_IPV6
+    case AF_INET6 : {
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+       return &sin6->sin6_addr;
+    }
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * Return the port number from `sa'.
+ */
+
+int ROKEN_LIB_FUNCTION
+socket_get_port (const struct sockaddr *sa)
+{
+    switch (sa->sa_family) {
+    case AF_INET : {
+       const struct sockaddr_in *sin = (const struct sockaddr_in *)sa;
+       return sin->sin_port;
+    }
+#ifdef HAVE_IPV6
+    case AF_INET6 : {
+       const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+       return sin6->sin6_port;
+    }
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * Set the port in `sa' to `port'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_port (struct sockaddr *sa, int port)
+{
+    switch (sa->sa_family) {
+    case AF_INET : {
+       struct sockaddr_in *sin = (struct sockaddr_in *)sa;
+       sin->sin_port = port;
+       break;
+    }
+#ifdef HAVE_IPV6
+    case AF_INET6 : {
+       struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+       sin6->sin6_port = port;
+       break;
+    }
+#endif
+    default :
+       errx (1, "unknown address family %d", sa->sa_family);
+       break;
+    }
+}
+
+/*
+ * Set the range of ports to use when binding with port = 0.
+ */
+void ROKEN_LIB_FUNCTION
+socket_set_portrange (int sock, int restr, int af)
+{
+#if defined(IP_PORTRANGE)
+       if (af == AF_INET) {
+               int on = restr ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT;
+               if (setsockopt (sock, IPPROTO_IP, IP_PORTRANGE, &on,
+                   sizeof(on)) < 0)
+                       warn ("setsockopt IP_PORTRANGE (ignored)");
+       }
+#endif
+#if defined(IPV6_PORTRANGE)
+       if (af == AF_INET6) {
+               int on = restr ? IPV6_PORTRANGE_HIGH : 
+                   IPV6_PORTRANGE_DEFAULT;
+               if (setsockopt (sock, IPPROTO_IPV6, IPV6_PORTRANGE, &on,
+                   sizeof(on)) < 0)
+                       warn ("setsockopt IPV6_PORTRANGE (ignored)");
+       }
+#endif
+}
+       
+/*
+ * Enable debug on `sock'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_debug (int sock)
+{
+#if defined(SO_DEBUG) && defined(HAVE_SETSOCKOPT)
+    int on = 1;
+
+    if (setsockopt (sock, SOL_SOCKET, SO_DEBUG, (void *) &on, sizeof (on)) < 0)
+       warn ("setsockopt SO_DEBUG (ignored)");
+#endif
+}
+
+/*
+ * Set the type-of-service of `sock' to `tos'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_tos (int sock, int tos)
+{
+#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
+    if (setsockopt (sock, IPPROTO_IP, IP_TOS, (void *) &tos, sizeof (int)) < 0)
+       if (errno != EINVAL)
+           warn ("setsockopt TOS (ignored)");
+#endif
+}
+
+/*
+ * set the reuse of addresses on `sock' to `val'.
+ */
+
+void ROKEN_LIB_FUNCTION
+socket_set_reuseaddr (int sock, int val)
+{
+#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
+    if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&val,
+                 sizeof(val)) < 0)
+       err (1, "setsockopt SO_REUSEADDR");
+#endif
+}
diff --git a/src/kerberosV/src/lib/roken/strcasecmp.c b/src/kerberosV/src/lib/roken/strcasecmp.c
new file mode 100644 (file)
index 0000000..3cb6524
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strcasecmp.c,v 1.11 2005/04/12 11:29:07 lha Exp $");
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+#include "roken.h"
+
+#ifndef HAVE_STRCASECMP
+
+int ROKEN_LIB_FUNCTION
+strcasecmp(const char *s1, const char *s2)
+{
+    while(toupper((unsigned char)*s1) == toupper((unsigned char)*s2)) {
+       if(*s1 == '\0')
+           return 0;
+       s1++;
+       s2++;
+    }
+    return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/strcollect.c b/src/kerberosV/src/lib/roken/strcollect.c
new file mode 100644 (file)
index 0000000..4e39bee
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strcollect.c,v 1.2 2005/04/12 11:29:07 lha Exp $");
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <roken.h>
+
+enum { initial = 10, increment = 5 };
+
+static char **
+sub (char **argv, int i, int argc, va_list *ap)
+{
+    do {
+       if(i == argc) {
+           /* realloc argv */
+           char **tmp = realloc(argv, (argc + increment) * sizeof(*argv));
+           if(tmp == NULL) {
+               free(argv);
+               errno = ENOMEM;
+               return NULL;
+           }
+           argv  = tmp;
+           argc += increment;
+       }
+       argv[i++] = va_arg(*ap, char*);
+    } while(argv[i - 1] != NULL);
+    return argv;
+}
+
+/*
+ * return a malloced vector of pointers to the strings in `ap'
+ * terminated by NULL.
+ */
+
+char ** ROKEN_LIB_FUNCTION
+vstrcollect(va_list *ap)
+{
+    return sub (NULL, 0, 0, ap);
+}
+
+/*
+ *
+ */
+
+char ** ROKEN_LIB_FUNCTION
+strcollect(char *first, ...)
+{
+    va_list ap;
+    char **ret = malloc (initial * sizeof(char *));
+
+    if (ret == NULL)
+       return ret;
+
+    ret[0] = first;
+    va_start(ap, first);
+    ret = sub (ret, 1, initial, &ap);
+    va_end(ap);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/strlcat.c b/src/kerberosV/src/lib/roken/strlcat.c
new file mode 100644 (file)
index 0000000..6cfd041
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$KTH: strlcat.c,v 1.7 2005/04/12 11:29:08 lha Exp $");
+
+#ifndef HAVE_STRLCAT
+
+size_t ROKEN_LIB_FUNCTION
+strlcat (char *dst, const char *src, size_t dst_sz)
+{
+    size_t len = strlen(dst);
+
+    if (dst_sz < len)
+       /* the total size of dst is less than the string it contains;
+           this could be considered bad input, but we might as well
+           handle it */
+       return len + strlen(src);
+
+    return len + strlcpy (dst + len, src, dst_sz - len);
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/strlcpy.c b/src/kerberosV/src/lib/roken/strlcpy.c
new file mode 100644 (file)
index 0000000..c2d3bbc
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1995-2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$KTH: strlcpy.c,v 1.7 2005/04/12 11:29:09 lha Exp $");
+
+#ifndef HAVE_STRLCPY
+
+size_t ROKEN_LIB_FUNCTION
+strlcpy (char *dst, const char *src, size_t dst_sz)
+{
+    size_t n;
+
+    for (n = 0; n < dst_sz; n++) {
+       if ((*dst++ = *src++) == '\0')
+           break;
+    }
+
+    if (n < dst_sz)
+       return n;
+    if (n > 0)
+       *(dst - 1) = '\0';
+    return n + strlen (src);
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/strlwr.c b/src/kerberosV/src/lib/roken/strlwr.c
new file mode 100644 (file)
index 0000000..84c3e92
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strlwr.c,v 1.6 2005/04/12 11:29:09 lha Exp $");
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include <roken.h>
+
+#ifndef HAVE_STRLWR
+char * ROKEN_LIB_FUNCTION
+strlwr(char *str)
+{
+  char *s;
+
+  for(s = str; *s; s++)
+    *s = tolower((unsigned char)*s);
+  return str;
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/strncasecmp.c b/src/kerberosV/src/lib/roken/strncasecmp.c
new file mode 100644 (file)
index 0000000..7c365ac
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strncasecmp.c,v 1.4 2005/04/12 11:29:09 lha Exp $");
+#endif
+
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
+
+#ifndef HAVE_STRNCASECMP
+
+int ROKEN_LIB_FUNCTION
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+    while(n > 0 
+         && toupper((unsigned char)*s1) == toupper((unsigned char)*s2))
+    {
+       if(*s1 == '\0')
+           return 0;
+       s1++;
+       s2++;
+       n--;
+    }
+    if(n == 0)
+       return 0;
+    return toupper((unsigned char)*s1) - toupper((unsigned char)*s2);
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/strndup.c b/src/kerberosV/src/lib/roken/strndup.c
new file mode 100644 (file)
index 0000000..08c7c10
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strndup.c,v 1.3 2005/04/12 11:29:10 lha Exp $");
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <roken.h>
+
+#ifndef HAVE_STRNDUP
+char * ROKEN_LIB_FUNCTION
+strndup(const char *old, size_t sz)
+{
+    size_t len = strnlen (old, sz);
+    char *t    = malloc(len + 1);
+
+    if (t != NULL) {
+       memcpy (t, old, len);
+       t[len] = '\0';
+    }
+    return t;
+}
+#endif /* HAVE_STRNDUP */
diff --git a/src/kerberosV/src/lib/roken/strnlen.c b/src/kerberosV/src/lib/roken/strnlen.c
new file mode 100644 (file)
index 0000000..199814c
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1995 - 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strnlen.c,v 1.8 2005/04/12 11:29:10 lha Exp $");
+#endif
+
+#include "roken.h"
+
+size_t ROKEN_LIB_FUNCTION
+strnlen(const char *s, size_t len)
+{
+    size_t i;
+
+    for(i = 0; i < len && s[i]; i++)
+       ;
+    return i;
+}
diff --git a/src/kerberosV/src/lib/roken/strpftime-test.c b/src/kerberosV/src/lib/roken/strpftime-test.c
new file mode 100644 (file)
index 0000000..3796d95
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+RCSID("$KTH: strpftime-test.c,v 1.3 2005/04/04 19:31:56 lha Exp $");
+
+enum { MAXSIZE = 26 };
+
+static struct testcase {
+    time_t t;
+    struct {
+       const char *format;
+       const char *result;
+    } vals[MAXSIZE];
+} tests[] = {
+    {0,
+     {
+        {"%A", "Thursday"},
+        {"%a", "Thu"},
+        {"%B", "January"},
+        {"%b", "Jan"},
+        {"%C", "19"},
+        {"%d", "01"},
+        {"%e", " 1"},
+        {"%H", "00"},
+        {"%I", "12"},
+        {"%j", "001"},
+        {"%k", " 0"},
+        {"%l", "12"},
+        {"%M", "00"},
+        {"%m", "01"},
+        {"%n", "\n"},
+        {"%p", "AM"},
+        {"%S", "00"},
+        {"%t", "\t"},
+        {"%w", "4"},
+        {"%Y", "1970"},
+        {"%y", "70"},
+        {"%U", "00"},
+        {"%W", "00"},
+        {"%V", "01"},
+        {"%%", "%"},
+        {NULL, NULL}}
+    },
+    {90000,
+     {
+        {"%A", "Friday"},
+        {"%a", "Fri"},
+        {"%B", "January"},
+        {"%b", "Jan"},
+        {"%C", "19"},
+        {"%d", "02"},
+        {"%e", " 2"},
+        {"%H", "01"},
+        {"%I", "01"},
+        {"%j", "002"},
+        {"%k", " 1"},
+        {"%l", " 1"},
+        {"%M", "00"},
+        {"%m", "01"},
+        {"%n", "\n"},
+        {"%p", "AM"},
+        {"%S", "00"},
+        {"%t", "\t"},
+        {"%w", "5"},
+        {"%Y", "1970"},
+        {"%y", "70"},
+        {"%U", "00"},
+        {"%W", "00"},
+        {"%V", "01"},
+        {"%%", "%"},
+        {NULL, NULL}
+     }
+    },
+    {216306,
+     {
+        {"%A", "Saturday"},
+        {"%a", "Sat"},
+        {"%B", "January"},
+        {"%b", "Jan"},
+        {"%C", "19"},
+        {"%d", "03"},
+        {"%e", " 3"},
+        {"%H", "12"},
+        {"%I", "12"},
+        {"%j", "003"},
+        {"%k", "12"},
+        {"%l", "12"},
+        {"%M", "05"},
+        {"%m", "01"},
+        {"%n", "\n"},
+        {"%p", "PM"},
+        {"%S", "06"},
+        {"%t", "\t"},
+        {"%w", "6"},
+        {"%Y", "1970"},
+        {"%y", "70"},
+        {"%U", "00"},
+        {"%W", "00"},
+        {"%V", "01"},
+        {"%%", "%"},
+        {NULL, NULL}
+     }
+    },
+    {259200,
+     {
+        {"%A", "Sunday"},
+        {"%a", "Sun"},
+        {"%B", "January"},
+        {"%b", "Jan"},
+        {"%C", "19"},
+        {"%d", "04"},
+        {"%e", " 4"},
+        {"%H", "00"},
+        {"%I", "12"},
+        {"%j", "004"},
+        {"%k", " 0"},
+        {"%l", "12"},
+        {"%M", "00"},
+        {"%m", "01"},
+        {"%n", "\n"},
+        {"%p", "AM"},
+        {"%S", "00"},
+        {"%t", "\t"},
+        {"%w", "0"},
+        {"%Y", "1970"},
+        {"%y", "70"},
+        {"%U", "01"},
+        {"%W", "00"},
+        {"%V", "01"},
+        {"%%", "%"},
+        {NULL, NULL}
+     }
+    },
+    {915148800,
+     {
+        {"%A", "Friday"},
+        {"%a", "Fri"},
+        {"%B", "January"},
+        {"%b", "Jan"},
+        {"%C", "19"},
+        {"%d", "01"},
+        {"%e", " 1"},
+        {"%H", "00"},
+        {"%I", "12"},
+        {"%j", "001"},
+        {"%k", " 0"},
+        {"%l", "12"},
+        {"%M", "00"},
+        {"%m", "01"},
+        {"%n", "\n"},
+        {"%p", "AM"},
+        {"%S", "00"},
+        {"%t", "\t"},
+        {"%w", "5"},
+        {"%Y", "1999"},
+        {"%y", "99"},
+        {"%U", "00"},
+        {"%W", "00"},
+        {"%V", "53"},
+        {"%%", "%"},
+        {NULL, NULL}}
+    },
+    {942161105,
+     {
+
+        {"%A", "Tuesday"},
+        {"%a", "Tue"},
+        {"%B", "November"},
+        {"%b", "Nov"},
+        {"%C", "19"},
+        {"%d", "09"},
+        {"%e", " 9"},
+        {"%H", "15"},
+        {"%I", "03"},
+        {"%j", "313"},
+        {"%k", "15"},
+        {"%l", " 3"},
+        {"%M", "25"},
+        {"%m", "11"},
+        {"%n", "\n"},
+        {"%p", "PM"},
+        {"%S", "05"},
+        {"%t", "\t"},
+        {"%w", "2"},
+        {"%Y", "1999"},
+        {"%y", "99"},
+        {"%U", "45"},
+        {"%W", "45"},
+        {"%V", "45"},
+        {"%%", "%"},
+        {NULL, NULL}
+     }
+    }
+};
+
+int
+main(int argc, char **argv)
+{
+    int i, j;
+    int ret = 0;
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i) {
+       struct tm *tm;
+
+       tm = gmtime (&tests[i].t);
+
+       for (j = 0; tests[i].vals[j].format != NULL; ++j) {
+           char buf[128];
+           size_t len;
+           struct tm tm2;
+           char *ptr;
+
+           len = strftime (buf, sizeof(buf), tests[i].vals[j].format, tm);
+           if (len != strlen (buf)) {
+               printf ("length of strftime(\"%s\") = %lu (\"%s\")\n",
+                       tests[i].vals[j].format, (unsigned long)len,
+                       buf);
+               ++ret;
+               continue;
+           }
+           if (strcmp (buf, tests[i].vals[j].result) != 0) {
+               printf ("result of strftime(\"%s\") = \"%s\" != \"%s\"\n",
+                       tests[i].vals[j].format, buf,
+                       tests[i].vals[j].result);
+               ++ret;
+               continue;
+           }
+           memset (&tm2, 0, sizeof(tm2));
+           ptr = strptime (tests[i].vals[j].result,
+                           tests[i].vals[j].format,
+                           &tm2);
+           if (ptr == NULL || *ptr != '\0') {
+               printf ("bad return value from strptime("
+                       "\"%s\", \"%s\")\n",
+                       tests[i].vals[j].result,
+                       tests[i].vals[j].format);
+               ++ret;
+           }
+           strftime (buf, sizeof(buf), tests[i].vals[j].format, &tm2);
+           if (strcmp (buf, tests[i].vals[j].result) != 0) {
+               printf ("reverse of \"%s\" failed: \"%s\" vs \"%s\"\n",
+                       tests[i].vals[j].format,
+                       buf, tests[i].vals[j].result);
+               ++ret;
+           }
+       }
+    }
+    if (ret) {
+       printf ("%d errors\n", ret);
+       return 1;
+    } else
+       return 0;
+}
diff --git a/src/kerberosV/src/lib/roken/strptime.c b/src/kerberosV/src/lib/roken/strptime.c
new file mode 100644 (file)
index 0000000..5317c51
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 1999 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. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <ctype.h>
+#include "roken.h"
+
+RCSID("$KTH: strptime.c,v 1.6 2005/05/18 09:54:53 lha Exp $");
+
+static const char *abb_weekdays[] = {
+    "Sun",
+    "Mon",
+    "Tue",
+    "Wed",
+    "Thu",
+    "Fri",
+    "Sat",
+    NULL
+};
+
+static const char *full_weekdays[] = {
+    "Sunday",
+    "Monday",
+    "Tuesday",
+    "Wednesday",
+    "Thursday",
+    "Friday",
+    "Saturday",
+    NULL
+};
+
+static const char *abb_month[] = {
+    "Jan",
+    "Feb",
+    "Mar",
+    "Apr",
+    "May",
+    "Jun",
+    "Jul",
+    "Aug",
+    "Sep",
+    "Oct",
+    "Nov",
+    "Dec",
+    NULL
+};
+
+static const char *full_month[] = {
+    "January",
+    "February",
+    "March",
+    "April",
+    "May",
+    "June",
+    "July",
+    "August",
+    "September",
+    "October",
+    "November",
+    "December",
+    NULL,
+};
+
+static const char *ampm[] = {
+    "am",
+    "pm",
+    NULL
+};
+
+/*
+ * Try to match `*buf' to one of the strings in `strs'.  Return the
+ * index of the matching string (or -1 if none).  Also advance buf.
+ */
+
+static int
+match_string (const char **buf, const char **strs)
+{
+    int i = 0;
+
+    for (i = 0; strs[i] != NULL; ++i) {
+       int len = strlen (strs[i]);
+
+       if (strncasecmp (*buf, strs[i], len) == 0) {
+           *buf += len;
+           return i;
+       }
+    }
+    return -1;
+}
+
+/*
+ * tm_year is relative this year */
+
+const int tm_year_base = 1900;
+
+/*
+ * Return TRUE iff `year' was a leap year.
+ */
+
+static int
+is_leap_year (int year)
+{
+    return (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0);
+}
+
+/*
+ * Return the weekday [0,6] (0 = Sunday) of the first day of `year'
+ */
+
+static int
+first_day (int year)
+{
+    int ret = 4;
+
+    for (; year > 1970; --year)
+       ret = (ret + 365 + is_leap_year (year) ? 1 : 0) % 7;
+    return ret;
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_sun (struct tm *timeptr, int wnum)
+{
+    int fday = first_day (timeptr->tm_year + tm_year_base);
+
+    timeptr->tm_yday = wnum * 7 + timeptr->tm_wday - fday;
+    if (timeptr->tm_yday < 0) {
+       timeptr->tm_wday = fday;
+       timeptr->tm_yday = 0;
+    }
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_mon (struct tm *timeptr, int wnum)
+{
+    int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
+
+    timeptr->tm_yday = wnum * 7 + (timeptr->tm_wday + 6) % 7 - fday;
+    if (timeptr->tm_yday < 0) {
+       timeptr->tm_wday = (fday + 1) % 7;
+       timeptr->tm_yday = 0;
+    }
+}
+
+/*
+ * Set `timeptr' given `wnum' (week number [0, 53])
+ */
+
+static void
+set_week_number_mon4 (struct tm *timeptr, int wnum)
+{
+    int fday = (first_day (timeptr->tm_year + tm_year_base) + 6) % 7;
+    int offset = 0;
+
+    if (fday < 4)
+       offset += 7;
+
+    timeptr->tm_yday = offset + (wnum - 1) * 7 + timeptr->tm_wday - fday;
+    if (timeptr->tm_yday < 0) {
+       timeptr->tm_wday = fday;
+       timeptr->tm_yday = 0;
+    }
+}
+
+/*
+ *
+ */
+
+char * ROKEN_LIB_FUNCTION
+strptime (const char *buf, const char *format, struct tm *timeptr)
+{
+    char c;
+
+    for (; (c = *format) != '\0'; ++format) {
+       char *s;
+       int ret;
+
+       if (isspace ((unsigned char)c)) {
+           while (isspace ((unsigned char)*buf))
+               ++buf;
+       } else if (c == '%' && format[1] != '\0') {
+           c = *++format;
+           if (c == 'E' || c == 'O')
+               c = *++format;
+           switch (c) {
+           case 'A' :
+               ret = match_string (&buf, full_weekdays);
+               if (ret < 0)
+                   return NULL;
+               timeptr->tm_wday = ret;
+               break;
+           case 'a' :
+               ret = match_string (&buf, abb_weekdays);
+               if (ret < 0)
+                   return NULL;
+               timeptr->tm_wday = ret;
+               break;
+           case 'B' :
+               ret = match_string (&buf, full_month);
+               if (ret < 0)
+                   return NULL;
+               timeptr->tm_mon = ret;
+               break;
+           case 'b' :
+           case 'h' :
+               ret = match_string (&buf, abb_month);
+               if (ret < 0)
+                   return NULL;
+               timeptr->tm_mon = ret;
+               break;
+           case 'C' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_year = (ret * 100) - tm_year_base;
+               buf = s;
+               break;
+           case 'c' :
+               abort ();
+           case 'D' :          /* %m/%d/%y */
+               s = strptime (buf, "%m/%d/%y", timeptr);
+               if (s == NULL)
+                   return NULL;
+               buf = s;
+               break;
+           case 'd' :
+           case 'e' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_mday = ret;
+               buf = s;
+               break;
+           case 'H' :
+           case 'k' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_hour = ret;
+               buf = s;
+               break;
+           case 'I' :
+           case 'l' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               if (ret == 12)
+                   timeptr->tm_hour = 0;
+               else
+                   timeptr->tm_hour = ret;
+               buf = s;
+               break;
+           case 'j' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_yday = ret - 1;
+               buf = s;
+               break;
+           case 'm' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_mon = ret - 1;
+               buf = s;
+               break;
+           case 'M' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_min = ret;
+               buf = s;
+               break;
+           case 'n' :
+               while (isspace (*buf))
+                   buf++;
+               break;
+           case 'p' :
+               ret = match_string (&buf, ampm);
+               if (ret < 0)
+                   return NULL;
+               if (timeptr->tm_hour == 0) {
+                   if (ret == 1)
+                       timeptr->tm_hour = 12;
+               } else
+                   timeptr->tm_hour += 12;
+               break;
+           case 'r' :          /* %I:%M:%S %p */
+               s = strptime (buf, "%I:%M:%S %p", timeptr);
+               if (s == NULL)
+                   return NULL;
+               buf = s;
+               break;
+           case 'R' :          /* %H:%M */
+               s = strptime (buf, "%H:%M", timeptr);
+               if (s == NULL)
+                   return NULL;
+               buf = s;
+               break;
+           case 'S' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_sec = ret;
+               buf = s;
+               break;
+           case 't' :
+               while (isspace (*buf))
+                   buf++;
+               break;
+           case 'T' :          /* %H:%M:%S */
+           case 'X' :
+               s = strptime (buf, "%H:%M:%S", timeptr);
+               if (s == NULL)
+                   return NULL;
+               buf = s;
+               break;
+           case 'u' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_wday = ret - 1;
+               buf = s;
+               break;
+           case 'w' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_wday = ret;
+               buf = s;
+               break;
+           case 'U' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               set_week_number_sun (timeptr, ret);
+               buf = s;
+               break;
+           case 'V' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               set_week_number_mon4 (timeptr, ret);
+               buf = s;
+               break;
+           case 'W' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               set_week_number_mon (timeptr, ret);
+               buf = s;
+               break;
+           case 'x' :
+               s = strptime (buf, "%Y:%m:%d", timeptr);
+               if (s == NULL)
+                   return NULL;
+               buf = s;
+               break;
+           case 'y' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               if (ret < 70)
+                   timeptr->tm_year = 100 + ret;
+               else
+                   timeptr->tm_year = ret;
+               buf = s;
+               break;
+           case 'Y' :
+               ret = strtol (buf, &s, 10);
+               if (s == buf)
+                   return NULL;
+               timeptr->tm_year = ret - tm_year_base;
+               buf = s;
+               break;
+           case 'Z' :
+               abort ();
+           case '\0' :
+               --format;
+               /* FALLTHROUGH */
+           case '%' :
+               if (*buf == '%')
+                   ++buf;
+               else
+                   return NULL;
+               break;
+           default :
+               if (*buf == '%' || *++buf == c)
+                   ++buf;
+               else
+                   return NULL;
+               break;
+           }
+       } else {
+           if (*buf == c)
+               ++buf;
+           else
+               return NULL;
+       }
+    }
+    return (char *)buf;
+}
diff --git a/src/kerberosV/src/lib/roken/strsep.c b/src/kerberosV/src/lib/roken/strsep.c
new file mode 100644 (file)
index 0000000..009d185
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strsep.c,v 1.4 2005/04/12 11:29:10 lha Exp $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRSEP
+
+char * ROKEN_LIB_FUNCTION
+strsep(char **str, const char *delim)
+{
+    char *save = *str;
+    if(*str == NULL)
+       return NULL;
+    *str = *str + strcspn(*str, delim);
+    if(**str == 0)
+       *str = NULL;
+    else{
+       **str = 0;
+       (*str)++;
+    }
+    return save;
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/strsep_copy.c b/src/kerberosV/src/lib/roken/strsep_copy.c
new file mode 100644 (file)
index 0000000..3bae75a
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2000, 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strsep_copy.c,v 1.5 2005/04/12 11:29:11 lha Exp $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRSEP_COPY
+
+/* strsep, but with const stringp, so return string in buf */
+
+ssize_t ROKEN_LIB_FUNCTION
+strsep_copy(const char **stringp, const char *delim, char *buf, size_t len)
+{
+    const char *save = *stringp;
+    size_t l;
+    if(save == NULL)
+       return -1;
+    *stringp = *stringp + strcspn(*stringp, delim);
+    l = min(len, *stringp - save);
+    if(len > 0) {
+       memcpy(buf, save, l);
+       buf[l] = '\0';
+    }
+
+    l = *stringp - save;
+    if(**stringp == '\0')
+       *stringp = NULL;
+    else
+       (*stringp)++;
+    return l;
+}
+
+#endif
diff --git a/src/kerberosV/src/lib/roken/strtok_r.c b/src/kerberosV/src/lib/roken/strtok_r.c
new file mode 100644 (file)
index 0000000..9feb04b
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strtok_r.c,v 1.6 2005/04/12 11:29:11 lha Exp $");
+#endif
+
+#include <string.h>
+
+#include "roken.h"
+
+#ifndef HAVE_STRTOK_R
+
+char * ROKEN_LIB_FUNCTION
+strtok_r(char *s1, const char *s2, char **lasts)
+{
+  char *ret;
+
+  if (s1 == NULL)
+    s1 = *lasts;
+  while(*s1 && strchr(s2, *s1))
+    ++s1;
+  if(*s1 == '\0')
+    return NULL;
+  ret = s1;
+  while(*s1 && !strchr(s2, *s1))
+    ++s1;
+  if(*s1)
+    *s1++ = '\0';
+  *lasts = s1;
+  return ret;
+}
+
+#endif /* HAVE_STRTOK_R */
diff --git a/src/kerberosV/src/lib/roken/strupr.c b/src/kerberosV/src/lib/roken/strupr.c
new file mode 100644 (file)
index 0000000..5f19733
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: strupr.c,v 1.6 2005/04/12 11:29:11 lha Exp $");
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include <roken.h>
+
+#ifndef HAVE_STRUPR
+char * ROKEN_LIB_FUNCTION
+strupr(char *str)
+{
+  char *s;
+
+  for(s = str; *s; s++)
+    *s = toupper((unsigned char)*s);
+  return str;
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/swab.c b/src/kerberosV/src/lib/roken/swab.c
new file mode 100644 (file)
index 0000000..bfc80e3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include "roken.h"
+
+#ifndef HAVE_SWAB
+
+RCSID("$KTH: swab.c,v 1.8 2005/04/12 11:29:12 lha Exp $");
+
+void ROKEN_LIB_FUNCTION
+swab (char *from, char *to, int nbytes)
+{
+     while(nbytes >= 2) {
+         *(to + 1) = *from;
+         *to = *(from + 1);
+         to += 2;
+         from += 2;
+         nbytes -= 2;
+     }
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/test-mem.c b/src/kerberosV/src/lib/roken/test-mem.c
new file mode 100644 (file)
index 0000000..a9a6209
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1999 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <roken.h>
+
+#include "test-mem.h"
+
+RCSID("$KTH: test-mem.c,v 1.4 2005/05/29 21:20:26 lha Exp $");
+
+/* #undef HAVE_MMAP */
+
+struct {
+    void *start;
+    size_t size;
+    void *data_start;
+    size_t data_size;
+    enum rk_test_mem_type type;
+    int fd;
+} map;
+
+struct sigaction sa, osa;
+
+char *testname;
+
+static RETSIGTYPE
+segv_handler(int sig)
+{
+    int fd;
+    char msg[] = "SIGSEGV i current test: ";
+    
+    fd = open("/dev/stdout", O_WRONLY, 0600);
+    if (fd >= 0) {
+       write(fd, msg, sizeof(msg) - 1);
+       write(fd, testname, strlen(testname));
+       write(fd, "\n", 1);
+       close(fd);
+    }
+    _exit(1);
+}
+
+#define TESTREC()                                                      \
+    if (testname)                                                      \
+       errx(1, "test %s run recursively on %s", name, testname);       \
+    testname = strdup(name);                                           \
+    if (testname == NULL)                                              \
+       errx(1, "malloc");
+
+
+void * ROKEN_LIB_FUNCTION
+rk_test_mem_alloc(enum rk_test_mem_type type, const char *name,
+                 void *buf, size_t size)
+{
+#ifndef HAVE_MMAP
+    unsigned char *p;
+    
+    TESTREC();
+
+    p = malloc(size + 2);
+    if (p == NULL)
+       errx(1, "malloc");
+    map.type = type;
+    map.start = p;
+    map.size = size + 2;
+    p[0] = 0xff;
+    p[map.size] = 0xff;
+    map.data_start = p + 1;
+#else
+    unsigned char *p;
+    int flags, ret, fd;
+    size_t pagesize = getpagesize();
+
+    TESTREC();
+
+    map.type = type;
+
+#ifdef MAP_ANON
+    flags = MAP_ANON;
+    fd = -1;
+#else
+    flags = 0;
+    fd = open ("/dev/zero", O_RDONLY);
+    if(fd < 0)
+       err (1, "open /dev/zero");
+#endif
+    map.fd = fd;
+    flags |= MAP_PRIVATE;
+
+    map.size = size + pagesize - (size % pagesize) + pagesize * 2;
+
+    p = (unsigned char *)mmap(0, map.size, PROT_READ | PROT_WRITE,
+                             flags, fd, 0);
+    if (p == (unsigned char *)MAP_FAILED)
+       err (1, "mmap");
+
+    map.start = p;
+
+    ret = mprotect ((void *)p, pagesize, 0);
+    if (ret < 0)
+       err (1, "mprotect");
+
+    ret = mprotect (p + map.size - pagesize, pagesize, 0);
+    if (ret < 0)
+       err (1, "mprotect");
+
+    switch (type) {
+    case RK_TM_OVERRUN:
+       map.data_start = p + map.size - pagesize - size;
+       break;
+    case RK_TM_UNDERRUN:
+       map.data_start = p + pagesize;
+       break;
+    default:
+       abort();
+    }
+#endif
+    sigemptyset (&sa.sa_mask);
+    sa.sa_flags = 0;
+#ifdef SA_RESETHAND
+    sa.sa_flags |= SA_RESETHAND;
+#endif
+    sa.sa_handler = segv_handler;
+    sigaction (SIGSEGV, &sa, &osa);
+
+    map.data_size = size;
+    if (buf)
+       memcpy(map.data_start, buf, size);
+    return map.data_start;
+}
+
+void ROKEN_LIB_FUNCTION
+rk_test_mem_free(const char *map_name)
+{
+#ifndef HAVE_MMAP
+    unsigned char *p = map.start;
+    
+    if (testname == NULL)
+       errx(1, "test_mem_free call on no free");
+
+    if (p[0] != 0xff)
+       errx(1, "%s: %s underrun %x\n", testname, map_name, p[0]);
+    if (p[map.size] != 0xff)
+       errx(1, "%s: %s overrun %x\n", testname, map_name, p[map.size - 1]);
+    free(map.start);
+#else
+    int ret;
+    
+    if (testname == NULL)
+       errx(1, "test_mem_free call on no free");
+
+    ret = munmap (map.start, map.size);
+    if (ret < 0)
+       err (1, "munmap");
+    if (map.fd > 0)
+       close(map.fd);
+#endif
+    free(testname);
+    testname = NULL;
+
+    sigaction (SIGSEGV, &osa, NULL);
+}
diff --git a/src/kerberosV/src/lib/roken/test-mem.h b/src/kerberosV/src/lib/roken/test-mem.h
new file mode 100644 (file)
index 0000000..896222f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1999 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+enum rk_test_mem_type { RK_TM_OVERRUN, RK_TM_UNDERRUN };
+
+void * ROKEN_LIB_FUNCTION
+       rk_test_mem_alloc(enum rk_test_mem_type, const char *, void *, size_t);
+void ROKEN_LIB_FUNCTION
+       rk_test_mem_free(const char *);
diff --git a/src/kerberosV/src/lib/roken/test-readenv.c b/src/kerberosV/src/lib/roken/test-readenv.c
new file mode 100644 (file)
index 0000000..538b44c
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2005 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: test-readenv.c,v 1.1 2005/05/17 09:02:57 joda Exp $");
+#endif
+
+#include "roken.h"
+#include "test-mem.h"
+
+char *s1 = "VAR1=VAL1#comment\n\
+VAR2=VAL2 VAL2 #comment\n\
+#this another comment\n\
+\n\
+VAR3=FOO";
+
+char *s2 = "VAR1=ENV2\n\
+";
+
+static void
+make_file(char *tmpl, size_t l)
+{
+    int fd;
+    strlcpy(tmpl, "env.XXXXXX", l);
+    fd = mkstemp(tmpl);
+    if(fd < 0)
+       err(1, "mkstemp");
+    close(fd);
+}
+
+static void
+write_file(const char *fn, const char *s)
+{
+    FILE *f;
+    f = fopen(fn, "w");
+    if(f == NULL) {
+       unlink(fn);
+       err(1, "fopen");
+    }
+    if(fwrite(s, 1, strlen(s), f) != strlen(s))
+       err(1, "short write");
+    if(fclose(f) != 0) {
+       unlink(fn);
+       err(1, "fclose");
+    }
+}
+
+int
+main(int argc, char **argv)
+{
+    char **env = NULL;
+    int count = 0;
+    char fn[MAXPATHLEN];
+    int error = 0;
+
+    make_file(fn, sizeof(fn));
+
+    write_file(fn, s1);
+    count = read_environment(fn, &env);
+    if(count != 3) {
+       warnx("test 1: variable count %d != 3", count);
+       error++;
+    }
+
+    write_file(fn, s2);
+    count = read_environment(fn, &env);
+    if(count != 1) {
+       warnx("test 2: variable count %d != 1", count);
+       error++;
+    }
+    unlink(fn);
+    count = read_environment(fn, &env);
+    if(count != 0) {
+       warnx("test 3: variable count %d != 0", count);
+       error++;
+    }
+    for(count = 0; env && env[count]; count++);
+    if(count != 3) {
+       warnx("total variable count %d != 3", count);
+       error++;
+    }
+    
+    
+    return error;
+}
diff --git a/src/kerberosV/src/lib/roken/timeval.c b/src/kerberosV/src/lib/roken/timeval.c
new file mode 100644 (file)
index 0000000..af4a181
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Timeval stuff
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: timeval.c,v 1.2 2005/04/12 11:29:13 lha Exp $");
+#endif
+
+#include "roken.h"
+
+/*
+ * Make `t1' consistent.
+ */
+
+void ROKEN_LIB_FUNCTION
+timevalfix(struct timeval *t1)
+{
+    if (t1->tv_usec < 0) {
+        t1->tv_sec--;
+        t1->tv_usec += 1000000;
+    }
+    if (t1->tv_usec >= 1000000) {
+        t1->tv_sec++;
+        t1->tv_usec -= 1000000;
+    }
+}
+/*
+ * t1 += t2
+ */
+
+void ROKEN_LIB_FUNCTION
+timevaladd(struct timeval *t1, const struct timeval *t2)
+{
+    t1->tv_sec  += t2->tv_sec;
+    t1->tv_usec += t2->tv_usec;
+    timevalfix(t1);
+}
+/*
+ * t1 -= t2
+ */
+
+void ROKEN_LIB_FUNCTION
+timevalsub(struct timeval *t1, const struct timeval *t2)
+{
+    t1->tv_sec  -= t2->tv_sec;
+    t1->tv_usec -= t2->tv_usec;
+    timevalfix(t1);
+}
diff --git a/src/kerberosV/src/lib/roken/tm2time.c b/src/kerberosV/src/lib/roken/tm2time.c
new file mode 100644 (file)
index 0000000..2c5e6ef
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: tm2time.c,v 1.9 2005/04/12 11:29:13 lha Exp $");
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#include "roken.h"
+
+time_t ROKEN_LIB_FUNCTION
+tm2time (struct tm tm, int local)
+{
+    time_t t;
+
+    tm.tm_isdst = local ? -1 : 0;
+
+    t = mktime (&tm);
+
+    if (!local)
+       t += t - mktime (gmtime (&t));
+    return t;
+}
diff --git a/src/kerberosV/src/lib/roken/unsetenv.c b/src/kerberosV/src/lib/roken/unsetenv.c
new file mode 100644 (file)
index 0000000..57be970
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: unsetenv.c,v 1.8 2005/04/12 11:29:13 lha Exp $");
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "roken.h"
+
+extern char **environ;
+
+/*
+ * unsetenv --
+ */
+void ROKEN_LIB_FUNCTION
+unsetenv(const char *name)
+{
+  int len;
+  const char *np;
+  char **p;
+
+  if (name == 0 || environ == 0)
+    return;
+
+  for (np = name; *np && *np != '='; np++)
+    /* nop */;
+  len = np - name;
+  
+  for (p = environ; *p != 0; p++)
+    if (strncmp(*p, name, len) == 0 && (*p)[len] == '=')
+      break;
+
+  for (; *p != 0; p++)
+    *p = *(p + 1);
+}
+
diff --git a/src/kerberosV/src/lib/roken/unvis.c b/src/kerberosV/src/lib/roken/unvis.c
new file mode 100644 (file)
index 0000000..10df0d7
--- /dev/null
@@ -0,0 +1,284 @@
+/*     $NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $       */
+
+/*-
+ * 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. 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 1
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: unvis.c,v 1.5 2005/04/18 08:28:35 lha Exp $");
+#endif
+#include <roken.h>
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+#else
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)unvis.c    8.1 (Berkeley) 6/4/93";
+#else
+__RCSID("$NetBSD: unvis.c,v 1.19 2000/01/22 22:19:13 mycroft Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#define __LIBC12_SOURCE__
+
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <vis.h>
+
+#if 0
+#ifdef __weak_alias
+__weak_alias(strunvis,_strunvis)
+__weak_alias(unvis,_unvis)
+#endif
+
+__warn_references(unvis,
+    "warning: reference to compatibility unvis(); include <vis.h> for correct reference")
+#endif
+
+/*
+ * decode driven by state machine
+ */
+#define        S_GROUND        0       /* haven't seen escape char */
+#define        S_START         1       /* start decoding special sequence */
+#define        S_META          2       /* metachar started (M) */
+#define        S_META1         3       /* metachar more, regular char (-) */
+#define        S_CTRL          4       /* control char started (^) */
+#define        S_OCTAL2        5       /* octal digit 2 */
+#define        S_OCTAL3        6       /* octal digit 3 */
+
+#define        isoctal(c)      (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+
+/*
+ * unvis - decode characters previously encoded by vis
+ */
+#ifndef HAVE_UNVIS
+int ROKEN_LIB_FUNCTION
+unvis(char *cp, int c, int *astate, int flag)
+{
+
+       _DIAGASSERT(cp != NULL);
+       _DIAGASSERT(astate != NULL);
+
+       if (flag & UNVIS_END) {
+               if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               } 
+               return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
+       }
+
+       switch (*astate) {
+
+       case S_GROUND:
+               *cp = 0;
+               if (c == '\\') {
+                       *astate = S_START;
+                       return (0);
+               } 
+               *cp = c;
+               return (UNVIS_VALID);
+
+       case S_START:
+               switch(c) {
+               case '\\':
+                       *cp = c;
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case '0': case '1': case '2': case '3':
+               case '4': case '5': case '6': case '7':
+                       *cp = (c - '0');
+                       *astate = S_OCTAL2;
+                       return (0);
+               case 'M':
+                       *cp = (char)0200;
+                       *astate = S_META;
+                       return (0);
+               case '^':
+                       *astate = S_CTRL;
+                       return (0);
+               case 'n':
+                       *cp = '\n';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'r':
+                       *cp = '\r';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'b':
+                       *cp = '\b';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'a':
+                       *cp = '\007';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'v':
+                       *cp = '\v';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 't':
+                       *cp = '\t';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'f':
+                       *cp = '\f';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 's':
+                       *cp = ' ';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case 'E':
+                       *cp = '\033';
+                       *astate = S_GROUND;
+                       return (UNVIS_VALID);
+               case '\n':
+                       /*
+                        * hidden newline
+                        */
+                       *astate = S_GROUND;
+                       return (UNVIS_NOCHAR);
+               case '$':
+                       /*
+                        * hidden marker
+                        */
+                       *astate = S_GROUND;
+                       return (UNVIS_NOCHAR);
+               }
+               *astate = S_GROUND;
+               return (UNVIS_SYNBAD);
+                
+       case S_META:
+               if (c == '-')
+                       *astate = S_META1;
+               else if (c == '^')
+                       *astate = S_CTRL;
+               else {
+                       *astate = S_GROUND;
+                       return (UNVIS_SYNBAD);
+               }
+               return (0);
+                
+       case S_META1:
+               *astate = S_GROUND;
+               *cp |= c;
+               return (UNVIS_VALID);
+                
+       case S_CTRL:
+               if (c == '?')
+                       *cp |= 0177;
+               else
+                       *cp |= c & 037;
+               *astate = S_GROUND;
+               return (UNVIS_VALID);
+
+       case S_OCTAL2:  /* second possible octal digit */
+               if (isoctal(c)) {
+                       /* 
+                        * yes - and maybe a third 
+                        */
+                       *cp = (*cp << 3) + (c - '0');
+                       *astate = S_OCTAL3;     
+                       return (0);
+               } 
+               /* 
+                * no - done with current sequence, push back passed char 
+                */
+               *astate = S_GROUND;
+               return (UNVIS_VALIDPUSH);
+
+       case S_OCTAL3:  /* third possible octal digit */
+               *astate = S_GROUND;
+               if (isoctal(c)) {
+                       *cp = (*cp << 3) + (c - '0');
+                       return (UNVIS_VALID);
+               }
+               /*
+                * we were done, push back passed char
+                */
+               return (UNVIS_VALIDPUSH);
+                       
+       default:        
+               /* 
+                * decoder in unknown state - (probably uninitialized) 
+                */
+               *astate = S_GROUND;
+               return (UNVIS_SYNBAD);
+       }
+}
+#endif
+
+/*
+ * strunvis - decode src into dst 
+ *
+ *     Number of chars decoded into dst is returned, -1 on error.
+ *     Dst is null terminated.
+ */
+
+#ifndef HAVE_STRUNVIS
+int ROKEN_LIB_FUNCTION
+strunvis(char *dst, const char *src)
+{
+       char c;
+       char *start = dst;
+       int state = 0;
+
+       _DIAGASSERT(src != NULL);
+       _DIAGASSERT(dst != NULL);
+
+       while ((c = *src++) != '\0') {
+       again:
+               switch (unvis(dst, (unsigned char)c, &state, 0)) {
+               case UNVIS_VALID:
+                       dst++;
+                       break;
+               case UNVIS_VALIDPUSH:
+                       dst++;
+                       goto again;
+               case 0:
+               case UNVIS_NOCHAR:
+                       break;
+               default:
+                       return (-1);
+               }
+       }
+       if (unvis(dst, (unsigned char)c, &state, UNVIS_END) == UNVIS_VALID)
+               dst++;
+       *dst = '\0';
+       return (dst - start);
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/verify.c b/src/kerberosV/src/lib/roken/verify.c
new file mode 100644 (file)
index 0000000..939445e
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: verify.c,v 1.14 2005/04/12 11:29:14 lha Exp $");
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#include "roken.h"
+
+int ROKEN_LIB_FUNCTION
+unix_verify_user(char *user, char *password)
+{
+    struct passwd *pw;
+    
+    pw = k_getpwnam(user);
+    if(pw == NULL)
+       return -1;
+    if(strlen(pw->pw_passwd) == 0 && strlen(password) == 0)
+       return 0;
+    if(strcmp(crypt(password, pw->pw_passwd), pw->pw_passwd) == 0)
+        return 0;
+    return -1;
+}
+
diff --git a/src/kerberosV/src/lib/roken/verr.c b/src/kerberosV/src/lib/roken/verr.c
new file mode 100644 (file)
index 0000000..8efb823
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: verr.c,v 1.11 2005/04/12 11:29:14 lha Exp $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+verr(int eval, const char *fmt, va_list ap)
+{
+    warnerr(1, fmt, ap);
+    exit(eval);
+}
diff --git a/src/kerberosV/src/lib/roken/verrx.c b/src/kerberosV/src/lib/roken/verrx.c
new file mode 100644 (file)
index 0000000..34fe1f2
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: verrx.c,v 1.11 2005/04/12 11:29:15 lha Exp $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+verrx(int eval, const char *fmt, va_list ap)
+{
+    warnerr(0, fmt, ap);
+    exit(eval);
+}
diff --git a/src/kerberosV/src/lib/roken/vis.c b/src/kerberosV/src/lib/roken/vis.c
new file mode 100644 (file)
index 0000000..91952b6
--- /dev/null
@@ -0,0 +1,323 @@
+/*     $NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $      */
+
+/*-
+ * 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. 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) 1999 The NetBSD Foundation, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE 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 1
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vis.c,v 1.9 2005/04/12 11:29:15 lha Exp $");
+#endif
+#include <roken.h>
+#ifndef _DIAGASSERT
+#define _DIAGASSERT(X)
+#endif
+#else
+#include <sys/cdefs.h>
+#if !defined(lint)
+__RCSID("$NetBSD: vis.c,v 1.4 2003/08/07 09:15:32 agc Exp $");
+#endif /* not lint */
+#endif
+
+#if 0
+#include "namespace.h"
+#endif
+#include <sys/types.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include <vis.h>
+
+#if 0
+#ifdef __weak_alias
+__weak_alias(strsvis,_strsvis)
+__weak_alias(strsvisx,_strsvisx)
+__weak_alias(strvis,_strvis)
+__weak_alias(strvisx,_strvisx)
+__weak_alias(svis,_svis)
+__weak_alias(vis,_vis)
+#endif
+#endif
+
+#undef BELL
+#if defined(__STDC__)
+#define BELL '\a'
+#else
+#define BELL '\007'
+#endif
+
+#define isoctal(c)     (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define iswhite(c)     (c == ' ' || c == '\t' || c == '\n')
+#define issafe(c)      (c == '\b' || c == BELL || c == '\r')
+
+#define MAXEXTRAS       5
+
+
+#define MAKEEXTRALIST(flag, extra)                                           \
+do {                                                                         \
+       char *pextra = extra;                                                 \
+       if (flag & VIS_SP) *pextra++ = ' ';                                   \
+       if (flag & VIS_TAB) *pextra++ = '\t';                                 \
+       if (flag & VIS_NL) *pextra++ = '\n';                                  \
+       if ((flag & VIS_NOSLASH) == 0) *pextra++ = '\\';                      \
+       *pextra = '\0';                                                       \
+} while (/*CONSTCOND*/0)
+
+/*
+ * This is SVIS, the central macro of vis.
+ * dst:              Pointer to the destination buffer
+ * c:        Character to encode
+ * flag:      Flag word
+ * nextc:     The character following 'c'
+ * extra:     Pointer to the list of extra characters to be
+ *           backslash-protected.
+ */
+#define SVIS(dst, c, flag, nextc, extra)                                  \
+do {                                                                      \
+       int isextra, isc;                                                  \
+       isextra = strchr(extra, c) != NULL;                                \
+       if (!isextra &&                                                    \
+           isascii((unsigned char)c) &&                                   \
+           (isgraph((unsigned char)c) || iswhite(c) ||                    \
+           ((flag & VIS_SAFE) && issafe(c)))) {                           \
+               *dst++ = c;                                                \
+               break;                                                     \
+       }                                                                  \
+       isc = 0;                                                           \
+       if (flag & VIS_CSTYLE) {                                           \
+               switch (c) {                                               \
+               case '\n':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 'n';              \
+                       break;                                             \
+               case '\r':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 'r';              \
+                       break;                                             \
+               case '\b':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 'b';              \
+                       break;                                             \
+               case BELL:                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 'a';              \
+                       break;                                             \
+               case '\v':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 'v';              \
+                       break;                                             \
+               case '\t':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 't';              \
+                       break;                                             \
+               case '\f':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = 'f';              \
+                       break;                                             \
+               case ' ':                                                  \
+                       isc = 1; *dst++ = '\\'; *dst++ = 's';              \
+                       break;                                             \
+               case '\0':                                                 \
+                       isc = 1; *dst++ = '\\'; *dst++ = '0';              \
+                       if (isoctal(nextc)) {                              \
+                               *dst++ = '0';                              \
+                               *dst++ = '0';                              \
+                       }                                                  \
+               }                                                          \
+       }                                                                  \
+       if (isc) break;                                                    \
+       if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {        \
+               *dst++ = '\\';                                             \
+               *dst++ = (u_char)(((unsigned)(u_char)c >> 6) & 03) + '0';  \
+               *dst++ = (u_char)(((unsigned)(u_char)c >> 3) & 07) + '0';  \
+               *dst++ =                             (c       & 07) + '0'; \
+       } else {                                                           \
+               if ((flag & VIS_NOSLASH) == 0) *dst++ = '\\';              \
+               if (c & 0200) {                                            \
+                       c &= 0177; *dst++ = 'M';                           \
+               }                                                          \
+               if (iscntrl((unsigned char)c)) {                           \
+                       *dst++ = '^';                                      \
+                       if (c == 0177)                                     \
+                               *dst++ = '?';                              \
+                       else                                               \
+                               *dst++ = c + '@';                          \
+               } else {                                                   \
+                       *dst++ = '-'; *dst++ = c;                          \
+               }                                                          \
+       }                                                                  \
+} while (/*CONSTCOND*/0)
+
+
+/*
+ * svis - visually encode characters, also encoding the characters
+ *       pointed to by `extra'
+ */
+#ifndef HAVE_SVIS
+char * ROKEN_LIB_FUNCTION
+svis(char *dst, int c, int flag, int nextc, const char *extra)
+{
+       _DIAGASSERT(dst != NULL);
+       _DIAGASSERT(extra != NULL);
+
+       SVIS(dst, c, flag, nextc, extra);
+       *dst = '\0';
+       return(dst);
+}
+#endif
+
+
+/*
+ * strsvis, strsvisx - visually encode characters from src into dst
+ *
+ *     Extra is a pointer to a \0-terminated list of characters to
+ *     be encoded, too. These functions are useful e. g. to
+ *     encode strings in such a way so that they are not interpreted
+ *     by a shell.
+ *     
+ *     Dst must be 4 times the size of src to account for possible
+ *     expansion.  The length of dst, not including the trailing NULL,
+ *     is returned. 
+ *
+ *     Strsvisx encodes exactly len bytes from src into dst.
+ *     This is useful for encoding a block of data.
+ */
+#ifndef HAVE_STRSVIS
+int ROKEN_LIB_FUNCTION
+strsvis(char *dst, const char *src, int flag, const char *extra)
+{
+       char c;
+       char *start;
+
+       _DIAGASSERT(dst != NULL);
+       _DIAGASSERT(src != NULL);
+       _DIAGASSERT(extra != NULL);
+
+       for (start = dst; (c = *src++) != '\0'; /* empty */)
+           SVIS(dst, c, flag, *src, extra);
+       *dst = '\0';
+       return (dst - start);
+}
+#endif
+
+
+#ifndef HAVE_STRVISX
+int ROKEN_LIB_FUNCTION
+strsvisx(char *dst, const char *src, size_t len, int flag, const char *extra)
+{
+       char c;
+       char *start;
+
+       _DIAGASSERT(dst != NULL);
+       _DIAGASSERT(src != NULL);
+       _DIAGASSERT(extra != NULL);
+
+       for (start = dst; len > 0; len--) {
+               c = *src++;
+               SVIS(dst, c, flag, len ? *src : '\0', extra);
+       }
+       *dst = '\0';
+       return (dst - start);
+}
+#endif
+
+
+/*
+ * vis - visually encode characters
+ */
+#ifndef HAVE_VIS
+char * ROKEN_LIB_FUNCTION
+vis(char *dst, int c, int flag, int nextc)
+{
+       char extra[MAXEXTRAS];
+
+       _DIAGASSERT(dst != NULL);
+
+       MAKEEXTRALIST(flag, extra);
+       SVIS(dst, c, flag, nextc, extra);
+       *dst = '\0';
+       return (dst);
+}
+#endif
+
+
+/*
+ * strvis, strvisx - visually encode characters from src into dst
+ *     
+ *     Dst must be 4 times the size of src to account for possible
+ *     expansion.  The length of dst, not including the trailing NULL,
+ *     is returned. 
+ *
+ *     Strvisx encodes exactly len bytes from src into dst.
+ *     This is useful for encoding a block of data.
+ */
+#ifndef HAVE_STRVIS
+int ROKEN_LIB_FUNCTION
+strvis(char *dst, const char *src, int flag)
+{
+       char extra[MAXEXTRAS];
+
+       MAKEEXTRALIST(flag, extra);
+       return (strsvis(dst, src, flag, extra));
+}
+#endif
+
+
+#ifndef HAVE_STRVISX
+int ROKEN_LIB_FUNCTION
+strvisx(char *dst, const char *src, size_t len, int flag)
+{
+       char extra[MAXEXTRAS];
+
+       MAKEEXTRALIST(flag, extra);
+       return (strsvisx(dst, src, len, flag, extra));
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/vis.hin b/src/kerberosV/src/lib/roken/vis.hin
new file mode 100644 (file)
index 0000000..c9f3f7c
--- /dev/null
@@ -0,0 +1,98 @@
+/*     $NetBSD: vis.h,v 1.11 1999/11/25 16:55:50 wennmach Exp $        */
+/*     $KTH: vis.hin,v 1.3 2005/04/12 11:29:15 lha Exp $       */
+
+/*-
+ * Copyright (c) 1990, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ *     @(#)vis.h       8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _VIS_H_
+#define        _VIS_H_
+
+#ifndef ROKEN_LIB_FUNCTION
+#ifdef _WIN32
+#define ROKEN_LIB_FUNCTION _stdcall
+#else
+#define ROKEN_LIB_FUNCTION
+#endif
+#endif
+
+/*
+ * to select alternate encoding format
+ */
+#define        VIS_OCTAL       0x01    /* use octal \ddd format */
+#define        VIS_CSTYLE      0x02    /* use \[nrft0..] where appropiate */
+
+/*
+ * to alter set of characters encoded (default is to encode all
+ * non-graphic except space, tab, and newline).
+ */
+#define        VIS_SP          0x04    /* also encode space */
+#define        VIS_TAB         0x08    /* also encode tab */
+#define        VIS_NL          0x10    /* also encode newline */
+#define        VIS_WHITE       (VIS_SP | VIS_TAB | VIS_NL)
+#define        VIS_SAFE        0x20    /* only encode "unsafe" characters */
+
+/*
+ * other
+ */
+#define        VIS_NOSLASH     0x40    /* inhibit printing '\' */
+
+/*
+ * unvis return codes
+ */
+#define        UNVIS_VALID      1      /* character valid */
+#define        UNVIS_VALIDPUSH  2      /* character valid, push back passed char */
+#define        UNVIS_NOCHAR     3      /* valid sequence, no character produced */
+#define        UNVIS_SYNBAD    -1      /* unrecognized escape sequence */
+#define        UNVIS_ERROR     -2      /* decoder in unknown state (unrecoverable) */
+
+/*
+ * unvis flags
+ */
+#define        UNVIS_END       1       /* no more characters */
+
+char ROKEN_LIB_FUNCTION
+       *vis (char *, int, int, int);
+char ROKEN_LIB_FUNCTION
+       *svis (char *, int, int, int, const char *);
+int ROKEN_LIB_FUNCTION
+       strvis (char *, const char *, int);
+int ROKEN_LIB_FUNCTION
+       strsvis (char *, const char *, int, const char *);
+int ROKEN_LIB_FUNCTION
+       strvisx (char *, const char *, size_t, int);
+int ROKEN_LIB_FUNCTION
+       strsvisx (char *, const char *, size_t, int, const char *);
+int ROKEN_LIB_FUNCTION
+       strunvis (char *, const char *);
+int ROKEN_LIB_FUNCTION
+       unvis (char *, int, int *, int);
+
+#endif /* !_VIS_H_ */
diff --git a/src/kerberosV/src/lib/roken/vsyslog.c b/src/kerberosV/src/lib/roken/vsyslog.c
new file mode 100644 (file)
index 0000000..4497b72
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 1995 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vsyslog.c,v 1.7 2005/04/12 11:29:16 lha Exp $");
+#endif
+
+#ifndef HAVE_VSYSLOG
+
+#include <stdio.h>
+#include <syslog.h>
+#include <stdarg.h>
+
+#include "roken.h"
+
+/*
+ * the theory behind this is that we might be trying to call vsyslog
+ * when there's no memory left, and we should try to be as useful as
+ * possible.  And the format string should say something about what's
+ * failing.
+ */
+
+static void
+simple_vsyslog(int pri, const char *fmt, va_list ap)
+{
+    syslog (pri, "%s", fmt);
+}
+
+/*
+ * do like syslog but with a `va_list'
+ */
+
+void ROKEN_LIB_FUNCTION
+vsyslog(int pri, const char *fmt, va_list ap)
+{
+    char *fmt2;
+    const char *p;
+    char *p2;
+    int saved_errno = errno;
+    int fmt_len  = strlen (fmt);
+    int fmt2_len = fmt_len;
+    char *buf;
+
+    fmt2 = malloc (fmt_len + 1);
+    if (fmt2 == NULL) {
+       simple_vsyslog (pri, fmt, ap);
+       return;
+    }
+
+    for (p = fmt, p2 = fmt2; *p != '\0'; ++p) {
+       if (p[0] == '%' && p[1] == 'm') {
+           const char *e = strerror (saved_errno);
+           int e_len = strlen (e);
+           char *tmp;
+           int pos;
+
+           pos = p2 - fmt2;
+           fmt2_len += e_len - 2;
+           tmp = realloc (fmt2, fmt2_len + 1);
+           if (tmp == NULL) {
+               free (fmt2);
+               simple_vsyslog (pri, fmt, ap);
+               return;
+           }
+           fmt2 = tmp;
+           p2   = fmt2 + pos;
+           memmove (p2, e, e_len);
+           p2 += e_len;
+           ++p;
+       } else
+           *p2++ = *p;
+    }
+    *p2 = '\0';
+
+    vasprintf (&buf, fmt2, ap);
+    free (fmt2);
+    if (buf == NULL) {
+       simple_vsyslog (pri, fmt, ap);
+       return;
+    }
+    syslog (pri, "%s", buf);
+    free (buf);
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/vwarn.c b/src/kerberosV/src/lib/roken/vwarn.c
new file mode 100644 (file)
index 0000000..9b508f8
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vwarn.c,v 1.11 2005/04/12 11:29:16 lha Exp $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+vwarn(const char *fmt, va_list ap)
+{
+    warnerr(1, fmt, ap);
+}
diff --git a/src/kerberosV/src/lib/roken/vwarnx.c b/src/kerberosV/src/lib/roken/vwarnx.c
new file mode 100644 (file)
index 0000000..eca9a8c
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: vwarnx.c,v 1.11 2005/04/12 11:29:16 lha Exp $");
+#endif
+
+#include "roken.h"
+#include <err.h>
+
+void ROKEN_LIB_FUNCTION
+vwarnx(const char *fmt, va_list ap)
+{
+    warnerr(0, fmt, ap);
+}
+
diff --git a/src/kerberosV/src/lib/roken/warn.c b/src/kerberosV/src/lib/roken/warn.c
new file mode 100644 (file)
index 0000000..b4e5adb
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: warn.c,v 1.6 1999/12/02 16:58:54 joda Exp $");
+#endif
+
+#include "err.h"
+
+void
+warn(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  vwarn(fmt, ap);
+  va_end(ap);
+}
diff --git a/src/kerberosV/src/lib/roken/warnerr.c b/src/kerberosV/src/lib/roken/warnerr.c
new file mode 100644 (file)
index 0000000..0dbfa18
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1995 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: warnerr.c,v 1.16 2005/04/12 11:29:17 lha Exp $");
+#endif
+
+#include "roken.h"
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+warnerr(int doerrno, const char *fmt, va_list ap)
+{
+    int sverrno = errno;
+    extern char *__progname;
+
+    if(__progname != NULL){
+       fprintf(stderr, "%s", __progname);
+       if(fmt != NULL || doerrno)
+           fprintf(stderr, ": ");
+    }
+    if (fmt != NULL){
+       vfprintf(stderr, fmt, ap);
+       if(doerrno)
+           fprintf(stderr, ": ");
+    }
+    if(doerrno)
+       fprintf(stderr, "%s", strerror(sverrno));
+    fprintf(stderr, "\n");
+}
diff --git a/src/kerberosV/src/lib/roken/warnx.c b/src/kerberosV/src/lib/roken/warnx.c
new file mode 100644 (file)
index 0000000..86b73c9
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1995, 1996, 1997 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: warnx.c,v 1.7 2005/04/12 11:29:17 lha Exp $");
+#endif
+
+#include "err.h"
+
+void ROKEN_LIB_FUNCTION
+warnx(const char *fmt, ...)
+{
+  va_list ap;
+  va_start(ap, fmt);
+  vwarnx(fmt, ap);
+  va_end(ap);
+}
diff --git a/src/kerberosV/src/lib/roken/write_pid.c b/src/kerberosV/src/lib/roken/write_pid.c
new file mode 100644 (file)
index 0000000..2d5874e
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1999 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: write_pid.c,v 1.7 2005/04/12 11:29:17 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <roken.h>
+
+#include "roken.h"
+
+char * ROKEN_LIB_FUNCTION
+pid_file_write (const char *progname)
+{
+    FILE *fp;
+    char *ret;
+
+    asprintf (&ret, "%s%s.pid", _PATH_VARRUN, progname);
+    if (ret == NULL)
+       return NULL;
+    fp = fopen (ret, "w");
+    if (fp == NULL) {
+       free (ret);
+       return NULL;
+    }
+    fprintf (fp, "%u", (unsigned)getpid());
+    fclose (fp);
+    return ret;
+}
+
+void ROKEN_LIB_FUNCTION
+pid_file_delete (char **filename)
+{
+    if (*filename != NULL) {
+       unlink (*filename);
+       free (*filename);
+       *filename = NULL;
+    }
+}
+
+#ifndef HAVE_PIDFILE
+static char *pidfile_path;
+
+static void
+pidfile_cleanup(void)
+{
+    if(pidfile_path != NULL)
+       pid_file_delete(&pidfile_path);
+}
+
+void
+pidfile(const char *basename)
+{
+    if(pidfile_path != NULL)
+       return;
+    if(basename == NULL)
+       basename = __progname;
+    pidfile_path = pid_file_write(basename);
+#if defined(HAVE_ATEXIT)
+    atexit(pidfile_cleanup);
+#elif defined(HAVE_ON_EXIT)
+    on_exit(pidfile_cleanup);
+#endif
+}
+#endif
diff --git a/src/kerberosV/src/lib/roken/writev.c b/src/kerberosV/src/lib/roken/writev.c
new file mode 100644 (file)
index 0000000..a415091
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: writev.c,v 1.4 2005/04/12 11:29:18 lha Exp $");
+#endif
+
+#include "roken.h"
+
+ssize_t ROKEN_LIB_FUNCTION
+writev(int d, const struct iovec *iov, int iovcnt)
+{
+    ssize_t ret;
+    size_t tot = 0;
+    int i;
+    char *buf, *p;
+
+    for(i = 0; i < iovcnt; ++i)
+       tot += iov[i].iov_len;
+    buf = malloc(tot);
+    if (tot != 0 && buf == NULL) {
+       errno = ENOMEM;
+       return -1;
+    }
+    p = buf;
+    for (i = 0; i < iovcnt; ++i) {
+       memcpy (p, iov[i].iov_base, iov[i].iov_len);
+       p += iov[i].iov_len;
+    }
+    ret = write (d, buf, tot);
+    free (buf);
+    return ret;
+}
diff --git a/src/kerberosV/src/lib/roken/xdbm.h b/src/kerberosV/src/lib/roken/xdbm.h
new file mode 100644 (file)
index 0000000..a8fb31b
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1995 - 2002 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: xdbm.h,v 1.15 2002/05/17 16:02:22 joda Exp $ */
+
+/* Generic *dbm include file */
+
+#ifndef __XDBM_H__
+#define __XDBM_H__
+
+#if HAVE_DB_NDBM
+#define DB_DBM_HSEARCH 1
+#include <db.h>
+#elif HAVE_NDBM
+#if defined(HAVE_GDBM_NDBM_H)
+#include <gdbm/ndbm.h>
+#elif defined(HAVE_NDBM_H)
+#include <ndbm.h>
+#endif
+#endif /* HAVE_NDBM */
+
+#endif /* __XDBM_H__ */
diff --git a/src/kerberosV/src/lib/sl/CVS/Entries b/src/kerberosV/src/lib/sl/CVS/Entries
new file mode 100644 (file)
index 0000000..5b9e018
--- /dev/null
@@ -0,0 +1,15 @@
+/ChangeLog/1.1.1.5/Fri Apr 14 07:33:54 2006//
+/lex.l/1.1.1.2/Sun May 11 02:16:12 2003//
+/make_cmds.c/1.2/Wed Jun  5 16:16:50 2002//
+/make_cmds.h/1.1.1.1/Fri May 25 07:52:22 2001//
+/parse.y/1.1.1.1/Fri May 25 07:52:22 2001//
+/roken_rename.h/1.1.1.2/Fri Jun 22 21:26:31 2001//
+/sl.c/1.5/Mon Dec 18 21:08:28 2006//
+/sl.h/1.1.1.2/Fri Apr 14 07:33:55 2006//
+/sl_locl.h/1.1.1.1/Fri May 25 07:52:23 2001//
+/slc-gram.y/1.2/Fri Apr 14 09:49:26 2006//
+/slc-lex.l/1.2/Fri Apr 14 09:49:26 2006//
+/slc.h/1.1.1.1/Fri Apr 14 07:33:55 2006//
+/ss.c/1.2/Sat Apr 12 23:20:08 2003//
+/ss.h/1.1.1.1/Fri May 25 07:52:23 2001//
+D
diff --git a/src/kerberosV/src/lib/sl/CVS/Repository b/src/kerberosV/src/lib/sl/CVS/Repository
new file mode 100644 (file)
index 0000000..80c8707
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/sl
diff --git a/src/kerberosV/src/lib/sl/CVS/Root b/src/kerberosV/src/lib/sl/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/sl/ChangeLog b/src/kerberosV/src/lib/sl/ChangeLog
new file mode 100644 (file)
index 0000000..af4591c
--- /dev/null
@@ -0,0 +1,237 @@
+2005-05-10  Dave Love  <fx@gnu.org>
+
+       * slc-lex.l: Include <stdlib.h>.
+
+2005-05-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * sl.c (sl_command_loop): new return code -2 for EOF
+       (sl_loop): treat all return value from sl_command_loop >= 0 as ok, and
+       continue.
+
+2005-04-29  Dave Love  <fx@gnu.org>
+
+       * Makefile.am (LDADD): Add libsl.la.
+
+2005-04-19  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * slc-gram.y: include <config.h> since defines _GNU_SOURCE if
+       needed, avoid asprintf warning
+
+2005-01-21  Dave Love  <d.love@dl.ac.uk>
+
+       * slc-gram.y: include <roken.h>
+
+2005-01-09  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * slc-gram.y: cast argument to isalnum to unsigned char
+
+2004-09-22  Johan Danielsson  <joda@pdc.kth.se>
+
+       * slc-gram.y: add support for "strings" and "negative-flag" types,
+       plus some usability tweaks and bug fixes
+       
+2004-07-05  Johan Danielsson  <joda@pdc.kth.se>
+
+       * slc-gram.y: add min_args/max_args checking
+       
+2004-06-21  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * slc-gram.y: pull in <stdlib.h> and <vers.h> to avoid warnings
+       
+2004-03-02  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * sl.h: make it possible to use libsl from c++
+       From: Mattias Amnefelt <mattiasa@kth.se>
+       
+2002-05-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: just link mk_cmds against libsl; avoids libtool
+       problem
+
+2001-07-09  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add getprogname.c libss.la:add libcom_err.la noted
+       by Leif Johansson <leifj@it.su.se>
+
+2001-05-17  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump versions to 1:2:1 and 1:4:1
+
+2001-05-06  Assar Westerlund  <assar@sics.se>
+
+       * roken_rename.h (strdup): add
+
+2001-03-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: re do the roken-renaming properly
+
+2001-02-13  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add more functions to rename
+
+2001-01-26  Johan Danielsson  <joda@pdc.kth.se>
+
+       * sl.h: proto
+
+       * sl.c (sl_command_loop): try to handle user pressing C-c
+
+2000-12-11  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (libss_la_LDFLAGS): bump version to 1:2:1
+
+2000-08-19  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: add dependencies for libss/libsl shared libraries
+
+2000-07-25  Johan Danielsson  <joda@pdc.kth.se>
+
+       * Makefile.am: bump ss version to 1:1:1
+
+2000-06-27  Assar Westerlund  <assar@sics.se>
+
+       * parse.y (yyerror): static-ize
+       * make_cmds.h (error_message, yylex): add prototypes
+       * lex.l: fix prototypes and kill warnings
+
+2000-05-24  Assar Westerlund  <assar@sics.se>
+
+       * ss.h (SS_ET_COMMAND_NOT_FOUND): add
+       * ss.c: check allocation and return some other error codes too
+
+2000-04-29  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in: add LIB_tgetent.  From Derrick J Brashear
+       <shadow@dementia.org>
+
+2000-04-03  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: set version to 1:0:1
+
+2000-03-07  Assar Westerlund  <assar@sics.se>
+
+       * sl.h (SL_BADCOMMAND): define
+       (sl_apropos): add prototype
+
+       * sl.c: mandoc-generation
+       (sl_apropos): stolen from arla
+
+2000-01-06  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: bump both versions to 0:1:0
+
+1999-12-16  Assar Westerlund  <assar@sics.se>
+
+       * parse.y (name2number): not used here.  remove.
+
+Thu Apr  1 17:03:59 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * make_cmds.c: use getarg
+
+Tue Mar 23 14:36:21 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: don't rename
+
+Sun Mar 21 14:13:29 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: don't roken-rename
+
+Sat Mar 20 03:43:30 1999  Assar Westerlund  <assar@sics.se>
+
+       * parse.y: replace return with YYACCEPT
+
+Fri Mar 19 14:53:20 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: add libss; add version-info
+
+Thu Mar 18 15:07:06 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.am: clean lex.c parse.c parse.h
+
+       * Makefile.am: install ss.h
+
+       * Makefile.am: include Makefile.am.common
+
+Thu Mar 11 15:01:01 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * parse.y: prototype for error_message
+
+Tue Feb  9 23:45:37 1999  Johan Danielsson  <joda@hella.pdc.kth.se>
+
+       * Makefile.in: add snprintf.o to make_cmds
+
+Sun Nov 22 10:46:23 1998  Assar Westerlund  <assar@sics.se>
+
+       * sl.c (sl_command_loop): remove unused variable
+
+       * ss.c (ss_error): remove unused variable
+
+       * make_cmds.c: include err.h
+       (main): remove unused variable
+
+       * Makefile.in (WFLAGS): set
+
+Sun Sep 27 01:28:21 1998  Assar Westerlund  <assar@sics.se>
+
+       * make_cmds.c: clean-up and simplification
+
+Mon May 25 02:54:13 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in (clean): try to remove shared library debris
+
+       * Makefile.in: make symlink magic work
+
+Sun Apr 19 10:00:26 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.in: add symlink magic for linux
+
+Sun Apr  5 09:21:43 1998  Assar Westerlund  <assar@sics.se>
+
+       * parse.y: define alloca to malloc in case we're using bison but
+       don't have alloca
+
+Sat Mar 28 11:39:00 1998  Assar Westerlund  <assar@sics.se>
+
+       * sl.c (sl_loop): s/2/1
+
+Sat Mar 21 00:46:51 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * sl.c (sl_loop): check that there is at least one argument before
+       calling sl_command
+
+Sun Mar  1 05:14:37 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * sl.c (sl_loop): Fix general broken-ness.
+
+       * sl.c: Cleanup printing of help strings.
+
+Thu Feb 26 02:22:02 1998  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: @LEXLIB@
+
+Sat Feb 21 15:18:21 1998  assar westerlund  <assar@sics.se>
+
+       * Makefile.in: set YACC and LEX
+
+Mon Feb 16 16:08:25 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Makefile.am: Some fixes for ss/mk_cmds.
+
+Sun Feb 15 05:12:11 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * Makefile.in: Install libsl under the `libss' name too. Install
+       mk_cmds, and ss.h.
+
+       * make_cmds.c: A mk_cmds clone that creates SL structures.
+
+       * ss.c: SS compatibility functions.
+
+       * sl.c: Move command line split to function `sl_make_argv'.
+
+Tue Feb  3 16:45:44 1998  Johan Danielsson  <joda@emma.pdc.kth.se>
+
+       * sl.c: Add sl_command_loop, that is the loop body of sl_loop.
+
+Mon Oct 20 01:13:21 1997  Assar Westerlund  <assar@sics.se>
+
+       * sl.c (sl_help): actually use the `help' field of `SL_cmd'
+
diff --git a/src/kerberosV/src/lib/sl/lex.l b/src/kerberosV/src/lib/sl/lex.l
new file mode 100644 (file)
index 0000000..398518b
--- /dev/null
@@ -0,0 +1,119 @@
+%{
+/*
+ * Copyright (c) 1998 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#undef ECHO
+
+#include "make_cmds.h"
+#include "parse.h"
+
+RCSID("$KTH: lex.l,v 1.6 2001/09/16 23:10:10 assar Exp $");
+
+static unsigned lineno = 1;
+static int getstring(void);
+
+#define YY_NO_UNPUT
+
+#undef ECHO
+
+%}
+
+
+%%
+command_table          { return TABLE; }
+request                        { return REQUEST; }
+unknown                        { return UNKNOWN; }
+unimplemented          { return UNIMPLEMENTED; }
+end                    { return END; }
+#[^\n]*                        ;
+[ \t]                  ;
+\n                     { lineno++; }
+\"                     { return getstring(); }
+[a-zA-Z0-9_]+          { yylval.string = strdup(yytext); return STRING; }
+.                      { return *yytext; }
+%%
+
+#ifndef yywrap /* XXX */
+int
+yywrap () 
+{
+     return 1;
+}
+#endif
+
+static int
+getstring(void)
+{
+    char x[128];
+    int i = 0;
+    int c;
+    int backslash = 0;
+    while((c = input()) != EOF){
+       if(backslash) {
+           if(c == 'n')
+               c = '\n';
+           else if(c == 't')
+               c = '\t';
+           x[i++] = c;
+           backslash = 0;
+           continue;
+       }
+       if(c == '\n'){
+           error_message("unterminated string");
+           lineno++;
+           break;
+       }
+       if(c == '\\'){
+           backslash++;
+           continue;
+       }
+       if(c == '\"')
+           break;
+       x[i++] = c;
+    }
+    x[i] = '\0';
+    yylval.string = strdup(x);
+    return STRING;
+}
+
+void
+error_message (const char *format, ...)
+{
+     va_list args;
+
+     va_start (args, format);
+     fprintf (stderr, "%s:%d: ", filename, lineno);
+     vfprintf (stderr, format, args);
+     va_end (args);
+     numerror++;
+}
diff --git a/src/kerberosV/src/lib/sl/make_cmds.c b/src/kerberosV/src/lib/sl/make_cmds.c
new file mode 100644 (file)
index 0000000..8b1bc4c
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 1998-1999 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "make_cmds.h"
+#include <getarg.h>
+
+RCSID("$KTH: make_cmds.c,v 1.7 2001/02/20 01:44:55 assar Exp $");
+
+#include <roken.h>
+#include <err.h>
+#include "parse.h"
+
+int numerror;
+extern FILE *yyin;
+FILE *c_file;
+
+extern void yyparse(void);
+
+#ifdef YYDEBUG
+extern int yydebug = 1;
+#endif
+
+char *filename;
+char *table_name;
+
+static struct command_list *commands;
+
+void
+add_command(char *function, 
+           char *help, 
+           struct string_list *aliases, 
+           unsigned flags)
+{
+    struct command_list *cl = malloc(sizeof(*cl));
+
+    if (cl == NULL)
+       err (1, "malloc");
+    cl->function = function;
+    cl->help = help;
+    cl->aliases = aliases;
+    cl->flags = flags;
+    cl->next = NULL;
+    if(commands) {
+       *commands->tail = cl;
+       commands->tail = &cl->next;
+       return;
+    }
+    cl->tail = &cl->next;
+    commands = cl;
+}
+
+static char *
+quote(const char *str)
+{
+    char buf[1024]; /* XXX */
+    const char *p;
+    char *q;
+    q = buf;
+    
+    *q++ = '\"';
+    for(p = str; *p != '\0'; p++) {
+       if(*p == '\n') {
+           *q++ = '\\';
+           *q++ = 'n';
+           continue;
+       }
+       if(*p == '\t') {
+           *q++ = '\\';
+           *q++ = 't';
+           continue;
+       }
+       if(*p == '\"' || *p == '\\')
+           *q++ = '\\';
+       *q++ = *p;
+    }
+    *q++ = '\"';
+    *q++ = '\0';
+    return strdup(buf);
+}
+
+static void
+generate_commands(void)
+{
+    char *base;
+    char *cfn;
+    char *p;
+
+    p = strrchr(table_name, '/');
+    if(p == NULL)
+       p = table_name;
+    else
+       p++;
+
+    base = strdup (p);
+    if (base == NULL)
+       err (1, "strdup");
+
+    p = strrchr(base, '.');
+    if(p)
+       *p = '\0';
+    
+    asprintf(&cfn, "%s.c", base);
+    if (cfn == NULL)
+       err (1, "asprintf");
+
+    c_file = fopen(cfn, "w");
+    if (c_file == NULL)
+       err (1, "cannot fopen %s", cfn);
+    
+    fprintf(c_file, "/* Generated from %s */\n", filename);
+    fprintf(c_file, "\n");
+    fprintf(c_file, "#include <stddef.h>\n");
+    fprintf(c_file, "#include <sl.h>\n");
+    fprintf(c_file, "\n");
+
+    {
+       struct command_list *cl, *xl;
+       char *p, *q;
+
+       for(cl = commands; cl; cl = cl->next) {
+           for(xl = commands; xl != cl; xl = xl->next)
+               if(strcmp(cl->function, xl->function) == 0)
+                   break;
+           if(xl != cl)
+               continue;
+           /* XXX hack for ss_quit */
+           if(strcmp(cl->function, "ss_quit") == 0) {
+               fprintf(c_file, "int %s (int, char**);\n", cl->function);
+               fprintf(c_file, "#define _ss_quit_wrap ss_quit\n\n"); 
+               continue;
+           }
+           fprintf(c_file, "void %s (int, char**);\n", cl->function);
+           fprintf(c_file, "static int _%s_wrap (int argc, char **argv)\n", 
+                   cl->function);
+           fprintf(c_file, "{\n");
+           fprintf(c_file, "  %s (argc, argv);\n", cl->function);
+           fprintf(c_file, "  return 0;\n");
+           fprintf(c_file, "}\n\n");
+       }
+
+       fprintf(c_file, "SL_cmd %s[] = {\n", table_name);
+       for(cl = commands; cl; cl = cl->next) {
+           struct string_list *sl;
+           sl = cl->aliases;
+           p = quote(sl->string);
+           q = quote(cl->help);
+           fprintf(c_file, "  { %s, _%s_wrap, %s },\n", p, cl->function, q);
+           free(p);
+           free(q);
+    
+           for(sl = sl->next; sl; sl = sl->next) {
+               p = quote(sl->string);
+               fprintf(c_file, "  { %s },\n", p);
+               free(p);
+           }
+       }
+       fprintf(c_file, "  { NULL },\n");
+       fprintf(c_file, "};\n");
+       fprintf(c_file, "\n");
+    }
+    fclose(c_file);
+    free(base);
+    free(cfn);
+}
+
+int version_flag;
+int help_flag;
+struct getargs args[] = {
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+    arg_printusage(args, num_args, NULL, "command-table");
+    exit(code);
+}
+
+int
+main(int argc, char **argv)
+{
+    int optind = 0;
+
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    
+    if(argc == optind)
+       usage(1);
+    filename = argv[optind];
+    yyin = fopen(filename, "r");
+    if(yyin == NULL)
+       err(1, "%s", filename);
+    
+    yyparse();
+    
+    generate_commands();
+
+    if(numerror)
+       return 1;
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/sl/make_cmds.h b/src/kerberosV/src/lib/sl/make_cmds.h
new file mode 100644 (file)
index 0000000..9151c0a
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1998 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: make_cmds.h,v 1.3 2000/06/27 02:36:56 assar Exp $ */
+
+#ifndef __MAKE_CMDS_H__
+#define __MAKE_CMDS_H__
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <roken.h>
+
+extern char *filename;
+extern char *table_name;
+extern int numerror;
+
+struct command_list {
+    char *function;
+    char *help;
+    struct string_list *aliases;
+    unsigned flags;
+    struct command_list *next;
+    struct command_list **tail;
+};
+
+struct string_list {
+    char *string;
+    struct string_list *next;
+    struct string_list **tail;
+};
+
+void add_command(char*, char*, struct string_list*, unsigned);
+
+void error_message(const char *, ...)
+    __attribute__ ((format (printf, 1,2)));
+
+int yylex (void);
+
+#endif /* __MAKE_CMDS_H__ */
diff --git a/src/kerberosV/src/lib/sl/parse.y b/src/kerberosV/src/lib/sl/parse.y
new file mode 100644 (file)
index 0000000..87a8d86
--- /dev/null
@@ -0,0 +1,167 @@
+%{
+/*
+ * Copyright (c) 1998 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "make_cmds.h"
+RCSID("$KTH: parse.y,v 1.7 2000/06/27 02:37:18 assar Exp $");
+
+static void yyerror (char *s);
+
+struct string_list* append_string(struct string_list*, char*);
+void free_string_list(struct string_list *list);
+unsigned string_to_flag(const char *);
+
+/* This is for bison */
+
+#if !defined(alloca) && !defined(HAVE_ALLOCA)
+#define alloca(x) malloc(x)
+#endif
+
+%}
+
+%union {
+  char *string;
+  unsigned number;
+  struct string_list *list;
+}
+
+%token TABLE REQUEST UNKNOWN UNIMPLEMENTED END
+%token <string> STRING
+%type <number> flag flags
+%type <list> aliases
+
+%%
+
+file           : /* */ 
+               | statements
+               ;
+
+statements     : statement
+               | statements statement
+               ;
+
+statement      : TABLE STRING ';'
+               {
+                   table_name = $2;
+               }
+               | REQUEST STRING ',' STRING ',' aliases ',' '(' flags ')' ';'
+               {
+                   add_command($2, $4, $6, $9);
+               }
+               | REQUEST STRING ',' STRING ',' aliases ';'
+               {
+                   add_command($2, $4, $6, 0);
+               }
+               | UNIMPLEMENTED STRING ',' STRING ',' aliases ';'
+               {
+                   free($2);
+                   free($4);
+                   free_string_list($6);
+               }
+               | UNKNOWN aliases ';'
+               {
+                   free_string_list($2);
+               }
+               | END ';'
+               {
+                   YYACCEPT;
+               }
+               ;
+
+aliases                : STRING
+               {
+                   $$ = append_string(NULL, $1);
+               }
+               | aliases ',' STRING
+               {
+                   $$ = append_string($1, $3);
+               }
+               ;
+
+flags          : flag
+               {
+                   $$ = $1;
+               }
+               | flags ',' flag
+               {
+                   $$ = $1 | $3;
+               }
+               ;
+flag           : STRING
+               {
+                   $$ = string_to_flag($1);
+                   free($1);
+               }
+               ;
+
+
+
+%%
+
+static void
+yyerror (char *s)
+{
+    error_message ("%s\n", s);
+}
+
+struct string_list*
+append_string(struct string_list *list, char *str)
+{
+    struct string_list *sl = malloc(sizeof(*sl));
+    sl->string = str;
+    sl->next = NULL;
+    if(list) {
+       *list->tail = sl;
+       list->tail = &sl->next;
+       return list;
+    }
+    sl->tail = &sl->next;
+    return sl;
+}
+
+void
+free_string_list(struct string_list *list)
+{
+    while(list) {
+       struct string_list *sl = list->next;
+       free(list->string);
+       free(list);
+       list = sl;
+    }
+}
+
+unsigned
+string_to_flag(const char *string)
+{
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/sl/roken_rename.h b/src/kerberosV/src/lib/sl/roken_rename.h
new file mode 100644 (file)
index 0000000..951889e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1998 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: roken_rename.h,v 1.5 2001/05/06 21:47:54 assar Exp $ */
+
+#ifndef __roken_rename_h__
+#define __roken_rename_h__
+
+#ifndef HAVE_STRTOK_R
+#define strtok_r _sl_strtok_r
+#endif
+#ifndef HAVE_SNPRINTF
+#define snprintf _sl_snprintf
+#endif
+#ifndef HAVE_ASPRINTF
+#define asprintf _sl_asprintf
+#endif
+#ifndef HAVE_ASNPRINTF
+#define asnprintf _sl_asnprintf
+#endif
+#ifndef HAVE_VASPRINTF
+#define vasprintf _sl_vasprintf
+#endif
+#ifndef HAVE_VASNPRINTF
+#define vasnprintf _sl_vasnprintf
+#endif
+#ifndef HAVE_VSNPRINTF
+#define vsnprintf _sl_vsnprintf
+#endif
+#ifndef HAVE_STRUPR
+#define strupr _sl_strupr
+#endif
+#ifndef HAVE_STRDUP
+#define strdup _sl_strdup
+#endif
+
+#endif /* __roken_rename_h__ */
diff --git a/src/kerberosV/src/lib/sl/sl.c b/src/kerberosV/src/lib/sl/sl.c
new file mode 100644 (file)
index 0000000..dfe68b9
--- /dev/null
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 1995 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: sl.c,v 1.31 2005/05/09 15:31:43 lha Exp $");
+#endif
+
+#include "sl_locl.h"
+#include <setjmp.h>
+
+extern char *__progname;
+
+static size_t
+print_sl (FILE *stream, int mdoc, int longp, SL_cmd *c)
+    __attribute__ ((unused));
+
+static size_t
+print_sl (FILE *stream, int mdoc, int longp, SL_cmd *c)
+{
+    if(mdoc){
+       if(longp)
+           fprintf(stream, "= Ns");
+       fprintf(stream, " Ar ");
+    }else
+       if (longp)
+           putc ('=', stream);
+       else
+           putc (' ', stream);
+
+    return 1;
+}
+
+static void
+mandoc_template(SL_cmd *cmds,
+               const char *extra_string)
+{
+    SL_cmd *c, *prev;
+    char timestr[64], cmd[64];
+    const char *p;
+    time_t t;
+
+    printf(".\\\" Things to fix:\n");
+    printf(".\\\"   * correct section, and operating system\n");
+    printf(".\\\"   * remove Op from mandatory flags\n");
+    printf(".\\\"   * use better macros for arguments (like .Pa for files)\n");
+    printf(".\\\"\n");
+    t = time(NULL);
+    strftime(timestr, sizeof(timestr), "%b %d, %Y", localtime(&t));
+    printf(".Dd %s\n", timestr);
+    p = strrchr(__progname, '/');
+    if(p) p++; else p = __progname;
+    strncpy(cmd, p, sizeof(cmd));
+    cmd[sizeof(cmd)-1] = '\0';
+    strupr(cmd);
+       
+    printf(".Dt %s SECTION\n", cmd);
+    printf(".Os OPERATING_SYSTEM\n");
+    printf(".Sh NAME\n");
+    printf(".Nm %s\n", p);
+    printf(".Nd\n");
+    printf("in search of a description\n");
+    printf(".Sh SYNOPSIS\n");
+    printf(".Nm\n");
+    for(c = cmds; c->name; ++c) {
+/*     if (c->func == NULL)
+           continue; */
+       printf(".Op Fl %s", c->name);
+/*     print_sl(stdout, 1, 0, c);*/
+       printf("\n");
+       
+    }
+    if (extra_string && *extra_string)
+       printf (".Ar %s\n", extra_string);
+    printf(".Sh DESCRIPTION\n");
+    printf("Supported options:\n");
+    printf(".Bl -tag -width Ds\n");
+    prev = NULL;
+    for(c = cmds; c->name; ++c) {
+       if (c->func) {
+           if (prev)
+               printf ("\n%s\n", prev->usage);
+
+           printf (".It Fl %s", c->name);
+           prev = c;
+       } else
+           printf (", %s\n", c->name);
+    }
+    if (prev)
+       printf ("\n%s\n", prev->usage);
+
+    printf(".El\n");
+    printf(".\\\".Sh ENVIRONMENT\n");
+    printf(".\\\".Sh FILES\n");
+    printf(".\\\".Sh EXAMPLES\n");
+    printf(".\\\".Sh DIAGNOSTICS\n");
+    printf(".\\\".Sh SEE ALSO\n");
+    printf(".\\\".Sh STANDARDS\n");
+    printf(".\\\".Sh HISTORY\n");
+    printf(".\\\".Sh AUTHORS\n");
+    printf(".\\\".Sh BUGS\n");
+}
+
+SL_cmd *
+sl_match (SL_cmd *cmds, char *cmd, int exactp)
+{
+    SL_cmd *c, *current = NULL, *partial_cmd = NULL;
+    int partial_match = 0;
+
+    for (c = cmds; c->name; ++c) {
+       if (c->func)
+           current = c;
+       if (strcmp (cmd, c->name) == 0)
+           return current;
+       else if (strncmp (cmd, c->name, strlen(cmd)) == 0 &&
+                partial_cmd != current) {
+           ++partial_match;
+           partial_cmd = current;
+       }
+    }
+    if (partial_match == 1 && !exactp)
+       return partial_cmd;
+    else
+       return NULL;
+}
+
+void
+sl_help (SL_cmd *cmds, int argc, char **argv)
+{
+    SL_cmd *c, *prev_c;
+
+    if (getenv("SLMANDOC")) {
+       mandoc_template(cmds, NULL);
+       return;
+    }
+
+    if (argc == 1) {
+       prev_c = NULL;
+       for (c = cmds; c->name; ++c) {
+           if (c->func) {
+               if(prev_c)
+                   printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
+                           prev_c->usage ? "\n" : "");
+               prev_c = c;
+               printf ("%s", c->name);
+           } else
+               printf (", %s", c->name);
+       }
+       if(prev_c)
+           printf ("\n\t%s%s", prev_c->usage ? prev_c->usage : "",
+                   prev_c->usage ? "\n" : "");
+    } else { 
+       c = sl_match (cmds, argv[1], 0);
+       if (c == NULL)
+           printf ("No such command: %s. "
+                   "Try \"help\" for a list of all commands\n",
+                   argv[1]);
+       else {
+           printf ("%s\t%s\n", c->name, c->usage);
+           if(c->help && *c->help)
+               printf ("%s\n", c->help);
+           if((++c)->name && c->func == NULL) {
+               printf ("Synonyms:");
+               while (c->name && c->func == NULL)
+                   printf ("\t%s", (c++)->name);
+               printf ("\n");
+           }
+       }
+    }
+}
+
+#ifdef HAVE_READLINE
+
+char *readline(char *prompt);
+void add_history(char *p);
+
+#else
+
+static char *
+readline(char *prompt)
+{
+    char buf[BUFSIZ];
+    printf ("%s", prompt);
+    fflush (stdout);
+    if(fgets(buf, sizeof(buf), stdin) == NULL)
+       return NULL;
+    buf[strcspn(buf, "\r\n")] = '\0';
+    return strdup(buf);
+}
+
+static void
+add_history(char *p)
+{
+}
+
+#endif
+
+int
+sl_command(SL_cmd *cmds, int argc, char **argv)
+{
+    SL_cmd *c;
+    c = sl_match (cmds, argv[0], 0);
+    if (c == NULL)
+       return -1;
+    return (*c->func)(argc, argv);
+}
+
+struct sl_data {
+    int max_count;
+    char **ptr;
+};
+
+int
+sl_make_argv(char *line, int *ret_argc, char ***ret_argv)
+{
+    char *foo = NULL;
+    char *p;
+    int argc, nargv;
+    char **argv;
+    
+    nargv = 10;
+    argv = malloc(nargv * sizeof(*argv));
+    if(argv == NULL)
+       return ENOMEM;
+    argc = 0;
+
+    for(p = strtok_r (line, " \t", &foo);
+       p;
+       p = strtok_r (NULL, " \t", &foo)) {
+       if(argc == nargv - 1) {
+           char **tmp;
+           nargv *= 2;
+           tmp = realloc (argv, nargv * sizeof(*argv));
+           if (tmp == NULL) {
+               free(argv);
+               return ENOMEM;
+           }
+           argv = tmp;
+       }
+       argv[argc++] = p;
+    }
+    argv[argc] = NULL;
+    *ret_argc = argc;
+    *ret_argv = argv;
+    return 0;
+}
+
+static jmp_buf sl_jmp;
+
+static void sl_sigint(int sig)
+{
+    longjmp(sl_jmp, 1);
+}
+
+static char *sl_readline(const char *prompt)
+{
+    char *s;
+    void (*old)(int);
+    old = signal(SIGINT, sl_sigint);
+    if(setjmp(sl_jmp))
+       printf("\n");
+    s = readline((char*)prompt);
+    signal(SIGINT, old);
+    return s;
+}
+
+/* return values: 
+ * 0 on success,
+ * -1 on fatal error,
+ * -2 if EOF, or
+ * return value of command */
+int
+sl_command_loop(SL_cmd *cmds, const char *prompt, void **data)
+{
+    int ret = 0;
+    char *buf;
+    int argc;
+    char **argv;
+       
+    ret = 0;
+    buf = sl_readline(prompt);
+    if(buf == NULL)
+       return -2;
+
+    if(*buf)
+       add_history(buf);
+    ret = sl_make_argv(buf, &argc, &argv);
+    if(ret) {
+       fprintf(stderr, "sl_loop: out of memory\n");
+       free(buf);
+       return -1;
+    }
+    if (argc >= 1) {
+       ret = sl_command(cmds, argc, argv);
+       if(ret == -1) {
+           printf ("Unrecognized command: %s\n", argv[0]);
+           ret = 0;
+       }
+    }
+    free(buf);
+    free(argv);
+    return ret;
+}
+
+int 
+sl_loop(SL_cmd *cmds, const char *prompt)
+{
+    void *data = NULL;
+    int ret;
+    while((ret = sl_command_loop(cmds, prompt, &data)) >= 0)
+       ;
+    return ret;
+}
+
+void
+sl_apropos (SL_cmd *cmd, const char *topic)
+{
+    for (; cmd->name != NULL; ++cmd)
+        if (cmd->usage != NULL && strstr(cmd->usage, topic) != NULL)
+           printf ("%-20s%s\n", cmd->name, cmd->usage);
+}
diff --git a/src/kerberosV/src/lib/sl/sl.h b/src/kerberosV/src/lib/sl/sl.h
new file mode 100644 (file)
index 0000000..f01fc34
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1995 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: sl.h,v 1.11 2004/06/21 19:08:13 joda Exp $ */
+
+#ifndef _SL_H
+#define _SL_H
+
+#define SL_BADCOMMAND -1
+
+typedef int (*cmd_func)(int, char **);
+
+struct sl_cmd {
+  char *name;
+  cmd_func func;
+  char *usage;
+  char *help;
+};
+
+typedef struct sl_cmd SL_cmd;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void sl_help (SL_cmd *, int argc, char **argv);
+int  sl_loop (SL_cmd *, const char *prompt);
+int  sl_command_loop (SL_cmd *cmds, const char *prompt, void **data);
+int  sl_command (SL_cmd *cmds, int argc, char **argv);
+int sl_make_argv(char*, int*, char***);
+void sl_apropos (SL_cmd *cmd, const char *topic);
+SL_cmd *sl_match (SL_cmd *cmds, char *cmd, int exactp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SL_H */
diff --git a/src/kerberosV/src/lib/sl/sl_locl.h b/src/kerberosV/src/lib/sl/sl_locl.h
new file mode 100644 (file)
index 0000000..2b5efed
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: sl_locl.h,v 1.6 1999/12/02 16:58:55 joda Exp $ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <roken.h>
+
+#include <sl.h>
diff --git a/src/kerberosV/src/lib/sl/slc-gram.y b/src/kerberosV/src/lib/sl/slc-gram.y
new file mode 100644 (file)
index 0000000..da5f096
--- /dev/null
@@ -0,0 +1,727 @@
+%{
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: slc-gram.y,v 1.7 2005/04/19 10:28:28 lha Exp $");
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <ctype.h>
+#include <limits.h>
+#include <getarg.h>
+#include <roken.h>
+
+#include "slc.h"
+extern FILE *yyin;
+extern struct assignment *a;
+%}
+
+%union {
+       char *string;
+       struct assignment *assignment;
+}
+
+%token <string> LITERAL
+%token <string> STRING
+%type <assignment> assignment assignments
+
+%start start
+
+%%
+
+start          : assignments
+               {
+                       a = $1;
+               }
+               ;
+
+assignments    : assignment assignments
+               {
+                       $1->next = $2;
+                       $$ = $1;
+               }
+               | assignment
+               ;
+
+assignment     : LITERAL '=' STRING
+               {
+                       $$ = malloc(sizeof(*$$));
+                       $$->name = $1;
+                       $$->type = a_value;
+                       $$->lineno = lineno;
+                       $$->u.value = $3;
+                       $$->next = NULL;
+               }
+               | LITERAL '=' '{' assignments '}'
+               {
+                       $$ = malloc(sizeof(*$$));
+                       $$->name = $1;
+                       $$->type = a_assignment;
+                       $$->lineno = lineno;
+                       $$->u.assignment = $4;
+                       $$->next = NULL;
+               }
+               ;
+
+%%
+char *filename;
+FILE *cfile, *hfile;
+int error_flag;
+struct assignment *a;
+
+
+static void
+ex(struct assignment *a, const char *fmt, ...)
+{
+    va_list ap;
+    fprintf(stderr, "%s:%d: ", a->name, a->lineno);
+    va_start(ap, fmt);
+    vfprintf(stderr, fmt, ap);
+    va_end(ap);
+    fprintf(stderr, "\n");
+}
+
+
+
+static int
+check_option(struct assignment *as)
+{
+    struct assignment *a;
+    int seen_long = 0;
+    int seen_short = 0;
+    int seen_type = 0;
+    int seen_argument = 0;
+    int seen_help = 0;
+    int seen_default = 0;
+    int ret = 0;
+
+    for(a = as; a != NULL; a = a->next) {
+       if(strcmp(a->name, "long") == 0)
+           seen_long++;
+       else if(strcmp(a->name, "short") == 0)
+           seen_short++;
+       else if(strcmp(a->name, "type") == 0)
+           seen_type++;
+       else if(strcmp(a->name, "argument") == 0)
+           seen_argument++;
+       else if(strcmp(a->name, "help") == 0)
+           seen_help++;
+       else if(strcmp(a->name, "default") == 0)
+           seen_default++;
+       else {
+           ex(a, "unknown name");
+           ret++;
+       }
+    }
+    if(seen_long == 0 && seen_short == 0) {
+       ex(as, "neither long nor short option");
+       ret++;
+    }
+    if(seen_long > 1) {
+       ex(as, "multiple long options");
+       ret++;
+    }
+    if(seen_short > 1) {
+       ex(as, "multiple short options");
+       ret++;
+    }
+    if(seen_type > 1) {
+       ex(as, "multiple types");
+       ret++;
+    }
+    if(seen_argument > 1) {
+       ex(as, "multiple arguments");
+       ret++;
+    }
+    if(seen_help > 1) {
+       ex(as, "multiple help strings");
+       ret++;
+    }
+    if(seen_default > 1) {
+       ex(as, "multiple default values");
+       ret++;
+    }
+    return ret;
+}
+
+static int
+check_command(struct assignment *as)
+{
+       struct assignment *a;
+       int seen_name = 0;
+       int seen_function = 0;
+       int seen_help = 0;
+       int seen_argument = 0;
+       int seen_minargs = 0;
+       int seen_maxargs = 0;
+       int ret = 0;
+       for(a = as; a != NULL; a = a->next) {
+               if(strcmp(a->name, "name") == 0)
+                       seen_name++;
+               else if(strcmp(a->name, "function") == 0) {
+                       seen_function++;
+               } else if(strcmp(a->name, "option") == 0)
+                       ret += check_option(a->u.assignment);
+               else if(strcmp(a->name, "help") == 0) {
+                       seen_help++;
+               } else if(strcmp(a->name, "argument") == 0) {
+                       seen_argument++;
+               } else if(strcmp(a->name, "min_args") == 0) {
+                       seen_minargs++;
+               } else if(strcmp(a->name, "max_args") == 0) {
+                       seen_maxargs++;
+               } else {
+                       ex(a, "unknown name");
+                       ret++;
+               }
+       }
+       if(seen_name == 0) {
+               ex(as, "no command name");
+               ret++;
+       }
+       if(seen_function > 1) {
+               ex(as, "multiple function names");
+               ret++;
+       }
+       if(seen_help > 1) {
+               ex(as, "multiple help strings");
+               ret++;
+       }
+       if(seen_argument > 1) {
+               ex(as, "multiple argument strings");
+               ret++;
+       }
+       if(seen_minargs > 1) {
+               ex(as, "multiple min_args strings");
+               ret++;
+       }
+       if(seen_maxargs > 1) {
+               ex(as, "multiple max_args strings");
+               ret++;
+       }
+       
+       return ret;
+}
+
+static int
+check(struct assignment *as)
+{
+    struct assignment *a;
+    int ret = 0;
+    for(a = as; a != NULL; a = a->next) {
+       if(strcmp(a->name, "command")) {
+           fprintf(stderr, "unknown type %s line %d\n", a->name, a->lineno);
+           ret++;
+           continue;
+       }
+       if(a->type != a_assignment) {
+           fprintf(stderr, "bad command definition %s line %d\n", a->name, a->lineno);
+           ret++;
+           continue;
+       }
+       ret += check_command(a->u.assignment);
+    }
+    return ret;
+}
+
+static struct assignment *
+find_next(struct assignment *as, const char *name)
+{
+    for(as = as->next; as != NULL; as = as->next) {
+       if(strcmp(as->name, name) == 0)
+           return as;
+    }
+    return NULL;
+}
+
+static struct assignment *
+find(struct assignment *as, const char *name)
+{
+    for(; as != NULL; as = as->next) {
+       if(strcmp(as->name, name) == 0)
+           return as;
+    }
+    return NULL;
+}
+
+static void
+space(FILE *f, int level)
+{
+    fprintf(f, "%*.*s", level * 4, level * 4, " ");
+}
+
+static void
+cprint(int level, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    space(cfile, level);
+    vfprintf(cfile, fmt, ap);
+    va_end(ap);
+}
+
+static void
+hprint(int level, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    space(hfile, level);
+    vfprintf(hfile, fmt, ap);
+    va_end(ap);
+}
+
+static void gen_name(char *str);
+
+static void
+gen_command(struct assignment *as)
+{
+    struct assignment *a, *b;
+    char *f;
+    a = find(as, "name");
+    f = strdup(a->u.value);
+    gen_name(f);
+    cprint(1, "    { ");
+    fprintf(cfile, "\"%s\", ", a->u.value);
+    fprintf(cfile, "%s_wrap, ", f);
+    b = find(as, "argument");
+    if(b)
+       fprintf(cfile, "\"%s %s\", ", a->u.value, b->u.value);
+    else
+       fprintf(cfile, "\"%s\", ", a->u.value);
+    b = find(as, "help");
+    if(b)
+       fprintf(cfile, "\"%s\"", b->u.value);
+    else
+       fprintf(cfile, "NULL");
+    fprintf(cfile, " },\n");
+    for(a = a->next; a != NULL; a = a->next)
+       if(strcmp(a->name, "name") == 0)
+           cprint(1, "    { \"%s\" },\n", a->u.value);
+    cprint(0, "\n");
+}
+
+static void
+gen_name(char *str)
+{
+    char *p;
+    for(p = str; *p != '\0'; p++)
+       if(!isalnum((unsigned char)*p))
+           *p = '_';
+}
+
+static char *
+make_name(struct assignment *as)
+{
+    struct assignment *lopt;
+    struct assignment *type;
+    char *s;
+
+    lopt = find(as, "long");
+    if(lopt == NULL)
+       lopt = find(as, "name");
+    if(lopt == NULL)
+       return NULL;
+    
+    type = find(as, "type");
+    if(strcmp(type->u.value, "-flag") == 0)
+       asprintf(&s, "%s_flag", lopt->u.value);
+    else
+       asprintf(&s, "%s_%s", lopt->u.value, type->u.value);
+    gen_name(s);
+    return s;
+}
+
+static void
+gen_options(struct assignment *opt1, const char *name)
+{
+    struct assignment *tmp;
+
+    hprint(0, "struct %s_options {\n", name);
+
+    for(tmp = opt1; 
+       tmp != NULL; 
+       tmp = find_next(tmp, "option")) {
+       struct assignment *type;
+       char *s;
+       
+       s = make_name(tmp->u.assignment);
+       type = find(tmp->u.assignment, "type");
+       if(strcmp(type->u.value, "string") == 0)
+           hprint(1, "char *%s;\n", s);
+       else if(strcmp(type->u.value, "strings") == 0)
+           hprint(1, "struct getarg_strings %s;\n", s);
+       else if(strcmp(type->u.value, "integer") == 0)
+           hprint(1, "int %s;\n", s);
+       else if(strcmp(type->u.value, "flag") == 0) 
+           hprint(1, "int %s;\n", s);
+       else if(strcmp(type->u.value, "-flag") == 0) 
+           hprint(1, "int %s;\n", s);
+       else {
+           ex(type, "unknown type \"%s\"", type->u.value);
+           exit(1);
+       }
+       free(s);
+    }
+    hprint(0, "};\n");
+}
+
+static void
+gen_wrapper(struct assignment *as)
+{
+    struct assignment *name;
+    struct assignment *arg;
+    struct assignment *opt1;
+    struct assignment *function;
+    struct assignment *tmp;
+    char *f;
+    int nargs = 0;
+    int seen_strings = 0;
+
+    name = find(as, "name");
+    arg = find(as, "argument");
+    opt1 = find(as, "option");
+    function = find(as, "function");
+    if(function == NULL)
+       function = name;
+    f = strdup(name->u.value);
+    gen_name(f);
+       
+    if(opt1 != NULL) {
+       gen_options(opt1, name->u.value);
+       hprint(0, "int %s(struct %s_options*, int, char **);\n", 
+              function->u.value, name->u.value);
+    } else {
+       hprint(0, "int %s(void*, int, char **);\n", 
+              function->u.value);
+    }
+
+    fprintf(cfile, "static int\n");
+    fprintf(cfile, "%s_wrap(int argc, char **argv)\n", f);
+    fprintf(cfile, "{\n");
+    if(opt1 != NULL)
+       cprint(1, "struct %s_options opt;\n", name->u.value);
+    cprint(1, "int ret;\n");
+    cprint(1, "int optind = 0;\n");
+    cprint(1, "struct getargs args[] = {\n");
+    for(tmp = find(as, "option"); 
+       tmp != NULL; 
+       tmp = find_next(tmp, "option")) {
+       struct assignment *type = find(tmp->u.assignment, "type");
+       struct assignment *lopt = find(tmp->u.assignment, "long");
+       struct assignment *sopt = find(tmp->u.assignment, "short");
+       struct assignment *arg = find(tmp->u.assignment, "argument");
+       struct assignment *help = find(tmp->u.assignment, "help");
+       
+       cprint(2, "{ ");
+       if(lopt)
+           fprintf(cfile, "\"%s\", ", lopt->u.value);
+       else
+           fprintf(cfile, "NULL, ");
+       if(sopt)
+           fprintf(cfile, "'%c', ", *sopt->u.value);
+       else
+           fprintf(cfile, "0, ");
+       if(strcmp(type->u.value, "string") == 0)
+           fprintf(cfile, "arg_string, ");
+       else if(strcmp(type->u.value, "strings") == 0)
+           fprintf(cfile, "arg_strings, ");
+       else if(strcmp(type->u.value, "integer") == 0)
+           fprintf(cfile, "arg_integer, ");
+       else if(strcmp(type->u.value, "flag") == 0)
+           fprintf(cfile, "arg_flag, ");
+       else if(strcmp(type->u.value, "-flag") == 0)
+           fprintf(cfile, "arg_negative_flag, ");
+       else {
+           ex(type, "unknown type \"%s\"", type->u.value);
+           exit(1);
+       }
+       fprintf(cfile, "NULL, ");
+       if(help)
+           fprintf(cfile, "\"%s\", ", help->u.value);
+       else
+           fprintf(cfile, "NULL, ");
+       if(arg)
+           fprintf(cfile, "\"%s\"", arg->u.value);
+       else
+           fprintf(cfile, "NULL");
+       fprintf(cfile, " },\n");
+    }
+    cprint(2, "{ \"help\", 'h', arg_flag, NULL, NULL, NULL }\n");
+    cprint(1, "};\n");
+    cprint(1, "int help_flag = 0;\n");
+
+    for(tmp = find(as, "option"); 
+       tmp != NULL; 
+       tmp = find_next(tmp, "option")) {
+       char *s;
+       struct assignment *type = find(tmp->u.assignment, "type");
+
+       struct assignment *defval = find(tmp->u.assignment, "default");
+       s = make_name(tmp->u.assignment);
+       if(strcmp(type->u.value, "string") == 0) {
+           if(defval != NULL)
+               cprint(1, "opt.%s = \"%s\";\n", s, defval->u.value);
+           else
+               cprint(1, "opt.%s = NULL;\n", s);
+       } else if(strcmp(type->u.value, "strings") == 0) {
+           seen_strings = 1;
+           cprint(1, "opt.%s.num_strings = 0;\n", s);
+           cprint(1, "opt.%s.strings = NULL;\n", s);
+       } else if(strcmp(type->u.value, "integer") == 0) {
+           if(defval != NULL)
+               cprint(1, "opt.%s = %s;\n", s, defval->u.value);
+           else
+               cprint(1, "opt.%s = 0;\n", s);
+       } else if(strcmp(type->u.value, "flag") == 0 ||
+                 strcmp(type->u.value, "-flag") == 0) {
+           if(defval != NULL)
+               cprint(1, "opt.%s = %s;\n", s, defval->u.value);
+           else
+               cprint(1, "opt.%s = 0;\n", s);
+       } else {
+           ex(type, "unknown type \"%s\"", type->u.value);
+           exit(1);
+       }
+       free(s);
+    }
+
+    for(tmp = find(as, "option"); 
+       tmp != NULL; 
+       tmp = find_next(tmp, "option")) {
+       char *s;
+       s = make_name(tmp->u.assignment);
+       cprint(1, "args[%d].value = &opt.%s;\n", nargs++, s);
+       free(s);
+    }
+    cprint(1, "args[%d].value = &help_flag;\n", nargs++);
+    cprint(1, "if(getarg(args, %d, argc, argv, &optind))\n", nargs);
+    cprint(2, "goto usage;\n");
+
+    {
+       int min_args = -1;
+       int max_args = -1;
+       char *end;
+       if(arg == NULL) {
+           max_args = 0;
+       } else {
+           if((tmp = find(as, "min_args")) != NULL) {
+               min_args = strtol(tmp->u.value, &end, 0);
+               if(*end != '\0') {
+                   ex(tmp, "min_args is not numeric");
+                   exit(1);
+               }
+               if(min_args < 0) {
+                   ex(tmp, "min_args must be non-negative");
+                   exit(1);
+               }
+           }
+           if((tmp = find(as, "max_args")) != NULL) {
+               max_args = strtol(tmp->u.value, &end, 0);
+               if(*end != '\0') {
+                   ex(tmp, "max_args is not numeric");
+                   exit(1);
+               }
+               if(max_args < 0) {
+                   ex(tmp, "max_args must be non-negative");
+                   exit(1);
+               }
+           }
+       }
+       if(min_args != -1 || max_args != -1) {
+           if(min_args == max_args) {
+               cprint(1, "if(argc - optind != %d) {\n", 
+                      min_args);
+               cprint(2, "fprintf(stderr, \"Need exactly %u parameters (%%u given).\\n\\n\", argc - optind);\n", min_args);
+               cprint(2, "goto usage;\n");
+               cprint(1, "}\n");
+           } else {
+               if(max_args != -1) {
+                   cprint(1, "if(argc - optind > %d) {\n", max_args);
+                   cprint(2, "fprintf(stderr, \"Arguments given (%%u) are more than expected (%u).\\n\\n\", argc - optind);\n", max_args);
+                   cprint(2, "goto usage;\n");
+                   cprint(1, "}\n");
+               }
+               if(min_args != -1) {
+                   cprint(1, "if(argc - optind < %d) {\n", min_args);
+                   cprint(2, "fprintf(stderr, \"Arguments given (%%u) are less than expected (%u).\\n\\n\", argc - optind);\n", min_args);
+                   cprint(2, "goto usage;\n");
+                   cprint(1, "}\n");
+               }
+           }
+       }
+    }
+    
+    cprint(1, "if(help_flag)\n");
+    cprint(2, "goto usage;\n");
+
+    cprint(1, "ret = %s(%s, argc - optind, argv + optind);\n", 
+          function->u.value, 
+          opt1 ? "&opt": "NULL");
+    if(seen_strings) {
+       if(seen_strings) {
+           for(tmp = find(as, "option"); 
+               tmp != NULL; 
+               tmp = find_next(tmp, "option")) {
+               char *s;
+               struct assignment *type = find(tmp->u.assignment, "type");
+               
+               s = make_name(tmp->u.assignment);
+               if(strcmp(type->u.value, "strings") == 0) {
+                   cprint(1, "free_getarg_strings (&opt.%s);\n", s);
+               } 
+               free(s);
+           }
+       }
+    }
+    cprint(1, "return ret;\n");
+
+    cprint(0, "usage:\n");
+    cprint(1, "arg_printusage (args, %d, \"%s\", \"%s\");\n", nargs, 
+          name->u.value, arg ? arg->u.value : "");
+    if(seen_strings) {
+       for(tmp = find(as, "option"); 
+           tmp != NULL; 
+           tmp = find_next(tmp, "option")) {
+           char *s;
+           struct assignment *type = find(tmp->u.assignment, "type");
+
+           s = make_name(tmp->u.assignment);
+           if(strcmp(type->u.value, "strings") == 0) {
+               cprint(1, "free_getarg_strings (&opt.%s);\n", s);
+           } 
+           free(s);
+       }
+    }
+    cprint(1, "return 0;\n");
+    cprint(0, "}\n");
+    cprint(0, "\n");
+}
+
+char cname[PATH_MAX];
+char hname[PATH_MAX];
+
+static void
+gen(struct assignment *as)
+{
+    struct assignment *a;
+    cprint(0, "#include <stdio.h>\n");
+    cprint(0, "#include <getarg.h>\n");
+    cprint(0, "#include <sl.h>\n");
+    cprint(0, "#include \"%s\"\n\n", hname);
+
+    hprint(0, "#include <stdio.h>\n");
+    hprint(0, "#include <sl.h>\n");
+    hprint(0, "\n");
+
+
+    for(a = as; a != NULL; a = a->next)
+       gen_wrapper(a->u.assignment);
+
+    cprint(0, "SL_cmd commands[] = {\n");
+    for(a = as; a != NULL; a = a->next)
+       gen_command(a->u.assignment);
+    cprint(1, "{ NULL }\n");
+    cprint(0, "};\n");
+
+    hprint(0, "extern SL_cmd commands[];\n");
+}
+
+int version_flag;
+int help_flag;
+struct getargs args[] = {
+    { "version", 0, arg_flag, &version_flag },
+    { "help", 0, arg_flag, &help_flag }
+};
+int num_args = sizeof(args) / sizeof(args[0]);
+
+static void
+usage(int code)
+{
+    arg_printusage(args, num_args, NULL, "command-table");
+    exit(code);
+}
+
+int
+main(int argc, char **argv)
+{
+    char *p;
+
+    int optind = 0;
+
+    if(getarg(args, num_args, argc, argv, &optind))
+       usage(1);
+    if(help_flag)
+       usage(0);
+    if(version_flag) {
+       print_version(NULL);
+       exit(0);
+    }
+    
+    if(argc == optind)
+       usage(1);
+
+    filename = argv[optind];
+    yyin = fopen(filename, "r");
+    if(yyin == NULL)
+       err(1, "%s", filename);
+    p = strrchr(filename, '/');
+    if(p)
+       strlcpy(cname, p + 1, sizeof(cname));
+    else
+       strlcpy(cname, filename, sizeof(cname));
+    p = strrchr(cname, '.');
+    if(p)
+       *p = '\0';
+    strlcpy(hname, cname, sizeof(hname));
+    strlcat(cname, ".c", sizeof(cname));
+    strlcat(hname, ".h", sizeof(hname));
+    yyparse();
+    if(error_flag)
+       exit(1);
+    if(check(a) == 0) {
+       cfile = fopen(cname, "w");
+       if(cfile == NULL)
+         err(1, "%s", cname);
+       hfile = fopen(hname, "w");
+       if(hfile == NULL)
+         err(1, "%s", hname);
+       gen(a);
+       fclose(cfile);
+       fclose(hfile);
+    }
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/sl/slc-lex.l b/src/kerberosV/src/lib/sl/slc-lex.l
new file mode 100644 (file)
index 0000000..02db445
--- /dev/null
@@ -0,0 +1,164 @@
+%{
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: slc-lex.l,v 1.3 2005/05/10 22:19:01 lha Exp $ */
+
+#undef ECHO
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include "slc.h"
+#include "y.tab.h"
+unsigned lineno = 1;
+
+static void handle_comment(void);
+static char * handle_string(void);
+
+#define YY_NO_UNPUT
+
+#undef ECHO
+
+%}
+%%
+[A-Za-z][-A-Za-z0-9_]* {
+                         yylval.string = strdup ((const char *)yytext);
+                         return LITERAL;
+                       }
+"\""                   { yylval.string = handle_string(); return STRING; }
+\n                     { ++lineno; }
+\/\*                   { handle_comment(); }
+[={}]                  { return *yytext; }
+[ \t]                  ;
+%%
+
+void
+error_message (const char *format, ...)
+{
+     va_list args;
+
+     va_start (args, format);
+     fprintf (stderr, "%s:%d: ", filename, lineno);
+     vfprintf (stderr, format, args);
+     va_end (args);
+     error_flag++;
+}
+
+void
+yyerror (char *s)
+{
+    error_message("%s\n", s);
+}
+
+static void
+handle_comment(void)
+{
+    int c;
+    int start_lineno = lineno;
+    int level = 1;
+    int seen_star = 0;
+    int seen_slash = 0;
+    while((c = input()) != EOF) {
+       if(c == '/') {
+           if(seen_star) {
+               if(--level == 0)
+                   return;
+               seen_star = 0;
+               continue;
+           }
+           seen_slash = 1;
+           continue;
+       }
+       if(seen_star && c == '/') {
+           if(--level == 0)
+               return;
+           seen_star = 0;
+           continue;
+       }
+       if(c == '*') {
+           if(seen_slash) {
+               level++;
+               seen_star = seen_slash = 0;
+               continue;
+           } 
+           seen_star = 1;
+           continue;
+       }
+       seen_star = seen_slash = 0;
+       if(c == '\n') {
+           lineno++;
+           continue;
+       }
+    }
+    if(c == EOF)
+       error_message("unterminated comment, possibly started on line %d\n", start_lineno);
+}
+
+static char *
+handle_string(void)
+{
+    char x[1024];
+    int i = 0;
+    int c;
+    int quote = 0;
+    while((c = input()) != EOF){
+       if(quote) {
+           x[i++] = '\\';
+           x[i++] = c;
+           quote = 0;
+           continue;
+       }
+       if(c == '\n'){
+           error_message("unterminated string");
+           lineno++;
+           break;
+       }
+       if(c == '\\'){
+           quote++;
+           continue;
+       }
+       if(c == '\"')
+           break;
+       x[i++] = c;
+    }
+    x[i] = '\0';
+    return strdup(x);
+}
+
+int
+yywrap () 
+{
+     return 1;
+}
diff --git a/src/kerberosV/src/lib/sl/slc.h b/src/kerberosV/src/lib/sl/slc.h
new file mode 100644 (file)
index 0000000..d62eb09
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+/* $KTH: slc.h,v 1.1 2004/06/21 19:10:59 joda Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+struct assignment {
+    char *name;
+    enum { a_value, a_assignment } type;
+    union {
+       char *value;
+       struct assignment *assignment;
+    } u;
+    unsigned int lineno;
+    struct assignment *next;
+};
+
+extern char *filename;
+extern int error_flag;
+void error_message (const char *format, ...);
+int yylex(void);
+void yyerror (char *s);
+extern unsigned lineno;
diff --git a/src/kerberosV/src/lib/sl/ss.c b/src/kerberosV/src/lib/sl/ss.c
new file mode 100644 (file)
index 0000000..4f2918a
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1998 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (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 "sl_locl.h"
+#include <com_err.h>
+#include "ss.h"
+
+RCSID("$KTH: ss.c,v 1.6 2000/05/25 00:14:58 assar Exp $");
+
+struct ss_subst {
+    char *name;
+    char *version;
+    char *info;
+    ss_request_table *table;
+};
+
+static struct ss_subst subsystems[2];
+static int num_subsystems;
+
+int
+ss_create_invocation(const char *subsystem, 
+                    const char *version, 
+                    const char *info, 
+                    ss_request_table *table, 
+                    int *code)
+{
+    struct ss_subst *ss;
+
+    if(num_subsystems >= sizeof(subsystems) / sizeof(subsystems[0])) {
+       *code = 17;
+       return 0;
+    }
+    ss = &subsystems[num_subsystems];
+    ss->name = ss->version = ss->info = NULL;
+    if (subsystem != NULL) {
+       ss->name = strdup (subsystem);
+       if (ss->name == NULL) {
+           *code = ENOMEM;
+           return 0;
+       }
+    }
+    if (version != NULL) {
+       ss->version = strdup (version);
+       if (ss->version == NULL) {
+           *code = ENOMEM;
+           return 0;
+       }
+    }
+    if (info != NULL) {
+       ss->info = strdup (info);
+       if (ss->info == NULL) {
+           *code = ENOMEM;
+           return 0;
+       }
+    }
+    ss->table = table;
+    *code = 0;
+    return num_subsystems++;
+}
+
+void
+ss_error (int index, long code, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    com_err_va (subsystems[index].name, code, fmt, ap);
+    va_end(ap);
+}
+
+void
+ss_perror (int index, long code, const char *msg)
+{
+    ss_error(index, code, "%s", msg);
+}
+
+int
+ss_execute_command(int index, char **argv)
+{
+    int argc = 0;
+    int ret;
+
+    while(argv[argc++]);
+    ret = sl_command(subsystems[index].table, argc, argv);
+    if (ret == SL_BADCOMMAND)
+       return SS_ET_COMMAND_NOT_FOUND;
+    return 0;
+}
+
+int
+ss_execute_line (int index, const char *line)
+{
+    char *buf = strdup(line);
+    int argc;
+    char **argv;
+    int ret;
+    
+    if (buf == NULL)
+       return ENOMEM;
+    sl_make_argv(buf, &argc, &argv);
+    ret = sl_command(subsystems[index].table, argc, argv);
+    free(buf);
+    if (ret == SL_BADCOMMAND)
+       return SS_ET_COMMAND_NOT_FOUND;
+    return 0;
+}
+
+int
+ss_listen (int index)
+{
+    size_t len = strlen(subsystems[index].name) + 3;
+    char *prompt = malloc(len);
+    if (prompt == NULL)
+       return ENOMEM;
+
+    strlcpy(prompt, subsystems[index].name, len);
+    strlcat(prompt, ": ", len);
+    sl_loop(subsystems[index].table, prompt);
+    free(prompt);
+    return 0;
+}
+
+int
+ss_list_requests(int argc, char **argv /* , int index, void *info */)
+{
+    sl_help(subsystems[0 /* index */].table, argc, argv);
+    return 0;
+}
+
+int
+ss_quit(int argc, char **argv)
+{
+    return 1;
+}
diff --git a/src/kerberosV/src/lib/sl/ss.h b/src/kerberosV/src/lib/sl/ss.h
new file mode 100644 (file)
index 0000000..b0f0281
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1998 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+/* $KTH: ss.h,v 1.3 2000/05/25 00:15:21 assar Exp $ */
+
+/* SS compatibility for SL */
+
+#ifndef __ss_h__
+#define __ss_h__
+
+#include <sl.h>
+
+typedef SL_cmd ss_request_table;
+
+int ss_create_invocation (const char *, const char *, const char*, 
+                         ss_request_table*, int*);
+
+void ss_error (int, long, const char*, ...);
+int ss_execute_command (int, char**);
+int ss_execute_line (int, const char*);
+int ss_list_requests (int argc, char**);
+int ss_listen (int);
+void ss_perror (int, long, const char*);
+int ss_quit (int argc, char**);
+
+#define SS_ET_COMMAND_NOT_FOUND (-1)
+
+#endif /* __ss_h__ */
diff --git a/src/kerberosV/src/lib/vers/CVS/Entries b/src/kerberosV/src/lib/vers/CVS/Entries
new file mode 100644 (file)
index 0000000..1f1d86e
--- /dev/null
@@ -0,0 +1,5 @@
+/ChangeLog/1.1.1.5/Fri Apr 14 07:33:35 2006//
+/make-print-version.c/1.1.1.2/Sun May 11 02:16:02 2003//
+/print_version.c/1.6/Fri Apr 14 08:15:05 2006//
+/vers.h/1.1.1.1/Fri May 25 07:51:05 2001//
+D
diff --git a/src/kerberosV/src/lib/vers/CVS/Repository b/src/kerberosV/src/lib/vers/CVS/Repository
new file mode 100644 (file)
index 0000000..c89bdba
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/lib/vers
diff --git a/src/kerberosV/src/lib/vers/CVS/Root b/src/kerberosV/src/lib/vers/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/lib/vers/ChangeLog b/src/kerberosV/src/lib/vers/ChangeLog
new file mode 100644 (file)
index 0000000..26ef9fe
--- /dev/null
@@ -0,0 +1,50 @@
+2005-01-01  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * print_version.c: Happy New Year
+
+2004-01-05  Love Hörnquist Ã…strand  <lha@it.su.se>
+
+       * print_version.c: add year 2004
+       
+2003-01-02  Johan Danielsson  <joda@pdc.kth.se>
+
+       * print_version.c: considerable clean up
+
+       * make-print-version.c: make VERSIONLIST a string instead of an
+       array of strings
+
+2002-08-28  Assar Westerlund  <assar@kth.se>
+
+       * Makefile.am (make_print_version_LDADD): do not hardcode -ldes,
+       use $(LIB_des)
+
+2002-08-19  Johan Danielsson  <joda@pdc.kth.se>
+
+       * print_version.c: add bug-report message
+
+2002-05-20  Johan Danielsson  <joda@pdc.kth.se>
+
+       * print_version.c: update year
+
+2001-08-24  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am (make_print_version_LDADD): use = instead of += (be
+       nice to current automake)
+
+2001-04-21  Johan Danielsson  <joda@pdc.kth.se>
+
+       * print_version.c: 2001
+
+2001-01-31  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: remove -static turning this into a convenience
+       library
+
+2000-11-15  Assar Westerlund  <assar@sics.se>
+
+       * Makefile.am: make the library static and don't install it
+
+2000-07-08  Assar Westerlund  <assar@sics.se>
+
+       * make-print-version.c (heimdal_version, krb4_version): const-ize,
+       based on thorpej@netbsd.org's change to NetBSD
diff --git a/src/kerberosV/src/lib/vers/make-print-version.c b/src/kerberosV/src/lib/vers/make-print-version.c
new file mode 100644 (file)
index 0000000..1679f27
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1998 - 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: make-print-version.c,v 1.3 2003/01/02 15:31:38 joda Exp $");
+#endif
+
+#include <stdio.h>
+
+#ifdef KRB5
+extern const char *heimdal_version;
+#endif
+#ifdef KRB4
+extern const char *krb4_version;
+#endif
+#include <version.h>
+
+int
+main(int argc, char **argv)
+{
+    FILE *f;
+    if(argc != 2)
+       return 1;
+    f = fopen(argv[1], "w");
+    if(f == NULL)
+       return 1;
+    fprintf(f, "#define VERSIONLIST \"");
+#ifdef KRB5
+    fprintf(f, "%s", heimdal_version);
+#endif
+#ifdef KRB4
+#ifdef KRB5
+    fprintf(f, ", ");
+#endif
+    fprintf(f, "%s", krb4_version);
+#endif
+    fprintf(f, "\"\n");
+    fclose(f);
+    return 0;
+}
diff --git a/src/kerberosV/src/lib/vers/print_version.c b/src/kerberosV/src/lib/vers/print_version.c
new file mode 100644 (file)
index 0000000..499fd5e
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1998 - 2004 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+RCSID("$KTH: print_version.c,v 1.9 2005/01/01 14:27:47 lha Exp $");
+#endif
+#include "roken.h"
+
+#include "print_version.h"
+
+char *__progname;
+
+void
+print_version(const char *progname)
+{
+    const char *package_list = VERSIONLIST;
+    
+    if(progname == NULL)
+       progname = __progname;
+    
+    if(*package_list == '\0')
+       package_list = "no version information";
+    fprintf(stderr, "%s (%s)\n", progname, package_list);
+    fprintf(stderr, "Copyright 1999-2005 Kungliga Tekniska Högskolan\n");
+    fprintf(stderr, "Send bug-reports to %s\n", PACKAGE_BUGREPORT);
+}
diff --git a/src/kerberosV/src/lib/vers/vers.h b/src/kerberosV/src/lib/vers/vers.h
new file mode 100644 (file)
index 0000000..5f8442e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1995 - 2000 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* $KTH: vers.h,v 1.1 2000/07/01 19:47:36 assar Exp $ */
+
+#ifndef __VERS_H__
+#define __VERS_H__
+
+void print_version(const char *);
+
+#endif /*  __VERS_H__ */
diff --git a/src/kerberosV/src/tools/CVS/Entries b/src/kerberosV/src/tools/CVS/Entries
new file mode 100644 (file)
index 0000000..aed2820
--- /dev/null
@@ -0,0 +1,5 @@
+/build.sh/1.1.1.1/Sun May 11 02:16:16 2003//
+/kdc-log-analyze.pl/1.1.1.1/Fri Apr 14 07:34:01 2006//
+/krb5-config.1/1.1.1.3/Sun May 11 02:16:16 2003//
+/krb5-config.in/1.1.1.3/Fri Apr 14 07:34:01 2006//
+D
diff --git a/src/kerberosV/src/tools/CVS/Repository b/src/kerberosV/src/tools/CVS/Repository
new file mode 100644 (file)
index 0000000..63c31af
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/src/tools
diff --git a/src/kerberosV/src/tools/CVS/Root b/src/kerberosV/src/tools/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/src/tools/build.sh b/src/kerberosV/src/tools/build.sh
new file mode 100644 (file)
index 0000000..06a53dc
--- /dev/null
@@ -0,0 +1,212 @@
+#!/bin/sh
+#
+# Build many combinations of kth-krb/heimdal/openssl
+#
+# $KTH: build.sh,v 1.8 2003/04/17 12:55:02 lha Exp $
+
+opt_n= #:
+make_f= #-j
+
+heimdal_versions="0.5.2 0.6pre4"
+krb4_versions="1.2.2"
+openssl_versions="0.9.6i 0.9.7a 0.9.7b"
+
+make_check_version=".*heimdal-0.6.*"
+
+# 0.5 dont eat 0.9.7
+dont_build="openssl-0.9.7.*heimdal-0.5.*"
+# 1.2 dont eat 0.9.7
+dont_build="openssl-0.9.7.*krb4-1.2.* ${dont_build}"
+#yacc problems
+dont_build="openssl-0.9.6.*heimdal-0.5.*osf4.* ${dont_build}"
+#local openssl 09.7 and broken kuser/Makefile.am
+dont_build="openssl-0.9.6.*heimdal-0.5.*freebsd4.8.* ${dont_build}" 
+failed=
+
+# Allow override
+for a in $HOME . /etc ; do 
+    [ -f $a/.heimdal-build ] && . $a/.heimdal-build
+done
+
+targetdir=${targetdir:-/scratch/heimdal-test}
+logfile="${targetdir}/buildlog"
+
+distdirs="${distdirs} /afs/su.se/home/l/h/lha/Public/openssl"
+distdirs="${distdirs} /afs/pdc.kth.se/public/ftp/pub/heimdal/src"
+distdirs="${distdirs} /afs/pdc.kth.se/public/ftp/pub/heimdal/src/snapshots"
+distdirs="${distdirs} /afs/pdc.kth.se/public/ftp/pub/krb/src"
+
+
+logprint () {
+    d=`date '+%Y-%m-%d %H:%M:%S'`
+    echo "${d}: $*"
+    echo "${d}: --- $*" >> ${logfile}
+}
+
+logerror () {
+    echo "$*"
+    exit 1
+}
+
+find_unzip_prog () {
+    unzip_prog=
+    oldIFS="$IFS"
+    IFS=:
+    set -- $PATH
+    IFS="$oldIFS"
+    for a in $* ; do
+       if [ -x $a/gzip ] ; then
+           unzip_prog="$a/gzip -dc"
+           break
+       elif [ -x $a/gunzip ] ; then
+           unzip_prog="$a/gunzip -c"
+           break
+       fi
+    done
+    [ "$unzip_prog" = "" ] && logerror failed to find unzip program
+}
+
+find_canon_name () {
+    canon_name=
+    for a in ${distdirs} ; do
+       if [ -f $a/config.guess ] ; then
+           canon_name=`$a/config.guess`
+       fi
+       if [ "${canon_name}" != "" ] ; then
+           break
+       fi
+    done
+    [ "${canon_name}" = "" ] && logerror "cant find config.guess"
+}
+
+do_check_p () {
+    eval check_var=\$"$1"
+    for a in ${check_var} ; do
+       expr "$2${canon_name}" : "${a}" > /dev/null 2>&1 && return 1
+    done
+    return 0
+}
+
+unpack_tar () {
+    for a in ${distdirs} ; do
+       if [ -f $a/$1 ] ; then
+           ${opt_n} ${unzip_prog} ${a}/$1 | ${opt_n} tar xf -
+           return 0
+       fi
+    done
+    logerror "did not find $1"
+}
+
+build () {
+    real_ver=$1
+    prog=$2
+    ver=$3
+    confprog=$4
+    checks=$5
+    pv=${prog}-${ver}
+    mkdir tmp || logerror "failed to build tmpdir"
+    cd tmp || logerror "failed to change dir to tmpdir"
+    do_check_p dont_build ${real_ver} || \
+       { cd .. ; rmdir tmp ; logprint "not building $1" && return 0 ; }
+    cd .. || logerror "failed to change back from tmpdir"
+    rmdir tmp || logerror "failed to remove tmpdir"
+    logprint "preparing for ${pv}"
+    ${opt_n} rm -rf ${targetdir}/${prog}-${ver}
+    ${opt_n} rm -rf ${prog}-${ver}
+    unpack_tar ${pv}.tar.gz
+    ${opt_n} cd ${pv} || logerror directory ${pv} not there
+    logprint "configure ${prog} ${ver} (${confprog})"
+    ${opt_n} ./${confprog} \
+       --prefix=${targetdir}/${pv} >> ${logfile} 2>&1 || \
+           { logprint failed to configure ${pv} ; return 1 ; }
+    logprint "make ${prog} ${ver}"
+    ${opt_n} make ${make_f} >> ${logfile} 2>&1 || \
+       { logprint failed to make ${pv} ; return 1 ; }
+    ${opt_n} make install >> ${logfile} 2>&1 || \
+       { logprint failed to install ${pv} ; return 1 ; }
+    do_check_p make_check_version ${real_ver} || \
+       { ${opt_n} make check >> ${logfile} 2>&1 || return 1 ; }
+    ${opt_n} cd ..
+    [ "${checks}" != "" ] && ${opt_n} ${checks} >> ${logfile} 2>&1
+    return 0
+}
+
+find_canon_name
+
+logprint using host `hostname`
+logprint `uname -a`
+logprint canonical name ${canon_name}
+
+logprint clearing logfile
+> ${logfile}
+
+find_unzip_prog
+
+logprint using target dir ${targetdir}
+mkdir -p ${targetdir}/src
+cd ${targetdir}/src || exit 1
+rm -rf heimdal* openssl* krb4*
+
+logprint === building openssl versions
+for vo in ${openssl_versions} ; do
+    build openssl-${vo} openssl $vo config
+done
+
+wssl="--with-openssl=${targetdir}/openssl"
+wssli="--with-openssl-include=${targetdir}/openssl"    #this is a hack for broken heimdal 0.5.x autoconf test
+wossl="--without-openssl"
+wk4c="--with-krb4-config=${targetdir}/krb4"
+bk4c="/bin/krb4-config"
+wok4="--without-krb4"
+
+logprint === building heimdal w/o krb4 versions
+for vo in ${openssl_versions} ; do
+    for vh in ${heimdal_versions} ; do
+       v="openssl-${vo}-heimdal-${vh}"
+       build "${v}" \
+           heimdal ${vh} \
+           "configure ${wok4} ${wssl}-${vo} ${wssli}-${vo}/include" \
+           "${targetdir}/heimdal-${vh}/bin/krb5-config --libs | grep lcrypto" \ || \
+           { failed="${failed} ${v}" ; logprint ${v} failed ; }
+    done
+done
+
+logprint === building krb4
+for vo in ${openssl_versions} ; do
+    for vk in ${krb4_versions} ; do
+       v="openssl-${vo}-krb4-${vk}"
+       build "${v}" \
+           krb4 ${vk} \
+           "configure ${wssl}-${vo}" \
+           "${targetdir}/krb4-${vk}/bin/krb4-config --libs | grep lcrypto"|| \
+           { failed="${failed} ${v}" ; logprint ${v} failed ; }
+    done
+done
+
+logprint === building heimdal with krb4 versions
+for vo in ${openssl_versions} ; do
+    for vk in ${krb4_versions} ; do
+       for vh in ${heimdal_versions} ; do
+           v="openssl-${vo}-krb4-${vk}-heimdal-${vh}"
+           build "${v}" \
+               heimdal ${vh} \
+               "configure ${wk4c}-${vk}${bk4c} ${wssl}-${vo} ${wssli}-${vo}/include" \
+               "${targetdir}/heimdal-${vh}/bin/krb5-config --libs | grep lcrypto && ${targetdir}/heimdal-${vh}/bin/krb5-config --libs | grep krb4" \
+                || \
+           { failed="${failed} ${v}" ; logprint ${v} failed ; }
+       done
+    done
+done
+
+logprint === building heimdal without krb4 and openssl versions
+for vh in ${heimdal_versions} ; do
+    v="des-heimdal-${vh}"
+    build "${v}" \
+       heimdal ${vh} \
+       "configure ${wok4} ${wossl}" || \
+       { failed="${failed} ${v}" ; logprint ${v} failed ; }
+done
+
+logprint all done
+[ "${failed}" != "" ] && logprint "failed: ${failed}"
+exit 0
diff --git a/src/kerberosV/src/tools/kdc-log-analyze.pl b/src/kerberosV/src/tools/kdc-log-analyze.pl
new file mode 100755 (executable)
index 0000000..64e6cbd
--- /dev/null
@@ -0,0 +1,536 @@
+#! /usr/pkg/bin/perl
+# -*- mode: perl; perl-indent-level: 8 -*-
+# 
+# Copyright (c) 2003 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+# SUCH DAMAGE. 
+#
+# $KTH: kdc-log-analyze.pl,v 1.10 2004/03/07 16:05:15 lha Exp $
+#
+# kdc-log-analyze - Analyze a KDC log file and give a report on the contents
+#
+# Note: The parts you want likely want to customize are the variable $notlocal,
+# the array @local_network_re and the array @local_realms.
+#
+# Idea and implemetion for MIT Kerberos was done first by 
+# Ken Hornstein <kenh@cmf.nrl.navy.mil>, this program wouldn't exists
+# without his help.
+#
+
+use strict;
+use Sys::Hostname;
+
+my $notlocal = 'not SU';
+my @local_realms = ( "SU.SE" );
+my @local_networks_re = 
+    ( 
+      "130\.237",
+      "193\.11\.3[0-9]\.",
+      "130.242.128",
+      "2001:6b0:5:"
+      );
+
+my $as_req = 0;
+my %as_req_addr;
+my %as_req_addr_nonlocal;
+my %as_req_client;
+my %as_req_server;
+my %addr_uses_des;
+my %princ_uses_des;
+my $five24_req = 0;
+my %five24_req_addr;
+my %five24_req_addr_nonlocal;
+my %five24_req_server;
+my %five24_req_client;
+my $as_req_successful = 0;
+my $as_req_error = 0;
+my $no_such_princ = 0;
+my %no_such_princ_princ;
+my %no_such_princ_addr;
+my %no_such_princ_addr_nonlocal;
+my $as_req_etype_odd = 0;
+my %bw_addr;
+my $pa_alt_princ_request = 0;
+my $pa_alt_princ_verify = 0;
+my $tgs_req = 0;
+my %tgs_req_addr;
+my %tgs_req_addr_nonlocal;
+my %tgs_req_client;
+my %tgs_req_server;
+my $tgs_xrealm_out = 0;
+my %tgs_xrealm_out_realm;
+my %tgs_xrealm_out_princ;
+my $tgs_xrealm_in = 0;
+my %tgs_xrealm_in_realm;
+my %tgs_xrealm_in_princ;
+my %enctype_session;
+my %enctype_ticket;
+my $restarts = 0;
+my $forward_non_forward = 0;
+my $v4_req = 0;
+my %v4_req_addr;
+my %v4_req_addr_nonlocal;
+my $v4_cross = 0;
+my %v4_cross_realm;
+my $referrals = 0;
+my %referral_princ;
+my %referral_realm;
+my %strange_tcp_data;
+my $http_malformed = 0;
+my %http_malformed_addr;
+my $http_non_kdc = 0;
+my %http_non_kdc_addr;
+my $tcp_conn_timeout = 0;
+my %tcp_conn_timeout_addr;
+my $failed_processing = 0;
+my %failed_processing_addr;
+my $connection_closed = 0;
+my %connection_closed_addr;
+my $pa_failed = 0;
+my %pa_failed_princ;
+my %pa_failed_addr;
+my %ip;
+
+$ip{'4'} = $ip{'6'} = 0;
+
+while (<>) {
+       process_line($_);
+}
+
+print "Kerberos KDC Log Report for ", 
+    hostname, " on ", scalar localtime, "\n\n";
+
+print "General Statistics\n\n";
+
+print "\tNumber of IPv4 requests: $ip{'4'}\n";
+print "\tNumber of IPv6 requests: $ip{'6'}\n\n";
+
+print "\tNumber of restarts: $restarts\n";
+print "\tNumber of V4 requests: $v4_req\n";
+if ($v4_req > 0) {
+       print "\tTop ten IP addresses performing V4 requests:\n";
+       topten(\%v4_req_addr);
+}
+if (int(keys %v4_req_addr_nonlocal) > 0) {
+       print "\tTop ten $notlocal IP addresses performing V4 requests:\n";
+       topten(\%v4_req_addr_nonlocal);
+
+}
+print "\n";
+
+print "\tNumber of V4 cross realms (krb4 and 524) requests: $v4_cross\n";
+if ($v4_cross > 0) {
+       print "\tTop ten realms performing V4 cross requests:\n";
+       topten(\%v4_cross_realm);
+}
+print "\n";
+
+print "\tNumber of failed lookups: $no_such_princ\n";
+if ($no_such_princ > 0) {
+       print "\tTop ten IP addresses failing to find principal:\n";
+       topten(\%no_such_princ_addr);
+       print "\tTop ten $notlocal IP addresses failing find principal:\n";
+       topten(\%no_such_princ_addr_nonlocal);
+       print "\tTop ten failed to find principals\n";
+       topten(\%no_such_princ_princ);
+}
+print "\n";
+
+print "\tBandwidth pigs:\n";
+topten(\%bw_addr);
+print "\n";
+
+print "\tStrange TCP data clients: ", int(keys %strange_tcp_data),"\n";
+topten(\%strange_tcp_data);
+print "\n";
+
+print "\tTimeout waiting on TCP requests: ", $tcp_conn_timeout,"\n";
+if ($tcp_conn_timeout > 0) {
+       print "\tTop ten TCP timeout request clients\n";
+       topten(\%tcp_conn_timeout_addr);
+}
+print "\n";
+
+print "\tFailed processing requests: ", $failed_processing,"\n";
+if ($failed_processing > 0) {
+       print "\tTop ten failed processing request clients\n";
+       topten(\%failed_processing_addr);
+}
+print "\n";
+
+print "\tConnection closed requests: ", $connection_closed,"\n";
+if ($connection_closed > 0) {
+       print "\tTop ten connection closed request clients\n";
+       topten(\%connection_closed_addr);
+}
+print "\n";
+
+print "\tMalformed HTTP requests: ", $http_malformed,"\n";
+if ($http_malformed > 0) {
+       print "\tTop ten malformed HTTP request clients\n";
+       topten(\%http_malformed_addr);
+}
+print "\n";
+
+print "\tHTTP non kdc requests: ", $http_non_kdc,"\n";
+if ($http_non_kdc > 0) {
+       print "\tTop ten HTTP non KDC request clients\n";
+       topten(\%http_non_kdc_addr);
+}
+print "\n";
+
+print "Report on AS_REQ requests\n\n";
+print "Overall AS_REQ statistics\n\n";
+
+print "\tTotal number: $as_req\n";
+
+print "\nAS_REQ client/server statistics\n\n";
+
+print "\tDistinct IP Addresses performing requests: ", 
+    int(keys %as_req_addr),"\n";
+print "\tOverall top ten IP addresses\n";
+topten(\%as_req_addr);
+
+print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
+                                       int(keys %as_req_addr_nonlocal), "\n";
+print "\tTop ten non-local ($notlocal) IP address:\n";
+topten(\%as_req_addr_nonlocal);
+
+print "\n\tPreauth failed for for: ", $pa_failed, " requests\n";
+if ($pa_failed) {
+       print "\tPreauth failed top ten IP addresses:\n";
+       topten(\%pa_failed_addr);
+       print "\tPreauth failed top ten principals:\n";
+       topten(\%pa_failed_princ);
+}
+
+print "\n\tDistinct clients performing requests: ", 
+    int(keys %as_req_client), "\n";
+print "\tTop ten clients:\n";
+topten(\%as_req_client);
+
+print "\tDistinct services requested: ", int(keys %as_req_server), "\n";
+print "\tTop ten requested services:\n";
+topten(\%as_req_server);
+
+print "\n\n\nReport on TGS_REQ requests:\n\n";
+print "Overall TGS_REQ statistics\n\n";
+print "\tTotal number: $tgs_req\n";
+
+print "\nTGS_REQ client/server statistics\n\n";
+print "\tDistinct IP addresses performing requests: ",
+                               int(keys %tgs_req_addr), "\n";
+print "\tOverall top ten IP addresses\n";
+topten(\%tgs_req_addr);
+
+print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
+                               int(keys %tgs_req_addr_nonlocal), "\n";
+print "\tTop ten non-local ($notlocal) IP address:\n";
+topten(\%tgs_req_addr_nonlocal);
+
+print "\tDistinct clients performing requests: ",
+                               int(keys %tgs_req_client), "\n";
+print "\tTop ten clients:\n";
+topten(\%tgs_req_client);
+
+print "\tDistinct services requested: ", int(keys %tgs_req_server), "\n";
+print "\tTop ten requested services:\n";
+topten(\%tgs_req_server);
+
+print "\n\n\nReport on 524_REQ requests:\n\n";
+
+print "\t524_REQ client/server statistics\n\n";
+
+print "\tDistinct IP Addresses performing requests: ", 
+    int(keys %five24_req_addr),"\n";
+print "\tOverall top ten IP addresses\n";
+topten(\%five24_req_addr);
+
+print "\tDistinct non-local ($notlocal) IP Addresses performing requests: ",
+                                       int(keys %five24_req_addr_nonlocal), "\n";
+print "\tTop ten non-local ($notlocal) IP address:\n";
+topten(\%five24_req_addr_nonlocal);
+
+print "\tDistinct clients performing requests: ", int(keys %five24_req_client), "\n";
+print "\tTop ten clients:\n";
+topten(\%five24_req_client);
+
+print "\tDistinct services requested: ", int(keys %five24_req_server), "\n";
+print "\tTop ten requested services:\n";
+topten(\%five24_req_server);
+print "\n";
+
+print "Cross realm statistics\n\n";
+
+print "\tNumber of cross-realm tgs out: $tgs_xrealm_out\n";
+if ($tgs_xrealm_out > 0) {
+       print "\tTop ten realms used for out cross-realm:\n";
+       topten(\%tgs_xrealm_out_realm);
+       print "\tTop ten principals use out cross-realm:\n";
+       topten(\%tgs_xrealm_out_princ);
+}
+print "\tNumber of cross-realm tgs in: $tgs_xrealm_in\n";
+if ($tgs_xrealm_in > 0) {
+       print "\tTop ten realms used for in cross-realm:\n";
+       topten(\%tgs_xrealm_in_realm);
+       print "\tTop ten principals use in cross-realm:\n";
+       topten(\%tgs_xrealm_in_princ);
+}
+
+print "\n\nReport on referral:\n\n";
+
+print "\tNumber of referrals: $referrals\n";
+if ($referrals > 0) {
+       print "\tTop ten referral-ed principals:\n";
+       topten(\%referral_princ);
+       print "\tTop ten to realm referrals:\n";
+       topten(\%referral_realm);
+}
+
+print "\n\nEnctype Statistics:\n\n";
+print "\tTop ten session enctypes:\n";
+topten(\%enctype_session);
+print "\tTop ten ticket enctypes:\n";
+topten(\%enctype_ticket);
+
+print "\tDistinct IP addresses using DES: ", int(keys %addr_uses_des), "\n";
+print "\tTop IP addresses using DES:\n";
+topten(\%addr_uses_des);
+print "\tDistinct principals using DES: ", int(keys %princ_uses_des), "\n";
+print "\tTop ten principals using DES:\n";
+topten(\%princ_uses_des);
+
+print "\n";
+
+printf("Requests to forward non-forwardable ticket: $forward_non_forward\n");
+
+
+exit 0;
+
+my $last_addr = "";
+my $last_principal = "";
+
+sub process_line {
+       local($_) = @_;
+       #
+       # Eat these lines that are output as a result of startup (but
+       # log the number of restarts)
+       #
+       if (/AS-REQ \(krb4\) (.*) from IPv([46]):([0-9\.:a-fA-F]+) for krbtgt.*$/){
+               $v4_req++;
+               $v4_req_addr{$3}++;
+               $v4_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
+               $last_addr = $3;
+               $last_principal = $1;
+               $ip{$2}++;
+       } elsif (/AS-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) {
+               $as_req++;
+               $as_req_client{$1}++;
+               $as_req_server{$4}++;
+               $as_req_addr{$3}++;
+               $as_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
+               $last_addr = $3;
+               $last_principal = $1;
+               $ip{$2}++;
+       } elsif (/TGS-REQ \(krb4\)/) {
+               #Nothing
+       } elsif (/TGS-REQ (.+) from IPv([46]):([0-9\.:a-fA-F]+) for (.*?)( \[.*\]){0,1}$/) {
+               $tgs_req++;
+               $tgs_req_client{$1}++;
+               $tgs_req_server{$4}++;
+               $tgs_req_addr{$3}++;
+               $tgs_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
+               $last_addr = $3;
+               $last_principal = $1;
+               $ip{$2}++;
+
+               my $source = $1;
+               my $dest = $4;
+               
+               if (!islocalrealm($source)) {
+                       $tgs_xrealm_in++;
+                       $tgs_xrealm_in_princ{$source}++;
+                       if ($source =~ /[^@]+@([^@]+)/ ) {
+                               $tgs_xrealm_in_realm{$1}++;
+                       }
+               }
+               if ($dest =~ /krbtgt\/([^@]+)@[^@]+/) {
+                       if (!islocalrealm($1)) {
+                               $tgs_xrealm_out++;
+                               $tgs_xrealm_out_realm{$1}++;
+                               $tgs_xrealm_out_princ{$source}++;
+                       }
+               }
+       } elsif (/524-REQ (.*) from IPv([46]):([0-9\.:a-fA-F]+) for (.*)$/) {
+               $five24_req++;
+               $five24_req_client{$1}++;
+               $five24_req_server{$4}++;
+               $five24_req_addr{$3}++;
+               $five24_req_addr_nonlocal{$3}++ if (!islocaladdr($3));
+               $last_addr = $3;
+               $last_principal = $1;
+               $ip{$2}++;
+       } elsif (/TCP data of strange type from IPv[46]:([0-9\.:a-fA-F]+)/) {
+               $strange_tcp_data{$1}++;
+       } elsif (/Lookup (.*) failed: No such entry in the database/) {
+               $no_such_princ++;
+               $no_such_princ_addr{$last_addr}++;
+               $no_such_princ_addr_nonlocal{$last_addr}++ if (!islocaladdr($last_addr));
+               $no_such_princ_princ{$1}++;
+       } elsif (/Lookup .* succeeded$/) {
+               # Nothing
+       } elsif (/Malformed HTTP request from IPv[46]:([0-9\.:a-fA-F]+)$/) {
+               $http_malformed++;
+               $http_malformed_addr{$1}++;
+       } elsif (/TCP-connection from IPv[46]:([0-9\.:a-fA-F]+) expired after [0-9]+ bytes/) {
+               $tcp_conn_timeout++;
+               $tcp_conn_timeout_addr{$1}++;
+       } elsif (/Failed processing [0-9]+ byte request from IPv[46]:([0-9\.:a-fA-F]+)/) {
+               $failed_processing++;
+               $failed_processing_addr{$1}++;
+       } elsif (/connection closed before end of data after [0-9]+ bytes from IPv[46]:([0-9\.:a-fA-F]+)/) {
+               $connection_closed++;
+               $connection_closed_addr{$1}++;
+       } elsif (/HTTP request from IPv[46]:([0-9\.:a-fA-F]+) is non KDC request/) {
+               $http_non_kdc++;
+               $http_non_kdc_addr{$1}++;
+       } elsif (/returning a referral to realm (.*) for server (.*) that was not found/) {
+               $referrals++;
+               $referral_princ{$2}++;
+               $referral_realm{$1}++;
+       } elsif (/krb4 Cross-realm (.*) -> (.*) disabled/) {
+               $v4_cross++;
+               $v4_cross_realm{$1."->".$2}++;
+       } elsif (/524 cross-realm (.*) -> (.*) disabled/) {
+               $v4_cross++;
+               $v4_cross_realm{$1."->".$2}++;
+       } elsif (/cross-realm (.*) -> (.*): no transit through realm (.*)/) {
+       } elsif (/cross-realm (.*) -> (.*) via \[([^\]]+)\]/) {
+       } elsif (/cross-realm (.*) -> (.*)) {
+       } elsif (/sending ([0-9]+) bytes to IPv[46]:([0-9\.:a-fA-F]+)/) {
+               $bw_addr{$2} += $1;
+       } elsif (/Using ([-a-z0-9]+)\/([-a-z0-9]+)/) {
+               $enctype_ticket{$1}++;
+               $enctype_session{$2}++;
+
+               my $ticket = $1;
+               my $session = $2;
+
+               if ($ticket =~ /des-cbc-(crc|md4|md5)/) {
+                       $addr_uses_des{$last_addr}++;
+                       $princ_uses_des{$last_principal}++;
+               }
+
+       } elsif (/Failed to decrypt PA-DATA -- (.+)$/) {
+               $pa_failed++;
+               $pa_failed_princ{$last_principal}++;
+               $pa_failed_addr{$last_addr}++;
+
+       } elsif (/Request to forward non-forwardable ticket/) {
+               $forward_non_forward++;
+       } elsif (/HTTP request:/) {
+       } elsif (/krb_rd_req: Incorrect network address/) {
+       } elsif (/krb_rd_req: Ticket expired \(krb_rd_req\)/) {
+       } elsif (/Ticket expired \(.*\)/) {
+       } elsif (/krb_rd_req: Can't decode authenticator \(krb_rd_req\)/) {
+       } elsif (/Request from wrong address/) {
+               # XXX
+       } elsif (/UNKNOWN --/) {
+               # XXX
+       } elsif (/Too large time skew -- (.*)$/) {
+               # XXX
+       } elsif (/No PA-ENC-TIMESTAMP --/) {
+               # XXX
+       } elsif (/Looking for pa-data --/) {
+               # XXX
+       } elsif (/Pre-authentication succeded -- (.+)$/) {
+               # XXX
+       } elsif (/Bad request for ([,a-zA-Z0-9]+) ticket/) {
+               # XXX
+       } elsif (/Failed to verify AP-REQ: Ticket expired/) {
+               # XXX 
+       } elsif (/Client not found in database:/) {
+               # XXX
+       } elsif (/Server not found in database \(krb4\)/) {
+       } elsif (/Server not found in database:/) {
+               # XXX
+       } elsif (/newsyslog.*logfile turned over/) {
+               # Nothing
+       } elsif (/Requested flags:/) {
+               # Nothing
+       } elsif (/shutting down/) {
+               # Nothing
+       } elsif (/listening on IP/) {
+               # Nothing
+       } elsif (/commencing operation/) {
+               $restarts++;
+       }
+       #
+       # Log it if we didn't parse the line
+       #
+       else {
+               print "Unknown log file line: $_";
+       }
+}
+
+sub topten {
+       my ($list) = @_;
+       my @keys;
+
+       my $key;
+
+       @keys = (sort {$$list{$b} <=> $$list{$a}} (keys %{$list}));
+       splice @keys, 10;
+
+       foreach $key (@keys) {
+               print "\t\t$key - $$list{$key}\n";
+       }
+}
+
+sub islocaladdr (\$) {
+       my ($addr) = @_;
+       my $net;
+
+       foreach $net (@local_networks_re) {
+               return 1 if ($addr =~ /$net/);
+       }
+       return 0;
+}
+
+sub islocalrealm (\$) {
+       my ($princ) = @_;
+       my $realm;
+
+       foreach $realm (@local_realms) {
+               return 1 if ($princ eq $realm);
+               return 1 if ($princ =~ /[^@]+\@${realm}/);
+       }
+       return 0;
+}
diff --git a/src/kerberosV/src/tools/krb5-config.1 b/src/kerberosV/src/tools/krb5-config.1
new file mode 100644 (file)
index 0000000..960d1e9
--- /dev/null
@@ -0,0 +1,90 @@
+.\" Copyright (c) 2000 - 2001 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 the Institute nor the names 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+.\" SUCH DAMAGE. 
+.\" 
+.\" $KTH: krb5-config.1,v 1.5 2003/02/16 21:10:32 lha Exp $
+.\"
+.Dd November 30, 2000
+.Dt KRB5-CONFIG 1
+.Os HEIMDAL
+.Sh NAME
+.Nm krb5-config
+.Nd "give information on how to link code against Heimdal libraries"
+.Sh SYNOPSIS
+.Nm
+.Op Fl -prefix Ns Op = Ns Ar dir
+.Op Fl -exec-prefix Ns Op = Ns Ar dir
+.Op Fl -libs
+.Op Fl -cflags
+.Op Ar libraries
+.Sh DESCRIPTION
+.Nm
+tells the application programmer what special flags to use to compile
+and link programs against the libraries installed by Heimdal.
+.Pp
+Options supported:
+.Bl -tag -width Ds
+.It Fl -prefix Ns Op = Ns Ar dir
+Print the prefix if no
+.Ar dir
+is specified, otherwise set prefix to
+.Ar dir .
+.It Fl -exec-prefix Ns Op = Ns Ar dir
+Print the exec-prefix if no
+.Ar dir
+is specified, otherwise set exec-prefix to
+.Ar dir .
+.It Fl -libs
+Output the set of libraries that should be linked against.
+.It Fl -cflags
+Output the set of flags to give to the C compiler when using the
+Heimdal libraries.
+.El
+.Pp
+By default
+.Nm
+will output the set of flags and libraries to be used by a normal
+program using the krb5 API.  The user can also supply a library to be
+used, the supported ones are:
+.Bl -tag -width Ds
+.It krb5
+(the default)
+.It gssapi
+use the krb5 gssapi mechanism
+.It kadm-client
+use the client-side kadmin libraries
+.It kadm-server
+use the server-side kadmin libraries
+.El
+.Sh SEE ALSO
+.Xr cc 1
+.Sh HISTORY
+.Nm
+appeared in Heimdal 0.3d.
diff --git a/src/kerberosV/src/tools/krb5-config.in b/src/kerberosV/src/tools/krb5-config.in
new file mode 100644 (file)
index 0000000..e8e6800
--- /dev/null
@@ -0,0 +1,110 @@
+#!/bin/sh
+# $KTH: krb5-config.in,v 1.10.2.1 2006/02/03 15:01:28 lha Exp $
+
+do_libs=no
+do_cflags=no
+do_usage=no
+print_prefix=no
+print_exec_prefix=no
+library=krb5
+
+if test $# -eq 0; then
+  do_usage=yes
+  usage_exit=1
+fi
+
+for i in $*; do
+  case $i in
+  --help)
+    do_usage=yes
+    usage_exit=0
+    ;;
+  --version)
+    echo "@PACKAGE@ @VERSION@"
+    echo '$KTH: krb5-config.in,v 1.10.2.1 2006/02/03 15:01:28 lha Exp $'
+    exit 0
+    ;;
+  --prefix=*)
+    prefix=`echo $i | sed 's/^--prefix=//'`
+    ;;
+  --prefix)
+    print_prefix=yes
+    ;;
+  --exec-prefix=*)
+    exec_prefix=`echo $i | sed 's/^--exec-prefix=//'`
+    ;;
+  --exec-prefix)
+    print_exec_prefix=yes
+    ;;
+  --libs)
+    do_libs=yes
+    ;;
+  --cflags)
+    do_cflags=yes
+    ;;
+  krb5)
+    library=krb5
+    ;;
+  gssapi)
+    library=gssapi
+    ;;
+  kadm-client)
+    library=kadm-client
+    ;;
+  kadm-server)
+    library=kadm-server
+    ;;
+  *)
+    echo "unknown option: $i"
+    exit 1
+    ;;
+  esac
+done
+
+if test "$do_usage" = "yes"; then
+    echo "usage: $0 [options] [libraries]"
+    echo "options: [--prefix[=dir]] [--exec-prefix[=dir]] [--libs] [--cflags]"
+    echo "libraries: krb5 gssapi kadm-client kadm-server"
+    exit $usage_exit
+fi
+
+if test "$prefix" = ""; then
+  prefix=@prefix@
+fi
+if test "$exec_prefix" = ""; then
+  exec_prefix=@exec_prefix@
+fi
+
+libdir=@libdir@
+includedir=@includedir@
+
+if test "$print_prefix" = "yes"; then
+    echo $prefix
+fi
+
+if test "$print_exec_prefix" = "yes"; then
+    echo $exec_prefix
+fi
+
+if test "$do_libs" = "yes"; then
+    lib_flags="-L${libdir}"
+    case $library in
+    gssapi)
+       lib_flags="$lib_flags -lgssapi"
+       ;;
+    kadm-client)
+       lib_flags="$lib_flags -lkadm5clnt"
+       ;;
+    kadm-server)
+       lib_flags="$lib_flags -lkadm5srv"
+       ;;
+    esac
+    lib_flags="$lib_flags -lkrb5 -lasn1 -lcom_err @LIB_des_appl@ -lroken"
+    lib_flags="$lib_flags @LIB_crypt@ @LIB_dbopen@ @LIB_dlopen@ @LIBS@"
+    echo $lib_flags
+fi
+if test "$do_cflags" = "yes"; then
+    echo "-I${includedir} @INCLUDE_des@"
+fi
+
+exit 0
diff --git a/src/kerberosV/src/ylwrap b/src/kerberosV/src/ylwrap
new file mode 100755 (executable)
index 0000000..f86e217
--- /dev/null
@@ -0,0 +1,222 @@
+#! /bin/sh
+# ylwrap - wrapper for lex/yacc invocations.
+
+scriptversion=2003-11-18.20
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2001, 2002, 2003
+#   Free Software Foundation, Inc.
+#
+# Written by Tom Tromey <tromey@cygnus.com>.
+#
+# 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 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.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+case "$1" in
+  '')
+    echo "$0: No files given.  Try \`$0 --help' for more information." 1>&2
+    exit 1
+    ;;
+  --basedir)
+    basedir=$2
+    shift 2
+    ;;
+  -h|--h*)
+    cat <<\EOF
+Usage: ylwrap [--help|--version] INPUT [OUTPUT DESIRED]... -- PROGRAM [ARGS]...
+
+Wrapper for lex/yacc invocations, renaming files as desired.
+
+  INPUT is the input file
+  OUTPUT is one file PROG generates
+  DESIRED is the file we actually want instead of OUTPUT
+  PROGRAM is program to run
+  ARGS are passed to PROG
+
+Any number of OUTPUT,DESIRED pairs may be used.
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit 0
+    ;;
+  -v|--v*)
+    echo "ylwrap $scriptversion"
+    exit 0
+    ;;
+esac
+
+
+# The input.
+input="$1"
+shift
+case "$input" in
+  [\\/]* | ?:[\\/]*)
+    # Absolute path; do nothing.
+    ;;
+  *)
+    # Relative path.  Make it absolute.
+    input="`pwd`/$input"
+    ;;
+esac
+
+pairlist=
+while test "$#" -ne 0; do
+  if test "$1" = "--"; then
+    shift
+    break
+  fi
+  pairlist="$pairlist $1"
+  shift
+done
+
+# The program to run.
+prog="$1"
+shift
+# Make any relative path in $prog absolute.
+case "$prog" in
+  [\\/]* | ?:[\\/]*) ;;
+  *[\\/]*) prog="`pwd`/$prog" ;;
+esac
+
+# FIXME: add hostname here for parallel makes that run commands on
+# other machines.  But that might take us over the 14-char limit.
+dirname=ylwrap$$
+trap "cd `pwd`; rm -rf $dirname > /dev/null 2>&1" 1 2 3 15
+mkdir $dirname || exit 1
+
+cd $dirname
+
+case $# in
+  0) $prog "$input" ;;
+  *) $prog "$@" "$input" ;;
+esac
+status=$?
+
+if test $status -eq 0; then
+  set X $pairlist
+  shift
+  first=yes
+  # Since DOS filename conventions don't allow two dots,
+  # the DOS version of Bison writes out y_tab.c instead of y.tab.c
+  # and y_tab.h instead of y.tab.h. Test to see if this is the case.
+  y_tab_nodot="no"
+  if test -f y_tab.c || test -f y_tab.h; then
+    y_tab_nodot="yes"
+  fi
+
+  # The directory holding the input.
+  input_dir=`echo "$input" | sed -e 's,\([\\/]\)[^\\/]*$,\1,'`
+  # Quote $INPUT_DIR so we can use it in a regexp.
+  # FIXME: really we should care about more than `.' and `\'.
+  input_rx=`echo "$input_dir" | sed 's,\\\\,\\\\\\\\,g;s,\\.,\\\\.,g'`
+
+  while test "$#" -ne 0; do
+    from="$1"
+    # Handle y_tab.c and y_tab.h output by DOS
+    if test $y_tab_nodot = "yes"; then
+      if test $from = "y.tab.c"; then
+       from="y_tab.c"
+      else
+       if test $from = "y.tab.h"; then
+         from="y_tab.h"
+       fi
+      fi
+    fi
+    if test -f "$from"; then
+      # If $2 is an absolute path name, then just use that,
+      # otherwise prepend `../'.
+      case "$2" in
+       [\\/]* | ?:[\\/]*) target="$2";;
+       *) target="../$2";;
+      esac
+
+      # We do not want to overwrite a header file if it hasn't
+      # changed.  This avoid useless recompilations.  However the
+      # parser itself (the first file) should always be updated,
+      # because it is the destination of the .y.c rule in the
+      # Makefile.  Divert the output of all other files to a temporary
+      # file so we can compare them to existing versions.
+      if test $first = no; then
+       realtarget="$target"
+       target="tmp-`echo $target | sed s/.*[\\/]//g`"
+      fi
+      # Edit out `#line' or `#' directives.
+      #
+      # We don't want the resulting debug information to point at
+      # an absolute srcdir; it is better for it to just mention the
+      # .y file with no path.
+      #
+      # We want to use the real output file name, not yy.lex.c for
+      # instance.
+      #
+      # We want the include guards to be adjusted too.
+      FROM=`echo "$from" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+      TARGET=`echo "$2" | sed \
+            -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'\
+            -e 's/[^ABCDEFGHIJKLMNOPQRSTUVWXYZ]/_/g'`
+
+      sed -e "/^#/!b" -e "s,$input_rx,," -e "s,$from,$2," \
+          -e "s,$FROM,$TARGET," "$from" >"$target" || status=$?
+
+      # Check whether header files must be updated.
+      if test $first = no; then
+       if test -f "$realtarget" && cmp -s "$realtarget" "$target"; then
+         echo "$2" is unchanged
+         rm -f "$target"
+       else
+          echo updating "$2"
+          mv -f "$target" "$realtarget"
+        fi
+      fi
+    else
+      # A missing file is only an error for the first file.  This
+      # is a blatant hack to let us support using "yacc -d".  If -d
+      # is not specified, we don't want an error when the header
+      # file is "missing".
+      if test $first = yes; then
+        status=1
+      fi
+    fi
+    shift
+    shift
+    first=no
+  done
+else
+  status=$?
+fi
+
+# Remove the directory.
+cd ..
+rm -rf $dirname
+
+exit $status
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# 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/src/kerberosV/usr.bin/CVS/Entries b/src/kerberosV/usr.bin/CVS/Entries
new file mode 100644 (file)
index 0000000..3b13f19
--- /dev/null
@@ -0,0 +1,11 @@
+/Makefile/1.9/Mon Jul 14 16:14:44 2003//
+/Makefile.inc/1.1/Fri May 25 08:20:32 2001//
+D/afslog////
+D/kauth////
+D/kdestroy////
+D/kf////
+D/kinit////
+D/klist////
+D/pagsh////
+D/string2key////
+D/verify_krb5_conf////
diff --git a/src/kerberosV/usr.bin/CVS/Repository b/src/kerberosV/usr.bin/CVS/Repository
new file mode 100644 (file)
index 0000000..c8dfee0
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin
diff --git a/src/kerberosV/usr.bin/CVS/Root b/src/kerberosV/usr.bin/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/Makefile b/src/kerberosV/usr.bin/Makefile
new file mode 100644 (file)
index 0000000..f8ac28c
--- /dev/null
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.9 2003/07/14 16:14:44 mho Exp $
+
+# XXX asn1_compile is compiled in ../Makefile
+
+# kf - not imported?
+
+SUBDIR=        afslog \
+       kauth \
+       kdestroy \
+       kinit \
+       klist \
+       pagsh \
+       string2key \
+       verify_krb5_conf
+
+.include <bsd.subdir.mk>
diff --git a/src/kerberosV/usr.bin/Makefile.inc b/src/kerberosV/usr.bin/Makefile.inc
new file mode 100644 (file)
index 0000000..c381701
--- /dev/null
@@ -0,0 +1,3 @@
+# $OpenBSD: Makefile.inc,v 1.1 2001/05/25 08:20:32 hin Exp $
+
+BINDIR=        /usr/bin
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/afslog/CVS/Entries b/src/kerberosV/usr.bin/afslog/CVS/Entries
new file mode 100644 (file)
index 0000000..a9512c7
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.3/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/afslog/CVS/Repository b/src/kerberosV/usr.bin/afslog/CVS/Repository
new file mode 100644 (file)
index 0000000..3957254
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/afslog
diff --git a/src/kerberosV/usr.bin/afslog/CVS/Root b/src/kerberosV/usr.bin/afslog/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/afslog/Makefile b/src/kerberosV/usr.bin/afslog/Makefile
new file mode 100644 (file)
index 0000000..e622411
--- /dev/null
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.3 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG   = afslog
+
+.PATH: ${KRB5SRC}/appl/afsutil
+
+SRCS+= afslog.c
+SRCS+= ${PRINTVER}
+
+DPADD  += ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD  += -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/afslog/obj b/src/kerberosV/usr.bin/afslog/obj
new file mode 120000 (symlink)
index 0000000..73740ba
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/afslog
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/kauth/CVS/Entries b/src/kerberosV/usr.bin/kauth/CVS/Entries
new file mode 100644 (file)
index 0000000..f72d228
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.7/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/kauth/CVS/Repository b/src/kerberosV/usr.bin/kauth/CVS/Repository
new file mode 100644 (file)
index 0000000..24e8790
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/kauth
diff --git a/src/kerberosV/usr.bin/kauth/CVS/Root b/src/kerberosV/usr.bin/kauth/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/kauth/Makefile b/src/kerberosV/usr.bin/kauth/Makefile
new file mode 100644 (file)
index 0000000..c8f7943
--- /dev/null
@@ -0,0 +1,17 @@
+# $OpenBSD: Makefile,v 1.7 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kauth
+NOMAN=
+
+SRCS=  kinit.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/kuser
+
+DPADD+= ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/kauth/obj b/src/kerberosV/usr.bin/kauth/obj
new file mode 120000 (symlink)
index 0000000..9a49e1a
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/kauth
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/kdestroy/CVS/Entries b/src/kerberosV/usr.bin/kdestroy/CVS/Entries
new file mode 100644 (file)
index 0000000..1e14046
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.6/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/kdestroy/CVS/Repository b/src/kerberosV/usr.bin/kdestroy/CVS/Repository
new file mode 100644 (file)
index 0000000..7150d4c
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/kdestroy
diff --git a/src/kerberosV/usr.bin/kdestroy/CVS/Root b/src/kerberosV/usr.bin/kdestroy/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/kdestroy/Makefile b/src/kerberosV/usr.bin/kdestroy/Makefile
new file mode 100644 (file)
index 0000000..c813315
--- /dev/null
@@ -0,0 +1,16 @@
+# $OpenBSD: Makefile,v 1.6 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kdestroy
+
+SRCS=  kdestroy.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/kuser
+
+DPADD+= ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/kdestroy/obj b/src/kerberosV/usr.bin/kdestroy/obj
new file mode 120000 (symlink)
index 0000000..294514d
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/kdestroy
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/kf/CVS/Entries b/src/kerberosV/usr.bin/kf/CVS/Entries
new file mode 100644 (file)
index 0000000..a9512c7
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.3/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/kf/CVS/Repository b/src/kerberosV/usr.bin/kf/CVS/Repository
new file mode 100644 (file)
index 0000000..9d23332
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/kf
diff --git a/src/kerberosV/usr.bin/kf/CVS/Root b/src/kerberosV/usr.bin/kf/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/kf/Makefile b/src/kerberosV/usr.bin/kf/Makefile
new file mode 100644 (file)
index 0000000..2817d24
--- /dev/null
@@ -0,0 +1,15 @@
+# $OpenBSD: Makefile,v 1.3 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kf
+
+SRCS=  kf.c
+
+.PATH: ${KRB5SRC}/appl/kf
+
+DPADD+= ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/kinit/CVS/Entries b/src/kerberosV/usr.bin/kinit/CVS/Entries
new file mode 100644 (file)
index 0000000..08b9442
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.8/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/kinit/CVS/Repository b/src/kerberosV/usr.bin/kinit/CVS/Repository
new file mode 100644 (file)
index 0000000..2bd66e3
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/kinit
diff --git a/src/kerberosV/usr.bin/kinit/CVS/Root b/src/kerberosV/usr.bin/kinit/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/kinit/Makefile b/src/kerberosV/usr.bin/kinit/Makefile
new file mode 100644 (file)
index 0000000..39d8168
--- /dev/null
@@ -0,0 +1,17 @@
+# $OpenBSD: Makefile,v 1.8 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kinit
+MLINKS=        kinit.1 kauth.1
+
+SRCS=  kinit.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/kuser
+
+DPADD+=        ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/kinit/obj b/src/kerberosV/usr.bin/kinit/obj
new file mode 120000 (symlink)
index 0000000..cb95de2
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/kinit
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/klist/CVS/Entries b/src/kerberosV/usr.bin/klist/CVS/Entries
new file mode 100644 (file)
index 0000000..1e14046
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.6/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/klist/CVS/Repository b/src/kerberosV/usr.bin/klist/CVS/Repository
new file mode 100644 (file)
index 0000000..8375c26
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/klist
diff --git a/src/kerberosV/usr.bin/klist/CVS/Root b/src/kerberosV/usr.bin/klist/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/klist/Makefile b/src/kerberosV/usr.bin/klist/Makefile
new file mode 100644 (file)
index 0000000..23c06f8
--- /dev/null
@@ -0,0 +1,18 @@
+# $OpenBSD: Makefile,v 1.6 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  klist
+
+SRCS=  klist.c
+SRCS+= ${PRINTVER}
+SRCS+= rtbl.c
+
+.PATH: ${KRB5SRC}/kuser
+.PATH: ${ROKENSRC}
+
+DPADD+=        ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/klist/obj b/src/kerberosV/usr.bin/klist/obj
new file mode 120000 (symlink)
index 0000000..aaf2e2f
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/klist
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/pagsh/CVS/Entries b/src/kerberosV/usr.bin/pagsh/CVS/Entries
new file mode 100644 (file)
index 0000000..1e14046
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.6/Mon Jul 14 16:14:44 2003//
+D
diff --git a/src/kerberosV/usr.bin/pagsh/CVS/Repository b/src/kerberosV/usr.bin/pagsh/CVS/Repository
new file mode 100644 (file)
index 0000000..a40f8c6
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/pagsh
diff --git a/src/kerberosV/usr.bin/pagsh/CVS/Root b/src/kerberosV/usr.bin/pagsh/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/pagsh/Makefile b/src/kerberosV/usr.bin/pagsh/Makefile
new file mode 100644 (file)
index 0000000..aeaab53
--- /dev/null
@@ -0,0 +1,18 @@
+# $OpenBSD: Makefile,v 1.6 2003/07/14 16:14:44 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  pagsh
+
+SRCS=  pagsh.c
+SRCS+= ${PRINTVER}
+SRCS+= esetenv.c k_getpwuid.c
+
+.PATH: ${KRB5SRC}/appl/afsutil
+.PATH: ${ROKENSRC}
+
+DPADD+=        ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/pagsh/obj b/src/kerberosV/usr.bin/pagsh/obj
new file mode 120000 (symlink)
index 0000000..94d432a
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/pagsh
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/string2key/CVS/Entries b/src/kerberosV/usr.bin/string2key/CVS/Entries
new file mode 100644 (file)
index 0000000..326d2cd
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.4/Mon Jul 14 16:14:45 2003//
+D
diff --git a/src/kerberosV/usr.bin/string2key/CVS/Repository b/src/kerberosV/usr.bin/string2key/CVS/Repository
new file mode 100644 (file)
index 0000000..54cd5f7
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/string2key
diff --git a/src/kerberosV/usr.bin/string2key/CVS/Root b/src/kerberosV/usr.bin/string2key/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/string2key/Makefile b/src/kerberosV/usr.bin/string2key/Makefile
new file mode 100644 (file)
index 0000000..826192c
--- /dev/null
@@ -0,0 +1,21 @@
+# $OpenBSD: Makefile,v 1.4 2003/07/14 16:14:45 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  string2key
+MAN=   ${PROG}.8
+
+SRCS=  string2key.c
+SRCS+= ${PRINTVER}
+SRCS+= estrdup.c
+
+.PATH: ${KRB5SRC}/kdc
+.PATH: ${ROKENSRC}
+
+CFLAGS+=-I${KRB5SRC}/kdc -I${KRB5SRC}/lib/krb5
+
+DPADD+=        ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/string2key/obj b/src/kerberosV/usr.bin/string2key/obj
new file mode 120000 (symlink)
index 0000000..e445595
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/string2key
\ No newline at end of file
diff --git a/src/kerberosV/usr.bin/verify_krb5_conf/CVS/Entries b/src/kerberosV/usr.bin/verify_krb5_conf/CVS/Entries
new file mode 100644 (file)
index 0000000..326d2cd
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.4/Mon Jul 14 16:14:45 2003//
+D
diff --git a/src/kerberosV/usr.bin/verify_krb5_conf/CVS/Repository b/src/kerberosV/usr.bin/verify_krb5_conf/CVS/Repository
new file mode 100644 (file)
index 0000000..f40fbb0
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.bin/verify_krb5_conf
diff --git a/src/kerberosV/usr.bin/verify_krb5_conf/CVS/Root b/src/kerberosV/usr.bin/verify_krb5_conf/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.bin/verify_krb5_conf/Makefile b/src/kerberosV/usr.bin/verify_krb5_conf/Makefile
new file mode 100644 (file)
index 0000000..1004407
--- /dev/null
@@ -0,0 +1,19 @@
+# $OpenBSD: Makefile,v 1.4 2003/07/14 16:14:45 mho Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  verify_krb5_conf
+MAN=   ${PROG}.8
+
+SRCS=  verify_krb5_conf.c
+SRCS+= ${PRINTVER}
+SRCS+= parse_bytes.c
+
+.PATH: ${KRB5SRC}/lib/krb5
+.PATH: ${ROKENSRC}
+
+DPADD+= ${LIBKRB5} ${LIBDES} ${LIBCRYPTO}
+LDADD+=        -lkrb5 -ldes -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.bin/verify_krb5_conf/obj b/src/kerberosV/usr.bin/verify_krb5_conf/obj
new file mode 120000 (symlink)
index 0000000..fb3c3d9
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.bin/verify_krb5_conf
\ No newline at end of file
diff --git a/src/kerberosV/usr.sbin/CVS/Entries b/src/kerberosV/usr.sbin/CVS/Entries
new file mode 100644 (file)
index 0000000..50b881f
--- /dev/null
@@ -0,0 +1,5 @@
+/Makefile/1.2/Mon Jul 14 16:14:45 2003//
+/Makefile.inc/1.1/Fri May 25 08:21:12 2001//
+D/kadmin////
+D/kstash////
+D/ktutil////
diff --git a/src/kerberosV/usr.sbin/CVS/Repository b/src/kerberosV/usr.sbin/CVS/Repository
new file mode 100644 (file)
index 0000000..4fbe553
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.sbin
diff --git a/src/kerberosV/usr.sbin/CVS/Root b/src/kerberosV/usr.sbin/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.sbin/Makefile b/src/kerberosV/usr.sbin/Makefile
new file mode 100644 (file)
index 0000000..a583e6f
--- /dev/null
@@ -0,0 +1,5 @@
+# $OpenBSD: Makefile,v 1.2 2003/07/14 16:14:45 mho Exp $
+
+SUBDIR=        kadmin kstash ktutil
+
+.include <bsd.subdir.mk>
diff --git a/src/kerberosV/usr.sbin/Makefile.inc b/src/kerberosV/usr.sbin/Makefile.inc
new file mode 100644 (file)
index 0000000..fbe50f4
--- /dev/null
@@ -0,0 +1,3 @@
+# $OpenBSD: Makefile.inc,v 1.1 2001/05/25 08:21:12 hin Exp $
+
+BINDIR=        /usr/sbin
diff --git a/src/kerberosV/usr.sbin/kadmin/CVS/Entries b/src/kerberosV/usr.sbin/kadmin/CVS/Entries
new file mode 100644 (file)
index 0000000..63ba0c8
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.17/Mon Aug 17 09:40:37 2009//
+D
diff --git a/src/kerberosV/usr.sbin/kadmin/CVS/Repository b/src/kerberosV/usr.sbin/kadmin/CVS/Repository
new file mode 100644 (file)
index 0000000..44bad75
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.sbin/kadmin
diff --git a/src/kerberosV/usr.sbin/kadmin/CVS/Root b/src/kerberosV/usr.sbin/kadmin/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.sbin/kadmin/Makefile b/src/kerberosV/usr.sbin/kadmin/Makefile
new file mode 100644 (file)
index 0000000..7cc583f
--- /dev/null
@@ -0,0 +1,54 @@
+# $OpenBSD: Makefile,v 1.17 2009/08/17 09:40:37 jsg Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kadmin
+MAN=   kadmin.8
+
+SRCS=  ank.c \
+       cpw.c \
+       del.c \
+       del_enctype.c \
+       dump.c \
+       ext.c \
+       get.c \
+       init.c \
+       kadmin.c \
+       kadmin-commands.c \
+       kadmin-commands.h \
+       kadmin_locl.h \
+       load.c \
+       mod.c \
+       pw_quality.c \
+       random_password.c \
+       rename.c \
+       sl.c \
+       stash.c \
+       util.c
+SRCS+= ${PRINTVER}
+SRCS+= tm2time.c
+
+.PATH: ${KRB5SRC}/kadmin
+.PATH: ${KRB5SRC}/lib/sl
+.PATH: ${ROKENSRC}
+
+slc:   slc-gram.o slc-lex.o ${PRINTVER}
+       $(CC) -o slc $> -lkrb5 -lcrypto
+
+SLC=   slc
+
+kadmin:        kadmin-commands.h
+kadmin-commands.c kadmin-commands.h:   kadmin-commands.in $(SLC)
+       ./$(SLC) $(KRB5SRC)/kadmin/kadmin-commands.in
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/lib/kadm5 -I.
+
+DPADD+= ${LIBEDIT} ${LIBCURSES} ${LIBKADM5SRV} ${LIBKADM5CLNT} \
+       ${LIBKRB5} ${LIBCRYPTO} ${LIBDES}
+LDADD+=        -ledit -lcurses -lkadm5srv -lkadm5clnt \
+       -lkrb5 -lcrypto -ldes
+
+CLEANFILES+=   kadmin-commands.c slc lc-lex.o kadmin-commands.h \
+               slc-lex.o slc-gram.o
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.sbin/kadmin/obj b/src/kerberosV/usr.sbin/kadmin/obj
new file mode 120000 (symlink)
index 0000000..b146c5a
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.sbin/kadmin
\ No newline at end of file
diff --git a/src/kerberosV/usr.sbin/kstash/CVS/Entries b/src/kerberosV/usr.sbin/kstash/CVS/Entries
new file mode 100644 (file)
index 0000000..47460dd
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.8/Mon Aug 17 09:40:37 2009//
+D
diff --git a/src/kerberosV/usr.sbin/kstash/CVS/Repository b/src/kerberosV/usr.sbin/kstash/CVS/Repository
new file mode 100644 (file)
index 0000000..fbc63cc
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.sbin/kstash
diff --git a/src/kerberosV/usr.sbin/kstash/CVS/Root b/src/kerberosV/usr.sbin/kstash/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.sbin/kstash/Makefile b/src/kerberosV/usr.sbin/kstash/Makefile
new file mode 100644 (file)
index 0000000..260b5c2
--- /dev/null
@@ -0,0 +1,23 @@
+# $OpenBSD: Makefile,v 1.8 2009/08/17 09:40:37 jsg Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  kstash
+MAN=   ${PROG}.8
+
+SRCS=  kstash.c \
+       sl.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/kdc
+.PATH: ${KRB5SRC}/lib/sl
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5
+
+DPADD+= ${LIBEDIT} ${LIBCURSES} ${LIBDES} ${LIBKRB5} \
+       ${LIBCRYPTO}
+LDADD+=        -ledit -lcurses -ldes -lkrb5 \
+       -lcrypto
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.sbin/kstash/obj b/src/kerberosV/usr.sbin/kstash/obj
new file mode 120000 (symlink)
index 0000000..606d717
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.sbin/kstash
\ No newline at end of file
diff --git a/src/kerberosV/usr.sbin/ktutil/CVS/Entries b/src/kerberosV/usr.sbin/ktutil/CVS/Entries
new file mode 100644 (file)
index 0000000..8187032
--- /dev/null
@@ -0,0 +1,2 @@
+/Makefile/1.15/Mon Aug 17 09:40:37 2009//
+D
diff --git a/src/kerberosV/usr.sbin/ktutil/CVS/Repository b/src/kerberosV/usr.sbin/ktutil/CVS/Repository
new file mode 100644 (file)
index 0000000..729f0a4
--- /dev/null
@@ -0,0 +1 @@
+src/kerberosV/usr.sbin/ktutil
diff --git a/src/kerberosV/usr.sbin/ktutil/CVS/Root b/src/kerberosV/usr.sbin/ktutil/CVS/Root
new file mode 100644 (file)
index 0000000..5bdd6b1
--- /dev/null
@@ -0,0 +1 @@
+:ext:cvs.openbsd.org:/cvs
diff --git a/src/kerberosV/usr.sbin/ktutil/Makefile b/src/kerberosV/usr.sbin/ktutil/Makefile
new file mode 100644 (file)
index 0000000..c2725bf
--- /dev/null
@@ -0,0 +1,53 @@
+# $OpenBSD: Makefile,v 1.15 2009/08/17 09:40:37 jsg Exp $
+
+KRBDEPTH=../..
+.include <${.CURDIR}/../../Makefile.inc>
+
+PROG=  ktutil
+MAN=   ktutil.8
+
+SRCS=  add.c \
+       change.c \
+       copy.c \
+       get.c \
+       ktutil.c \
+       ktutil-commands.c \
+       list.c \
+       purge.c \
+       remove.c \
+       rename.c \
+       sl.c
+SRCS+= ${PRINTVER}
+
+.PATH: ${KRB5SRC}/admin
+.PATH: ${KRB5SRC}/lib/sl
+
+slc:   slc-gram.o slc-lex.o ${PRINTVER}
+       $(CC) -o slc $> -lkrb5 -lcrypto
+
+slc-lex.o: y.tab.h
+y.tab.h slc-gram.o: stamp_grammar
+
+stamp_grammar:
+       ${YACC} -d ${KRB5SRC}/lib/sl/slc-gram.y
+       $(CC) -c ${CFLAGS} -o slc-gram.o y.tab.c
+       rm -f y.tab.c
+       touch $@
+
+SLC=   slc
+
+ktutil:        ktutil-commands.h
+ktutil-commands.c ktutil-commands.h:   ktutil-commands.in $(SLC)
+       ./$(SLC) $(KRB5SRC)/admin/ktutil-commands.in
+
+CFLAGS+=-I${KRB5SRC}/lib/krb5 -I${KRB5SRC}/lib/kadm5 -I.
+
+DPADD+=        ${LIBEDIT} ${LIBCURSES} ${LIBKADM5CLNT} ${LIBKRB5} \
+       ${LIBCRYPTO} ${LIBDES}
+LDADD+=        -ledit -lcurses -lkadm5clnt -lkrb5 \
+       -lcrypto -ldes
+
+CLEANFILES+=   ktutil-commands.c slc slc-lex.o \
+               ktutil-commands.h slc-gram.o stamp_grammar
+
+.include <bsd.prog.mk>
diff --git a/src/kerberosV/usr.sbin/ktutil/obj b/src/kerberosV/usr.sbin/ktutil/obj
new file mode 120000 (symlink)
index 0000000..bb08bca
--- /dev/null
@@ -0,0 +1 @@
+/usr/obj/kerberosV/usr.sbin/ktutil
\ No newline at end of file