summaryrefslogtreecommitdiffstats
path: root/third_party/heimdal/lib/kafs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/heimdal/lib/kafs')
-rw-r--r--third_party/heimdal/lib/kafs/ChangeLog572
-rw-r--r--third_party/heimdal/lib/kafs/Makefile.am96
-rw-r--r--third_party/heimdal/lib/kafs/NTMakefile35
-rw-r--r--third_party/heimdal/lib/kafs/afskrb5.c353
-rw-r--r--third_party/heimdal/lib/kafs/afsl.exp6
-rw-r--r--third_party/heimdal/lib/kafs/afslib.c53
-rw-r--r--third_party/heimdal/lib/kafs/afslib.exp3
-rw-r--r--third_party/heimdal/lib/kafs/afssys.c630
-rw-r--r--third_party/heimdal/lib/kafs/afssysdefs.h109
-rw-r--r--third_party/heimdal/lib/kafs/common.c469
-rw-r--r--third_party/heimdal/lib/kafs/kafs.3296
-rw-r--r--third_party/heimdal/lib/kafs/kafs.h216
-rw-r--r--third_party/heimdal/lib/kafs/kafs_locl.h162
-rw-r--r--third_party/heimdal/lib/kafs/roken_rename.h64
-rw-r--r--third_party/heimdal/lib/kafs/rxkad_kdf.c221
15 files changed, 3285 insertions, 0 deletions
diff --git a/third_party/heimdal/lib/kafs/ChangeLog b/third_party/heimdal/lib/kafs/ChangeLog
new file mode 100644
index 0000000..302146a
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/ChangeLog
@@ -0,0 +1,572 @@
+2008-07-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * common.c: Try afs/cell@REALM before afs@REALM since that is what
+ OpenAFS folks have been saying is best pratices for some time
+ now. Patch from Derrick Brashear.
+
+2008-04-15 Love Hörnquist Åstrand <lha@it.su.se>
+ * afssys.c: Avoid using entry points depending on _IOWR if there
+ is no _IOWR (on cygwin).
+
+2007-07-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: New library version.
+
+2007-05-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * kafs.h: Add VIOCSETTOK2
+
+2006-10-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: unbreak previous
+
+ * Makefile.am: split dist and nodist sources
+
+2006-10-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: add more files
+
+2006-05-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * kafs.3: Spelling, from Björn Sandell.
+
+2006-04-11 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * afssys.c: use afs_ioctlnum, From Tomas Olsson <tol@it.su.se>
+
+2006-04-10 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * afssys.c: Try harder to get the pioctl to work via the /proc or
+ /dev interface, OpenAFS choose to reuse the same ioctl number,
+ while Arla didn't. Also, try new ioctl before the the old
+ syscalls.
+
+ * afskrb5.c (afslog_uid_int): use the simpler
+ krb5_principal_get_realm function.
+
+2005-12-21 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * Makefile.am: Remove dependency on config.h, breaks IRIX build,
+ could depend on libkafs_la_OBJECTS, but that is just asking for
+ trubble.
+
+2005-10-20 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * afssys.c (k_hasafs_recheck): new function, allow rechecking if
+ AFS client have started now, internaly it resets the internal
+ state from k_hasafs() and retry retry the probing. The problem
+ with calling k_hasaf() is that is plays around with signals, and
+ that cases problem for some systems/applications.
+
+2005-10-02 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * kafs_locl.h: Maybe include <sys/sysctl.h>.
+
+ * afssys.c: Mac OS X 10.4 needs a runtime check if we are going to
+ use the syscall, there is no cpp define to use to check the
+ version. Every after 10.0 (darwin 8.0) uses the /dev/ version of
+ the pioctl.
+
+2005-10-01 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * afssys.c: Support the new MacOS X 10.4 ioctl interface that is a
+ device node. Patched from Tomas Olson <tol@it.su.se>.
+
+2005-08-26 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * afskrb5.c: Default to use 2b tokens.
+
+2005-06-17 Love Hörnquist Åstrand <lha@it.su.se>
+
+ * common.c: rename index to idx
+
+ * afssys.c (k_afs_cell_of_file): unconst path
+
+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/third_party/heimdal/lib/kafs/Makefile.am b/third_party/heimdal/lib/kafs/Makefile.am
new file mode 100644
index 0000000..50d4878
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/Makefile.am
@@ -0,0 +1,96 @@
+# $Id$
+
+include $(top_srcdir)/Makefile.am.common
+
+WFLAGS += $(WFLAGS_ENUM_CONV)
+
+AM_CPPFLAGS += $(AFS_EXTRA_DEFS) $(ROKEN_RENAME)
+
+if KRB5
+DEPLIB_krb5 = ../krb5/libkrb5.la $(LIB_hcrypto)
+krb5_am_workaround = -I$(top_srcdir)/lib/krb5
+else
+DEPLIB_krb5 =
+krb5_am_workaround =
+endif # KRB5
+AM_CPPFLAGS += $(krb5_am_workaround)
+
+
+if AIX
+AFSL_EXP = $(srcdir)/afsl.exp
+
+if AIX4
+AFS_EXTRA_LD = -bnoentry
+else
+AFS_EXTRA_LD = -e _nostart
+endif
+
+if AIX_DYNAMIC_AFS
+AIX_SRC =
+AFS_EXTRA_LIBS = afslib.so
+AFS_EXTRA_DEFS =
+else
+AIX_SRC = afslib.c
+AFS_EXTRA_LIBS =
+AFS_EXTRA_DEFS = -DSTATIC_AFS
+endif
+
+else
+AFSL_EXP =
+AIX_SRC =
+endif # AIX
+
+libkafs_la_LIBADD = $(DEPLIB_krb5) $(LIBADD_roken)
+
+lib_LTLIBRARIES = libkafs.la
+libkafs_la_LDFLAGS = -version-info 5:1:5
+foodir = $(libdir)
+foo_DATA = $(AFS_EXTRA_LIBS)
+# EXTRA_DATA = afslib.so
+
+CLEANFILES= $(AFS_EXTRA_LIBS) $(ROKEN_SRCS)
+
+include_HEADERS = kafs.h
+
+if KRB5
+afskrb5_c =
+endif
+
+if do_roken_rename
+ROKEN_SRCS = resolve.c strtok_r.c strlcpy.c strsep.c
+endif
+
+dist_libkafs_la_SOURCES = \
+ afssys.c \
+ afskrb5.c \
+ rxkad_kdf.c \
+ common.c \
+ $(AIX_SRC) \
+ kafs_locl.h \
+ afssysdefs.h \
+ roken_rename.h
+
+nodist_libkafs_la_SOURCES = $(ROKEN_SRCS)
+
+EXTRA_libkafs_la_SOURCES = afskrb5.c afslib.c
+
+EXTRA_DIST = NTMakefile afsl.exp afslib.exp $(man_MANS)
+
+man_MANS = kafs.3
+
+# AIX: this almost works with gcc, but somehow it fails to use the
+# correct ld, use ld instead
+afslib.so: afslib.o
+ ld -o $@ -bM:SRE -bI:$(srcdir)/afsl.exp -bE:$(srcdir)/afslib.exp $(AFS_EXTRA_LD) afslib.o -lc
+
+resolve.c:
+ $(LN_S) $(srcdir)/../roken/resolve.c .
+
+strtok_r.c:
+ $(LN_S) $(srcdir)/../roken/strtok_r.c .
+
+strlcpy.c:
+ $(LN_S) $(srcdir)/../roken/strlcpy.c .
+
+strsep.c:
+ $(LN_S) $(srcdir)/../roken/strsep.c .
diff --git a/third_party/heimdal/lib/kafs/NTMakefile b/third_party/heimdal/lib/kafs/NTMakefile
new file mode 100644
index 0000000..4cff342
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/NTMakefile
@@ -0,0 +1,35 @@
+########################################################################
+#
+# Copyright (c) 2009, Secure Endpoints Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# - Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+RELDIR=lib\kafs
+
+!include ../../windows/NTMakefile.w32
+
diff --git a/third_party/heimdal/lib/kafs/afskrb5.c b/third_party/heimdal/lib/kafs/afskrb5.c
new file mode 100644
index 0000000..0077016
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/afskrb5.c
@@ -0,0 +1,353 @@
+/*
+ * 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"
+
+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;
+
+ 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);
+ }
+
+
+ /*
+ * Build a struct ClearToken
+ */
+
+ ret = _kafs_derive_des_key(cred->session.keytype,
+ cred->session.keyvalue.data,
+ cred->session.keyvalue.length,
+ kt->ct.HandShakeKey);
+ if (ret) {
+ free(kt->ticket);
+ kt->ticket = NULL;
+ return ret;
+ }
+ kt->ct.AuthHandle = kvno;
+ 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", "2b", &val);
+ free(c);
+
+ if (strcasecmp(val, "local") == 0 ||
+ strcasecmp(val, "2b") == 0)
+ ret = v5_to_kt(cred, uid, kt, 1);
+ else
+ ret = v5_to_kt(cred, uid, kt, 0);
+
+ 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;
+ int invalid;
+
+ memset(&in_creds, 0, sizeof(in_creds));
+
+ ret = krb5_make_principal(d->context, &in_creds.server,
+ realm, name, inst, NULL);
+ 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;
+ }
+
+ /* check if des is disable, and in that case enable it for afs */
+ invalid = krb5_enctype_valid(d->context, ETYPE_DES_CBC_CRC);
+ if (invalid)
+ krb5_enctype_enable(d->context, ETYPE_DES_CBC_CRC);
+
+ ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds);
+
+ if (invalid)
+ krb5_enctype_disable(d->context, ETYPE_DES_CBC_CRC);
+
+ 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 const char *
+get_error(struct kafs_data *data, int error)
+{
+ struct krb5_kafs_data *d = data->data;
+ return krb5_get_error_message(d->context, error);
+}
+
+static void
+free_error(struct kafs_data *data, const char *str)
+{
+ struct krb5_kafs_data *d = data->data;
+ krb5_free_error_message(d->context, str);
+}
+
+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;
+ const char *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_principal_get_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.get_error = get_error;
+ kd.free_error = free_error;
+ 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;
+ kd.get_error = get_error;
+ kd.free_error = free_error;
+ 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/third_party/heimdal/lib/kafs/afsl.exp b/third_party/heimdal/lib/kafs/afsl.exp
new file mode 100644
index 0000000..4d2b00e
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/afsl.exp
@@ -0,0 +1,6 @@
+#!/unix
+
+* This mumbo jumbo creates entry points to syscalls in _AIX
+
+lpioctl syscall
+lsetpag syscall
diff --git a/third_party/heimdal/lib/kafs/afslib.c b/third_party/heimdal/lib/kafs/afslib.c
new file mode 100644
index 0000000..f2ef848
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/afslib.c
@@ -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.
+ */
+
+/*
+ * This file is only used with AIX
+ */
+
+#include "kafs_locl.h"
+
+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/third_party/heimdal/lib/kafs/afslib.exp b/third_party/heimdal/lib/kafs/afslib.exp
new file mode 100644
index 0000000..f288717
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/afslib.exp
@@ -0,0 +1,3 @@
+#!
+aix_pioctl
+aix_setpag
diff --git a/third_party/heimdal/lib/kafs/afssys.c b/third_party/heimdal/lib/kafs/afssys.c
new file mode 100644
index 0000000..b400626
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/afssys.c
@@ -0,0 +1,630 @@
+/*
+ * Copyright (c) 1995 - 2000, 2002, 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 "kafs_locl.h"
+
+struct procdata {
+ unsigned long param4;
+ unsigned long param3;
+ unsigned long param2;
+ unsigned long param1;
+ unsigned long syscall;
+};
+#ifdef __GNU__
+#define _IOT_procdata _IOT(_IOTS(long), 5, 0, 0, 0, 0)
+#define VIOC_SYSCALL_PROC _IOW('C', 1, struct procdata)
+#else
+#define VIOC_SYSCALL_PROC _IOW('C', 1, void *)
+#endif
+
+struct devdata {
+ unsigned long syscall;
+ unsigned long param1;
+ unsigned long param2;
+ unsigned long param3;
+ unsigned long param4;
+ unsigned long param5;
+ unsigned long param6;
+ unsigned long retval;
+};
+#ifdef __GNU__
+#define _IOT_devdata _IOT(_IOTS(long), 8, 0, 0, 0, 0)
+#endif
+#ifdef _IOWR
+#define VIOC_SYSCALL_DEV _IOWR('C', 2, struct devdata)
+#define VIOC_SYSCALL_DEV_OPENAFS _IOWR('C', 1, struct devdata)
+#endif
+
+#ifdef _IOW
+#ifdef _ILP32
+struct sundevdata {
+ uint32_t param6;
+ uint32_t param5;
+ uint32_t param4;
+ uint32_t param3;
+ uint32_t param2;
+ uint32_t param1;
+ uint32_t syscall;
+};
+#define VIOC_SUN_SYSCALL_DEV _IOW('C', 2, struct sundevdata)
+#else
+struct sundevdata {
+ uint64_t param6;
+ uint64_t param5;
+ uint64_t param4;
+ uint64_t param3;
+ uint64_t param2;
+ uint64_t param1;
+ uint64_t syscall;
+};
+#define VIOC_SUN_SYSCALL_DEV _IOW('C', 1, struct sundevdata)
+#endif
+#endif /* _IOW */
+
+
+int _kafs_debug; /* this should be done in a better way */
+
+#define UNKNOWN_ENTRY_POINT (-1)
+#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 MACOS_DEV_POINT 7
+#define SUN_PROC_POINT 8
+
+static int afs_entry_point = UNKNOWN_ENTRY_POINT;
+#if defined(AFS_SYSCALL) || defined(AFS_SYSCALL2) || defined(AFS_SYSCALL3) || defined(AFS_PIOCTL)
+static int afs_syscalls[2];
+#endif
+static char *afs_ioctlpath;
+static unsigned long afs_ioctlnum;
+
+/* 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 && (p = secure_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_ioctlpath(const char *path, unsigned long ioctlnum, int entrypoint)
+{
+ int fd, ret, saved_errno;
+
+ fd = open(path, O_RDWR);
+ if (fd < 0)
+ return 1;
+ switch (entrypoint) {
+ case LINUX_PROC_POINT: {
+ struct procdata data = { 0, 0, 0, 0, AFSCALL_PIOCTL };
+ data.param2 = (unsigned long)VIOCGETTOK;
+ ret = ioctl(fd, ioctlnum, &data);
+ break;
+ }
+ case MACOS_DEV_POINT: {
+ struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
+ data.param2 = (unsigned long)VIOCGETTOK;
+ ret = ioctl(fd, ioctlnum, &data);
+ break;
+ }
+ case SUN_PROC_POINT: {
+ struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_PIOCTL };
+ data.param2 = (unsigned long)VIOCGETTOK;
+ ret = ioctl(fd, ioctlnum, &data);
+ break;
+ }
+ default:
+ abort();
+ }
+ saved_errno = errno;
+ close(fd);
+ /*
+ * Be quite liberal in what error are ok, the first is the one
+ * that should trigger given that params is NULL.
+ */
+ if (ret &&
+ (saved_errno != EFAULT &&
+ saved_errno != EDOM &&
+ saved_errno != ENOTCONN))
+ return 1;
+ afs_ioctlnum = ioctlnum;
+ afs_ioctlpath = strdup(path);
+ if (afs_ioctlpath == NULL)
+ return 1;
+ afs_entry_point = entrypoint;
+ return 0;
+}
+
+static int
+do_ioctl(void *data)
+{
+ int fd, ret, saved_errno;
+ fd = open(afs_ioctlpath, O_RDWR);
+ if (fd < 0) {
+ errno = EINVAL;
+ return -1;
+ }
+ ret = ioctl(fd, afs_ioctlnum, 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_ioctl(&data);
+ }
+ case MACOS_DEV_POINT: {
+ struct devdata data = { AFSCALL_PIOCTL, 0, 0, 0, 0, 0, 0, 0 };
+ int ret;
+
+ data.param1 = (unsigned long)a_path;
+ data.param2 = (unsigned long)o_opcode;
+ data.param3 = (unsigned long)a_paramsP;
+ data.param4 = (unsigned long)a_followSymlinks;
+
+ ret = do_ioctl(&data);
+ if (ret)
+ return ret;
+
+ return data.retval;
+ }
+ case SUN_PROC_POINT: {
+ struct sundevdata data = { 0, 0, 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_ioctl(&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(rk_UNCONST(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_ioctl(&data);
+ }
+ case MACOS_DEV_POINT: {
+ struct devdata data = { AFSCALL_SETPAG, 0, 0, 0, 0, 0, 0, 0 };
+ int ret = do_ioctl(&data);
+ if (ret)
+ return ret;
+ return data.retval;
+ }
+ case SUN_PROC_POINT: {
+ struct sundevdata data = { 0, 0, 0, 0, 0, 0, AFSCALL_SETPAG };
+ return do_ioctl(&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, ret;
+ char *env = NULL;
+
+ env = secure_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 (env && strstr(env, "..") == NULL) {
+
+ if (strncmp("/proc/", env, 6) == 0) {
+ if (try_ioctlpath(env, VIOC_SYSCALL_PROC, LINUX_PROC_POINT) == 0)
+ goto done;
+ }
+ if (strncmp("/dev/", env, 5) == 0) {
+#ifdef VIOC_SYSCALL_DEV
+ if (try_ioctlpath(env, VIOC_SYSCALL_DEV, MACOS_DEV_POINT) == 0)
+ goto done;
+#endif
+#ifdef VIOC_SYSCALL_DEV_OPENAFS
+ if (try_ioctlpath(env,VIOC_SYSCALL_DEV_OPENAFS,MACOS_DEV_POINT) ==0)
+ goto done;
+#endif
+ }
+ }
+
+ ret = try_ioctlpath("/proc/fs/openafs/afs_ioctl",
+ VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
+ if (ret == 0)
+ goto done;
+ ret = try_ioctlpath("/proc/fs/nnpfs/afs_ioctl",
+ VIOC_SYSCALL_PROC, LINUX_PROC_POINT);
+ if (ret == 0)
+ goto done;
+
+#ifdef VIOC_SYSCALL_DEV_OPENAFS
+ ret = try_ioctlpath("/dev/openafs_ioctl",
+ VIOC_SYSCALL_DEV_OPENAFS, MACOS_DEV_POINT);
+ if (ret == 0)
+ goto done;
+#endif
+#ifdef VIOC_SYSCALL_DEV
+ ret = try_ioctlpath("/dev/nnpfs_ioctl", VIOC_SYSCALL_DEV, MACOS_DEV_POINT);
+ if (ret == 0)
+ goto done;
+#endif
+#ifdef VIOC_SUN_SYSCALL_DEV
+ ret = try_ioctlpath("/dev/afs", VIOC_SUN_SYSCALL_DEV, SUN_PROC_POINT);
+ if (ret == 0)
+ goto done;
+#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
+
+
+done:
+#ifdef SIGSYS
+ signal(SIGSYS, saved_func);
+#endif
+#endif /* NO_AFS */
+ errno = saved_errno;
+ return afs_entry_point != NO_ENTRY_POINT;
+}
+
+int
+k_hasafs_recheck(void)
+{
+ afs_entry_point = UNKNOWN_ENTRY_POINT;
+ return k_hasafs();
+}
diff --git a/third_party/heimdal/lib/kafs/afssysdefs.h b/third_party/heimdal/lib/kafs/afssysdefs.h
new file mode 100644
index 0000000..18734e3
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/afssysdefs.h
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+/*
+ * 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 SYS_afs_syscall
+#define AFS_SYSCALL3 SYS_afs_syscall
+#endif
diff --git a/third_party/heimdal/lib/kafs/common.c b/third_party/heimdal/lib/kafs/common.c
new file mode 100644
index 0000000..ff42cf7
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/common.c
@@ -0,0 +1,469 @@
+/*
+ * 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 "kafs_locl.h"
+
+#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--;
+ }
+}
+
+/* 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 rk_dns_reply *r;
+ int ok = -1;
+ r = rk_dns_lookup(cell, "afsdb");
+ if(r){
+ struct rk_resource_record *rr = r->head;
+ while(rr){
+ if(rr->type == rk_ns_t_afsdb && rr->u.afsdb->preference == 1){
+ strlcpy(dbserver,
+ rr->u.afsdb->domain,
+ len);
+ ok = 0;
+ break;
+ }
+ rr = rr->next;
+ }
+ rk_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 *idx)
+{
+ FILE *f;
+ char cell[64];
+ int i;
+ int ind = *idx;
+
+ 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);
+ *idx = 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 idx = 0;
+
+ if (homedir == NULL)
+ homedir = getenv("HOME");
+ if (homedir != NULL) {
+ char home[MaxPathLen];
+ snprintf(home, sizeof(home), "%s/.TheseCells", homedir);
+ find_cells(home, &cells, &idx);
+ }
+ find_cells(_PATH_THESECELLS, &cells, &idx);
+ find_cells(_PATH_THISCELL, &cells, &idx);
+ find_cells(_PATH_ARLA_THESECELLS, &cells, &idx);
+ find_cells(_PATH_ARLA_THISCELL, &cells, &idx);
+ find_cells(_PATH_OPENAFS_DEBIAN_THESECELLS, &cells, &idx);
+ find_cells(_PATH_OPENAFS_DEBIAN_THISCELL, &cells, &idx);
+ find_cells(_PATH_OPENAFS_MACOSX_THESECELLS, &cells, &idx);
+ find_cells(_PATH_OPENAFS_MACOSX_THISCELL, &cells, &idx);
+ find_cells(_PATH_ARLA_DEBIAN_THESECELLS, &cells, &idx);
+ find_cells(_PATH_ARLA_DEBIAN_THISCELL, &cells, &idx);
+ find_cells(_PATH_ARLA_OPENBSD_THESECELLS, &cells, &idx);
+ find_cells(_PATH_ARLA_OPENBSD_THISCELL, &cells, &idx);
+
+ ret = afslog_cells(data, cells, idx, uid, homedir);
+ while(idx > 0)
+ free(cells[--idx]);
+ 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_CELLSERVDB, "r"))
+ || (F = fopen(_PATH_ARLA_CELLSERVDB, "r"))
+ || (F = fopen(_PATH_OPENAFS_DEBIAN_CELLSERVDB, "r"))
+ || (F = fopen(_PATH_OPENAFS_MACOSX_CELLSERVDB, "r"))
+ || (F = fopen(_PATH_ARLA_DEBIAN_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) {
+ const char *estr = (*data->get_error)(data, ret);
+ char *str;
+ int aret;
+
+ aret = asprintf(&str, "%s tried afs%s%s@%s -> %s (%d)",
+ data->name, cell ? "/" : "",
+ cell ? cell : "", realm, estr ? estr : "unknown", ret);
+ if (aret != -1) {
+ (*kafs_verbose)(kafs_verbose_ctx, str);
+ free(str);
+ } else {
+ (*kafs_verbose)(kafs_verbose_ctx, "out of memory");
+ }
+ if (estr)
+ (*data->free_error)(data, estr);
+ }
+
+ 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,
+ NULL, realm_hint, uid, kt);
+ if (ret == 0) return 0;
+ }
+
+ _kafs_foldup(CELL, cell);
+
+ /*
+ * 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;
+
+ /*
+ * 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,
+ NULL, 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,
+ NULL, 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,
+ NULL, vl_realm, uid, kt);
+ free(vl_realm);
+ if (ret == 0) return 0;
+ }
+
+ return ret;
+}
diff --git a/third_party/heimdal/lib/kafs/kafs.3 b/third_party/heimdal/lib/kafs/kafs.3
new file mode 100644
index 0000000..d44e35e
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/kafs.3
@@ -0,0 +1,296 @@
+.\" Copyright (c) 1998 - 2006 Kungliga Tekniska Högskolan
+.\" (Royal Institute of Technology, Stockholm, Sweden).
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" 3. Neither the name of the Institute nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id$
+.\"
+.Dd May 1, 2006
+.Os HEIMDAL
+.Dt KAFS 3
+.Sh NAME
+.Nm k_hasafs ,
+.Nm k_hasafs_recheck ,
+.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_hasafs_recheck "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 k_hasafs_recheck
+forces a recheck if a AFS client has started since last time
+.Fn k_hasafs
+or
+.Fn k_hasafs_recheck
+was called.
+.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_appdefault 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 FILES
+libkafs will search for
+.Pa ThisCell and
+.Pa TheseCells
+in the following locations:
+.Pa /usr/vice/etc ,
+.Pa /etc/openafs ,
+.Pa /var/db/openafs/etc ,
+.Pa /usr/arla/etc ,
+.Pa /etc/arla ,
+and
+.Pa /etc/afs
+.Sh BUGS
+.Ev AFS_SYSCALL
+has no effect under AIX.
diff --git a/third_party/heimdal/lib/kafs/kafs.h b/third_party/heimdal/lib/kafs/kafs.h
new file mode 100644
index 0000000..6f6eb63
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/kafs.h
@@ -0,0 +1,216 @@
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+#ifndef __KAFS_H
+#define __KAFS_H
+
+/* XXX must include krb5.h or krb.h */
+
+/* sys/ioctl.h must be included manually before kafs.h */
+
+/*
+ */
+#define AFSCALL_PIOCTL 20
+#define AFSCALL_SETPAG 21
+
+#ifndef _VICEIOCTL
+#ifdef __GNU__
+#define _IOT_ViceIoctl _IOT(_IOTS(caddr_t), 2, _IOTS(short), 2, 0, 0)
+#endif
+#define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
+#define _AFSCIOCTL(id) ((unsigned int ) _IOW('C', id, struct ViceIoctl))
+#endif /* _VICEIOCTL */
+
+#define VIOCSETAL _VICEIOCTL(1)
+#define VIOCGETAL _VICEIOCTL(2)
+#define VIOCSETTOK _VICEIOCTL(3)
+#define VIOCGETVOLSTAT _VICEIOCTL(4)
+#define VIOCSETVOLSTAT _VICEIOCTL(5)
+#define VIOCFLUSH _VICEIOCTL(6)
+#define VIOCGETTOK _VICEIOCTL(8)
+#define VIOCUNLOG _VICEIOCTL(9)
+#define VIOCCKSERV _VICEIOCTL(10)
+#define VIOCCKBACK _VICEIOCTL(11)
+#define VIOCCKCONN _VICEIOCTL(12)
+#define VIOCWHEREIS _VICEIOCTL(14)
+#define VIOCACCESS _VICEIOCTL(20)
+#define VIOCUNPAG _VICEIOCTL(21)
+#define VIOCGETFID _VICEIOCTL(22)
+#define VIOCSETCACHESIZE _VICEIOCTL(24)
+#define VIOCFLUSHCB _VICEIOCTL(25)
+#define VIOCNEWCELL _VICEIOCTL(26)
+#define VIOCGETCELL _VICEIOCTL(27)
+#define VIOC_AFS_DELETE_MT_PT _VICEIOCTL(28)
+#define VIOC_AFS_STAT_MT_PT _VICEIOCTL(29)
+#define VIOC_FILE_CELL_NAME _VICEIOCTL(30)
+#define VIOC_GET_WS_CELL _VICEIOCTL(31)
+#define VIOC_AFS_MARINER_HOST _VICEIOCTL(32)
+#define VIOC_GET_PRIMARY_CELL _VICEIOCTL(33)
+#define VIOC_VENUSLOG _VICEIOCTL(34)
+#define VIOC_GETCELLSTATUS _VICEIOCTL(35)
+#define VIOC_SETCELLSTATUS _VICEIOCTL(36)
+#define VIOC_FLUSHVOLUME _VICEIOCTL(37)
+#define VIOC_AFS_SYSNAME _VICEIOCTL(38)
+#define VIOC_EXPORTAFS _VICEIOCTL(39)
+#define VIOCGETCACHEPARAMS _VICEIOCTL(40)
+#define VIOC_GCPAGS _VICEIOCTL(48)
+
+#define VIOCGETTOK2 _AFSCIOCTL(7)
+#define VIOCSETTOK2 _AFSCIOCTL(8)
+
+struct ViceIoctl {
+ caddr_t in, out;
+ unsigned short in_size;
+ unsigned short out_size;
+};
+
+struct ClearToken {
+ int32_t AuthHandle;
+ char HandShakeKey[8];
+ int32_t ViceId;
+ int32_t BeginTimestamp;
+ int32_t EndTimestamp;
+};
+
+/* 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 k_hasafs_recheck (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 "/usr/vice/etc/"
+#define _PATH_THISCELL _PATH_VICE "ThisCell"
+#define _PATH_CELLSERVDB _PATH_VICE "CellServDB"
+#define _PATH_THESECELLS _PATH_VICE "TheseCells"
+
+#define _PATH_ARLA_VICE "/usr/arla/etc/"
+#define _PATH_ARLA_THISCELL _PATH_ARLA_VICE "ThisCell"
+#define _PATH_ARLA_CELLSERVDB _PATH_ARLA_VICE "CellServDB"
+#define _PATH_ARLA_THESECELLS _PATH_ARLA_VICE "TheseCells"
+
+#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"
+
+#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/third_party/heimdal/lib/kafs/kafs_locl.h b/third_party/heimdal/lib/kafs/kafs_locl.h
new file mode 100644
index 0000000..f4e2f64
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/kafs_locl.h
@@ -0,0 +1,162 @@
+/*
+ * 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.
+ */
+
+/* $Id$ */
+
+#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_SYSCTL_H
+#include <sys/sysctl.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 KRB5
+#include "crypto-headers.h"
+typedef struct credentials CREDENTIALS;
+#endif /* KRB5 */
+#ifndef NO_AFS
+#include <kafs.h>
+#endif
+
+#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;
+ const char *(*get_error)(struct kafs_data *, int);
+ void (*free_error)(struct kafs_data *, const char *);
+ 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);
+
+int
+_kafs_derive_des_key(krb5_enctype, void *, size_t, char[8]);
+
+#ifdef _AIX
+int aix_pioctl(char*, int, struct ViceIoctl*, int);
+int aix_setpag(void);
+#endif
+
+#endif /* __KAFS_LOCL_H__ */
diff --git a/third_party/heimdal/lib/kafs/roken_rename.h b/third_party/heimdal/lib/kafs/roken_rename.h
new file mode 100644
index 0000000..26da265
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/roken_rename.h
@@ -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.
+ */
+
+/* $Id$ */
+
+#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 rk_strtok_r _kafs_strtok_r
+#endif
+#ifndef HAVE_STRLCPY
+#define rk_strlcpy _kafs_strlcpy
+#endif
+#ifndef HAVE_STRSEP
+#define rk_strsep _kafs_strsep
+#endif
+
+#endif /* __roken_rename_h__ */
diff --git a/third_party/heimdal/lib/kafs/rxkad_kdf.c b/third_party/heimdal/lib/kafs/rxkad_kdf.c
new file mode 100644
index 0000000..b542e89
--- /dev/null
+++ b/third_party/heimdal/lib/kafs/rxkad_kdf.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1995-2003 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2013-2014 Carnegie Mellon University
+ * All rights reserved.
+ *
+ * Portions Copyright (c) 2013 by the Massachusetts Institute of Technology
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (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 HC_DEPRECATED_CRYPTO
+#include "kafs_locl.h"
+
+static int rxkad_derive_des_key(const void *, size_t, char[8]);
+static int compress_parity_bits(void *, size_t *);
+
+/**
+ * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a
+ * des key from another type of key.
+ *
+ * L is 64, as we take 64 random bits and turn them into a 56-bit des key.
+ * The output of hmac_md5 is 128 bits; we take the first 64 only, so n
+ * properly should be 1. However, we apply a slight variation due to the
+ * possibility of producing a weak des key. If the output key is weak, do NOT
+ * simply correct it, instead, the counter is advanced and the next output
+ * used. As such, we code so as to have n be the full 255 permitted by our
+ * encoding of the counter i in an 8-bit field. L itself is encoded as a
+ * 32-bit field, big-endian. We use the constant string "rxkad" as a label
+ * for this key derivation, the standard NUL byte separator, and omit a
+ * key-derivation context. The input key is unique to the krb5 service ticket,
+ * which is unlikely to be used in an other location. If it is used in such
+ * a fashion, both locations will derive the same des key from the PRF, but
+ * this is no different from if a krb5 des key had been used in the same way,
+ * as traditional krb5 rxkad uses the ticket session key directly as the token
+ * key.
+ *
+ * @param[in] in pointer to input key data
+ * @param[in] insize length of input key data
+ * @param[out] out 8-byte buffer to hold the derived key
+ *
+ * @return Returns 0 to indicate success, or an error code.
+ *
+ * @retval KRB5DES_WEAK_KEY Successive derivation attempts with all
+ * 255 possible counter values each produced weak DES keys. This input
+ * cannot be used to produce a usable key.
+ */
+static int
+rxkad_derive_des_key(const void *in, size_t insize, char out[8])
+{
+ unsigned char i;
+ static unsigned char label[] = "rxkad";
+ /* bits of output, as 32 bit word, MSB first */
+ static unsigned char Lbuf[4] = { 0, 0, 0, 64 };
+ /* only needs to be 16 for md5, but lets be sure it fits */
+ unsigned char tmp[64];
+ unsigned int mdsize;
+ DES_cblock ktmp;
+ HMAC_CTX mctx;
+
+ /* stop when 8 bit counter wraps to 0 */
+ for (i = 1; i; i++) {
+ HMAC_CTX_init(&mctx);
+ if (HMAC_Init_ex(&mctx, in, insize, EVP_md5(), NULL) == 0) {
+ HMAC_CTX_cleanup(&mctx);
+ return ENOMEM;
+ }
+ HMAC_Update(&mctx, &i, 1);
+ HMAC_Update(&mctx, label, sizeof(label)); /* includes label and separator */
+ HMAC_Update(&mctx, Lbuf, 4);
+ mdsize = sizeof(tmp);
+ HMAC_Final(&mctx, tmp, &mdsize);
+ HMAC_CTX_cleanup(&mctx);
+ memcpy(ktmp, tmp, 8);
+ DES_set_odd_parity(&ktmp);
+ if (!DES_is_weak_key(&ktmp)) {
+ memcpy(out, ktmp, 8);
+ return 0;
+ }
+ }
+ return KRB5DES_WEAK_KEY;
+}
+
+/**
+ * This is the inverse of the random-to-key for 3des specified in
+ * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing
+ * the bits of each 8th byte as the lsb of the previous 7 bytes.
+ *
+ * @param[in,out] buffer Buffer containing the key to be converted
+ * @param[in,out] bufsiz Points to the size of the key data. On
+ * return, this is updated to reflect the size of the compressed data.
+ *
+ * @return Returns 0 to indicate success, or an error code.
+ *
+ * @retval KRB5_BAD_KEYSIZE The key size was not a multiple of 8 bytes.
+ */
+static int
+compress_parity_bits(void *buffer, size_t *bufsiz)
+{
+ unsigned char *cb, tmp;
+ int i, j, nk;
+
+ if (*bufsiz % 8 != 0)
+ return KRB5_BAD_KEYSIZE;
+ cb = (unsigned char *)buffer;
+ nk = *bufsiz / 8;
+ for (i = 0; i < nk; i++) {
+ tmp = cb[8 * i + 7] >> 1;
+ for (j = 0; j < 7; j++) {
+ cb[8 * i + j] &= 0xfe;
+ cb[8 * i + j] |= tmp & 0x1;
+ tmp >>= 1;
+ }
+ }
+ for (i = 1; i < nk; i++)
+ memmove(cb + 7 * i, cb + 8 * i, 7);
+ *bufsiz = 7 * nk;
+ return 0;
+}
+
+/**
+ * Derive a DES key for use with rxkad and fcrypt from a given Kerberos
+ * key of (almost) any type. This function encodes enctype-specific
+ * knowledge about how to derive a DES key from a given key type.
+ * If given a des key, use it directly; otherwise, perform any parity
+ * fixup that may be needed and pass through to the hmad-md5 bits.
+ *
+ * @param[in] enctype Kerberos enctype of the input key
+ * @param[in] keydata Input key data
+ * @param[in] keylen Size of input key data
+ * @param[out] output 8-byte buffer to hold the derived key
+ *
+ * @return Returns 0 to indicate success, or an error code.
+ *
+ * @retval KRB5_PROG_ETYPE_NOSUPP The enctype is one for which rxkad-kdf
+ * is not supported. This includes several reserved enctypes, enctype
+ * values used in PKINIT to stand for CMS algorithm identifiers, and all
+ * private-use (negative) enctypes.
+ *
+ * @retval KRB5_BAD_KEYSIZE The key size was not a multiple of 8 bytes
+ * (for 3DES key types), exactly 8 bytes (for DES key types), or at least
+ * 8 bytes (for other key types).
+ *
+ * @retval KRB5DES_WEAK_KEY Successive derivation attempts with all
+ * 255 possible counter values each produced weak DES keys. This input
+ * cannot be used to produce a usable key.
+ */
+int
+_kafs_derive_des_key(krb5_enctype enctype, void *keydata, size_t keylen,
+ char output[8])
+{
+ int ret = 0;
+
+ switch ((int)enctype) {
+ case ETYPE_DES_CBC_CRC:
+ case ETYPE_DES_CBC_MD4:
+ case ETYPE_DES_CBC_MD5:
+ if (keylen != 8)
+ return KRB5_BAD_KEYSIZE;
+
+ /* Extract session key */
+ memcpy(output, keydata, 8);
+ break;
+ case ETYPE_NULL:
+ case 4:
+ case 6:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 13:
+ case 14:
+ case 15:
+ return KRB5_PROG_ETYPE_NOSUPP;
+ /*In order to become a "Cryptographic Key" as specified in
+ * SP800-108, it must be indistinguishable from a random bitstring. */
+ case ETYPE_DES3_CBC_MD5:
+ case ETYPE_OLD_DES3_CBC_SHA1:
+ case ETYPE_DES3_CBC_SHA1:
+ ret = compress_parity_bits(keydata, &keylen);
+ if (ret)
+ return ret;
+ HEIM_FALLTHROUGH;
+ default:
+ if (enctype < 0)
+ return KRB5_PROG_ETYPE_NOSUPP;
+ if (keylen < 7)
+ return KRB5_BAD_KEYSIZE;
+ ret = rxkad_derive_des_key(keydata, keylen, output);
+ }
+ return ret;
+}