summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ChangeLog4
-rw-r--r--src/lib/configure.in2
-rw-r--r--src/lib/crypto/des/ChangeLog6
-rw-r--r--src/lib/crypto/des/cbc_cksum.c1
-rw-r--r--src/lib/gssapi/ChangeLog5
-rw-r--r--src/lib/gssapi/Makefile.in16
-rw-r--r--src/lib/gssapi/configure.in3
-rw-r--r--src/lib/gssapi/generic/ChangeLog20
-rw-r--r--src/lib/gssapi/generic/Makefile.in26
-rw-r--r--src/lib/gssapi/generic/disp_com_err_status.c4
-rw-r--r--src/lib/gssapi/generic/disp_major_status.c4
-rw-r--r--src/lib/gssapi/generic/gssapi.h77
-rw-r--r--src/lib/gssapi/generic/gssapiP_generic.h75
-rw-r--r--src/lib/gssapi/generic/gssapi_err_generic.et8
-rw-r--r--src/lib/gssapi/generic/gssapi_generic.c59
-rw-r--r--src/lib/gssapi/generic/gssapi_generic.h4
-rw-r--r--src/lib/gssapi/generic/oid_ops.c385
-rw-r--r--src/lib/gssapi/generic/release_buffer.c58
-rw-r--r--src/lib/gssapi/generic/release_oid_set.c62
-rw-r--r--src/lib/gssapi/generic/util_buffer.c4
-rw-r--r--src/lib/gssapi/generic/util_canonhost.c12
-rw-r--r--src/lib/gssapi/generic/util_dup.c4
-rw-r--r--src/lib/gssapi/generic/util_oid.c4
-rw-r--r--src/lib/gssapi/generic/util_token.c84
-rw-r--r--src/lib/gssapi/generic/util_validate.c123
-rw-r--r--src/lib/gssapi/krb5/ChangeLog97
-rw-r--r--src/lib/gssapi/krb5/Makefile.in31
-rw-r--r--src/lib/gssapi/krb5/accept_sec_context.c169
-rw-r--r--src/lib/gssapi/krb5/acquire_cred.c84
-rw-r--r--src/lib/gssapi/krb5/compare_name.c13
-rw-r--r--src/lib/gssapi/krb5/configure.in1
-rw-r--r--src/lib/gssapi/krb5/context_time.c12
-rw-r--r--src/lib/gssapi/krb5/delete_sec_context.c17
-rw-r--r--src/lib/gssapi/krb5/disp_name.c8
-rw-r--r--src/lib/gssapi/krb5/disp_status.c8
-rw-r--r--src/lib/gssapi/krb5/export_sec_context.c39
-rw-r--r--src/lib/gssapi/krb5/get_tkt_flags.c4
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h167
-rw-r--r--src/lib/gssapi/krb5/gssapi_err_krb5.et2
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c76
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.h12
-rw-r--r--src/lib/gssapi/krb5/import_name.c23
-rw-r--r--src/lib/gssapi/krb5/import_sec_context.c55
-rw-r--r--src/lib/gssapi/krb5/indicate_mechs.c7
-rw-r--r--src/lib/gssapi/krb5/init_sec_context.c225
-rw-r--r--src/lib/gssapi/krb5/inq_context.c10
-rw-r--r--src/lib/gssapi/krb5/inq_cred.c21
-rw-r--r--src/lib/gssapi/krb5/inq_names.c10
-rw-r--r--src/lib/gssapi/krb5/k5seal.c269
-rw-r--r--src/lib/gssapi/krb5/k5unseal.c322
-rw-r--r--src/lib/gssapi/krb5/krb5_gss_glue.c538
-rw-r--r--src/lib/gssapi/krb5/process_context_token.c14
-rw-r--r--src/lib/gssapi/krb5/rel_cred.c8
-rw-r--r--src/lib/gssapi/krb5/rel_name.c8
-rw-r--r--src/lib/gssapi/krb5/rel_oid.c1
-rw-r--r--src/lib/gssapi/krb5/seal.c39
-rw-r--r--src/lib/gssapi/krb5/ser_sctx.c464
-rw-r--r--src/lib/gssapi/krb5/sign.c20
-rw-r--r--src/lib/gssapi/krb5/unseal.c21
-rw-r--r--src/lib/gssapi/krb5/util_cksum.c36
-rw-r--r--src/lib/gssapi/krb5/util_crypt.c42
-rw-r--r--src/lib/gssapi/krb5/util_seed.c20
-rw-r--r--src/lib/gssapi/krb5/util_seqnum.c38
-rw-r--r--src/lib/gssapi/krb5/verify.c29
-rw-r--r--src/lib/gssapi/krb5/wrap_size_limit.c75
-rw-r--r--src/lib/gssapi/mechglue/mglueP.h11
-rw-r--r--src/lib/kadm/ChangeLog5
-rw-r--r--src/lib/kadm/alt_prof.c5
-rw-r--r--src/lib/kadm5/ChangeLog81
-rw-r--r--src/lib/kadm5/Makefile.in165
-rw-r--r--src/lib/kadm5/Makefile.ov61
-rw-r--r--src/lib/kadm5/adb.h141
-rw-r--r--src/lib/kadm5/adb_err.et16
-rw-r--r--src/lib/kadm5/adb_free.c71
-rw-r--r--src/lib/kadm5/adb_openclose.c338
-rw-r--r--src/lib/kadm5/adb_policy.c401
-rw-r--r--src/lib/kadm5/adb_principal.c408
-rw-r--r--src/lib/kadm5/adb_xdr.c132
-rw-r--r--src/lib/kadm5/admin.h649
-rw-r--r--src/lib/kadm5/admin_internal.h79
-rw-r--r--src/lib/kadm5/admin_xdr.h65
-rw-r--r--src/lib/kadm5/alt_prof.c861
-rw-r--r--src/lib/kadm5/chpass_util.c229
-rw-r--r--src/lib/kadm5/chpass_util_strings.et58
-rw-r--r--src/lib/kadm5/client_handle.c9
-rw-r--r--src/lib/kadm5/client_init.c554
-rw-r--r--src/lib/kadm5/client_internal.h93
-rw-r--r--src/lib/kadm5/client_principal.c307
-rw-r--r--src/lib/kadm5/client_rpc.c221
-rw-r--r--src/lib/kadm5/clnt_chpass_util.c15
-rw-r--r--src/lib/kadm5/clnt_policy.c151
-rw-r--r--src/lib/kadm5/clnt_privs.c66
-rw-r--r--src/lib/kadm5/configure.in49
-rw-r--r--src/lib/kadm5/get_admhst.c89
-rw-r--r--src/lib/kadm5/kadm_err.et54
-rw-r--r--src/lib/kadm5/kadm_rpc.h205
-rw-r--r--src/lib/kadm5/kadm_rpc_xdr.c830
-rw-r--r--src/lib/kadm5/logger.c940
-rw-r--r--src/lib/kadm5/misc_free.c96
-rw-r--r--src/lib/kadm5/ovsec_glue.c188
-rw-r--r--src/lib/kadm5/server_acl.c511
-rw-r--r--src/lib/kadm5/server_acl.h81
-rw-r--r--src/lib/kadm5/server_dict.c199
-rw-r--r--src/lib/kadm5/server_handle.c9
-rw-r--r--src/lib/kadm5/server_init.c330
-rw-r--r--src/lib/kadm5/server_internal.h103
-rw-r--r--src/lib/kadm5/server_kdb.c424
-rw-r--r--src/lib/kadm5/server_misc.c101
-rw-r--r--src/lib/kadm5/setenv.c163
-rw-r--r--src/lib/kadm5/str_conv.c397
-rw-r--r--src/lib/kadm5/svr_chpass_util.c15
-rw-r--r--src/lib/kadm5/svr_iters.c248
-rw-r--r--src/lib/kadm5/svr_misc_free.c37
-rw-r--r--src/lib/kadm5/svr_policy.c315
-rw-r--r--src/lib/kadm5/svr_principal.c1350
-rw-r--r--src/lib/kadm5/unit-test/ChangeLog18
-rw-r--r--src/lib/kadm5/unit-test/Makefile.ov154
-rw-r--r--src/lib/kadm5/unit-test/api.0/chpass-principal.exp176
-rw-r--r--src/lib/kadm5/unit-test/api.0/crte-policy.exp991
-rw-r--r--src/lib/kadm5/unit-test/api.0/crte-principal.exp1330
-rw-r--r--src/lib/kadm5/unit-test/api.0/destroy.exp203
-rw-r--r--src/lib/kadm5/unit-test/api.0/dlte-policy.exp207
-rw-r--r--src/lib/kadm5/unit-test/api.0/dlte-principal.exp329
-rw-r--r--src/lib/kadm5/unit-test/api.0/get-policy.exp199
-rw-r--r--src/lib/kadm5/unit-test/api.0/get-principal.exp346
-rw-r--r--src/lib/kadm5/unit-test/api.0/init.exp727
-rw-r--r--src/lib/kadm5/unit-test/api.0/mod-policy.exp703
-rw-r--r--src/lib/kadm5/unit-test/api.0/mod-principal.exp1942
-rw-r--r--src/lib/kadm5/unit-test/api.0/randkey-principal.exp319
-rw-r--r--src/lib/kadm5/unit-test/api.0/rename-principal.exp509
-rw-r--r--src/lib/kadm5/unit-test/api.1/lock.exp242
-rw-r--r--src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp68
-rw-r--r--src/lib/kadm5/unit-test/api.2/chpass-principal.exp176
-rw-r--r--src/lib/kadm5/unit-test/api.2/crte-policy.exp991
-rw-r--r--src/lib/kadm5/unit-test/api.2/crte-principal.exp1330
-rw-r--r--src/lib/kadm5/unit-test/api.2/destroy.exp203
-rw-r--r--src/lib/kadm5/unit-test/api.2/dlte-policy.exp207
-rw-r--r--src/lib/kadm5/unit-test/api.2/dlte-principal.exp329
-rw-r--r--src/lib/kadm5/unit-test/api.2/get-policy.exp199
-rw-r--r--src/lib/kadm5/unit-test/api.2/get-principal-v2.exp234
-rw-r--r--src/lib/kadm5/unit-test/api.2/get-principal.exp346
-rw-r--r--src/lib/kadm5/unit-test/api.2/init-v2.exp545
-rw-r--r--src/lib/kadm5/unit-test/api.2/init.exp731
-rw-r--r--src/lib/kadm5/unit-test/api.2/mod-policy.exp703
-rw-r--r--src/lib/kadm5/unit-test/api.2/mod-principal.exp1942
-rw-r--r--src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp62
-rw-r--r--src/lib/kadm5/unit-test/api.2/randkey-principal.exp319
-rw-r--r--src/lib/kadm5/unit-test/config/unix.exp113
-rw-r--r--src/lib/kadm5/unit-test/destroy-test.c42
-rw-r--r--src/lib/kadm5/unit-test/diff-files/destroy-12
-rw-r--r--src/lib/kadm5/unit-test/diff-files/no-diffs2
-rw-r--r--src/lib/kadm5/unit-test/handle-test.c131
-rw-r--r--src/lib/kadm5/unit-test/init-test.c26
-rw-r--r--src/lib/kadm5/unit-test/iter-test.c47
-rw-r--r--src/lib/kadm5/unit-test/lib.t367
-rw-r--r--src/lib/kadm5/unit-test/lock-test.c105
-rw-r--r--src/lib/kadm5/unit-test/randkey-test.c44
-rw-r--r--src/lib/kadm5/unit-test/site.exp2
-rw-r--r--src/lib/kadm5/unit-test/sizes-test.c21
-rw-r--r--src/lib/kdb/ChangeLog40
-rw-r--r--src/lib/kdb/Makefile.in21
-rw-r--r--src/lib/kdb/configure.in3
-rw-r--r--src/lib/kdb/kdb_cpw.c46
-rw-r--r--src/lib/kdb/kdb_dbm.c138
-rw-r--r--src/lib/kdb/kdb_xdr.c297
-rw-r--r--src/lib/krb5/keytab/file/ChangeLog5
-rw-r--r--src/lib/krb5/keytab/file/ktf_g_name.c18
-rw-r--r--src/lib/krb5/os/ChangeLog5
-rw-r--r--src/lib/krb5/os/ktdefname.c14
-rw-r--r--src/lib/rpc/ChangeLog20
-rw-r--r--src/lib/rpc/Makefile.in148
-rw-r--r--src/lib/rpc/Makefile.ov52
-rw-r--r--src/lib/rpc/auth.h197
-rw-r--r--src/lib/rpc/auth_any.c19
-rw-r--r--src/lib/rpc/auth_gssapi.c901
-rw-r--r--src/lib/rpc/auth_gssapi.h161
-rw-r--r--src/lib/rpc/auth_gssapi_misc.c390
-rw-r--r--src/lib/rpc/auth_none.c136
-rw-r--r--src/lib/rpc/auth_unix.c322
-rw-r--r--src/lib/rpc/auth_unix.h72
-rw-r--r--src/lib/rpc/authunix_prot.c66
-rw-r--r--src/lib/rpc/bindresvport.c79
-rw-r--r--src/lib/rpc/clnt.h335
-rw-r--r--src/lib/rpc/clnt_generic.c110
-rw-r--r--src/lib/rpc/clnt_perror.c306
-rw-r--r--src/lib/rpc/clnt_raw.c239
-rw-r--r--src/lib/rpc/clnt_simple.c112
-rw-r--r--src/lib/rpc/clnt_tcp.c476
-rw-r--r--src/lib/rpc/clnt_udp.c460
-rw-r--r--src/lib/rpc/configure.in41
-rw-r--r--src/lib/rpc/get_myaddress.c95
-rw-r--r--src/lib/rpc/getrpcent.c256
-rw-r--r--src/lib/rpc/getrpcport.c55
-rw-r--r--src/lib/rpc/netdb.h50
-rw-r--r--src/lib/rpc/pmap_clnt.c115
-rw-r--r--src/lib/rpc/pmap_clnt.h65
-rw-r--r--src/lib/rpc/pmap_getmaps.c88
-rw-r--r--src/lib/rpc/pmap_getport.c91
-rw-r--r--src/lib/rpc/pmap_prot.c57
-rw-r--r--src/lib/rpc/pmap_prot.h94
-rw-r--r--src/lib/rpc/pmap_prot2.c116
-rw-r--r--src/lib/rpc/pmap_rmt.c403
-rw-r--r--src/lib/rpc/pmap_rmt.h53
-rw-r--r--src/lib/rpc/rpc.h74
-rw-r--r--src/lib/rpc/rpc_callmsg.c195
-rw-r--r--src/lib/rpc/rpc_commondata.c41
-rw-r--r--src/lib/rpc/rpc_dtablesize.c60
-rw-r--r--src/lib/rpc/rpc_msg.h187
-rw-r--r--src/lib/rpc/rpc_prot.c287
-rw-r--r--src/lib/rpc/svc.c492
-rw-r--r--src/lib/rpc/svc.h298
-rw-r--r--src/lib/rpc/svc_auth.c119
-rw-r--r--src/lib/rpc/svc_auth.h61
-rw-r--r--src/lib/rpc/svc_auth_any.c22
-rw-r--r--src/lib/rpc/svc_auth_gssapi.c1181
-rw-r--r--src/lib/rpc/svc_auth_unix.c137
-rw-r--r--src/lib/rpc/svc_raw.c166
-rw-r--r--src/lib/rpc/svc_run.c72
-rw-r--r--src/lib/rpc/svc_simple.c143
-rw-r--r--src/lib/rpc/svc_tcp.c453
-rw-r--r--src/lib/rpc/svc_udp.c496
-rw-r--r--src/lib/rpc/types.hin90
-rw-r--r--src/lib/rpc/unit-test/Makefile97
-rw-r--r--src/lib/rpc/unit-test/client.c320
-rw-r--r--src/lib/rpc/unit-test/rpc_test.x30
-rw-r--r--src/lib/rpc/unit-test/server.c306
-rw-r--r--src/lib/rpc/unit-test/testsuite/Makefile24
-rw-r--r--src/lib/rpc/unit-test/testsuite/config/unix.exp79
-rw-r--r--src/lib/rpc/unit-test/testsuite/helpers.exp128
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp21
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp95
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp27
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh56
-rw-r--r--src/lib/rpc/xdr.c674
-rw-r--r--src/lib/rpc/xdr.h276
-rw-r--r--src/lib/rpc/xdr_alloc.c173
-rw-r--r--src/lib/rpc/xdr_array.c153
-rw-r--r--src/lib/rpc/xdr_float.c293
-rw-r--r--src/lib/rpc/xdr_mem.c188
-rw-r--r--src/lib/rpc/xdr_rec.c596
-rw-r--r--src/lib/rpc/xdr_reference.c132
-rw-r--r--src/lib/rpc/xdr_stdio.c189
242 files changed, 47582 insertions, 1309 deletions
diff --git a/src/lib/ChangeLog b/src/lib/ChangeLog
index 210d8cf51..c7e7fb6b1 100644
--- a/src/lib/ChangeLog
+++ b/src/lib/ChangeLog
@@ -12,6 +12,10 @@ Wed Jul 10 20:32:22 1996 Theodore Y. Ts'o <tytso@mit.edu>
timebomb and version server code was moved to
krb5_win_do_init(), which is called by krb5_init_context().
+Tue Jul 9 17:31:57 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in (CONFIG_DIRS): add rpc subdir
+
Tue Jul 9 16:44:22 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* win_glue.c: Add a quick hack so we can time-bomb the libkrb5.dll
diff --git a/src/lib/configure.in b/src/lib/configure.in
index aebd96c6a..80c359eb3 100644
--- a/src/lib/configure.in
+++ b/src/lib/configure.in
@@ -7,7 +7,7 @@ else
AC_MSG_RESULT(skipping Kerberos 4 libraries)
krb4=
fi
-CONFIG_DIRS(crypto krb5 des425 $krb4 krb5util kdb gssapi kadm)
+CONFIG_DIRS(crypto krb5 des425 $krb4 krb5util kdb gssapi rpc kadm5)
AC_PROG_ARCHIVE
AC_PROG_RANLIB
DO_SUBDIRS
diff --git a/src/lib/crypto/des/ChangeLog b/src/lib/crypto/des/ChangeLog
index f8637a6e7..c6f707290 100644
--- a/src/lib/crypto/des/ChangeLog
+++ b/src/lib/crypto/des/ChangeLog
@@ -1,3 +1,4 @@
+<<<<<<< ChangeLog
Sat Jun 15 03:51:19 1996 Ezra Peisach <epeisach@kangaroo.mit.edu>
* Makefile.in (clean): Add space before \
@@ -66,6 +67,11 @@ Thu May 2 18:29:01 1996 Richard Basch <basch@lehman.com>
[3-DES uses DES3-CBC-CRC to increment a 192 bit sequence
number, instead of being only as secure as DES.]
+Wed Apr 17 19:25:01 1996 Marc Horowitz <marc@mit.edu>
+
+ * cbc_cksum.c (mit_des_cbc_checksum): don't allocate the checksum
+ contents. The caller is supposed to do this.
+
Wed Apr 10 17:46:40 1996 Theodore Y. Ts'o <tytso@dcl>
* Makefile.in (SRCS,OBJS): Added afsstring2key.c to the list of
diff --git a/src/lib/crypto/des/cbc_cksum.c b/src/lib/crypto/des/cbc_cksum.c
index 9c98263a2..c4fb8c086 100644
--- a/src/lib/crypto/des/cbc_cksum.c
+++ b/src/lib/crypto/des/cbc_cksum.c
@@ -86,7 +86,6 @@ mit_des_cbc_checksum(in, in_length, key, key_size, cksum)
cksum->checksum_type = CKSUMTYPE_DESCBC;
cksum->length = sizeof(mit_des_cblock);
-
mit_des_cbc_cksum(in, cksum->contents, in_length, schedule, key);
cleanup();
diff --git a/src/lib/gssapi/ChangeLog b/src/lib/gssapi/ChangeLog
index 0ad7c89bd..036bd4693 100644
--- a/src/lib/gssapi/ChangeLog
+++ b/src/lib/gssapi/ChangeLog
@@ -12,6 +12,11 @@ Mon May 6 21:33:25 1996 Ezra Peisach <epeisach@kangaroo.mit.edu>
* Makefile.in (clean-unix): Remove libgssapi_krb5.stamp.
+Wed Apr 17 21:48:15 1996 Marc Horowitz <marc@mit.edu>
+
+ * Makefile.in, configure.in: Nothing in mechglue is used anymore,
+ for now.
+
Tue Feb 27 22:10:48 1996 Theodore Y. Ts'o <tytso@dcl>
* Makefile.in (all-windows, clean-windows): Add mechglue to the
diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in
index c27788dc2..b874a951c 100644
--- a/src/lib/gssapi/Makefile.in
+++ b/src/lib/gssapi/Makefile.in
@@ -10,8 +10,8 @@ KRB5_VER=@KRB5_SH_VERS@
DEPLIBS=$(TOPLIBD)/libcrypto.$(SHEXT).$(CRYPTO_VER) \
$(TOPLIBD)/libcom_err.$(SHEXT).$(COMERR_VER) \
$(TOPLIBD)/libkrb5.$(SHEXT).$(KRB5_VER)
-LIB_SUBDIRS= generic krb5 mechglue
-LIBDONE= generic/DONE krb5/DONE mechglue/DONE
+LIB_SUBDIRS= generic krb5
+LIBDONE= generic/DONE krb5/DONE # mechglue/DONE
LIBUPDATE= $(BUILDTOP)/util/libupdate
SHLIB_LIBS=-lkrb5 -lcrypto -lcom_err
@@ -51,9 +51,9 @@ all-windows::
cd ..\krb5
@echo Making in gssapi\krb5
-$(MAKE) -$(MFLAGS)
- cd ..\mechglue
- @echo Making in gssapi\mechglue
- -$(MAKE) -$(MFLAGS)
+# cd ..\mechglue
+# @echo Making in gssapi\mechglue
+# -$(MAKE) -$(MFLAGS)
cd ..
clean-windows::
@@ -63,9 +63,9 @@ clean-windows::
cd ..\krb5
@echo Making clean in gssapi\krb5
-$(MAKE) -$(MFLAGS) clean
- cd ..\mechglue
- @echo Making clean in gssapi\mechglue
- -$(MAKE) -$(MFLAGS) clean
+# cd ..\mechglue
+# @echo Making clean in gssapi\mechglue
+# -$(MAKE) -$(MFLAGS) clean
cd ..
@echo Making clean in gssapi
diff --git a/src/lib/gssapi/configure.in b/src/lib/gssapi/configure.in
index ee150e11f..164582c64 100644
--- a/src/lib/gssapi/configure.in
+++ b/src/lib/gssapi/configure.in
@@ -1,6 +1,7 @@
AC_INIT(configure.in)
CONFIG_RULES
-CONFIG_DIRS(generic krb5 mechglue)
+CONFIG_DIRS(generic krb5)
+dnl CONFIG_DIRS(generic krb5 mechglue)
AC_PROG_ARCHIVE
AC_PROG_ARCHIVE_ADD
AC_PROG_RANLIB
diff --git a/src/lib/gssapi/generic/ChangeLog b/src/lib/gssapi/generic/ChangeLog
index d43459914..a3b2a1411 100644
--- a/src/lib/gssapi/generic/ChangeLog
+++ b/src/lib/gssapi/generic/ChangeLog
@@ -28,6 +28,26 @@ Wed Jun 12 00:46:41 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
all uses of INTERFACE in favor of KRB5_CALLCONV and
KRB5_DLLIMP.
+Sun Apr 21 03:07:02 1996 Marc Horowitz <marc@mit.edu>
+
+ * gssapi_generic.c, release_buffer.c, release_oid_set.c: added
+ files which should have been added before, but either I or commit
+ was confused.
+
+Wed Apr 17 20:59:23 1996 Marc Horowitz <marc@mit.edu>
+
+ * oid_ops.c: moved from mechglue
+
+ * util_canonhost.c (g_canonicalize_host): cast the return value of
+ malloc()
+
+ * gssapiP_generic.h: Added prototypes for oid_ops.c
+
+ * gssapi.h: Make the types of OM_uint32 constants portable,
+ fix some minor compile-time nits
+
+ * Makefile.in: change the list of files which need to be built
+
Tue Apr 2 15:31:25 1996 Theodore Y. Ts'o <tytso@dcl>
* Makefile.in (SRCS): Inlined list of source files for SRCS and
diff --git a/src/lib/gssapi/generic/Makefile.in b/src/lib/gssapi/generic/Makefile.in
index 9c90244f2..c9e940962 100644
--- a/src/lib/gssapi/generic/Makefile.in
+++ b/src/lib/gssapi/generic/Makefile.in
@@ -39,28 +39,40 @@ gssapi_err_generic.c: gssapi_err_generic.et
#endif
SRCS = \
- $(srcdir)/disp_major_status.c \
$(srcdir)/disp_com_err_status.c \
+ $(srcdir)/disp_major_status.c \
+ $(srcdir)/gssapi_generic.c \
+ $(srcdir)/oid_ops.c \
+ $(srcdir)/release_buffer.c \
+ $(srcdir)/release_oid_set.c \
$(srcdir)/util_buffer.c \
$(srcdir)/util_canonhost.c \
$(srcdir)/util_dup.c \
$(srcdir)/util_oid.c \
+ $(srcdir)/util_ordering.c \
+ $(srcdir)/util_set.c \
$(srcdir)/util_token.c \
- $(srcdir)/utl_nohash_validate.c \
+ $(srcdir)/util_validate.c \
gssapi_err_generic.c
OBJS = \
- disp_major_status.$(OBJEXT) \
disp_com_err_status.$(OBJEXT) \
+ disp_major_status.$(OBJEXT) \
+ gssapi_generic.$(OBJEXT) \
+ oid_ops.$(OBJEXT) \
+ release_buffer.$(OBJEXT) \
+ release_oid_set.$(OBJEXT) \
util_buffer.$(OBJEXT) \
util_canonhost.$(OBJEXT) \
util_dup.$(OBJEXT) \
util_oid.$(OBJEXT) \
+ util_ordering.$(OBJEXT) \
+ util_set.$(OBJEXT) \
util_token.$(OBJEXT) \
- utl_nohash_validate.$(OBJEXT) \
+ util_validate.$(OBJEXT) \
gssapi_err_generic.$(OBJEXT)
-EHDRDIR= $(BUILDTOP)$(S)include$(S)gssapi
+EHDRDIR= $(BUILDTOP)/include/gssapi
EXPORTED_HEADERS= gssapi.h gssapi_generic.h
HDRS= $(ETHDRS)
@@ -89,8 +101,8 @@ clean-windows::
# Krb5InstallHeaders($(EXPORTED_HEADERS), $(KRB5_INCDIR)/krb5)
install::
@set -x; for f in $(EXPORTED_HEADERS) ; \
- do $(INSTALL_DATA) $(srcdir)$(S)$$f \
- $(DESTDIR)$(KRB5_INCDIR)$(S)gssapi$(S)$$f ; \
+ do $(INSTALL_DATA) $(srcdir)/$$f \
+ $(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \
done
depend:: $(ETSRCS)
diff --git a/src/lib/gssapi/generic/disp_com_err_status.c b/src/lib/gssapi/generic/disp_com_err_status.c
index 79b5fbbe2..c4db91375 100644
--- a/src/lib/gssapi/generic/disp_com_err_status.c
+++ b/src/lib/gssapi/generic/disp_com_err_status.c
@@ -20,6 +20,10 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_generic.h"
#include "com_err.h"
diff --git a/src/lib/gssapi/generic/disp_major_status.c b/src/lib/gssapi/generic/disp_major_status.c
index ad0b17f20..4dd91d25f 100644
--- a/src/lib/gssapi/generic/disp_major_status.c
+++ b/src/lib/gssapi/generic/disp_major_status.c
@@ -23,6 +23,10 @@
#include "gssapiP_generic.h"
#include <string.h>
+/*
+ * $Id$
+ */
+
/* This code has knowledge of the min and max errors of each type
within the gssapi major status */
diff --git a/src/lib/gssapi/generic/gssapi.h b/src/lib/gssapi/generic/gssapi.h
index 2b2e6002b..28cc4ca41 100644
--- a/src/lib/gssapi/generic/gssapi.h
+++ b/src/lib/gssapi/generic/gssapi.h
@@ -131,14 +131,6 @@ typedef unsigned int uid_t;
#endif
#endif
-#ifndef NPROTOTYPE
-#if defined(__ultrix) && !defined (__GNUC__)
-#define NPROTOTYPE(x) ()
-#else
-#define NPROTOTYPE(x) PROTOTYPE(x)
-#endif
-#endif
-
/*
* First, include stddef.h to get size_t defined.
*/
@@ -161,8 +153,13 @@ typedef unsigned int uid_t;
#endif /* HAVE_XOM_H */
/*
+ * $Id$
+ */
+
+/*
* First, define the three platform-dependent pointer types.
*/
+
typedef void FAR * gss_name_t;
typedef void FAR * gss_cred_id_t;
typedef void FAR * gss_ctx_id_t;
@@ -305,7 +302,7 @@ typedef int gss_cred_usage_t;
* Expiration time of 2^32-1 seconds means infinite lifetime for a
* credential or security context
*/
-#define GSS_C_INDEFINITE 0xffffffffl
+#define GSS_C_INDEFINITE ((OM_uint32) 0xfffffffful)
/* Major status codes */
@@ -318,9 +315,9 @@ typedef int gss_cred_usage_t;
#define GSS_C_CALLING_ERROR_OFFSET 24
#define GSS_C_ROUTINE_ERROR_OFFSET 16
#define GSS_C_SUPPLEMENTARY_OFFSET 0
-#define GSS_C_CALLING_ERROR_MASK 0377l
-#define GSS_C_ROUTINE_ERROR_MASK 0377l
-#define GSS_C_SUPPLEMENTARY_MASK 0177777l
+#define GSS_C_CALLING_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_ROUTINE_ERROR_MASK ((OM_uint32) 0377ul)
+#define GSS_C_SUPPLEMENTARY_MASK ((OM_uint32) 0177777ul)
/*
* The macros that test status codes for error conditions. Note that the
@@ -345,43 +342,51 @@ typedef int gss_cred_usage_t;
* Calling errors:
*/
#define GSS_S_CALL_INACCESSIBLE_READ \
- (1l << GSS_C_CALLING_ERROR_OFFSET)
+ (((OM_uint32) 1ul) << GSS_C_CALLING_ERROR_OFFSET)
#define GSS_S_CALL_INACCESSIBLE_WRITE \
- (2l << GSS_C_CALLING_ERROR_OFFSET)
+ (((OM_uint32) 2ul) << GSS_C_CALLING_ERROR_OFFSET)
#define GSS_S_CALL_BAD_STRUCTURE \
- (3l << GSS_C_CALLING_ERROR_OFFSET)
+ (((OM_uint32) 3ul) << GSS_C_CALLING_ERROR_OFFSET)
/*
* Routine errors:
*/
-#define GSS_S_BAD_MECH (1l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_NAME (2l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_NAMETYPE (3l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_BINDINGS (4l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_STATUS (5l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_SIG (6l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_NO_CRED (7l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_NO_CONTEXT (8l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_DEFECTIVE_TOKEN (9l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_DEFECTIVE_CREDENTIAL (10l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_CREDENTIALS_EXPIRED (11l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_CONTEXT_EXPIRED (12l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_FAILURE (13l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_BAD_QOP (14l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_UNAUTHORIZED (15l << GSS_C_ROUTINE_ERROR_OFFSET)
-#define GSS_S_UNAVAILABLE (16l << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_MECH (((OM_uint32) 1ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAME (((OM_uint32) 2ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_NAMETYPE (((OM_uint32) 3ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_BINDINGS (((OM_uint32) 4ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_STATUS (((OM_uint32) 5ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_SIG (((OM_uint32) 6ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CRED (((OM_uint32) 7ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NO_CONTEXT (((OM_uint32) 8ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_TOKEN (((OM_uint32) 9ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DEFECTIVE_CREDENTIAL \
+ (((OM_uint32) 10ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CREDENTIALS_EXPIRED \
+ (((OM_uint32) 11ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_CONTEXT_EXPIRED \
+ (((OM_uint32) 12ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_FAILURE (((OM_uint32) 13ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
/*
* XXX new functions. Check to get official error number assigments?
*/
-#define GSS_S_DUPLICATE_ELEMENT (17l << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_DUPLICATE_ELEMENT \
+ (((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
/*
* Supplementary info bits:
*/
-#define GSS_S_CONTINUE_NEEDED (1l << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
-#define GSS_S_DUPLICATE_TOKEN (1l << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
-#define GSS_S_OLD_TOKEN (1l << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
-#define GSS_S_UNSEQ_TOKEN (1l << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
+#define GSS_S_CONTINUE_NEEDED (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 0))
+#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
+#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
+#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
+/*
+ * XXX not in the cbindings yet. remove this comment when it is
+ */
+#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
/*
diff --git a/src/lib/gssapi/generic/gssapiP_generic.h b/src/lib/gssapi/generic/gssapiP_generic.h
index a882f6139..e0bb28d44 100644
--- a/src/lib/gssapi/generic/gssapiP_generic.h
+++ b/src/lib/gssapi/generic/gssapiP_generic.h
@@ -23,7 +23,10 @@
#ifndef _GSSAPIP_GENERIC_H_
#define _GSSAPIP_GENERIC_H_
-#include "k5-int.h"
+/*
+ * $Id$
+ */
+
#include "gssapi.h"
#include "gssapi_err_generic.h"
@@ -86,6 +89,14 @@
/** helper functions **/
+typedef struct _g_set *g_set;
+
+int g_set_init PROTOTYPE((g_set *s));
+int g_set_destroy PROTOTYPE((g_set *s));
+int g_set_entry_add PROTOTYPE((g_set *s, void *key, void *value));
+int g_set_entry_delete PROTOTYPE((g_set *s, void *key));
+int g_set_entry_get PROTOTYPE((g_set *s, void *key, void **value));
+
int g_save_name PROTOTYPE((void **vdb, gss_name_t *name));
int g_save_cred_id PROTOTYPE((void **vdb, gss_cred_id_t *cred));
int g_save_ctx_id PROTOTYPE((void **vdb, gss_ctx_id_t *ctx));
@@ -119,8 +130,64 @@ OM_uint32 g_display_com_err_status PROTOTYPE((OM_uint32 *minor_status,
OM_uint32 status_value,
gss_buffer_t status_string));
-char * g_canonicalize_host PROTOTYPE((char *hostname));
-
-char * g_strdup PROTOTYPE((char *str));
+OM_uint32 g_order_init PROTOTYPE((void **queue, unsigned int seqnum,
+ int do_replay, int do_sequence));
+
+OM_uint32 g_order_check PROTOTYPE((void **queue, unsigned int seqnum));
+
+void g_order_free PROTOTYPE((void **queue));
+
+char *g_canonicalize_host PROTOTYPE((char *hostname));
+char *g_local_host_name PROTOTYPE((void));
+
+char *g_strdup PROTOTYPE((char *str));
+
+/** declarations of internal name mechanism functions **/
+
+OM_uint32 generic_gss_release_buffer
+PROTOTYPE((OM_uint32*, /* minor_status */
+ gss_buffer_t /* buffer */
+ ));
+
+OM_uint32 generic_gss_release_oid_set
+PROTOTYPE((OM_uint32*, /* minor_status */
+ gss_OID_set* /* set */
+ ));
+
+OM_uint32 generic_gss_copy_oid
+PROTOTYPE( (OM_uint32 *, /* minor_status */
+ gss_OID, /* oid */
+ gss_OID * /* new_oid */
+ ));
+
+OM_uint32 generic_gss_create_empty_oid_set
+PROTOTYPE( (OM_uint32 *, /* minor_status */
+ gss_OID_set * /* oid_set */
+ ));
+
+OM_uint32 generic_gss_add_oid_set_member
+PROTOTYPE( (OM_uint32 *, /* minor_status */
+ gss_OID, /* member_oid */
+ gss_OID_set * /* oid_set */
+ ));
+
+OM_uint32 generic_gss_test_oid_set_member
+PROTOTYPE( (OM_uint32 *, /* minor_status */
+ gss_OID, /* member */
+ gss_OID_set, /* set */
+ int * /* present */
+ ));
+
+OM_uint32 generic_gss_oid_to_str
+PROTOTYPE( (OM_uint32 *, /* minor_status */
+ gss_OID, /* oid */
+ gss_buffer_t /* oid_str */
+ ));
+
+OM_uint32 generic_gss_str_to_oid
+PROTOTYPE( (OM_uint32 *, /* minor_status */
+ gss_buffer_t, /* oid_str */
+ gss_OID * /* oid */
+ ));
#endif /* _GSSAPIP_GENERIC_H_ */
diff --git a/src/lib/gssapi/generic/gssapi_err_generic.et b/src/lib/gssapi/generic/gssapi_err_generic.et
index 91d958d12..ddeed4227 100644
--- a/src/lib/gssapi/generic/gssapi_err_generic.et
+++ b/src/lib/gssapi/generic/gssapi_err_generic.et
@@ -20,6 +20,10 @@
# PERFORMANCE OF THIS SOFTWARE.
#
+#
+# $Id$
+#
+
error_table ggss
error_code G_BAD_SERVICE_NAME, "No @ in SERVICE-NAME name string"
@@ -31,5 +35,9 @@ error_code G_BAD_MSG_CTX, "Message context invalid"
error_code G_WRONG_SIZE, "Buffer is the wrong size"
error_code G_BAD_USAGE, "Credential usage type is unknown"
error_code G_UNKNOWN_QOP, "Unknown quality of protection specified"
+error_code G_NO_HOSTNAME, "Local host name could not be determined"
error_code G_BAD_HOSTNAME, "Hostname in SERVICE-NAME string could not be canonicalized"
+error_code G_WRONG_MECH, "Mechanism is incorrect"
+error_code G_BAD_TOK_HEADER, "Token header is malformed or corrupt"
+error_code G_BAD_DIRECTION, "Packet was replayed in wrong direction"
end
diff --git a/src/lib/gssapi/generic/gssapi_generic.c b/src/lib/gssapi/generic/gssapi_generic.c
new file mode 100644
index 000000000..7072329b7
--- /dev/null
+++ b/src/lib/gssapi/generic/gssapi_generic.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_generic.h"
+
+/*
+ * See krb5/gssapi_krb5.c for a description of the algorithm for
+ * encoding an object identifier.
+ */
+
+/*
+ * The OID of user_name is:
+ * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) user_name(1) = 1.2.840.113554.1.2.1.1
+ * machine_uid_name:
+ * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) machine_uid_name(2) = 1.2.840.113554.1.2.1.2
+ * string_uid_name:
+ * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) string_uid_name(3) = 1.2.840.113554.1.2.1.3
+ * service_name:
+ * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * generic(1) service_name(4) = 1.2.840.113554.1.2.1.4
+ */
+
+static gss_OID_desc oids[] = {
+ {10, "\052\206\110\206\367\022\001\002\001\001"},
+ {10, "\052\206\110\206\367\022\001\002\001\002"},
+ {10, "\052\206\110\206\367\022\001\002\001\003"},
+ {10, "\052\206\110\206\367\022\001\002\001\004"},
+};
+
+gss_OID gss_nt_user_name = oids+0;
+gss_OID gss_nt_machine_uid_name = oids+1;
+gss_OID gss_nt_string_uid_name = oids+2;
+gss_OID gss_nt_service_name = oids+3;
diff --git a/src/lib/gssapi/generic/gssapi_generic.h b/src/lib/gssapi/generic/gssapi_generic.h
index fe2282796..88c054788 100644
--- a/src/lib/gssapi/generic/gssapi_generic.h
+++ b/src/lib/gssapi/generic/gssapi_generic.h
@@ -23,6 +23,10 @@
#ifndef _GSSAPI_GENERIC_H_
#define _GSSAPI_GENERIC_H_
+/*
+ * $Id$
+ */
+
#if defined(__MWERKS__) || defined(applec) || defined(THINK_C)
#include <gssapi.h>
#else
diff --git a/src/lib/gssapi/generic/oid_ops.c b/src/lib/gssapi/generic/oid_ops.c
new file mode 100644
index 000000000..38d73f429
--- /dev/null
+++ b/src/lib/gssapi/generic/oid_ops.c
@@ -0,0 +1,385 @@
+/*
+ * lib/gssapi/generic/oid_ops.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * oid_ops.c - GSS-API V2 interfaces to manipulate OIDs
+ */
+
+#include "gssapiP_generic.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+
+#if 0
+OM_uint32
+generic_gss_release_oid(minor_status, oid)
+ OM_uint32 *minor_status;
+ gss_OID *oid;
+{
+ *minor_status = 0;
+
+ if (*oid == GSS_C_NO_OID)
+ return(GSS_S_COMPLETE);
+
+ /*
+ * The V2 API says the following!
+ *
+ * gss_release_oid[()] will recognize any of the GSSAPI's own OID values,
+ * and will silently ignore attempts to free these OIDs; for other OIDs
+ * it will call the C free() routine for both the OID data and the
+ * descriptor. This allows applications to freely mix their own heap-
+ * allocated OID values with OIDs returned by GSS-API.
+ */
+ if ((*oid != gss_nt_user_name) &&
+ (*oid != gss_nt_machine_uid_name) &&
+ (*oid != gss_nt_string_uid_name) &&
+ (*oid != gss_nt_service_name)) {
+ free((*oid)->elements);
+ free(*oid);
+ }
+ *oid = GSS_C_NO_OID;
+ return(GSS_S_COMPLETE);
+}
+#endif
+
+OM_uint32
+generic_gss_copy_oid(minor_status, oid, new_oid)
+ OM_uint32 *minor_status;
+ gss_OID oid, *new_oid;
+{
+ gss_OID p;
+
+ p = (gss_OID) malloc(sizeof(gss_OID_desc));
+ if (!p) {
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ p->length = oid->length;
+ p->elements = malloc(p->length);
+ if (!p->elements) {
+ free(p);
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+ memcpy(p->elements, oid->elements, p->length);
+ *new_oid = p;
+ return(GSS_S_COMPLETE);
+}
+
+
+OM_uint32
+generic_gss_create_empty_oid_set(minor_status, oid_set)
+ OM_uint32 *minor_status;
+ gss_OID_set *oid_set;
+{
+ if ((*oid_set = (gss_OID_set) malloc(sizeof(gss_OID_set_desc)))) {
+ memset(*oid_set, 0, sizeof(gss_OID_set_desc));
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+ }
+ else {
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+}
+
+OM_uint32
+generic_gss_add_oid_set_member(minor_status, member_oid, oid_set)
+ OM_uint32 *minor_status;
+ gss_OID member_oid;
+ gss_OID_set *oid_set;
+{
+ gss_OID elist;
+ gss_OID lastel;
+
+ elist = (*oid_set)->elements;
+ /* Get an enlarged copy of the array */
+ if (((*oid_set)->elements = (gss_OID) malloc(((*oid_set)->count+1) *
+ sizeof(gss_OID_desc)))) {
+ /* Copy in the old junk */
+ if (elist)
+ memcpy((*oid_set)->elements,
+ elist,
+ ((*oid_set)->count * sizeof(gss_OID_desc)));
+
+ /* Duplicate the input element */
+ lastel = &(*oid_set)->elements[(*oid_set)->count];
+ if ((lastel->elements =
+ (void *) malloc((size_t) member_oid->length))) {
+ /* Success - copy elements */
+ memcpy(lastel->elements, member_oid->elements,
+ (size_t) member_oid->length);
+ /* Set length */
+ lastel->length = member_oid->length;
+
+ /* Update count */
+ (*oid_set)->count++;
+ if (elist)
+ free(elist);
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+ }
+ else
+ free((*oid_set)->elements);
+ }
+ /* Failure - restore old contents of list */
+ (*oid_set)->elements = elist;
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_test_oid_set_member(minor_status, member, set, present)
+ OM_uint32 *minor_status;
+ gss_OID member;
+ gss_OID_set set;
+ int *present;
+{
+ size_t i;
+ int result;
+
+ result = 0;
+ for (i=0; i<set->count; i++) {
+ if ((set->elements[i].length == member->length) &&
+ !memcmp(set->elements[i].elements,
+ member->elements,
+ (size_t) member->length)) {
+ result = 1;
+ break;
+ }
+ }
+ *present = result;
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+}
+
+/*
+ * OID<->string routines. These are uuuuugly.
+ */
+OM_uint32
+generic_gss_oid_to_str(minor_status, oid, oid_str)
+ OM_uint32 *minor_status;
+ gss_OID oid;
+ gss_buffer_t oid_str;
+{
+ char numstr[128];
+ unsigned long number;
+ int numshift;
+ size_t string_length;
+ size_t i;
+ unsigned char *cp;
+ char *bp;
+
+ /* Decoded according to krb5/gssapi_krb5.c */
+
+ /* First determine the size of the string */
+ string_length = 0;
+ number = 0;
+ numshift = 0;
+ cp = (unsigned char *) oid->elements;
+ number = (unsigned long) cp[0];
+ sprintf(numstr, "%ld ", number/40);
+ string_length += strlen(numstr);
+ sprintf(numstr, "%ld ", number%40);
+ string_length += strlen(numstr);
+ for (i=1; i<oid->length; i++) {
+ if ( (size_t) (numshift+7) < (sizeof(unsigned long)*8)) {
+ number = (number << 7) | (cp[i] & 0x7f);
+ numshift += 7;
+ }
+ else {
+ *minor_status = EINVAL;
+ return(GSS_S_FAILURE);
+ }
+ if ((cp[i] & 0x80) == 0) {
+ sprintf(numstr, "%ld ", number);
+ string_length += strlen(numstr);
+ number = 0;
+ numshift = 0;
+ }
+ }
+ /*
+ * If we get here, we've calculated the length of "n n n ... n ". Add 4
+ * here for "{ " and "}\0".
+ */
+ string_length += 4;
+ if ((bp = (char *) malloc(string_length))) {
+ strcpy(bp, "{ ");
+ number = (unsigned long) cp[0];
+ sprintf(numstr, "%ld ", number/40);
+ strcat(bp, numstr);
+ sprintf(numstr, "%ld ", number%40);
+ strcat(bp, numstr);
+ number = 0;
+ cp = (unsigned char *) oid->elements;
+ for (i=1; i<oid->length; i++) {
+ number = (number << 7) | (cp[i] & 0x7f);
+ if ((cp[i] & 0x80) == 0) {
+ sprintf(numstr, "%ld ", number);
+ strcat(bp, numstr);
+ number = 0;
+ }
+ }
+ strcat(bp, "}");
+ oid_str->length = strlen(bp)+1;
+ oid_str->value = (void *) bp;
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+ }
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+}
+
+OM_uint32
+generic_gss_str_to_oid(minor_status, oid_str, oid)
+ OM_uint32 *minor_status;
+ gss_buffer_t oid_str;
+ gss_OID *oid;
+{
+ char *cp, *bp, *startp;
+ int brace;
+ long numbuf;
+ long onumbuf;
+ OM_uint32 nbytes;
+ int index;
+ unsigned char *op;
+
+ brace = 0;
+ bp = (char *) oid_str->value;
+ cp = bp;
+ /* Skip over leading space */
+ while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ bp++;
+ if (*bp == '{') {
+ brace = 1;
+ bp++;
+ }
+ while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ bp++;
+ startp = bp;
+ nbytes = 0;
+
+ /*
+ * The first two numbers are chewed up by the first octet.
+ */
+ if (sscanf(bp, "%ld", &numbuf) != 1) {
+ *minor_status = EINVAL;
+ return(GSS_S_FAILURE);
+ }
+ while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+ bp++;
+ while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ bp++;
+ if (sscanf(bp, "%ld", &numbuf) != 1) {
+ *minor_status = EINVAL;
+ return(GSS_S_FAILURE);
+ }
+ while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+ bp++;
+ while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ bp++;
+ nbytes++;
+ while (isdigit(*bp)) {
+ if (sscanf(bp, "%ld", &numbuf) != 1) {
+ *minor_status = EINVAL;
+ return(GSS_S_FAILURE);
+ }
+ while (numbuf) {
+ nbytes++;
+ numbuf >>= 7;
+ }
+ while ((bp < &cp[oid_str->length]) && isdigit(*bp))
+ bp++;
+ while ((bp < &cp[oid_str->length]) && isspace(*bp))
+ bp++;
+ }
+ if (brace && (*bp != '}')) {
+ *minor_status = EINVAL;
+ return(GSS_S_FAILURE);
+ }
+
+ /*
+ * Phew! We've come this far, so the syntax is good.
+ */
+ if ((*oid = (gss_OID) malloc(sizeof(gss_OID_desc)))) {
+ if (((*oid)->elements = (void *) malloc((size_t) nbytes))) {
+ (*oid)->length = nbytes;
+ op = (unsigned char *) (*oid)->elements;
+ bp = startp;
+ sscanf(bp, "%ld", &numbuf);
+ while (isdigit(*bp))
+ bp++;
+ while (isspace(*bp))
+ bp++;
+ onumbuf = 40*numbuf;
+ sscanf(bp, "%ld", &numbuf);
+ onumbuf += numbuf;
+ *op = (unsigned char) onumbuf;
+ op++;
+ while (isdigit(*bp))
+ bp++;
+ while (isspace(*bp))
+ bp++;
+ while (isdigit(*bp)) {
+ sscanf(bp, "%ld", &numbuf);
+ nbytes = 0;
+ /* Have to fill in the bytes msb-first */
+ onumbuf = numbuf;
+ while (numbuf) {
+ nbytes++;
+ numbuf >>= 7;
+ }
+ numbuf = onumbuf;
+ op += nbytes;
+ index = -1;
+ while (numbuf) {
+ op[index] = (unsigned char) numbuf & 0x7f;
+ if (index != -1)
+ op[index] |= 0x80;
+ index--;
+ numbuf >>= 7;
+ }
+ while (isdigit(*bp))
+ bp++;
+ while (isspace(*bp))
+ bp++;
+ }
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+ }
+ else {
+ free(*oid);
+ *oid = GSS_C_NO_OID;
+ }
+ }
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+}
+
diff --git a/src/lib/gssapi/generic/release_buffer.c b/src/lib/gssapi/generic/release_buffer.c
new file mode 100644
index 000000000..d367ef31e
--- /dev/null
+++ b/src/lib/gssapi/generic/release_buffer.c
@@ -0,0 +1,58 @@
+/* #ident "@(#)g_rel_buffer.c 1.2 96/02/06 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * glue routine for gss_release_buffer
+ */
+
+#include "gssapiP_generic.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 INTERFACE
+generic_gss_release_buffer (minor_status,
+ buffer)
+ OM_uint32 * minor_status;
+ gss_buffer_t buffer;
+{
+ if (minor_status)
+ *minor_status = 0;
+
+ /* if buffer is NULL, return */
+
+ if (buffer == GSS_C_NO_BUFFER)
+ return(GSS_S_COMPLETE);
+
+ if ((buffer->length) &&
+ (buffer->value)) {
+ free(buffer->value);
+ buffer->length = 0;
+ buffer->value = NULL;
+ }
+
+ return (GSS_S_COMPLETE);
+}
diff --git a/src/lib/gssapi/generic/release_oid_set.c b/src/lib/gssapi/generic/release_oid_set.c
new file mode 100644
index 000000000..01e814bcb
--- /dev/null
+++ b/src/lib/gssapi/generic/release_oid_set.c
@@ -0,0 +1,62 @@
+/* #ident "@(#)gss_release_oid_set.c 1.12 95/08/23 SMI" */
+
+/*
+ * Copyright 1996 by Sun Microsystems, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Sun Microsystems not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. Sun Microsystems makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * glue routine for gss_release_oid_set
+ */
+
+#include "gssapiP_generic.h"
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+OM_uint32 INTERFACE
+generic_gss_release_oid_set (minor_status,
+ set)
+ OM_uint32 * minor_status;
+ gss_OID_set * set;
+{
+ size_t i;
+ gss_OID oid;
+ if (minor_status)
+ *minor_status = 0;
+
+ if (set == NULL)
+ return(GSS_S_COMPLETE);
+
+ if (*set == GSS_C_NULL_OID_SET)
+ return(GSS_S_COMPLETE);
+
+ for (i=0; i<(*set)->count; i++)
+ free((*set)->elements[i].elements);
+
+ free((*set)->elements);
+ free(*set);
+
+ *set = GSS_C_NULL_OID_SET;
+
+ return(GSS_S_COMPLETE);
+}
diff --git a/src/lib/gssapi/generic/util_buffer.c b/src/lib/gssapi/generic/util_buffer.c
index cf144495f..e715834d9 100644
--- a/src/lib/gssapi/generic/util_buffer.c
+++ b/src/lib/gssapi/generic/util_buffer.c
@@ -20,6 +20,10 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_generic.h"
#include <string.h>
diff --git a/src/lib/gssapi/generic/util_canonhost.c b/src/lib/gssapi/generic/util_canonhost.c
index 896b950b1..900834f40 100644
--- a/src/lib/gssapi/generic/util_canonhost.c
+++ b/src/lib/gssapi/generic/util_canonhost.c
@@ -20,10 +20,16 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
/* This file could be OS specific */
-#define NEED_SOCKETS
+
#include "gssapiP_generic.h"
+#include "port-sockets.h"
+
#ifndef _MACINTOSH
#include <sys/types.h>
#endif
@@ -41,7 +47,7 @@ g_canonicalize_host(hostname)
if ((hent = gethostbyname(hostname)) == NULL)
return(NULL);
- if (! (haddr = xmalloc(hent->h_length))) {
+ if (! (haddr = (char *) xmalloc(hent->h_length))) {
return(NULL);
}
@@ -53,7 +59,7 @@ g_canonicalize_host(hostname)
xfree(haddr);
- if ((canon = xmalloc(strlen(hent->h_name)+1)) == NULL)
+ if ((canon = (char *) xmalloc(strlen(hent->h_name)+1)) == NULL)
return(NULL);
strcpy(canon, hent->h_name);
diff --git a/src/lib/gssapi/generic/util_dup.c b/src/lib/gssapi/generic/util_dup.c
index 6b19092db..d601ceef2 100644
--- a/src/lib/gssapi/generic/util_dup.c
+++ b/src/lib/gssapi/generic/util_dup.c
@@ -20,6 +20,10 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_generic.h"
#include <string.h>
diff --git a/src/lib/gssapi/generic/util_oid.c b/src/lib/gssapi/generic/util_oid.c
index 91bb544ed..8843a7ff6 100644
--- a/src/lib/gssapi/generic/util_oid.c
+++ b/src/lib/gssapi/generic/util_oid.c
@@ -22,6 +22,10 @@
#include "gssapiP_generic.h"
+/*
+ * $Id$
+ */
+
int
g_copy_OID_set(in, out)
const gss_OID_set_desc * const in;
diff --git a/src/lib/gssapi/generic/util_token.c b/src/lib/gssapi/generic/util_token.c
index e440d907a..027d2a765 100644
--- a/src/lib/gssapi/generic/util_token.c
+++ b/src/lib/gssapi/generic/util_token.c
@@ -23,11 +23,9 @@
#include "gssapiP_generic.h"
#include <memory.h>
-#if (SIZEOF_INT == 2)
-#define VALID_INT_BITS 0x7fff
-#elif (SIZEOF_INT == 4)
-#define VALID_INT_BITS 0x7fffffff
-#endif
+/*
+ * $Id$
+ */
/* XXXX this code currently makes the assumption that a mech oid will
never be longer than 127 bytes. This assumption is not inherent in
@@ -153,58 +151,68 @@ void g_make_token_header(mech, body_size, buf, tok_type)
*(*buf)++ = (unsigned char) (tok_type&0xff);
}
-/* given a buffer containing a token, reads and verifies the token,
- leaving buf advanced past the token header, and setting body_size
- to the number of remaining bytes */
-
-int g_verify_token_header(mech, body_size, buf, tok_type, toksize)
+/*
+ * Given a buffer containing a token, reads and verifies the token,
+ * leaving buf advanced past the token header, and setting body_size
+ * to the number of remaining bytes. Returns 0 on success,
+ * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
+ * mechanism in the token does not match the mech argument. buf and
+ * *body_size are left unmodified on error.
+ */
+int g_verify_token_header(mech, body_size, buf_in, tok_type, toksize)
gss_OID mech;
int *body_size;
- unsigned char **buf;
+ unsigned char **buf_in;
int tok_type;
int toksize;
{
+ char *buf = *buf_in;
int seqsize;
gss_OID_desc toid;
+ int ret = 0;
if ((toksize-=1) < 0)
- return(0);
- if (*(*buf)++ != 0x60)
- return(0);
+ return(G_BAD_TOK_HEADER);
+ if (*buf++ != 0x60)
+ return(G_BAD_TOK_HEADER);
- if ((seqsize = der_read_length(buf, &toksize)) < 0)
- return(0);
+ if ((seqsize = der_read_length(&buf, &toksize)) < 0)
+ return(G_BAD_TOK_HEADER);
if (seqsize != toksize)
- return(0);
+ return(G_BAD_TOK_HEADER);
if ((toksize-=1) < 0)
- return(0);
- if (*(*buf)++ != 0x06)
- return(0);
+ return(G_BAD_TOK_HEADER);
+ if (*buf++ != 0x06)
+ return(G_BAD_TOK_HEADER);
if ((toksize-=1) < 0)
- return(0);
- toid.length = *(*buf)++;
-
- if ((toid.length & VALID_INT_BITS) != toid.length) /* Overflow??? */
- return(0);
- if ((toksize-= (int) toid.length) < 0)
- return(0);
- toid.elements = *buf;
- (*buf)+=toid.length;
-
- if (! g_OID_equal(&toid, mech))
- return(0);
+ return(G_BAD_TOK_HEADER);
+ toid.length = *buf++;
+
+ if ((toksize-=toid.length) < 0)
+ return(G_BAD_TOK_HEADER);
+ toid.elements = buf;
+ buf+=toid.length;
+
+ if (! g_OID_equal(&toid, mech))
+ ret = G_WRONG_MECH;
+ /* G_WRONG_MECH is not returned immediately because it's more important
+ to return G_BAD_TOK_HEADER if the token header is in fact bad */
+
if ((toksize-=2) < 0)
- return(0);
+ return(G_BAD_TOK_HEADER);
- if ((*(*buf)++ != ((tok_type>>8)&0xff)) ||
- (*(*buf)++ != (tok_type&0xff)))
- return(0);
+ if ((*buf++ != ((tok_type>>8)&0xff)) ||
+ (*buf++ != (tok_type&0xff)))
+ return(G_BAD_TOK_HEADER);
- *body_size = toksize;
+ if (!ret) {
+ *buf_in = buf;
+ *body_size = toksize;
+ }
- return(1);
+ return(ret);
}
diff --git a/src/lib/gssapi/generic/util_validate.c b/src/lib/gssapi/generic/util_validate.c
index 72631341b..63f552859 100644
--- a/src/lib/gssapi/generic/util_validate.c
+++ b/src/lib/gssapi/generic/util_validate.c
@@ -21,6 +21,10 @@
*/
/*
+ * $Id$
+ */
+
+/*
* functions to validate name, credential, and context handles
*/
@@ -30,24 +34,31 @@
#include <sys/file.h>
#include <fcntl.h>
#include <limits.h>
+#ifdef HAVE_BSD_DB
#include <db.h>
-#define V_NAME 1
-#define V_CRED_ID 2
-#define V_CTX_ID 3
+static const int one = 1;
+static const DBT dbtone = { (void *) &one, sizeof(one) };
typedef struct _vkey {
int type;
void *ptr;
} vkey;
+#endif
-static const int one = 1;
-static const DBT dbtone = { (void *) &one, sizeof(one) };
+#define V_NAME 1
+#define V_CRED_ID 2
+#define V_CTX_ID 3
/* All these functions return 0 on failure, and non-zero on success */
-static int g_save(DB **vdb, int type, void *ptr)
+static int g_save(db, type, ptr)
+ void **db;
+ int type;
+ void *ptr;
{
+#ifdef HAVE_BSD_DB
+ DB **vdb = (DB **) db;
vkey vk;
DBT key;
@@ -61,10 +72,24 @@ static int g_save(DB **vdb, int type, void *ptr)
key.size = sizeof(vk);
return((*((*vdb)->put))(*vdb, &key, &dbtone, 0) == 0);
+#else
+ g_set *gs = (g_set *) db;
+
+ if (!*gs)
+ if (g_set_init(gs))
+ return(0);
+
+ return(g_set_entry_add(gs, ptr, (void *) type) == 0);
+#endif
}
-static int g_validate(DB **vdb, int type, void *ptr)
+static int g_validate(db, type, ptr)
+ void **db;
+ int type;
+ void *ptr;
{
+#ifdef HAVE_BSD_DB
+ DB **vdb = (DB **) db;
vkey vk;
DBT key, value;
@@ -82,10 +107,27 @@ static int g_validate(DB **vdb, int type, void *ptr)
return((value.size == sizeof(one)) &&
(*((int *) value.data) == one));
+#else
+ g_set *gs = (g_set *) db;
+ void *value;
+
+ if (!*gs)
+ return(0);
+
+ if (g_set_entry_get(gs, ptr, (void **) &value))
+ return(0);
+
+ return(((int) value) == type);
+#endif
}
-static int g_delete(DB **vdb, int type, void *ptr)
+static int g_delete(db, type, ptr)
+ void **db;
+ int type;
+ void *ptr;
{
+#ifdef HAVE_BSD_DB
+ DB **vdb = (DB **) db;
vkey vk;
DBT key;
@@ -99,52 +141,81 @@ static int g_delete(DB **vdb, int type, void *ptr)
key.size = sizeof(vk);
return((*((*vdb)->del))(*vdb, &key, 0) == 0);
+#else
+ g_set *gs = (g_set *) db;
+
+ if (!*gs)
+ return(0);
+
+ if (g_set_entry_delete(gs, ptr))
+ return(0);
+
+ return(1);
+#endif
}
/* functions for each type */
/* save */
-int g_save_name(void **vdb, gss_name_t *name)
+int g_save_name(vdb, name)
+ void **vdb;
+ gss_name_t *name;
{
- return(g_save((DB **) vdb, V_NAME, (void *) name));
+ return(g_save(vdb, V_NAME, (void *) name));
}
-int g_save_cred_id(void **vdb, gss_cred_id_t *cred)
+int g_save_cred_id(vdb, cred)
+ void **vdb;
+ gss_cred_id_t *cred;
{
- return(g_save((DB **) vdb, V_CRED_ID, (void *) cred));
+ return(g_save(vdb, V_CRED_ID, (void *) cred));
}
-int g_save_ctx_id(void **vdb, gss_ctx_id_t *ctx)
+int g_save_ctx_id(vdb, ctx)
+ void **vdb;
+ gss_ctx_id_t *ctx;
{
- return(g_save((DB **) vdb, V_CTX_ID, (void *) ctx));
+ return(g_save(vdb, V_CTX_ID, (void *) ctx));
}
/* validate */
-int g_validate_name(void **vdb, gss_name_t *name)
+int g_validate_name(vdb, name)
+ void **vdb;
+ gss_name_t *name;
{
- return(g_validate((DB **) vdb, V_NAME, (void *) name));
+ return(g_validate(vdb, V_NAME, (void *) name));
}
-int g_validate_cred_id(void **vdb, gss_cred_id_t *cred)
+int g_validate_cred_id(vdb, cred)
+ void **vdb;
+ gss_cred_id_t *cred;
{
- return(g_validate((DB **) vdb, V_CRED_ID, (void *) cred));
+ return(g_validate(vdb, V_CRED_ID, (void *) cred));
}
-int g_validate_ctx_id(void **vdb, gss_ctx_id_t *ctx)
+int g_validate_ctx_id(vdb, ctx)
+ void **vdb;
+ gss_ctx_id_t *ctx;
{
- return(g_validate((DB **) vdb, V_CTX_ID, (void *) ctx));
+ return(g_validate(vdb, V_CTX_ID, (void *) ctx));
}
/* delete */
-int g_delete_name(void **vdb, gss_name_t *name)
+int g_delete_name(vdb, name)
+ void **vdb;
+ gss_name_t *name;
{
- return(g_delete((DB **) vdb, V_NAME, (void *) name));
+ return(g_delete(vdb, V_NAME, (void *) name));
}
-int g_delete_cred_id(void **vdb, gss_cred_id_t *cred)
+int g_delete_cred_id(vdb, cred)
+ void **vdb;
+ gss_cred_id_t *cred;
{
- return(g_delete((DB **) vdb, V_CRED_ID, (void *) cred));
+ return(g_delete(vdb, V_CRED_ID, (void *) cred));
}
-int g_delete_ctx_id(void **vdb, gss_ctx_id_t *ctx)
+int g_delete_ctx_id(vdb, ctx)
+ void **vdb;
+ gss_ctx_id_t *ctx;
{
- return(g_delete((DB **) vdb, V_CTX_ID, (void *) ctx));
+ return(g_delete(vdb, V_CTX_ID, (void *) ctx));
}
diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog
index 73a09c111..a996733e6 100644
--- a/src/lib/gssapi/krb5/ChangeLog
+++ b/src/lib/gssapi/krb5/ChangeLog
@@ -1,3 +1,43 @@
+Thu Jul 18 19:48:48 1996 Marc Horowitz <marc@mit.edu>
+
+ * init_sec_context.c (krb5_gss_init_sec_context),
+ accept_sec_context.c (krb5_gss_accept_sec_context): ifdef'd out
+ reference to 3des.
+
+Fri Jul 5 15:27:29 1996 Marc Horowitz <marc@mit.edu>
+
+ * gssapi_krb5.h: Add declarations for _old mech set, and _both
+ mech set
+
+Thu Jun 20 23:15:57 1996 Marc Horowitz <marc@mit.edu>
+
+ * ser_sctx.c (kg_oid_size, kg_ctx_size): pull the oid-related code
+ out of kg_ctx_size into kg_oid_size.
+
+ * k5unseal.c (kg_unseal), k5seal.c (make_seal_token): == cannot be
+ used to compare oid's. The g_OID_equal macro must be used.
+
+ * init_sec_context.c (make_ap_req, krb5_gss_init_sec_context): -
+ gss_init_sec_context should use the mech set in the credential.
+ If the default mech is requested, but the old mech oid was
+ explicitly passed to gss_acquire_cred, then the context should be
+ the old mech, otherwise, the new mech. If a mech was requested
+ explicitly, then the code should insure that the credential is
+ compatible.
+
+ * acquire_cred.c (krb5_gss_acquire_cred), gssapiP_krb5.h (struct
+ _krb5_gss_cred_it_rec), gssapi_krb5.c (gss_mech_set_krb5*),
+ inq_cred.c (krb5_gss_inquire_cred): gss_acquire_cred needs to be
+ able to deal with both mech oid's. It should return in
+ actual_mechs the intersection of the set passed in and the
+ {old,new} mechs, or if the default was requested, it should return
+ both mech oid's. This state should be stored in the credential
+ handle, and regurgitated by gss_inquire_cred.
+
+ * accept_sec_context.c (krb5_gss_accept_sec_context): make sure
+ that the oid in the token is compatible with the mechanisms
+ specified by the credential.
+
Thu Jun 13 22:11:30 1996 Tom Yu <tlyu@voltage-multiplier.mit.edu>
* configure.in: remove ref to ET_RULES
@@ -29,6 +69,63 @@ Tue May 14 04:42:11 1996 Theodore Y. Ts'o <tytso@mit.edu>
krb5_auth_con_setcksumtype to use
krb5_auth_con_set_req_cksumtype by default instead.
+Sun May 12 00:54:35 1996 Marc Horowitz <marc@mit.edu>
+
+ * util_crypt.c (kg_encrypt): It used to be that krb5_encrypt could
+ be used to encrypt in place. That's broken now. This would need
+ to be fixed in several places in the crypto layer, and it's not
+ clear what the right thing is, so it's worked around here in the
+ interests of portability and reliablility, at the expense of a
+ malloc/memcpy/free.
+
+ * Makefile.in, configure.in: gssapi_krb5.h should be installed
+ inside the tree. This is really only half the work, as it should
+ be installed outside of the tree, too.
+
+Sat Apr 20 00:02:51 1996 Marc Horowitz <marc@mit.edu>
+
+ * accept_sec_context.c, export_sec_context.c, gssapiP_krb5.h,
+ import_sec_context.c, init_sec_context.c, k5seal.c, k5unseal.c,
+ ser_sctx.c, wrap_size_limit.c: Implemented triple-des changes
+ based on Richard's patches.
+
+Wed Apr 17 21:08:59 1996 Marc Horowitz <marc@mit.edu>
+
+ * accept_sec_context.c (krb5_gss_set_backward_mode): removed
+
+ * krb5_gss_glue.c, wrap_size_limit.c: added
+
+ * import_sec_context.c: intern the newly created context id so
+ that the validation functions will accept it.
+
+ * Makefile.in (CFLAGS): Don't need md5 header files anymore.
+ (OBJS, SRCS): Change the list of files to build.
+
+ * export_sec_context.c, import_sec_context.c, gssapiP_krb5.h,
+ ser_sctx.c: don't use the serialization abstraction, since it
+ doesn't add anything, and is internal to kerberos. Instead, make
+ the {de,}serialization functions internal gssapi functions, and
+ call those directly.
+
+ * accept_sec_context.c, acquire_cred.c, context_time.c,
+ delete_sec_context.c, disp_name.c, disp_status.c,
+ export_sec_context.c, gssapi_krb5.c (kg_get_context),
+ import_name.c, import_sec_context.c, indicate_mechs.c,
+ init_sec_context.c, inq_context.c, inq_cred.c, inq_names.c,
+ process_context_token.c, rel_cred.c, rel_name.c, seal.c, sign.c,
+ unseal.c, verify.c:
+ Don't pass in the context from the caller. Instead, call
+ kg_get_context() to find out the kerberos library context. Also,
+ random minor compile-time fixes.
+
+ * accept_sec_context.c, gssapi_krb5.c (kg_get_defcred),
+ gssapiP_krb5.h, init_sec_context.c, k5seal.c, k5unseal.c,
+ util_cksum.c (kg_checksum_channel_bindings), util_seqnum.c
+ (kg_make_seq_num, kg_get_seq_num), util_seed.c (kg_make_seed),
+ util_crypt.c (kg_encrypt, kg_decrypt):
+ pass the context to the kg_* functions which need it instead of
+ determining it directly.
+
Fri Apr 12 21:47:46 1996 Richard Basch <basch@lehman.com>
* k5seal.c k5unseal.c:
diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in
index d5061fa14..4a18efeea 100644
--- a/src/lib/gssapi/krb5/Makefile.in
+++ b/src/lib/gssapi/krb5/Makefile.in
@@ -1,4 +1,4 @@
-CFLAGS = $(CCOPTS) $(DEFS) -I. -I$(srcdir) -I../generic -I$(srcdir)/../generic -I$(srcdir)/../../crypto/md5 -DUSE_AUTOCONF_H
+CFLAGS = $(CCOPTS) $(DEFS) -I. -I$(srcdir) -I../generic -I$(srcdir)/../generic -DUSE_AUTOCONF_H
##DOSBUILDTOP = ..\..\..
##DOSLIBNAME=..\gssapi.$(LIBEXT)
@@ -50,12 +50,10 @@ SRCS = \
$(srcdir)/inq_names.c \
$(srcdir)/k5seal.c \
$(srcdir)/k5unseal.c \
- $(srcdir)/k5mech.c \
- $(srcdir)/pname_to_uid.c \
+ $(srcdir)/krb5_gss_glue.c \
$(srcdir)/process_context_token.c \
$(srcdir)/rel_cred.c \
$(srcdir)/rel_name.c \
- $(srcdir)/rel_oid.c \
$(srcdir)/seal.c \
$(srcdir)/ser_sctx.c \
$(srcdir)/sign.c \
@@ -65,8 +63,13 @@ SRCS = \
$(srcdir)/util_seed.c \
$(srcdir)/util_seqnum.c \
$(srcdir)/verify.c \
+ $(srcdir)/wrap_size_limit.c \
gssapi_err_krb5.c
+# $(srcdir)/pname_to_uid.c \
+# $(srcdir)/k5mech.c \
+# $(srcdir)/rel_oid.c
+
OBJS = \
accept_sec_context.$(OBJEXT) \
acquire_cred.$(OBJEXT) \
@@ -87,12 +90,10 @@ OBJS = \
inq_names.$(OBJEXT) \
k5seal.$(OBJEXT) \
k5unseal.$(OBJEXT) \
- k5mech.$(OBJEXT) \
- pname_to_uid.$(OBJEXT) \
+ krb5_gss_glue.$(OBJEXT) \
process_context_token.$(OBJEXT) \
rel_cred.$(OBJEXT) \
rel_name.$(OBJEXT) \
- rel_oid.$(OBJEXT) \
seal.$(OBJEXT) \
ser_sctx.$(OBJEXT) \
sign.$(OBJEXT) \
@@ -102,15 +103,23 @@ OBJS = \
util_seed.$(OBJEXT) \
util_seqnum.$(OBJEXT) \
verify.$(OBJEXT) \
+ wrap_size_limit.$(OBJEXT) \
gssapi_err_krb5.$(OBJEXT)
+# k5mech.$(OBJEXT) \
+# pname_to_uid.$(OBJEXT) \
+# rel_oid.$(OBJEXT)
+
HDRS= $(ETHDRS)
EHDRDIR=$(TOP)/include/gssapi
+EXPORTED_HEADERS= gssapi_krb5.h
all-unix:: $(SRCS) $(HDRS) includes $(OBJS)
all-mac:: $(SRCS) $(HDRS) includes $(OBJS)
all-windows:: $(SRCS) $(HDRS) includes $(OBJS)
+ if not exist $(EHDRDIR)\nul mkdir $(EHDRDIR)
+ copy gssapi_krb5.h $(EHDRDIR)
clean-unix::
$(RM) $(ETHDRS) $(ETSRCS) shared/*
@@ -119,6 +128,14 @@ clean-mac::
$(RM) $(ETHDRS) $(ETSRCS) shared/*
clean-windows::
+ $(RM) $(EHDRDIR)\gssapi_krb5.h
+ if exist $(EHDRDIR)\nul rmdir $(EHDRDIR)
+
+install::
+ @set -x; for f in $(EXPORTED_HEADERS) ; \
+ do $(INSTALL_DATA) $(srcdir)/$$f \
+ $(DESTDIR)$(KRB5_INCDIR)/gssapi/$$f ; \
+ done
depend:: $(ETSRCS)
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index 79d41b71d..09ed41247 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -21,9 +21,40 @@
*/
#include "gssapiP_krb5.h"
-#include "rsa-md5.h"
#include <memory.h>
+/*
+ * $Id$
+ */
+
+#if 0
+
+/* XXXX This widen/narrow stuff is bletcherous, but it seems to be
+ necessary. Perhaps there is a "better" way, but I don't know what it
+ is */
+
+#include <krb5/widen.h>
+static krb5_error_code
+rd_req_keyproc(krb5_pointer keyprocarg, krb5_principal server,
+ krb5_kvno kvno, krb5_keyblock **keyblock)
+#include <krb5/narrow.h>
+{
+ krb5_error_code code;
+ krb5_keytab_entry ktentry;
+
+ if (code = krb5_kt_get_entry((krb5_keytab) keyprocarg, server, kvno,
+ &ktentry))
+ return(code);
+
+ code = krb5_copy_keyblock(&ktentry.key, keyblock);
+
+ (void) krb5_kt_free_entry(&ktentry);
+
+ return(code);
+}
+
+#endif
+
/* Decode, decrypt and store the forwarded creds in the local ccache. */
static krb5_error_code
rd_and_store_for_creds(context, auth_context, inbuf)
@@ -56,12 +87,11 @@ cleanup:
}
OM_uint32
-krb5_gss_accept_sec_context(ct, minor_status, context_handle,
+krb5_gss_accept_sec_context(minor_status, context_handle,
verifier_cred_handle, input_token,
input_chan_bindings, src_name, mech_type,
output_token, ret_flags, time_rec,
delegated_cred_handle)
- void *ct;
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_cred_id_t verifier_cred_handle;
@@ -74,7 +104,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
OM_uint32 *time_rec;
gss_cred_id_t *delegated_cred_handle;
{
- krb5_context context = ct;
+ krb5_context context;
unsigned char *ptr, *ptr2;
char *sptr;
long tmp;
@@ -89,14 +119,20 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
krb5_principal name;
int gss_flags;
krb5_gss_ctx_id_rec *ctx;
+ krb5_enctype enctype;
krb5_timestamp now;
gss_buffer_desc token;
+ int err;
krb5_auth_context auth_context = NULL;
krb5_ticket * ticket = NULL;
int option_id;
krb5_data option;
krb5_auth_context auth_context_cred = NULL;
+ const gss_OID_desc *mech_used = NULL;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
/* set up returns to be freeable */
@@ -141,14 +177,43 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
return(GSS_S_NO_CRED);
}
- /* verify the token's integrity, and leave the token in ap_req */
+ /* verify the token's integrity, and leave the token in ap_req.
+ figure out which mech oid was used, and save it */
ptr = (unsigned char *) input_token->value;
- if (! g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ, input_token->length)) {
- *minor_status = 0;
- return(GSS_S_DEFECTIVE_TOKEN);
+ if (err = g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_req.length),
+ &ptr, KG_TOK_CTX_AP_REQ,
+ input_token->length)) {
+ /*
+ * Previous versions of this library used the old mech_id
+ * and some broken behavior (wrong IV on checksum
+ * encryption). We support the old mech_id for
+ * compatibility, and use it to decide when to use the
+ * old behavior.
+ */
+ if (err != G_WRONG_MECH ||
+ (err = g_verify_token_header((gss_OID) gss_mech_krb5_old,
+ &(ap_req.length),
+ &ptr, KG_TOK_CTX_AP_REQ,
+ input_token->length))) {
+ *minor_status = err;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ } else {
+ if (! cred->prerfc_mech) {
+ *minor_status = G_WRONG_MECH;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ mech_used = gss_mech_krb5_old;
+ }
+ } else {
+ if (! cred->rfc_mech) {
+ *minor_status = G_WRONG_MECH;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ mech_used = gss_mech_krb5;
}
sptr = (char *) ptr;
@@ -180,6 +245,17 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
krb5_auth_con_getauthenticator(context, auth_context, &authdat);
+#if 0
+ /* make sure the necessary parts of the authdat are present */
+
+ if ((authdat->authenticator->subkey == NULL) ||
+ (authdat->ticket->enc_part2 == NULL)) {
+ krb5_free_tkt_authent(authdat);
+ *minor_status = KG_NO_SUBKEY;
+ return(GSS_S_FAILURE);
+ }
+#endif
+
/* verify that the checksum is correct */
/*
@@ -210,13 +286,13 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
TREAD_INT(ptr, tmp, bigend);
- if (tmp != RSA_MD5_CKSUM_LENGTH) {
+ if (tmp != krb5_checksum_size(context, CKSUMTYPE_RSA_MD5)) {
ptr = (unsigned char *) authdat->checksum->contents;
bigend = 1;
TREAD_INT(ptr, tmp, bigend);
- if (tmp != RSA_MD5_CKSUM_LENGTH) {
+ if (tmp != krb5_checksum_size(context, CKSUMTYPE_RSA_MD5)) {
xfree(md5.contents);
krb5_free_authenticator(context, authdat);
*minor_status = KG_BAD_LENGTH;
@@ -226,7 +302,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
/* at this point, bigend is set according to the initiator's byte order */
- if ((code = kg_checksum_channel_bindings(input_chan_bindings, &md5,
+ if ((code = kg_checksum_channel_bindings(context, input_chan_bindings, &md5,
bigend))) {
krb5_free_authenticator(context, authdat);
*minor_status = code;
@@ -289,21 +365,13 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
break;
- default :
+ /* default: */
+ /* unknown options aren't an error */
- /* any other options are unrecognized. return
- generic GSS_C_FAILURE error with a minor status
- of KRB5_PARSE_MALFORMED (XXX this is probably
- not the right error, since it is used for
- string parsing errors not token parsing errors.) */
-
- *minor_status = KRB5_PARSE_MALFORMED;
- return(GSS_S_FAILURE);
} /* switch */
} /* while */
} /* if */
-
/* create the ctx struct and start filling it in */
if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
@@ -313,6 +381,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
}
memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+ ctx->mech_used = mech_used;
ctx->auth_context = auth_context;
ctx->initiate = 0;
ctx->gss_flags = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG |
@@ -345,20 +414,42 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
return(GSS_S_FAILURE);
}
+ switch(ctx->subkey->enctype) {
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ enctype = ENCTYPE_DES_CBC_RAW;
+ ctx->signalg = 0;
+ ctx->cksum_size = 8;
+ ctx->sealalg = 0;
+ break;
+#if 0
+ case ENCTYPE_DES3_CBC_MD5:
+ enctype = ENCTYPE_DES3_CBC_RAW;
+ ctx->signalg = 3;
+ ctx->cksum_size = 16;
+ ctx->sealalg = 1;
+ break;
+#endif
+ default:
+ return GSS_S_FAILURE;
+ }
+
/* fill in the encryption descriptors */
- krb5_use_enctype(context, &ctx->enc.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->enc.eblock, enctype);
ctx->enc.processed = 0;
- if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
+
+ if (code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key))
return(code);
for (i=0; i<ctx->enc.key->length; i++)
/*SUPPRESS 113*/
ctx->enc.key->contents[i] ^= 0xf0;
- krb5_use_enctype(context, &ctx->seq.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->seq.eblock, enctype);
ctx->seq.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
return(code);
+
ctx->endtime = ticket->enc_part2->times.endtime;
ctx->flags = ticket->enc_part2->flags;
@@ -366,6 +457,10 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
krb5_auth_con_getremoteseqnumber(context, auth_context, &ctx->seq_recv);
+ g_order_init(&(ctx->seqstate), ctx->seq_recv,
+ gss_flags & GSS_C_REPLAY_FLAG,
+ gss_flags & GSS_C_SEQUENCE_FLAG);
+
/* at this point, the entire context structure is filled in,
so it can be released. */
@@ -375,23 +470,23 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
krb5_data ap_rep;
unsigned char * ptr;
if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
*minor_status = code;
return(GSS_S_FAILURE);
}
krb5_auth_con_getlocalseqnumber(context, auth_context, &ctx->seq_send);
- token.length = g_token_size((gss_OID) gss_mech_krb5, ap_rep.length);
+ token.length = g_token_size((gss_OID) mech_used, ap_rep.length);
if ((token.value = (unsigned char *) xmalloc(token.length)) == NULL) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
- *minor_status = code;
+ *minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
ptr = token.value;
- g_make_token_header((gss_OID) gss_mech_krb5, ap_rep.length,
- &ptr, KG_TOK_CTX_AP_REP);
+ g_make_token_header((gss_OID) mech_used, ap_rep.length,
+ &ptr, KG_TOK_CTX_AP_REP);
TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
xfree(ap_rep.data);
@@ -410,7 +505,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
if ((code = krb5_copy_principal(context, ctx->there, &name))) {
if (token.value)
xfree(token.value);
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
*minor_status = code;
return(GSS_S_FAILURE);
@@ -418,14 +513,14 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
}
if (mech_type)
- *mech_type = (gss_OID) gss_mech_krb5;
+ *mech_type = (gss_OID) mech_used;
if (time_rec) {
if ((code = krb5_timeofday(context, &now))) {
if (src_name)
krb5_free_principal(context, name);
xfree(token.value);
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
*minor_status = code;
return(GSS_S_FAILURE);
@@ -434,7 +529,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
}
if (ret_flags)
- *ret_flags = ctx->gss_flags;
+ *ret_flags = KG_IMPLFLAGS(gss_flags);
ctx->established = 1;
@@ -445,7 +540,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
krb5_free_principal(context, name);
if (token.value)
xfree(token.value);
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_FAILURE);
@@ -460,7 +555,7 @@ krb5_gss_accept_sec_context(ct, minor_status, context_handle,
}
if (token.value)
xfree(token.value);
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_FAILURE);
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 526e6dddb..b2d6ce111 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -27,6 +27,10 @@
#include <strings.h>
#endif
+/*
+ * $Id$
+ */
+
/* get credentials corresponding to a key in the krb5 keytab.
If the default name is requested, return the name in output_princ.
If output_princ is non-NULL, the caller will use or free it, regardless
@@ -35,14 +39,13 @@
*/
static OM_uint32
-acquire_accept_cred(ctx, minor_status, desired_name, output_princ, cred)
- void *ctx;
+acquire_accept_cred(context, minor_status, desired_name, output_princ, cred)
+ krb5_context context;
OM_uint32 *minor_status;
gss_name_t desired_name;
krb5_principal *output_princ;
krb5_gss_cred_id_rec *cred;
{
- krb5_context context = ctx;
krb5_error_code code;
krb5_principal princ;
krb5_keytab kt;
@@ -65,6 +68,7 @@ acquire_accept_cred(ctx, minor_status, desired_name, output_princ, cred)
if (desired_name == (gss_name_t) NULL) {
if (code = krb5_sname_to_principal(context, NULL, NULL, KRB5_NT_SRV_HST,
&princ)) {
+ (void) krb5_kt_close(context, kt);
*minor_status = code;
return(GSS_S_FAILURE);
}
@@ -76,6 +80,7 @@ acquire_accept_cred(ctx, minor_status, desired_name, output_princ, cred)
/* iterate over the keytab searching for the principal */
if (code = krb5_kt_start_seq_get(context, kt, &cur)) {
+ (void) krb5_kt_close(context, kt);
*minor_status = code;
return(GSS_S_FAILURE);
}
@@ -92,16 +97,19 @@ acquire_accept_cred(ctx, minor_status, desired_name, output_princ, cred)
if (code == KRB5_KT_END) {
/* this means that the principal wasn't in the keytab */
(void)krb5_kt_end_seq_get(context, kt, &cur);
+ (void) krb5_kt_close(context, kt);
*minor_status = KG_KEYTAB_NOMATCH;
return(GSS_S_CRED_UNAVAIL);
} else if (code) {
/* this means some error occurred reading the keytab */
(void)krb5_kt_end_seq_get(context, kt, &cur);
+ (void) krb5_kt_close(context, kt);
*minor_status = code;
return(GSS_S_FAILURE);
} else {
/* this means that we found a matching entry */
if (code = krb5_kt_end_seq_get(context, kt, &cur)) {
+ (void) krb5_kt_close(context, kt);
*minor_status = code;
return(GSS_S_FAILURE);
}
@@ -204,7 +212,6 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
if (got_endtime == 0) {
cred->tgt_expire = creds.times.endtime;
got_endtime = 1;
- *minor_status = KG_TGT_MISSING;
}
krb5_free_cred_contents(context, &creds);
}
@@ -215,6 +222,12 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
(void)krb5_cc_close(context, ccache);
*minor_status = code;
return(GSS_S_FAILURE);
+ } else if (! got_endtime) {
+ /* this means the ccache was entirely empty */
+ (void)krb5_cc_end_seq_get(context, ccache, &cur);
+ (void)krb5_cc_close(context, ccache);
+ *minor_status = KG_EMPTY_CCACHE;
+ return(GSS_S_FAILURE);
} else {
/* this means that we found an endtime to use. */
if (code = krb5_cc_end_seq_get(context, ccache, &cur)) {
@@ -239,10 +252,9 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
/*ARGSUSED*/
OM_uint32
-krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
+krb5_gss_acquire_cred(minor_status, desired_name, time_req,
desired_mechs, cred_usage, output_cred_handle,
actual_mechs, time_rec)
- void *ctx;
OM_uint32 *minor_status;
gss_name_t desired_name;
OM_uint32 time_req;
@@ -252,13 +264,17 @@ krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
gss_OID_set *actual_mechs;
OM_uint32 *time_rec;
{
- krb5_context context = ctx;
+ krb5_context context;
size_t i;
krb5_gss_cred_id_t cred;
- gss_OID_set mechs;
+ gss_OID_set valid_mechs, ret_mechs;
+ int req_old, req_new;
OM_uint32 ret;
krb5_error_code code;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/* make sure all outputs are valid */
*output_cred_handle = NULL;
@@ -279,11 +295,26 @@ krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
/* verify that the requested mechanism set is the default, or
contains krb5 */
- if (desired_mechs != GSS_C_NULL_OID_SET) {
- for (i=0; i<desired_mechs->count; i++)
+ if (desired_mechs == GSS_C_NULL_OID_SET) {
+ valid_mechs = gss_mech_set_krb5_both;
+ } else {
+ req_old = 0;
+ req_new = 0;
+
+ for (i=0; i<desired_mechs->count; i++) {
+ if (g_OID_equal(gss_mech_krb5_old, &(desired_mechs->elements[i])))
+ req_old++;
if (g_OID_equal(gss_mech_krb5, &(desired_mechs->elements[i])))
- break;
- if (i == desired_mechs->count) {
+ req_new++;
+ }
+
+ if (req_old && req_new) {
+ valid_mechs = gss_mech_set_krb5_both;
+ } else if (req_old) {
+ valid_mechs = gss_mech_set_krb5_old;
+ } else if (req_new) {
+ valid_mechs = gss_mech_set_krb5;
+ } else {
*minor_status = 0;
return(GSS_S_BAD_MECH);
}
@@ -300,6 +331,9 @@ krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
cred->usage = cred_usage;
cred->princ = NULL;
+ cred->actual_mechs = valid_mechs;
+ cred->prerfc_mech = req_old;
+ cred->rfc_mech = req_new;
cred->keytab = NULL;
cred->ccache = NULL;
@@ -390,7 +424,7 @@ krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
/* create mechs */
if (actual_mechs) {
- if (! g_copy_OID_set(gss_mech_set_krb5, &mechs)) {
+ if (! g_copy_OID_set(cred->actual_mechs, &ret_mechs)) {
if (cred->ccache)
(void)krb5_cc_close(context, cred->ccache);
if (cred->keytab)
@@ -406,8 +440,8 @@ krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
/* intern the credential handle */
if (! kg_save_cred_id((gss_cred_id_t) cred)) {
- free(mechs->elements);
- free(mechs);
+ free(ret_mechs->elements);
+ free(ret_mechs);
if (cred->ccache)
(void)krb5_cc_close(context, cred->ccache);
if (cred->keytab)
@@ -424,19 +458,18 @@ krb5_gss_acquire_cred(ctx, minor_status, desired_name, time_req,
*minor_status = 0;
*output_cred_handle = (gss_cred_id_t) cred;
if (actual_mechs)
- *actual_mechs = mechs;
+ *actual_mechs = ret_mechs;
return(GSS_S_COMPLETE);
}
/* V2 interface */
OM_uint32
-krb5_gss_add_cred(ctx, minor_status, input_cred_handle,
+krb5_gss_add_cred(minor_status, input_cred_handle,
desired_name, desired_mech, cred_usage,
initiator_time_req, acceptor_time_req,
output_cred_handle, actual_mechs,
initiator_time_rec, acceptor_time_rec)
- void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t input_cred_handle;
gss_name_t desired_name;
@@ -449,12 +482,19 @@ krb5_gss_add_cred(ctx, minor_status, input_cred_handle,
OM_uint32 *initiator_time_rec;
OM_uint32 *acceptor_time_rec;
{
- krb5_context context = ctx;
/*
- * This does not apply to our single-mechanism implementation. Until we
- * come up with a better error code, return failure.
+ * This does not apply to our single-mechanism implementation. Decide
+ * if the correct error is BAD_MECH or DUPLICATE_ELEMENT.
*/
+
+ /* verify that the requested mechanism is the default, or
+ is krb5 */
+
+ if ((desired_mech != GSS_C_NULL_OID) &&
+ (g_OID_equal(desired_mech, gss_mech_krb5)))
+ return(GSS_S_BAD_MECH);
+
*minor_status = 0;
- return(GSS_S_FAILURE);
+ return(GSS_S_DUPLICATE_ELEMENT);
}
diff --git a/src/lib/gssapi/krb5/compare_name.c b/src/lib/gssapi/krb5/compare_name.c
index 19b94f452..75a534220 100644
--- a/src/lib/gssapi/krb5/compare_name.c
+++ b/src/lib/gssapi/krb5/compare_name.c
@@ -20,17 +20,24 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_compare_name(ctx, minor_status, name1, name2, name_equal)
- void *ctx;
+krb5_gss_compare_name(minor_status, name1, name2, name_equal)
OM_uint32 *minor_status;
gss_name_t name1;
gss_name_t name2;
int *name_equal;
{
- krb5_context context = ctx;
+ krb5_context context;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if (! kg_validate_name(name1)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
diff --git a/src/lib/gssapi/krb5/configure.in b/src/lib/gssapi/krb5/configure.in
index d5fc0695f..a05531893 100644
--- a/src/lib/gssapi/krb5/configure.in
+++ b/src/lib/gssapi/krb5/configure.in
@@ -4,4 +4,5 @@ AC_PROG_AWK
AC_CHECK_HEADERS(stdlib.h)
V5_SHARED_LIB_OBJS
SubdirLibraryRule([${OBJS}])
+CopySrcHeader(gssapi_krb5.h,[$](BUILDTOP)/include/gssapi)
V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/gssapi/krb5/context_time.c b/src/lib/gssapi/krb5/context_time.c
index 3bc42e603..76f1489b7 100644
--- a/src/lib/gssapi/krb5/context_time.c
+++ b/src/lib/gssapi/krb5/context_time.c
@@ -22,19 +22,25 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_context_time(ct, minor_status, context_handle, time_rec)
- void *ct;
+krb5_gss_context_time(minor_status, context_handle, time_rec)
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
OM_uint32 *time_rec;
{
- krb5_context context = ct;
+ krb5_context context;
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
krb5_timestamp now;
krb5_deltat lifetime;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/* validate the context handle */
if (! kg_validate_ctx_id(context_handle)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
diff --git a/src/lib/gssapi/krb5/delete_sec_context.c b/src/lib/gssapi/krb5/delete_sec_context.c
index fded9afa8..5b5ff74fa 100644
--- a/src/lib/gssapi/krb5/delete_sec_context.c
+++ b/src/lib/gssapi/krb5/delete_sec_context.c
@@ -22,16 +22,22 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_delete_sec_context(ct, minor_status, context_handle, output_token)
- void *ct;
+krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_buffer_t output_token;
{
- krb5_context context = ct;
+ krb5_context context;
krb5_gss_ctx_id_rec *ctx;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if (output_token) {
output_token->length = 0;
output_token->value = NULL;
@@ -71,6 +77,9 @@ krb5_gss_delete_sec_context(ct, minor_status, context_handle, output_token)
ctx = (gss_ctx_id_t) *context_handle;
+ if (ctx->seqstate)
+ g_order_free(&(ctx->seqstate));
+
if (ctx->enc.processed)
krb5_finish_key(context, &ctx->enc.eblock);
krb5_free_keyblock(context, ctx->enc.key);
@@ -86,6 +95,8 @@ krb5_gss_delete_sec_context(ct, minor_status, context_handle, output_token)
if (ctx->auth_context)
krb5_auth_con_free(context, ctx->auth_context);
+ /* Zero out context */
+ memset(ctx, 0, sizeof(*ctx));
xfree(ctx);
/* zero the handle itself */
diff --git a/src/lib/gssapi/krb5/disp_name.c b/src/lib/gssapi/krb5/disp_name.c
index a9cbcae06..77f520035 100644
--- a/src/lib/gssapi/krb5/disp_name.c
+++ b/src/lib/gssapi/krb5/disp_name.c
@@ -23,18 +23,20 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_display_name(ctx, minor_status, input_name, output_name_buffer,
+krb5_gss_display_name(minor_status, input_name, output_name_buffer,
output_name_type)
- void *ctx;
OM_uint32 *minor_status;
gss_name_t input_name;
gss_buffer_t output_name_buffer;
gss_OID *output_name_type;
{
- krb5_context context = ctx;
+ krb5_context context;
krb5_error_code code;
char *str;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
output_name_buffer->length = 0;
output_name_buffer->value = NULL;
diff --git a/src/lib/gssapi/krb5/disp_status.c b/src/lib/gssapi/krb5/disp_status.c
index 326d3fc7c..143f7a624 100644
--- a/src/lib/gssapi/krb5/disp_status.c
+++ b/src/lib/gssapi/krb5/disp_status.c
@@ -32,9 +32,8 @@ static int init_et = 0;
/**/
OM_uint32
-krb5_gss_display_status(ctx, minor_status, status_value, status_type,
+krb5_gss_display_status(minor_status, status_value, status_type,
mech_type, message_context, status_string)
- void *ctx;
OM_uint32 *minor_status;
OM_uint32 status_value;
int status_type;
@@ -42,10 +41,13 @@ krb5_gss_display_status(ctx, minor_status, status_value, status_type,
OM_uint32 *message_context;
gss_buffer_t status_string;
{
- krb5_context context = ctx;
+ krb5_context context;
status_string->length = 0;
status_string->value = NULL;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if ((mech_type != GSS_C_NULL_OID) &&
(! g_OID_equal(gss_mech_krb5, mech_type))) {
*minor_status = 0;
diff --git a/src/lib/gssapi/krb5/export_sec_context.c b/src/lib/gssapi/krb5/export_sec_context.c
index 180cc2ef5..fba8a684b 100644
--- a/src/lib/gssapi/krb5/export_sec_context.c
+++ b/src/lib/gssapi/krb5/export_sec_context.c
@@ -28,20 +28,21 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_export_sec_context(ct,
- minor_status, context_handle, interprocess_token)
- void *ct;
+krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
OM_uint32 *minor_status;
gss_ctx_id_t *context_handle;
gss_buffer_t interprocess_token;
{
- krb5_context ser_ctx = ct;
+ krb5_context context;
krb5_error_code kret;
OM_uint32 retval;
size_t bufsize, blen;
- krb5_gss_ctx_id_t *ctx;
+ krb5_gss_ctx_id_t ctx;
krb5_octet *obuffer, *obp;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/* Assume a tragic failure */
obuffer = (krb5_octet *) NULL;
retval = GSS_S_FAILURE;
@@ -53,12 +54,12 @@ krb5_gss_export_sec_context(ct,
goto error_out;
}
- ctx = (krb5_gss_ctx_id_t *) *context_handle;
+ ctx = (krb5_gss_ctx_id_t) *context_handle;
/* Determine size needed for externalization of context */
bufsize = 0;
- if ((kret = krb5_size_opaque(ser_ctx, KG_CONTEXT, (krb5_pointer) ctx,
- &bufsize)))
+ if ((kret = kg_ctx_size(context, (krb5_pointer) ctx,
+ &bufsize)))
goto error_out;
/* Allocate the buffer */
@@ -70,8 +71,8 @@ krb5_gss_export_sec_context(ct,
obp = obuffer;
blen = bufsize;
/* Externalize the context */
- if ((kret = krb5_externalize_opaque(ser_ctx, KG_CONTEXT,
- (krb5_pointer)ctx, &obp, &blen)))
+ if ((kret = kg_ctx_externalize(context,
+ (krb5_pointer) ctx, &obp, &blen)))
goto error_out;
/* Success! Return the buffer */
@@ -81,23 +82,7 @@ krb5_gss_export_sec_context(ct,
retval = GSS_S_COMPLETE;
/* Now, clean up the context state */
- (void) kg_delete_ctx_id((gss_ctx_id_t) ctx);
- if (ctx->enc.processed)
- krb5_finish_key(ser_ctx, &ctx->enc.eblock);
- krb5_free_keyblock(ser_ctx, ctx->enc.key);
- if (ctx->seq.processed)
- krb5_finish_key(ser_ctx, &ctx->seq.eblock);
- krb5_free_keyblock(ser_ctx, ctx->seq.key);
- krb5_free_principal(ser_ctx, ctx->here);
- krb5_free_principal(ser_ctx, ctx->there);
- krb5_free_keyblock(ser_ctx, ctx->subkey);
-
- if (ctx->auth_context)
- krb5_auth_con_free(ser_ctx, ctx->auth_context);
-
- /* Zero out context */
- memset(ctx, 0, sizeof(*ctx));
- xfree(ctx);
+ (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
*context_handle = GSS_C_NO_CONTEXT;
return (GSS_S_COMPLETE);
diff --git a/src/lib/gssapi/krb5/get_tkt_flags.c b/src/lib/gssapi/krb5/get_tkt_flags.c
index 2e73cacfe..5dd91064f 100644
--- a/src/lib/gssapi/krb5/get_tkt_flags.c
+++ b/src/lib/gssapi/krb5/get_tkt_flags.c
@@ -22,6 +22,10 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
gss_krb5_get_tkt_flags(minor_status, context_handle, ticket_flags)
OM_uint32 *minor_status;
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 53c4f4691..7ccc4b828 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -23,7 +23,11 @@
#ifndef _GSSAPIP_KRB5_H_
#define _GSSAPIP_KRB5_H_
-#include "k5-int.h"
+/*
+ * $Id$
+ */
+
+#include <krb5.h>
#include <memory.h>
/* work around sunos braindamage */
@@ -34,12 +38,15 @@
#undef minor
#endif
-/* this must be after "krb5.h", since krb5 #defines xfree(), too */
#ifndef _MACINTOSH
#include "../generic/gssapiP_generic.h"
#else
#include "gssapiP_generic.h"
#endif
+
+/* The include of gssapi_krb5.h will dtrt with the above #defines in
+ * effect.
+ */
#include "gssapi_krb5.h"
#include "gssapi_err_krb5.h"
@@ -56,6 +63,10 @@
#define KG_TOK_WRAP_MSG 0x0201
#define KG_TOK_DEL_CTX 0x0102
+#define KG_IMPLFLAGS(x) (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG | \
+ ((x) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \
+ GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)))
+
#define KRB5_GSS_FOR_CREDS_OPTION 1
/** internal types **/
@@ -66,6 +77,9 @@ typedef struct _krb5_gss_cred_id_rec {
/* name/type of credential */
gss_cred_usage_t usage;
krb5_principal princ; /* this is not interned as a gss_name_t */
+ const gss_OID_set_desc *actual_mechs;
+ int prerfc_mech; /* these are a cache of the set above */
+ int rfc_mech;
/* keytab (accept) data */
krb5_keytab keytab;
@@ -89,21 +103,24 @@ typedef struct _krb5_gss_ctx_id_rec {
krb5_principal here;
krb5_principal there;
krb5_keyblock *subkey;
+ int signalg;
+ int cksum_size;
+ int sealalg;
krb5_gss_enc_desc enc;
krb5_gss_enc_desc seq;
krb5_timestamp endtime;
krb5_flags flags;
krb5_int32 seq_send;
krb5_int32 seq_recv;
+ void *seqstate;
int established;
int big_endian;
krb5_auth_context auth_context;
-} krb5_gss_ctx_id_rec, krb5_gss_ctx_id_t;
+ const gss_OID_desc *mech_used;
+} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
extern void *kg_vdb;
-extern krb5_context kg_context;
-
/* helper macros */
#define kg_save_name(name) g_save_name(&kg_vdb,name)
@@ -127,16 +144,23 @@ OM_uint32 kg_get_defcred
OM_uint32 kg_release_defcred PROTOTYPE((OM_uint32 *minor_status));
krb5_error_code kg_checksum_channel_bindings
- PROTOTYPE((gss_channel_bindings_t cb,
+ PROTOTYPE((krb5_context context, gss_channel_bindings_t cb,
krb5_checksum *cksum,
int bigend));
-krb5_error_code kg_make_seq_num PROTOTYPE((krb5_gss_enc_desc *ed,
+krb5_error_code kg_make_seq_num PROTOTYPE((krb5_context context,
+ krb5_gss_enc_desc *ed,
int direction, krb5_int32 seqnum, unsigned char *cksum,
unsigned char *buf));
-krb5_error_code kg_make_seed PROTOTYPE((krb5_keyblock *key,
- unsigned char *seed));
+krb5_error_code kg_get_seq_num PROTOTYPE((krb5_context context,
+ krb5_gss_enc_desc *ed,
+ unsigned char *cksum, unsigned char *buf, int *direction,
+ krb5_int32 *seqnum));
+
+krb5_error_code kg_make_seed PROTOTYPE((krb5_context context,
+ krb5_keyblock *key,
+ unsigned char *seed));
int kg_confounder_size PROTOTYPE((krb5_gss_enc_desc *ed));
@@ -145,10 +169,12 @@ krb5_error_code kg_make_confounder PROTOTYPE((krb5_gss_enc_desc *ed,
int kg_encrypt_size PROTOTYPE((krb5_gss_enc_desc *ed, int n));
-krb5_error_code kg_encrypt PROTOTYPE((krb5_gss_enc_desc *ed,
+krb5_error_code kg_encrypt PROTOTYPE((krb5_context context,
+ krb5_gss_enc_desc *ed,
krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length));
-krb5_error_code kg_decrypt PROTOTYPE((krb5_gss_enc_desc *ed,
+krb5_error_code kg_decrypt PROTOTYPE((krb5_context context,
+ krb5_gss_enc_desc *ed,
krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length));
OM_uint32 kg_seal PROTOTYPE((krb5_context context,
@@ -178,14 +204,27 @@ OM_uint32 kg_seal_size PROTOTYPE((krb5_context context,
OM_uint32 output_size,
OM_uint32 *input_size));
-krb5_error_code
-kg_ser_context_init PROTOTYPE((krb5_context));
+krb5_error_code kg_ctx_size PROTOTYPE((krb5_context kcontext,
+ krb5_pointer arg,
+ size_t *sizep));
+
+krb5_error_code kg_ctx_externalize PROTOTYPE((krb5_context kcontext,
+ krb5_pointer arg,
+ krb5_octet **buffer,
+ size_t *lenremain));
+
+krb5_error_code kg_ctx_internalize PROTOTYPE((krb5_context kcontext,
+ krb5_pointer *argp,
+ krb5_octet **buffer,
+ size_t *lenremain));
+OM_uint32 kg_get_context PROTOTYPE((OM_uint32 *minor_status,
+ krb5_context *context));
+
/** declarations of internal name mechanism functions **/
OM_uint32 krb5_gss_acquire_cred
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_name_t, /* desired_name */
OM_uint32, /* time_req */
gss_OID_set, /* desired_mechs */
@@ -196,14 +235,12 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_release_cred
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_cred_id_t* /* cred_handle */
));
OM_uint32 krb5_gss_init_sec_context
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_cred_id_t, /* claimant_cred_handle */
gss_ctx_id_t*, /* context_handle */
gss_name_t, /* target_name */
@@ -220,8 +257,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_accept_sec_context
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t*, /* context_handle */
gss_cred_id_t, /* verifier_cred_handle */
gss_buffer_t, /* input_token_buffer */
@@ -236,29 +272,25 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_process_context_token
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_buffer_t /* token_buffer */
));
OM_uint32 krb5_gss_delete_sec_context
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t*, /* context_handle */
gss_buffer_t /* output_token */
));
OM_uint32 krb5_gss_context_time
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
OM_uint32* /* time_rec */
));
OM_uint32 krb5_gss_sign
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
int, /* qop_req */
gss_buffer_t, /* message_buffer */
@@ -266,8 +298,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_verify
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_buffer_t, /* message_buffer */
gss_buffer_t, /* token_buffer */
@@ -275,8 +306,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_seal
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
int, /* conf_req_flag */
int, /* qop_req */
@@ -286,8 +316,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_unseal
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_buffer_t, /* input_message_buffer */
gss_buffer_t, /* output_message_buffer */
@@ -296,8 +325,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_display_status
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
OM_uint32, /* status_value */
int, /* status_type */
gss_OID, /* mech_type */
@@ -306,44 +334,38 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_indicate_mechs
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_OID_set* /* mech_set */
));
OM_uint32 krb5_gss_compare_name
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_name_t, /* name1 */
gss_name_t, /* name2 */
int* /* name_equal */
));
OM_uint32 krb5_gss_display_name
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_name_t, /* input_name */
gss_buffer_t, /* output_name_buffer */
gss_OID* /* output_name_type */
));
OM_uint32 krb5_gss_import_name
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_buffer_t, /* input_name_buffer */
gss_OID, /* input_name_type */
gss_name_t* /* output_name */
));
OM_uint32 krb5_gss_release_name
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_name_t* /* input_name */
));
OM_uint32 krb5_gss_inquire_cred
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_cred_id_t, /* cred_handle */
gss_name_t *, /* name */
OM_uint32 *, /* lifetime */
@@ -352,8 +374,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_inquire_context
-PROTOTYPE( (void *,
- OM_uint32*, /* minor_status */
+PROTOTYPE( (OM_uint32*, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_name_t*, /* initiator_name */
gss_name_t*, /* acceptor_name */
@@ -366,8 +387,7 @@ PROTOTYPE( (void *,
/* New V2 entry points */
OM_uint32 krb5_gss_get_mic
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_qop_t, /* qop_req */
gss_buffer_t, /* message_buffer */
@@ -375,8 +395,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_verify_mic
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_buffer_t, /* message_buffer */
gss_buffer_t, /* message_token */
@@ -384,8 +403,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_wrap
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_ctx_id_t, /* context_handle */
int, /* conf_req_flag */
gss_qop_t, /* qop_req */
@@ -395,8 +413,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_unwrap
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_ctx_id_t, /* context_handle */
gss_buffer_t, /* input_message_buffer */
gss_buffer_t, /* output_message_buffer */
@@ -405,8 +422,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_wrap_size_limit
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_ctx_id_t, /* context_handle */
int, /* conf_req_flag */
gss_qop_t, /* qop_req */
@@ -415,24 +431,21 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_import_name_object
-PROTOTYPE( (krb5_context,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
void *, /* input_name */
gss_OID, /* input_name_type */
gss_name_t * /* output_name */
));
OM_uint32 krb5_gss_export_name_object
-PROTOTYPE( (krb5_context,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_name_t, /* input_name */
gss_OID, /* desired_name_type */
void * * /* output_name */
));
OM_uint32 krb5_gss_add_cred
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_cred_id_t, /* input_cred_handle */
gss_name_t, /* desired_name */
gss_OID, /* desired_mech */
@@ -446,8 +459,7 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_inquire_cred_by_mech
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_cred_id_t, /* cred_handle */
gss_OID, /* mech_type */
gss_name_t *, /* name */
@@ -457,38 +469,33 @@ PROTOTYPE( (void *,
));
OM_uint32 krb5_gss_export_sec_context
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_ctx_id_t *, /* context_handle */
gss_buffer_t /* interprocess_token */
));
OM_uint32 krb5_gss_import_sec_context
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_buffer_t, /* interprocess_token */
gss_ctx_id_t * /* context_handle */
));
+#if 0
OM_uint32 krb5_gss_release_oid
PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_OID * /* oid */
));
-
+#endif
OM_uint32 krb5_gss_internal_release_oid
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_OID * /* oid */
));
OM_uint32 krb5_gss_inquire_names_for_mech
-PROTOTYPE( (void *,
- OM_uint32 *, /* minor_status */
+PROTOTYPE( (OM_uint32 *, /* minor_status */
gss_OID, /* mechanism */
gss_OID_set * /* name_types */
));
-OM_uint32 kg_get_context();
-
#endif /* _GSSAPIP_KRB5_H_ */
diff --git a/src/lib/gssapi/krb5/gssapi_err_krb5.et b/src/lib/gssapi/krb5/gssapi_err_krb5.et
index 0f26773b1..54a126518 100644
--- a/src/lib/gssapi/krb5/gssapi_err_krb5.et
+++ b/src/lib/gssapi/krb5/gssapi_err_krb5.et
@@ -33,4 +33,6 @@ error_code KG_CTX_INCOMPLETE, "Attempt to use incomplete security context"
error_code KG_CONTEXT, "Bad magic number for krb5_gss_ctx_id_t"
error_code KG_CRED, "Bad magic number for krb5_gss_cred_id_t"
error_code KG_ENC_DESC, "Bad magic number for krb5_gss_enc_desc"
+error_code KG_BAD_SEQ, "Sequence number in token is corrupt"
+error_code KG_EMPTY_CCACHE, "Credential cache is empty"
end
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index e18455755..feec0bc71 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -20,50 +20,62 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_krb5.h"
-/** exported constants defined in gssapi_krb5.h **/
+/** exported constants defined in gssapi_krb5{,_nx}.h **/
/* these are bogus, but will compile */
/*
- * The OID of the krb5 mechanism, assigned by IETF, is:
- * 1.3.5.1.5.2
+ * The OID of the draft krb5 mechanism, assigned by IETF, is:
+ * iso(1) org(3) dod(5) internet(1) security(5)
+ * kerberosv5(2) = 1.3.5.1.5.2
* The OID of the krb5_name type is:
* iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
- * krb5(2) krb5_name(1) = 1.2.840.113554.2.1.2.1
+ * krb5(2) krb5_name(1) = 1.2.840.113554.1.2.2.1
* The OID of the krb5_principal type is:
* iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
- * krb5(2) krb5_principal(2) = 1.2.840.113554.2.1.2.2
+ * krb5(2) krb5_principal(2) = 1.2.840.113554.1.2.2.2
+ * The OID of the proposed standard krb5 mechanism is:
+ * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * krb5(2) = 1.2.840.113554.1.2.2
+ *
*/
/*
* Encoding rules: The first two values are encoded in one byte as 40
* * value1 + value2. Subsequent values are encoded base 128, most
- * significant digit first, with the high bit set on all octets except
- * the last in each value's encoding.
+ * significant digit first, with the high bit (\200) set on all octets
+ * except the last in each value's encoding.
*/
static const gss_OID_desc oids[] = {
- /* this OID is from Ted. It's not official yet, but it's close. */
+ /* this is the unofficial, wrong OID */
{5, "\053\005\001\005\002"},
+ /* this is the official, rfc-specified OID */
+ {9, "\052\206\110\206\367\022\001\002\002"},
{10, "\052\206\110\206\367\022\001\002\002\001"},
{10, "\052\206\110\206\367\022\001\002\002\002"},
- {9, "\052\206\110\206\367\022\001\002\002"},
};
-const gss_OID_desc * const gss_mech_krb5 = oids+0;
+const gss_OID_desc * const gss_mech_krb5_old = oids+0;
+const gss_OID_desc * const gss_mech_krb5 = oids+1;
const gss_OID_desc * const gss_nt_krb5_name = oids+1;
-const gss_OID_desc * const gss_nt_krb5_principal = oids+2;
-const gss_OID_desc * const gss_new_mech_krb5 = oids+3;
+const gss_OID_desc * const gss_nt_krb5_principal = oids+3;
static const gss_OID_set_desc oidsets[] = {
- {1, (gss_OID) oids},
+ {1, (gss_OID) oids+0},
+ {1, (gss_OID) oids+1},
+ {2, (gss_OID) oids+0},
};
-const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+0;
-
-krb5_context kg_context;
+const gss_OID_set_desc * const gss_mech_set_krb5_old = oidsets+0;
+const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+1;
+const gss_OID_set_desc * const gss_mech_set_krb5_both = oidsets+2;
void *kg_vdb = NULL;
@@ -83,10 +95,7 @@ kg_get_defcred(minor_status, cred)
if (defcred == GSS_C_NO_CREDENTIAL) {
OM_uint32 major;
- if (!kg_context && kg_get_context())
- return GSS_S_FAILURE;
-
- if ((major = krb5_gss_acquire_cred(kg_context, minor_status,
+ if ((major = krb5_gss_acquire_cred(minor_status,
(gss_name_t) NULL, GSS_C_INDEFINITE,
GSS_C_NULL_OID_SET, GSS_C_INITIATE,
&defcred, NULL, NULL)) &&
@@ -110,19 +119,24 @@ kg_release_defcred(minor_status)
return(GSS_S_COMPLETE);
}
- if (!kg_context && kg_get_context())
- return GSS_S_FAILURE;
-
- return(krb5_gss_release_cred(kg_context, minor_status, &defcred));
+ return(krb5_gss_release_cred(minor_status, &defcred));
}
OM_uint32
-kg_get_context()
+kg_get_context(minor_status, context)
+ OM_uint32 *minor_status;
+ krb5_context *context;
{
- if (kg_context)
- return GSS_S_COMPLETE;
- if (krb5_init_context(&kg_context))
- return GSS_S_FAILURE;
- krb5_init_ets(kg_context);
- return GSS_S_COMPLETE;
+ static krb5_context kg_context = NULL;
+ krb5_error_code code;
+
+ if ((! kg_context) &&
+ (code = krb5_init_context(&kg_context))) {
+ *minor_status = (OM_uint32) code;
+ return GSS_S_FAILURE;
+ }
+
+ *context = kg_context;
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
}
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h
index 450081d97..71182f22b 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.h
+++ b/src/lib/gssapi/krb5/gssapi_krb5.h
@@ -28,10 +28,13 @@
#else
#include <gssapi_generic.h>
#endif
-#include "krb5.h"
+#include <krb5.h>
extern const gss_OID_desc * const gss_mech_krb5;
+extern const gss_OID_desc * const gss_mech_krb5_old;
extern const gss_OID_set_desc * const gss_mech_set_krb5;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_old;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_both;
extern const gss_OID_desc * const gss_nt_krb5_name;
extern const gss_OID_desc * const gss_nt_krb5_principal;
@@ -49,4 +52,11 @@ OM_uint32 gss_krb5_get_tkt_flags
krb5_flags *ticket_flags));
+/* this is for backward compatibility only. It is declared here for
+ completeness, but should not be used */
+
+OM_uint32 krb5_gss_set_backward_mode
+ PROTOTYPE((OM_uint32 *minor_status,
+ int mode));
+
#endif /* _GSSAPI_KRB5_H_ */
diff --git a/src/lib/gssapi/krb5/import_name.c b/src/lib/gssapi/krb5/import_name.c
index ee44132ae..5c2c6f43a 100644
--- a/src/lib/gssapi/krb5/import_name.c
+++ b/src/lib/gssapi/krb5/import_name.c
@@ -20,7 +20,12 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_krb5.h"
+
#ifndef NO_PASSWORD
#include <pwd.h>
#endif
@@ -39,21 +44,24 @@
*/
OM_uint32
-krb5_gss_import_name(ctx, minor_status, input_name_buffer,
+krb5_gss_import_name(minor_status, input_name_buffer,
input_name_type, output_name)
- void *ctx;
OM_uint32 *minor_status;
gss_buffer_t input_name_buffer;
gss_OID input_name_type;
gss_name_t *output_name;
{
- krb5_context context = ctx;
+ krb5_context context;
krb5_principal princ;
krb5_error_code code;
char *stringrep, *tmp;
#ifndef NO_PASSWORD
struct passwd *pw;
#endif
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/* set up default returns */
*output_name = NULL;
@@ -75,13 +83,10 @@ krb5_gss_import_name(ctx, minor_status, input_name_buffer,
tmp[input_name_buffer->length] = 0;
service = tmp;
- if ((host = strchr(tmp, '@')) == NULL) {
- xfree(tmp);
- *minor_status = (OM_uint32) G_BAD_SERVICE_NAME;
- return(GSS_S_BAD_NAME);
+ if (host = strchr(tmp, '@')) {
+ *host = '\0';
+ host++;
}
- *host = '\0';
- host++;
code = krb5_sname_to_principal(context, host, service, KRB5_NT_SRV_HST,
&princ);
diff --git a/src/lib/gssapi/krb5/import_sec_context.c b/src/lib/gssapi/krb5/import_sec_context.c
index d802ecdd0..c1d1bfa72 100644
--- a/src/lib/gssapi/krb5/import_sec_context.c
+++ b/src/lib/gssapi/krb5/import_sec_context.c
@@ -28,59 +28,46 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_import_sec_context(ct,
- minor_status, interprocess_token, context_handle)
- void *ct;
+krb5_gss_import_sec_context(minor_status, interprocess_token, context_handle)
OM_uint32 *minor_status;
gss_buffer_t interprocess_token;
gss_ctx_id_t *context_handle;
{
- krb5_context ser_ctx = ct;
+ krb5_context context;
krb5_error_code kret = 0;
OM_uint32 retval;
size_t blen;
- krb5_gss_ctx_id_t *ctx;
+ krb5_gss_ctx_id_t ctx;
krb5_octet *ibp;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/* Assume a tragic failure */
- ctx = (krb5_gss_ctx_id_t *) NULL;
+ ctx = (krb5_gss_ctx_id_t) NULL;
retval = GSS_S_FAILURE;
*minor_status = 0;
/* Internalize the context */
ibp = (krb5_octet *) interprocess_token->value;
blen = (size_t) interprocess_token->length;
- if ((kret = krb5_internalize_opaque(ser_ctx, KG_CONTEXT,
- (krb5_pointer *) &ctx,
- &ibp, &blen)))
- goto error_out;
-
+ if ((kret = kg_ctx_internalize(context,
+ (krb5_pointer *) &ctx,
+ &ibp, &blen))) {
+ *minor_status = (OM_uint32) kret;
+ return(GSS_S_FAILURE);
+ }
- /* Make sure that everything is cool. */
- if (!kg_validate_ctx_id((gss_ctx_id_t) ctx))
- goto error_out;
+ /* intern the context handle */
+ if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
+ (void)krb5_gss_delete_sec_context(minor_status,
+ (gss_ctx_id_t *) &ctx, NULL);
+ *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ return(GSS_S_FAILURE);
+ }
*context_handle = (gss_ctx_id_t) ctx;
+ *minor_status = 0;
return (GSS_S_COMPLETE);
-
-error_out:
- if (ctx) {
- (void) kg_delete_ctx_id((gss_ctx_id_t) ctx);
- if (ctx->enc.processed)
- krb5_finish_key(ser_ctx, &ctx->enc.eblock);
- krb5_free_keyblock(ser_ctx, ctx->enc.key);
- if (ctx->seq.processed)
- krb5_finish_key(ser_ctx, &ctx->seq.eblock);
- krb5_free_principal(ser_ctx, ctx->here);
- krb5_free_principal(ser_ctx, ctx->there);
- krb5_free_keyblock(ser_ctx, ctx->subkey);
-
- /* Zero out context */
- memset(ctx, 0, sizeof(*ctx));
- xfree(ctx);
- }
- if (*minor_status == 0)
- *minor_status = (OM_uint32) kret;
- return(retval);
}
diff --git a/src/lib/gssapi/krb5/indicate_mechs.c b/src/lib/gssapi/krb5/indicate_mechs.c
index 0f78de219..bc53b4434 100644
--- a/src/lib/gssapi/krb5/indicate_mechs.c
+++ b/src/lib/gssapi/krb5/indicate_mechs.c
@@ -20,11 +20,14 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_indicate_mechs(ctx, minor_status, mech_set)
- void *ctx;
+krb5_gss_indicate_mechs(minor_status, mech_set)
OM_uint32 *minor_status;
gss_OID_set *mech_set;
{
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 2b671680a..686384216 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -22,22 +22,25 @@
#include "gssapiP_krb5.h"
#include <memory.h>
-#include "k5-int.h"
+
+/*
+ * $Id$
+ */
static krb5_error_code
-make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
- do_mutual, flags, token)
- void *ctx;
+make_ap_req(context, auth_context, cred, server, endtime, chan_bindings,
+ req_flags, flags, mech_type, token)
+ krb5_context context;
krb5_auth_context * auth_context;
krb5_gss_cred_id_t cred;
krb5_principal server;
krb5_timestamp *endtime;
gss_channel_bindings_t chan_bindings;
- OM_uint32 do_mutual;
+ OM_uint32 req_flags;
krb5_flags *flags;
+ gss_OID mech_type;
gss_buffer_t token;
{
- krb5_context context = ctx;
krb5_flags mk_req_flags = 0;
krb5_error_code code;
krb5_data checksum_data;
@@ -46,19 +49,19 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
krb5_data ap_req;
unsigned char *ptr;
krb5_data credmsg;
- unsigned char ckbuf[24]; /* see the token formats doc */
unsigned char *t;
int tlen;
krb5_int32 con_flags;
ap_req.data = 0;
checksum_data.data = 0;
+ credmsg.data = 0;
/* build the checksum buffer */
/* compute the hash of the channel bindings */
- if ((code = kg_checksum_channel_bindings(chan_bindings, &md5, 0)))
+ if ((code = kg_checksum_channel_bindings(context, chan_bindings, &md5, 0)))
return(code);
/* get an auth_context structure and fill in checksum type */
@@ -92,25 +95,31 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
return(KRB5KRB_ERR_FIELD_TOOLONG);
}
- /* now allocate a buffer to hold the checksum data and KRB_CRED msg
- and write it */
+ checksum_data.length = 28+credmsg.length;
+ } else {
+ checksum_data.length = 24;
+ }
+
+ /* now allocate a buffer to hold the checksum data and
+ (maybe) KRB_CRED msg */
- if ((ptr = (unsigned char *) xmalloc(credmsg.length+28)) == NULL) {
+ if ((checksum_data.data =
+ (char *) xmalloc(checksum_data.length)) == NULL) {
+ if (credmsg.data)
krb5_xfree(credmsg.data);
- return(ENOMEM);
- }
+ return(ENOMEM);
+ }
- checksum_data.data = (char *) ptr;
- checksum_data.length = credmsg.length+28;
+ ptr = checksum_data.data;
- TWRITE_INT(ptr, md5.length, 0);
- TWRITE_STR(ptr, (unsigned char *) md5.contents, md5.length);
- TWRITE_INT(ptr, do_mutual?GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG
- :GSS_C_DELEG_FLAG, 0);
+ TWRITE_INT(ptr, md5.length, 0);
+ TWRITE_STR(ptr, (unsigned char *) md5.contents, md5.length);
+ TWRITE_INT(ptr, KG_IMPLFLAGS(req_flags), 0);
- /* done with this, free it */
- xfree(md5.contents);
+ /* done with this, free it */
+ xfree(md5.contents);
+ if (credmsg.data) {
TWRITE_INT16(ptr, KRB5_GSS_FOR_CREDS_OPTION, 0);
TWRITE_INT16(ptr, credmsg.length, 0);
TWRITE_STR(ptr, (unsigned char *) credmsg.data, credmsg.length);
@@ -118,20 +127,6 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
/* free credmsg data */
krb5_xfree(credmsg.data);
-
- } else {
-
- ptr = ckbuf;
-
- TWRITE_INT(ptr, md5.length, 0);
- TWRITE_STR(ptr, (unsigned char *) md5.contents, md5.length);
- TWRITE_INT(ptr, do_mutual?GSS_C_MUTUAL_FLAG:0, 0);
-
- /* done with this, free it */
- xfree(md5.contents);
-
- checksum_data.data = (char *) ckbuf;
- checksum_data.length = sizeof(ckbuf);
}
/* fill in the necessary fields in creds */
@@ -142,7 +137,7 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
goto cleanup;
in_creds.times.endtime = *endtime;
- in_creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
+
/*
* Get the credential..., I don't know in 0 is a good value for the
* kdcoptions
@@ -155,7 +150,7 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
mk_req_flags = AP_OPTS_USE_SUBKEY;
- if (do_mutual)
+ if (req_flags & GSS_C_MUTUAL_FLAG)
mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED;
if ((code = krb5_mk_req_extended(context, auth_context, mk_req_flags,
@@ -169,7 +164,7 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
/* build up the token */
/* allocate space for the token */
- tlen = g_token_size((gss_OID) gss_mech_krb5, ap_req.length);
+ tlen = g_token_size((gss_OID) mech_type, ap_req.length);
if ((t = (unsigned char *) xmalloc(tlen)) == NULL) {
code = ENOMEM;
@@ -180,38 +175,38 @@ make_ap_req(ctx, auth_context, cred, server, endtime, chan_bindings,
ptr = t;
- g_make_token_header((gss_OID) gss_mech_krb5, ap_req.length,
+ g_make_token_header((gss_OID) mech_type, ap_req.length,
&ptr, KG_TOK_CTX_AP_REQ);
TWRITE_STR(ptr, (unsigned char *) ap_req.data, ap_req.length);
/* pass it back */
+
token->length = tlen;
token->value = (void *) t;
code = 0;
cleanup:
- if (checksum_data.data && checksum_data.data != (char *) ckbuf)
- free(checksum_data.data);
- krb5_free_cred_contents(context, &in_creds);
- if (out_creds)
- krb5_free_creds(context, out_creds);
- if (ap_req.data)
- xfree(ap_req.data);
- if (code)
- krb5_auth_con_free(context, *auth_context);
-
- return (code);
+ if (checksum_data.data)
+ free(checksum_data.data);
+ krb5_free_cred_contents(context, &in_creds);
+ if (out_creds)
+ krb5_free_creds(context, out_creds);
+ if (ap_req.data)
+ xfree(ap_req.data);
+ if (code)
+ krb5_auth_con_free(context, *auth_context);
+
+ return (code);
}
OM_uint32
-krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
- context_handle, target_name, mech_type,
- req_flags, time_req, input_chan_bindings,
- input_token, actual_mech_type, output_token,
- ret_flags, time_rec)
- void *ct;
+krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
+ context_handle, target_name, mech_type,
+ req_flags, time_req, input_chan_bindings,
+ input_token, actual_mech_type, output_token,
+ ret_flags, time_rec)
OM_uint32 *minor_status;
gss_cred_id_t claimant_cred_handle;
gss_ctx_id_t *context_handle;
@@ -226,28 +221,25 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
OM_uint32 *ret_flags;
OM_uint32 *time_rec;
{
- krb5_context context = ct;
- krb5_gss_cred_id_t cred;
- krb5_error_code code;
- krb5_gss_ctx_id_rec *ctx;
- krb5_timestamp now;
- gss_buffer_desc token;
- int i;
+ krb5_context context;
+ krb5_gss_cred_id_t cred;
+ krb5_error_code code;
+ krb5_gss_ctx_id_rec *ctx;
+ krb5_timestamp now;
+ krb5_enctype enctype;
+ gss_buffer_desc token;
+ int i;
+ int err;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
/* set up return values so they can be "freed" successfully */
output_token->length = 0;
output_token->value = NULL;
if (actual_mech_type)
- *actual_mech_type = (gss_OID) gss_mech_krb5;
-
- /* verify the mech_type */
-
- if ((mech_type != GSS_C_NULL_OID) &&
- (! g_OID_equal(mech_type, gss_mech_krb5))) {
- *minor_status = 0;
- return(GSS_S_BAD_MECH);
- }
+ *actual_mech_type = NULL;
/* verify the credential, or use the default */
/*SUPPRESS 29*/
@@ -267,6 +259,17 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
cred = (krb5_gss_cred_id_t) claimant_cred_handle;
+ /* verify the mech_type */
+
+ if (mech_type == GSS_C_NULL_OID) {
+ mech_type = cred->rfc_mech?gss_mech_krb5:gss_mech_krb5_old;
+ } else if ((g_OID_equal(mech_type, gss_mech_krb5) && !cred->rfc_mech) ||
+ (g_OID_equal(mech_type, gss_mech_krb5_old) &&
+ !cred->prerfc_mech)) {
+ *minor_status = 0;
+ return(GSS_S_BAD_MECH);
+ }
+
/* verify that the target_name is valid and usable */
if (! kg_validate_name(target_name)) {
@@ -303,6 +306,7 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
/* fill in the ctx */
memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
+ ctx->mech_used = mech_type;
ctx->auth_context = NULL;
ctx->initiate = 1;
ctx->gss_flags = ((req_flags & (GSS_C_MUTUAL_FLAG | GSS_C_DELEG_FLAG)) |
@@ -310,6 +314,7 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
ctx->flags = req_flags & GSS_C_DELEG_FLAG;
ctx->seed_init = 0;
ctx->big_endian = 0; /* all initiators do little-endian, as per spec */
+ ctx->seqstate = 0;
if (time_req == 0 || time_req == GSS_C_INDEFINITE) {
ctx->endtime = 0;
@@ -338,8 +343,7 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
if ((code = make_ap_req(context, &(ctx->auth_context), cred,
ctx->there, &ctx->endtime, input_chan_bindings,
- ctx->gss_flags & GSS_C_MUTUAL_FLAG, &ctx->flags,
- &token))) {
+ req_flags, &ctx->flags, mech_type, &token))) {
krb5_free_principal(context, ctx->here);
krb5_free_principal(context, ctx->there);
xfree(ctx);
@@ -354,9 +358,29 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
/* fill in the encryption descriptors */
+ switch(ctx->subkey->enctype) {
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ enctype = ENCTYPE_DES_CBC_RAW;
+ ctx->signalg = 0;
+ ctx->cksum_size = 8;
+ ctx->sealalg = 0;
+ break;
+#if 0
+ case ENCTYPE_DES3_CBC_MD5:
+ enctype = ENCTYPE_DES3_CBC_RAW;
+ ctx->signalg = 3;
+ ctx->cksum_size = 16;
+ ctx->sealalg = 1;
+ break;
+#endif
+ default:
+ return GSS_S_FAILURE;
+ }
+
/* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */
- krb5_use_enctype(context, &ctx->enc.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->enc.eblock, enctype);
ctx->enc.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
return(code);
@@ -364,7 +388,7 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
/*SUPPRESS 113*/
ctx->enc.key->contents[i] ^= 0xf0;
- krb5_use_enctype(context, &ctx->seq.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ctx->seq.eblock, enctype);
ctx->seq.processed = 0;
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
return(code);
@@ -390,7 +414,7 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
if (time_rec) {
if ((code = krb5_timeofday(context, &now))) {
xfree(token.value);
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t) ctx, NULL);
*minor_status = code;
return(GSS_S_FAILURE);
@@ -405,7 +429,10 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
*output_token = token;
if (ret_flags)
- *ret_flags = ctx->gss_flags;
+ *ret_flags = KG_IMPLFLAGS(req_flags);
+
+ if (actual_mech_type)
+ *actual_mech_type = mech_type;
/* return successfully */
@@ -415,8 +442,11 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
return(GSS_S_CONTINUE_NEEDED);
} else {
ctx->seq_recv = ctx->seq_send;
+ g_order_init(&(ctx->seqstate), ctx->seq_recv,
+ req_flags & GSS_C_REPLAY_FLAG,
+ req_flags & GSS_C_SEQUENCE_FLAG);
ctx->established = 1;
- return(GSS_S_COMPLETE);
+ /* fall through to GSS_S_COMPLETE */
}
} else {
unsigned char *ptr;
@@ -439,15 +469,16 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
if ((ctx->established) ||
(((gss_cred_id_t) cred) != claimant_cred_handle) ||
((req_flags & GSS_C_MUTUAL_FLAG) == 0)) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
context_handle, NULL);
+ /* XXX this minor status is wrong if an arg was changed */
*minor_status = KG_CONTEXT_ESTABLISHED;
return(GSS_S_FAILURE);
}
if (! krb5_principal_compare(context, ctx->there,
(krb5_principal) target_name)) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
context_handle, NULL);
*minor_status = 0;
return(GSS_S_BAD_NAME);
@@ -456,7 +487,7 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
/* verify the token and leave the AP_REP message in ap_rep */
if (input_token == GSS_C_NO_BUFFER) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
context_handle, NULL);
*minor_status = 0;
return(GSS_S_DEFECTIVE_TOKEN);
@@ -464,10 +495,10 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
ptr = (unsigned char *) input_token->value;
- if (! g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_rep.length),
- &ptr, KG_TOK_CTX_AP_REP,
- input_token->length)) {
- *minor_status = 0;
+ if (err = g_verify_token_header((gss_OID) mech_type, &(ap_rep.length),
+ &ptr, KG_TOK_CTX_AP_REP,
+ input_token->length)) {
+ *minor_status = err;
return(GSS_S_DEFECTIVE_TOKEN);
}
@@ -482,9 +513,9 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
* To be removed in 1999 -- proven
*/
krb5_auth_con_setuseruserkey(context,ctx->auth_context,ctx->subkey);
- if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
- &ap_rep_data))) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
+ &ap_rep_data))) {
+ (void)krb5_gss_delete_sec_context(minor_status,
context_handle, NULL);
*minor_status = code;
return(GSS_S_FAILURE);
@@ -493,6 +524,9 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
/* store away the sequence number */
ctx->seq_recv = ap_rep_data->seq_number;
+ g_order_init(&(ctx->seqstate), ctx->seq_recv,
+ req_flags & GSS_C_REPLAY_FLAG,
+ req_flags & GSS_C_SEQUENCE_FLAG);
/* free the ap_rep_data */
krb5_free_ap_rep_enc_part(context, ap_rep_data);
@@ -504,20 +538,25 @@ krb5_gss_init_sec_context(ct, minor_status, claimant_cred_handle,
if (time_rec) {
if ((code = krb5_timeofday(context, &now))) {
- (void)krb5_gss_delete_sec_context(context, minor_status,
+ (void)krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t) ctx, NULL);
*minor_status = code;
return(GSS_S_FAILURE);
-
}
+ *time_rec = ctx->endtime - now;
}
if (ret_flags)
- *ret_flags = GSS_C_CONF_FLAG | GSS_C_INTEG_FLAG | GSS_C_MUTUAL_FLAG;
+ *ret_flags = KG_IMPLFLAGS(req_flags);
+
+ if (actual_mech_type)
+ *actual_mech_type = mech_type;
/* success */
*minor_status = 0;
- return(GSS_S_COMPLETE);
+ /* fall through to GSS_S_COMPLETE */
}
+
+ return(GSS_S_COMPLETE);
}
diff --git a/src/lib/gssapi/krb5/inq_context.c b/src/lib/gssapi/krb5/inq_context.c
index c8499212f..5e5746344 100644
--- a/src/lib/gssapi/krb5/inq_context.c
+++ b/src/lib/gssapi/krb5/inq_context.c
@@ -23,10 +23,9 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_inquire_context(ct, minor_status, context_handle, initiator_name,
+krb5_gss_inquire_context(minor_status, context_handle, initiator_name,
acceptor_name, lifetime_rec, mech_type, ret_flags,
locally_initiated, open)
- void *ct;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_name_t *initiator_name;
@@ -37,13 +36,16 @@ krb5_gss_inquire_context(ct, minor_status, context_handle, initiator_name,
int *locally_initiated;
int *open;
{
- krb5_context context = ct;
+ krb5_context context;
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
krb5_principal init, accept;
krb5_timestamp now;
krb5_deltat lifetime;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if (initiator_name)
*initiator_name = (gss_name_t) NULL;
if (acceptor_name)
@@ -116,7 +118,7 @@ krb5_gss_inquire_context(ct, minor_status, context_handle, initiator_name,
*lifetime_rec = lifetime;
if (mech_type)
- *mech_type = (gss_OID) gss_mech_krb5;
+ *mech_type = (gss_OID) ctx->mech_used;
if (ret_flags)
*ret_flags = ctx->gss_flags;
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
index e3e01bf4e..f9811c347 100644
--- a/src/lib/gssapi/krb5/inq_cred.c
+++ b/src/lib/gssapi/krb5/inq_cred.c
@@ -23,9 +23,8 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
+krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
cred_usage, mechanisms)
- void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
gss_name_t *name;
@@ -33,7 +32,7 @@ krb5_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
gss_cred_usage_t *cred_usage;
gss_OID_set *mechanisms;
{
- krb5_context context = ctx;
+ krb5_context context;
krb5_gss_cred_id_t cred;
krb5_error_code code;
krb5_timestamp now;
@@ -41,6 +40,9 @@ krb5_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
krb5_principal ret_name;
gss_OID_set mechs;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if (name) *name = NULL;
if (mechanisms) *mechanisms = NULL;
@@ -82,7 +84,7 @@ krb5_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
}
if (mechanisms)
- if (! g_copy_OID_set(gss_mech_set_krb5, &mechs)) {
+ if (! g_copy_OID_set(cred->actual_mechs, &mechs)) {
krb5_free_principal(context, ret_name);
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
@@ -113,10 +115,9 @@ krb5_gss_inquire_cred(ctx, minor_status, cred_handle, name, lifetime_ret,
/* V2 interface */
OM_uint32
-krb5_gss_inquire_cred_by_mech(ctx, minor_status, cred_handle,
+krb5_gss_inquire_cred_by_mech(minor_status, cred_handle,
mech_type, name, initiator_lifetime,
acceptor_lifetime, cred_usage)
- void *ctx;
OM_uint32 *minor_status;
gss_cred_id_t cred_handle;
gss_OID mech_type;
@@ -125,11 +126,14 @@ krb5_gss_inquire_cred_by_mech(ctx, minor_status, cred_handle,
OM_uint32 *acceptor_lifetime;
gss_cred_usage_t *cred_usage;
{
- krb5_context context = ctx;
+ krb5_context context;
krb5_gss_cred_id_t cred;
OM_uint32 lifetime;
OM_uint32 mstat;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/*
* We only know how to handle our own creds.
*/
@@ -140,8 +144,7 @@ krb5_gss_inquire_cred_by_mech(ctx, minor_status, cred_handle,
}
cred = (krb5_gss_cred_id_t) cred_handle;
- mstat = krb5_gss_inquire_cred(context,
- minor_status,
+ mstat = krb5_gss_inquire_cred(minor_status,
cred_handle,
name,
&lifetime,
diff --git a/src/lib/gssapi/krb5/inq_names.c b/src/lib/gssapi/krb5/inq_names.c
index fe61eb01a..948346dc6 100644
--- a/src/lib/gssapi/krb5/inq_names.c
+++ b/src/lib/gssapi/krb5/inq_names.c
@@ -28,19 +28,23 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_inquire_names_for_mech(context, minor_status, mechanism, name_types)
- void *context;
+krb5_gss_inquire_names_for_mech(minor_status, mechanism, name_types)
OM_uint32 *minor_status;
gss_OID mechanism;
gss_OID_set *name_types;
{
+ krb5_context context;
OM_uint32 major, minor;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/*
* We only know how to handle our own mechanism.
*/
if ((mechanism != GSS_C_NULL_OID) &&
- !g_OID_equal(gss_mech_krb5, mechanism)) {
+ !g_OID_equal(gss_mech_krb5, mechanism) &&
+ !g_OID_equal(gss_mech_krb5_old, mechanism)) {
*minor_status = 0;
return(GSS_S_FAILURE);
}
diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
index 4e5c78bd1..254d51680 100644
--- a/src/lib/gssapi/krb5/k5seal.c
+++ b/src/lib/gssapi/krb5/k5seal.c
@@ -21,11 +21,11 @@
*/
#include "gssapiP_krb5.h"
-#include "rsa-md5.h"
static krb5_error_code
make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
- encrypt, toktype, bigend)
+ signalg, cksum_size, sealalg, encrypt, toktype,
+ bigend, oid)
krb5_context context;
krb5_gss_enc_desc *enc_ed;
krb5_gss_enc_desc *seq_ed;
@@ -33,29 +33,36 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
int direction;
gss_buffer_t text;
gss_buffer_t token;
+ int signalg;
+ int cksum_size;
+ int sealalg;
int encrypt;
int toktype;
int bigend;
+ gss_OID oid;
{
krb5_error_code code;
- krb5_MD5_CTX md5;
- krb5_checksum desmac;
- krb5_octet cbc_checksum[KRB5_MIT_DES_KEYSIZE];
- int tmsglen, tlen;
+ char *data_ptr;
+ krb5_checksum md5cksum;
+ krb5_checksum cksum;
+ int conflen, tmsglen, tlen;
unsigned char *t, *ptr;
/* create the token buffer */
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)) {
- if (bigend && !encrypt)
+ if (toktype == KG_TOK_SEAL_MSG) {
+ if (bigend && !encrypt) {
tmsglen = text->length;
- else
- tmsglen = (kg_confounder_size(enc_ed)+text->length+8)&(~7);
+ } else {
+ conflen = kg_confounder_size(enc_ed);
+ /* XXX knows that des block size is 8 */
+ tmsglen = (conflen+text->length+8)&(~7);
+ }
} else {
tmsglen = 0;
}
- tlen = g_token_size((gss_OID) gss_mech_krb5, 22+tmsglen);
+ tlen = g_token_size((gss_OID) oid, 14+cksum_size+tmsglen);
if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
return(ENOMEM);
@@ -64,104 +71,192 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
ptr = t;
- g_make_token_header((gss_OID) gss_mech_krb5, 22+tmsglen, &ptr, toktype);
+ g_make_token_header((gss_OID) oid, 14+cksum_size+tmsglen, &ptr, toktype);
- /* for now, only generate DES integrity */
+ /* 0..1 SIGN_ALG */
- ptr[0] = 0;
+ ptr[0] = signalg;
ptr[1] = 0;
+
+ /* 2..3 SEAL_ALG or Filler */
- /* SEAL_ALG, or filler */
-
- if (((toktype == KG_TOK_SEAL_MSG) ||
- (toktype == KG_TOK_WRAP_MSG)) && encrypt) {
- ptr[2] = 0;
+ if ((toktype == KG_TOK_SEAL_MSG) && encrypt) {
+ ptr[2] = sealalg;
ptr[3] = 0;
} else {
+ /* No seal */
ptr[2] = 0xff;
ptr[3] = 0xff;
}
- /* filler */
+ /* 4..5 Filler */
ptr[4] = 0xff;
ptr[5] = 0xff;
/* pad the plaintext, encrypt if needed, and stick it in the token */
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)) {
+ /* initialize the the cksum and allocate the contents buffer */
+ md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
+ md5cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
+ if ((md5cksum.contents = (krb5_octet *) xmalloc(md5cksum.length)) == NULL) {
+ return(ENOMEM);
+ }
+
+ if (toktype == KG_TOK_SEAL_MSG) {
unsigned char *plain;
unsigned char pad;
- if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
- xfree(t);
- return(ENOMEM);
- }
+ if (!bigend || encrypt) {
+ if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(ENOMEM);
+ }
- if (code = kg_make_confounder(enc_ed, plain)) {
- xfree(plain);
- xfree(t);
- return(code);
- }
+ if (code = kg_make_confounder(enc_ed, plain)) {
+ xfree(plain);
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(code);
+ }
- memcpy(plain+8, text->value, text->length);
+ memcpy(plain+conflen, text->value, text->length);
- pad = 8-(text->length%8);
+ /* XXX 8 is DES cblock size */
+ pad = 8-(text->length%8);
- memset(plain+8+text->length, pad, pad);
+ memset(plain+conflen+text->length, pad, pad);
+ } else {
+ /* plain is never used in the bigend && !encrypt case */
+ plain = NULL;
+ }
if (encrypt) {
- if (code = kg_encrypt(enc_ed, NULL, (krb5_pointer) plain,
- (krb5_pointer) (ptr+22), tmsglen)) {
- xfree(plain);
+ if (code = kg_encrypt(context, enc_ed, NULL, (krb5_pointer) plain,
+ (krb5_pointer) (ptr+cksum_size+14), tmsglen)) {
+ if (plain)
+ xfree(plain);
+ xfree(md5cksum.contents);
xfree(t);
return(code);
}
} else {
if (bigend)
- memcpy(ptr+22, text->value, text->length);
+ memcpy(ptr+14+cksum_size, text->value, text->length);
else
- memcpy(ptr+22, plain, tmsglen);
+ memcpy(ptr+14+cksum_size, plain, tmsglen);
}
/* compute the checksum */
- krb5_MD5Init(&md5);
- krb5_MD5Update(&md5, (unsigned char *) ptr-2, 8);
+ /* 8 = head of token body as specified by mech spec */
+ if (! (data_ptr =
+ (char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) {
+ if (plain)
+ xfree(plain);
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(ENOMEM);
+ }
+ (void) memcpy(data_ptr, ptr-2, 8);
if (bigend)
- krb5_MD5Update(&md5, text->value, text->length);
+ (void) memcpy(data_ptr+8, text->value, text->length);
else
- krb5_MD5Update(&md5, plain, tmsglen);
- krb5_MD5Final(&md5);
+ (void) memcpy(data_ptr+8, plain, tmsglen);
+ code = krb5_calculate_checksum(context, md5cksum.checksum_type, data_ptr,
+ 8 + (bigend ? text->length : tmsglen),
+ 0, 0, &md5cksum);
+ xfree(data_ptr);
+
+ if (code) {
+ if (plain)
+ xfree(plain);
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(code);
+ memcpy(ptr+14+cksum_size, plain, tmsglen);
+ }
- xfree(plain);
+ if (plain)
+ xfree(plain);
} else {
/* compute the checksum */
- krb5_MD5Init(&md5);
- krb5_MD5Update(&md5, (unsigned char *) ptr-2, 8);
- krb5_MD5Update(&md5, text->value, text->length);
- krb5_MD5Final(&md5);
+ if (! (data_ptr = (char *) xmalloc(8 + text->length))) {
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(ENOMEM);
+ }
+ (void) memcpy(data_ptr, ptr-2, 8);
+ (void) memcpy(data_ptr+8, text->value, text->length);
+ code = krb5_calculate_checksum(context, md5cksum.checksum_type, data_ptr,
+ 8 + text->length,
+ 0, 0, &md5cksum);
+ xfree(data_ptr);
+ if (code) {
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(code);
+ }
}
- /* XXX this depends on the key being a single-des key, but that's
- all that kerberos supports right now */
-
- desmac.length = sizeof(cbc_checksum);
- desmac.contents = cbc_checksum;
- if (code = krb5_calculate_checksum(context, CKSUMTYPE_DESCBC, md5.digest, 16,
- seq_ed->key->contents,
- seq_ed->key->length,
- &desmac)) {
- xfree(t);
- return(code);
+ switch(signalg) {
+ case 0:
+ case 3:
+
+#if 0
+ /* XXX this depends on the key being a single-des key */
+
+ /* DES CBC doesn't use a zero IV like it should in some
+ krb5 implementations (beta5+). So we just do the
+ DES encryption the long way, and keep the last block
+ as the MAC */
+
+ /* initialize the the cksum and allocate the contents buffer */
+ cksum.checksum_type = CKSUMTYPE_DESCBC;
+ cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC);
+ if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL)
+ return(ENOMEM);
+
+ if (code = krb5_calculate_checksum(context, cksum.checksum_type,
+ md5cksum.contents, 16,
+ seq_ed->key->contents,
+ seq_ed->key->length,
+ &cksum)) {
+ xfree(cksum.contents);
+ xfree(md5cksum.contents);
+ xfree(t);
+ return(code);
+ }
+
+ memcpy(ptr+14, cksum.contents, 8);
+
+ xfree(cksum.contents);
+#else
+ if (code = kg_encrypt(context, seq_ed,
+ (g_OID_equal(oid, gss_mech_krb5_old) ?
+ seq_ed->key->contents : NULL),
+ md5cksum.contents, md5cksum.contents, 16)) {
+ xfree(md5cksum.contents);
+ xfree(t);
+ return code;
+ }
+
+ cksum.length = cksum_size;
+ cksum.contents = md5cksum.contents + 16 - cksum.length;
+
+ memcpy(ptr+14, cksum.contents, cksum.length);
+#endif
+
+ break;
}
- memcpy(ptr+14, desmac.contents, 8);
+ xfree(md5cksum.contents);
/* create the seq_num */
- if (code = kg_make_seq_num(seq_ed, direction?0:0xff, *seqnum,
+ if (code = kg_make_seq_num(context, seq_ed, direction?0:0xff, *seqnum,
ptr+14, ptr+6)) {
xfree(t);
return(code);
@@ -227,60 +322,16 @@ kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req,
if (code = make_seal_token(context, &ctx->enc, &ctx->seq,
&ctx->seq_send, ctx->initiate,
input_message_buffer, output_message_buffer,
- conf_req_flag, toktype, ctx->big_endian)) {
+ ctx->signalg, ctx->cksum_size, ctx->sealalg,
+ conf_req_flag, toktype, ctx->big_endian,
+ ctx->mech_used)) {
*minor_status = code;
return(GSS_S_FAILURE);
}
- if (((toktype == KG_TOK_SEAL_MSG) ||
- (toktype == KG_TOK_WRAP_MSG)) && conf_state) {
+ if ((toktype == KG_TOK_SEAL_MSG) && conf_state)
*conf_state = conf_req_flag;
- }
*minor_status = 0;
return((ctx->endtime < now)?GSS_S_CONTEXT_EXPIRED:GSS_S_COMPLETE);
}
-
-OM_uint32
-kg_seal_size(context, minor_status, context_handle, conf_req_flag, qop_req,
- output_size, input_size)
- krb5_context context;
- OM_uint32 *minor_status;
- gss_ctx_id_t context_handle;
- int conf_req_flag;
- gss_qop_t qop_req;
- OM_uint32 output_size;
- OM_uint32 *input_size;
-{
- krb5_gss_ctx_id_rec *ctx;
- OM_uint32 cfsize;
- OM_uint32 ohlen;
-
- /* only default qop is allowed */
- if (qop_req != GSS_C_QOP_DEFAULT) {
- *minor_status = (OM_uint32) G_UNKNOWN_QOP;
- return(GSS_S_FAILURE);
- }
-
- /* validate the context handle */
- if (! kg_validate_ctx_id(context_handle)) {
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
- return(GSS_S_NO_CONTEXT);
- }
-
- ctx = (krb5_gss_ctx_id_rec *) context_handle;
- if (! ctx->established) {
- *minor_status = KG_CTX_INCOMPLETE;
- return(GSS_S_NO_CONTEXT);
- }
-
- /* Calculate the token size and subtract that from the output size */
- cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
- ohlen = g_token_size((gss_OID) gss_mech_krb5, (unsigned int) cfsize + 22);
-
- /* Cannot have trailer length that will cause us to pad over our length */
- *input_size = (output_size - ohlen) & (~7);
- *minor_status = 0;
- return(GSS_S_COMPLETE);
-}
-
diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
index 1b4288c0c..70d2d4d7b 100644
--- a/src/lib/gssapi/krb5/k5unseal.c
+++ b/src/lib/gssapi/krb5/k5unseal.c
@@ -22,7 +22,10 @@
#include "gssapiP_krb5.h"
#include <memory.h>
-#include "rsa-md5.h"
+
+/*
+ * $Id$
+ */
/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
conf_state is only valid if SEAL.
@@ -44,19 +47,25 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
krb5_error_code code;
int bodysize;
int tmsglen;
+ int conflen;
int signalg;
int sealalg;
gss_buffer_desc token;
unsigned char *ptr;
+ krb5_checksum cksum;
krb5_checksum desmac;
- krb5_octet cbc_checksum[KRB5_MIT_DES_KEYSIZE];
- krb5_MD5_CTX md5;
- unsigned char *cksum;
+ krb5_checksum md5cksum;
+ char *data_ptr;
krb5_timestamp now;
unsigned char *plain;
+ int cksum_len;
int plainlen;
+ int err;
+ int direction;
+ krb5_int32 seqnum;
+ OM_uint32 retval;
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)) {
+ if (toktype == KG_TOK_SEAL_MSG) {
message_buffer->length = 0;
message_buffer->value = NULL;
}
@@ -80,73 +89,109 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
ptr = (unsigned char *) input_token_buffer->value;
- if (! g_verify_token_header((gss_OID) gss_mech_krb5, &bodysize,
- &ptr, toktype, input_token_buffer->length)) {
- *minor_status = 0;
+ if (err = g_verify_token_header((gss_OID) ctx->mech_used, &bodysize,
+ &ptr, toktype,
+ input_token_buffer->length)) {
+ *minor_status = err;
return(GSS_S_DEFECTIVE_TOKEN);
}
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
- tmsglen = bodysize-22;
-
/* get the sign and seal algorithms */
signalg = ptr[0] + (ptr[1]<<8);
sealalg = ptr[2] + (ptr[3]<<8);
- if (((signalg != 0) && (signalg != 1)) ||
- (((toktype != KG_TOK_SEAL_MSG) &&
- (toktype != KG_TOK_WRAP_MSG)) && (sealalg != 0xffff)) ||
- (((toktype == KG_TOK_SEAL_MSG) ||
- (toktype == KG_TOK_WRAP_MSG)) &&
- ((sealalg != 0xffff) && (sealalg != 0))) ||
- (ptr[4] != 0xff) ||
- (ptr[5] != 0xff)) {
- *minor_status = 0;
- return(GSS_S_DEFECTIVE_TOKEN);
+ /* Sanity checks */
+
+ if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
}
+ if ((toktype != KG_TOK_SEAL_MSG) &&
+ (sealalg != 0xffff)) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ /* in the current spec, there is only one valid seal algorithm per
+ key type, so a simple comparison is ok */
+
+ if ((toktype == KG_TOK_SEAL_MSG) &&
+ !((sealalg == 0xffff) ||
+ (sealalg == ctx->sealalg))) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ /* there are several mappings of seal algorithms to sign algorithms,
+ but few enough that we can try them all. */
+
+ if (((ctx->sealalg == 0) &&
+ (signalg > 1)) ||
+ ((ctx->sealalg == 1) &&
+ (signalg != 3))) {
+ *minor_status = 0;
+ return GSS_S_DEFECTIVE_TOKEN;
+ }
+
+ switch (signalg) {
+ case 0:
+ case 1:
+ cksum_len = 8;
+ break;
+ case 3:
+ cksum_len = 16;
+ break;
+ }
+
+ if (toktype == KG_TOK_SEAL_MSG)
+ tmsglen = bodysize-(14+cksum_len);
+
/* get the token parameters */
/* decode the message, if SEAL */
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG)) {
- if (sealalg == 0) {
+ if (toktype == KG_TOK_SEAL_MSG) {
+ if (sealalg != 0xffff) {
if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
- if (code = kg_decrypt(&ctx->enc, NULL, ptr+22, plain, tmsglen)) {
+ if (code = kg_decrypt(context, &ctx->enc, NULL,
+ ptr+14+cksum_len, plain, tmsglen)) {
xfree(plain);
*minor_status = code;
return(GSS_S_FAILURE);
}
} else {
- plain = ptr+22;
+ plain = ptr+14+cksum_len;
}
plainlen = tmsglen;
- if (sealalg && ctx->big_endian)
+ if ((sealalg == 0xffff) && ctx->big_endian) {
token.length = tmsglen;
- else
- token.length = tmsglen - 8 - plain[tmsglen-1];
+ } else {
+ conflen = kg_confounder_size(&ctx->enc);
+ token.length = tmsglen - conflen - plain[tmsglen-1];
+ }
if (token.length) {
- if ((token.value = xmalloc(token.length)) == NULL) {
- if (sealalg == 0)
+ if ((token.value = (void *) xmalloc(token.length)) == NULL) {
+ if (sealalg != 0xffff)
xfree(plain);
*minor_status = ENOMEM;
return(GSS_S_FAILURE);
}
- if (sealalg && ctx->big_endian)
+ if ((sealalg == 0xffff) && ctx->big_endian)
memcpy(token.value, plain, token.length);
else
- memcpy(token.value, plain+8, token.length);
+ memcpy(token.value, plain+conflen, token.length);
}
- } else if ((toktype == KG_TOK_SIGN_MSG) || (toktype == KG_TOK_MIC_MSG)) {
+ } else if (toktype == KG_TOK_SIGN_MSG) {
token = *message_buffer;
plain = token.value;
plainlen = token.length;
@@ -159,81 +204,184 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
/* compute the checksum of the message */
- if (signalg == 0) {
+ /* initialize the the cksum and allocate the contents buffer */
+ md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
+ md5cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
+ if ((md5cksum.contents = (krb5_octet *) xmalloc(md5cksum.length)) == NULL) {
+ if (sealalg != 0xffff)
+ xfree(plain);
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ switch (signalg) {
+ case 0:
+ case 3:
/* compute the checksum of the message */
- krb5_MD5Init(&md5);
- krb5_MD5Update(&md5, (unsigned char *) ptr-2, 8);
+ /* 8 = bytes of token body to be checksummed according to spec */
+
+ if (! (data_ptr = (void *)
+ xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
+ xfree(md5cksum.contents);
+ if (sealalg != 0xffff)
+ xfree(plain);
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ (void) memcpy(data_ptr, ptr-2, 8);
+
if (ctx->big_endian)
- krb5_MD5Update(&md5, token.value, token.length);
+ (void) memcpy(data_ptr+8, token.value, token.length);
else
- krb5_MD5Update(&md5, plain, plainlen);
- krb5_MD5Final(&md5);
-
- if (sealalg == 0)
- xfree(plain);
+ (void) memcpy(data_ptr+8, plain, plainlen);
+
+ code = krb5_calculate_checksum(context, md5cksum.checksum_type,
+ data_ptr, 8 +
+ (ctx->big_endian ? token.length :
+ plainlen), 0, 0, &md5cksum);
+ xfree(data_ptr);
+
+ if (code) {
+ xfree(md5cksum.contents);
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+#if 0
/* XXX this depends on the key being a single-des key, but that's
all that kerberos supports right now */
- desmac.length = sizeof(cbc_checksum);
- desmac.contents = cbc_checksum;
- if (code = krb5_calculate_checksum(context, CKSUMTYPE_DESCBC, md5.digest,
- 16, ctx->seq.key->contents,
+
+ /* initialize the the cksum and allocate the contents buffer */
+ cksum.checksum_type = CKSUMTYPE_DESCBC;
+ cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC);
+ if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL) {
+ xfree(md5cksum.contents);
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ if (code = krb5_calculate_checksum(context, cksum.checksum_type,
+ md5cksum.contents, 16,
+ ctx->seq.key->contents,
ctx->seq.key->length,
- &desmac)) {
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
+ &cksum)) {
+ xfree(cksum.contents);
+ xfree(md5cksum.contents);
+ if (toktype == KG_TOK_SEAL_MSG)
xfree(token.value);
*minor_status = code;
return(GSS_S_FAILURE);
}
- cksum = desmac.contents;
- } else {
- if (! ctx->seed_init) {
- if (code = kg_make_seed(ctx->subkey, ctx->seed)) {
- if (sealalg == 0)
+ code = memcmp(cksum.contents, ptr+14, cksum.length);
+
+ xfree(cksum.contents);
+#else
+ if (code = kg_encrypt(context, &ctx->seq,
+ (g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ?
+ ctx->seq.key->contents : NULL),
+ md5cksum.contents, md5cksum.contents, 16)) {
+ xfree(md5cksum.contents);
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (signalg == 0)
+ cksum.length = 8;
+ else
+ cksum.length = 16;
+ cksum.contents = md5cksum.contents + 16 - cksum.length;
+
+ code = memcmp(cksum.contents, ptr+14, cksum.length);
+#endif
+ break;
+
+ case 1:
+ if (!ctx->seed_init &&
+ (code = kg_make_seed(context, ctx->subkey, ctx->seed))) {
+ xfree(md5cksum.contents);
+ if (sealalg != 0xffff)
xfree(plain);
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
+ if (toktype == KG_TOK_SEAL_MSG)
xfree(token.value);
- *minor_status = code;
- return(GSS_S_FAILURE);
- }
- ctx->seed_init = 1;
+ *minor_status = code;
+ return GSS_S_FAILURE;
+ }
+
+ if (! (data_ptr = (void *)
+ xmalloc(sizeof(ctx->seed) + 8 +
+ (ctx->big_endian ? token.length : plainlen)))) {
+ xfree(md5cksum.contents);
+ if (sealalg == 0)
+ xfree(plain);
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
}
-
- krb5_MD5Init(&md5);
- krb5_MD5Update(&md5, ctx->seed, sizeof(ctx->seed));
- krb5_MD5Update(&md5, (unsigned char *) ptr-2, 8);
+ (void) memcpy(data_ptr, ptr-2, 8);
+ (void) memcpy(data_ptr+8, ctx->seed, sizeof(ctx->seed));
if (ctx->big_endian)
- krb5_MD5Update(&md5, token.value, token.length);
+ (void) memcpy(data_ptr+8+sizeof(ctx->seed),
+ token.value, token.length);
else
- krb5_MD5Update(&md5, plain, plainlen);
- krb5_MD5Final(&md5);
+ (void) memcpy(data_ptr+8+sizeof(ctx->seed),
+ plain, plainlen);
+ code = krb5_calculate_checksum(context, md5cksum.checksum_type,
+ data_ptr, 8 + sizeof(ctx->seed) +
+ (ctx->big_endian ? token.length :
+ plainlen), 0, 0, &md5cksum);
+
+ xfree(data_ptr);
+
+ if (code) {
+ xfree(md5cksum.contents);
+ if (sealalg == 0)
+ xfree(plain);
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
- if (sealalg == 0)
- xfree(plain);
+ code = memcmp(md5cksum.contents, ptr+14, 8);
- cksum = md5.digest;
+ default:
+ *minor_status = 0;
+ return(GSS_S_DEFECTIVE_TOKEN);
}
-
+
+ xfree(md5cksum.contents);
+ if (sealalg != 0xffff)
+ xfree(plain);
+
/* compare the computed checksum against the transmitted checksum */
- if (memcmp(cksum, ptr+14, 8) != 0) {
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype == KG_TOK_WRAP_MSG))
+ if (code) {
+ if (toktype == KG_TOK_SEAL_MSG)
xfree(token.value);
*minor_status = 0;
return(GSS_S_BAD_SIG);
}
+
- /* XXX this is where the seq_num check would go */
-
/* it got through unscathed. Make sure the context is unexpired */
- if ((toktype == KG_TOK_SEAL_MSG) || (toktype = KG_TOK_WRAP_MSG))
+ if (toktype == KG_TOK_SEAL_MSG)
*message_buffer = token;
if (conf_state)
- *conf_state = (sealalg == 0);
+ *conf_state = (sealalg != 0xffff);
if (qop_state)
*qop_state = GSS_C_QOP_DEFAULT;
@@ -248,8 +396,28 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
return(GSS_S_CONTEXT_EXPIRED);
}
- /* success */
+ /* do sequencing checks */
+
+ if (code = kg_get_seq_num(context, &(ctx->seq), ptr+14, ptr+6, &direction,
+ &seqnum)) {
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = code;
+ return(GSS_S_BAD_SIG);
+ }
+
+ if ((ctx->initiate && direction != 0xff) ||
+ (!ctx->initiate && direction != 0)) {
+ if (toktype == KG_TOK_SEAL_MSG)
+ xfree(token.value);
+ *minor_status = G_BAD_DIRECTION;
+ return(GSS_S_BAD_SIG);
+ }
+
+ retval = g_order_check(&(ctx->seqstate), seqnum);
+
+ /* success or ordering violation */
*minor_status = 0;
- return(GSS_S_COMPLETE);
+ return(retval);
}
diff --git a/src/lib/gssapi/krb5/krb5_gss_glue.c b/src/lib/gssapi/krb5/krb5_gss_glue.c
new file mode 100644
index 000000000..f22e9d633
--- /dev/null
+++ b/src/lib/gssapi/krb5/krb5_gss_glue.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id$
+ */
+
+#include "gssapiP_krb5.h"
+
+OM_uint32 INTERFACE
+gss_accept_sec_context(minor_status, context_handle, verifier_cred_handle,
+ input_token, input_chan_bindings, src_name, mech_type,
+ output_token, ret_flags, time_rec, delegated_cred_handle)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t *context_handle;
+ gss_cred_id_t verifier_cred_handle;
+ gss_buffer_t input_token;
+ gss_channel_bindings_t input_chan_bindings;
+ gss_name_t *src_name;
+ gss_OID *mech_type;
+ gss_buffer_t output_token;
+ OM_uint32 *ret_flags;
+ OM_uint32 *time_rec;
+ gss_cred_id_t *delegated_cred_handle;
+{
+ return(krb5_gss_accept_sec_context(minor_status,
+ context_handle,
+ verifier_cred_handle,
+ input_token,
+ input_chan_bindings,
+ src_name,
+ mech_type,
+ output_token,
+ ret_flags,
+ time_rec,
+ delegated_cred_handle));
+}
+
+OM_uint32 INTERFACE
+gss_acquire_cred(minor_status, desired_name, time_req, desired_mechs,
+ cred_usage, output_cred_handle, actual_mechs, time_rec)
+ OM_uint32 *minor_status;
+ gss_name_t desired_name;
+ OM_uint32 time_req;
+ gss_OID_set desired_mechs;
+ gss_cred_usage_t cred_usage;
+ gss_cred_id_t *output_cred_handle;
+ gss_OID_set *actual_mechs;
+ OM_uint32 *time_rec;
+{
+ return(krb5_gss_acquire_cred(minor_status,
+ desired_name,
+ time_req,
+ desired_mechs,
+ cred_usage,
+ output_cred_handle,
+ actual_mechs,
+ time_rec));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech,
+ cred_usage, initiator_time_req, acceptor_time_req,
+ output_cred_handle, actual_mechs, initiator_time_rec,
+ acceptor_time_rec)
+ OM_uint32 *minor_status;
+ gss_cred_id_t input_cred_handle;
+ gss_name_t desired_name;
+ gss_OID desired_mech;
+ gss_cred_usage_t cred_usage;
+ OM_uint32 initiator_time_req;
+ OM_uint32 acceptor_time_req;
+ gss_cred_id_t *output_cred_handle;
+ gss_OID_set *actual_mechs;
+ OM_uint32 *initiator_time_rec;
+ OM_uint32 *acceptor_time_rec;
+{
+ return(krb5_gss_add_cred(minor_status, input_cred_handle, desired_name,
+ desired_mech, cred_usage, initiator_time_req,
+ acceptor_time_req, output_cred_handle,
+ actual_mechs, initiator_time_rec,
+ acceptor_time_rec));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_add_oid_set_member(minor_status, member_oid, oid_set)
+ OM_uint32 *minor_status;
+ gss_OID member_oid;
+ gss_OID_set *oid_set;
+{
+ return(generic_gss_add_oid_set_member(minor_status, member_oid, oid_set));
+}
+
+OM_uint32 INTERFACE
+gss_compare_name(minor_status, name1, name2, name_equal)
+ OM_uint32 *minor_status;
+ gss_name_t name1;
+ gss_name_t name2;
+ int *name_equal;
+{
+ return(krb5_gss_compare_name(minor_status, name1,
+ name2, name_equal));
+}
+
+OM_uint32 INTERFACE
+gss_context_time(minor_status, context_handle, time_rec)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ OM_uint32 *time_rec;
+{
+ return(krb5_gss_context_time(minor_status, context_handle,
+ time_rec));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_create_empty_oid_set(minor_status, oid_set)
+ OM_uint32 *minor_status;
+ gss_OID_set *oid_set;
+{
+ return(generic_gss_create_empty_oid_set(minor_status, oid_set));
+}
+
+OM_uint32 INTERFACE
+gss_delete_sec_context(minor_status, context_handle, output_token)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t *context_handle;
+ gss_buffer_t output_token;
+{
+ return(krb5_gss_delete_sec_context(minor_status,
+ context_handle, output_token));
+}
+
+OM_uint32 INTERFACE
+gss_display_name(minor_status, input_name, output_name_buffer, output_name_type)
+ OM_uint32 *minor_status;
+ gss_name_t input_name;
+ gss_buffer_t output_name_buffer;
+ gss_OID *output_name_type;
+{
+ return(krb5_gss_display_name(minor_status, input_name,
+ output_name_buffer, output_name_type));
+}
+
+OM_uint32 INTERFACE
+gss_display_status(minor_status, status_value, status_type,
+ mech_type, message_context, status_string)
+ OM_uint32 *minor_status;
+ OM_uint32 status_value;
+ int status_type;
+ gss_OID mech_type;
+ OM_uint32 *message_context;
+ gss_buffer_t status_string;
+{
+ return(krb5_gss_display_status(minor_status, status_value,
+ status_type, mech_type, message_context,
+ status_string));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_export_sec_context(minor_status, context_handle, interprocess_token)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t *context_handle;
+ gss_buffer_t interprocess_token;
+{
+ return(krb5_gss_export_sec_context(minor_status,
+ context_handle,
+ interprocess_token));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_get_mic(minor_status, context_handle, qop_req,
+ message_buffer, message_token)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_qop_t qop_req;
+ gss_buffer_t message_buffer;
+ gss_buffer_t message_token;
+{
+ return(krb5_gss_get_mic(minor_status, context_handle,
+ qop_req, message_buffer, message_token));
+}
+
+OM_uint32 INTERFACE
+gss_import_name(minor_status, input_name_buffer, input_name_type, output_name)
+ OM_uint32 *minor_status;
+ gss_buffer_t input_name_buffer;
+ gss_OID input_name_type;
+ gss_name_t *output_name;
+{
+ return(krb5_gss_import_name(minor_status, input_name_buffer,
+ input_name_type, output_name));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_import_sec_context(minor_status, interprocess_token, context_handle)
+ OM_uint32 *minor_status;
+ gss_buffer_t interprocess_token;
+ gss_ctx_id_t *context_handle;
+{
+ return(krb5_gss_import_sec_context(minor_status,
+ interprocess_token,
+ context_handle));
+}
+
+OM_uint32 INTERFACE
+gss_indicate_mechs(minor_status, mech_set)
+ OM_uint32 *minor_status;
+ gss_OID_set *mech_set;
+{
+ return(krb5_gss_indicate_mechs(minor_status, mech_set));
+}
+
+OM_uint32 INTERFACE
+gss_init_sec_context(minor_status, claimant_cred_handle, context_handle,
+ target_name, mech_type, req_flags, time_req,
+ input_chan_bindings, input_token, actual_mech_type,
+ output_token, ret_flags, time_rec)
+ OM_uint32 *minor_status;
+ gss_cred_id_t claimant_cred_handle;
+ gss_ctx_id_t *context_handle;
+ gss_name_t target_name;
+ gss_OID mech_type;
+ OM_uint32 req_flags;
+ OM_uint32 time_req;
+ gss_channel_bindings_t input_chan_bindings;
+ gss_buffer_t input_token;
+ gss_OID *actual_mech_type;
+ gss_buffer_t output_token;
+ OM_uint32 *ret_flags;
+ OM_uint32 *time_rec;
+{
+ return(krb5_gss_init_sec_context(minor_status,
+ claimant_cred_handle, context_handle,
+ target_name, mech_type, req_flags,
+ time_req, input_chan_bindings, input_token,
+ actual_mech_type, output_token, ret_flags,
+ time_rec));
+}
+
+OM_uint32 INTERFACE
+gss_inquire_context(minor_status, context_handle, initiator_name, acceptor_name,
+ lifetime_rec, mech_type, ret_flags,
+ locally_initiated, open)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_name_t *initiator_name;
+ gss_name_t *acceptor_name;
+ OM_uint32 *lifetime_rec;
+ gss_OID *mech_type;
+ OM_uint32 *ret_flags;
+ int *locally_initiated;
+ int *open;
+{
+ return(krb5_gss_inquire_context(minor_status, context_handle,
+ initiator_name, acceptor_name, lifetime_rec,
+ mech_type, ret_flags, locally_initiated,
+ open));
+}
+
+OM_uint32 INTERFACE
+gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
+ cred_usage, mechanisms)
+ OM_uint32 *minor_status;
+ gss_cred_id_t cred_handle;
+ gss_name_t *name;
+ OM_uint32 *lifetime_ret;
+ gss_cred_usage_t *cred_usage;
+ gss_OID_set *mechanisms;
+{
+ return(krb5_gss_inquire_cred(minor_status, cred_handle,
+ name, lifetime_ret, cred_usage, mechanisms));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, name,
+ initiator_lifetime, acceptor_lifetime, cred_usage)
+ OM_uint32 *minor_status;
+ gss_cred_id_t cred_handle;
+ gss_OID mech_type;
+ gss_name_t *name;
+ OM_uint32 *initiator_lifetime;
+ OM_uint32 *acceptor_lifetime;
+ gss_cred_usage_t *cred_usage;
+{
+ return(krb5_gss_inquire_cred_by_mech(minor_status, cred_handle,
+ mech_type, name, initiator_lifetime,
+ acceptor_lifetime, cred_usage));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_inquire_names_for_mech(minor_status, mechanism, name_types)
+ OM_uint32 *minor_status;
+ gss_OID mechanism;
+ gss_OID_set *name_types;
+{
+ return(krb5_gss_inquire_names_for_mech(minor_status,
+ mechanism,
+ name_types));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_oid_to_str(minor_status, oid, oid_str)
+ OM_uint32 *minor_status;
+ gss_OID oid;
+ gss_buffer_t oid_str;
+{
+ return(generic_gss_oid_to_str(minor_status, oid, oid_str));
+}
+
+OM_uint32 INTERFACE
+gss_process_context_token(minor_status, context_handle, token_buffer)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_buffer_t token_buffer;
+{
+ return(krb5_gss_process_context_token(minor_status,
+ context_handle, token_buffer));
+}
+
+OM_uint32 INTERFACE
+gss_release_cred(minor_status, cred_handle)
+ OM_uint32 *minor_status;
+ gss_cred_id_t *cred_handle;
+{
+ return(krb5_gss_release_cred(minor_status, cred_handle));
+}
+
+OM_uint32 INTERFACE
+gss_release_name(minor_status, input_name)
+ OM_uint32 *minor_status;
+ gss_name_t *input_name;
+{
+ return(krb5_gss_release_name(minor_status, input_name));
+}
+
+OM_uint32 INTERFACE
+gss_release_buffer(minor_status, buffer)
+ OM_uint32 *minor_status;
+ gss_buffer_t buffer;
+{
+ return(generic_gss_release_buffer(minor_status,
+ buffer));
+}
+
+#if 0
+/* V2 */
+OM_uint32 INTERFACE
+gss_release_oid(minor_status, oid)
+ OM_uint32 *minor_status;
+ gss_OID *oid;
+{
+ return(krb5_gss_release_oid(minor_status, oid));
+}
+#endif
+
+OM_uint32 INTERFACE
+gss_release_oid_set(minor_status, set)
+ OM_uint32* minor_status;
+ gss_OID_set *set;
+{
+ return(generic_gss_release_oid_set(minor_status, set));
+}
+
+/* V1 only */
+OM_uint32 INTERFACE
+gss_seal(minor_status, context_handle, conf_req_flag, qop_req,
+ input_message_buffer, conf_state, output_message_buffer)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ int conf_req_flag;
+ int qop_req;
+ gss_buffer_t input_message_buffer;
+ int *conf_state;
+ gss_buffer_t output_message_buffer;
+{
+ return(krb5_gss_seal(minor_status, context_handle,
+ conf_req_flag, qop_req, input_message_buffer,
+ conf_state, output_message_buffer));
+}
+
+OM_uint32 INTERFACE
+gss_sign(minor_status, context_handle,
+ qop_req, message_buffer,
+ message_token)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ int qop_req;
+ gss_buffer_t message_buffer;
+ gss_buffer_t message_token;
+{
+ return(krb5_gss_sign(minor_status, context_handle,
+ qop_req, message_buffer, message_token));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_verify_mic(minor_status, context_handle,
+ message_buffer, token_buffer, qop_state)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_buffer_t message_buffer;
+ gss_buffer_t token_buffer;
+ gss_qop_t *qop_state;
+{
+ return(krb5_gss_verify_mic(minor_status, context_handle,
+ message_buffer, token_buffer, qop_state));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_wrap(minor_status, context_handle, conf_req_flag, qop_req,
+ input_message_buffer, conf_state, output_message_buffer)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ int conf_req_flag;
+ gss_qop_t qop_req;
+ gss_buffer_t input_message_buffer;
+ int *conf_state;
+ gss_buffer_t output_message_buffer;
+{
+ return(krb5_gss_wrap(minor_status, context_handle, conf_req_flag, qop_req,
+ input_message_buffer, conf_state,
+ output_message_buffer));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_str_to_oid(minor_status, oid_str, oid)
+ OM_uint32 *minor_status;
+ gss_buffer_t oid_str;
+ gss_OID *oid;
+{
+ return(generic_gss_str_to_oid(minor_status, oid_str, oid));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_test_oid_set_member(minor_status, member, set, present)
+ OM_uint32 *minor_status;
+ gss_OID member;
+ gss_OID_set set;
+ int *present;
+{
+ return(generic_gss_test_oid_set_member(minor_status, member, set,
+ present));
+}
+
+/* V1 only */
+OM_uint32 INTERFACE
+gss_unseal(minor_status, context_handle, input_message_buffer,
+ output_message_buffer, conf_state, qop_state)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_buffer_t input_message_buffer;
+ gss_buffer_t output_message_buffer;
+ int *conf_state;
+ int *qop_state;
+{
+ return(krb5_gss_unseal(minor_status, context_handle,
+ input_message_buffer, output_message_buffer,
+ conf_state, qop_state));
+}
+
+/* V2 */
+OM_uint32 INTERFACE
+gss_unwrap(minor_status, context_handle, input_message_buffer,
+ output_message_buffer, conf_state, qop_state)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_buffer_t input_message_buffer;
+ gss_buffer_t output_message_buffer;
+ int *conf_state;
+ gss_qop_t *qop_state;
+{
+ return(krb5_gss_unwrap(minor_status, context_handle, input_message_buffer,
+ output_message_buffer, conf_state, qop_state));
+}
+
+/* V1 only */
+OM_uint32 INTERFACE
+gss_verify(minor_status, context_handle, message_buffer,
+ token_buffer, qop_state)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_buffer_t message_buffer;
+ gss_buffer_t token_buffer;
+ int *qop_state;
+{
+ return(krb5_gss_verify(minor_status,
+ context_handle,
+ message_buffer,
+ token_buffer,
+ qop_state));
+}
+
+/* V2 interface */
+OM_uint32 INTERFACE
+gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+ qop_req, req_output_size, max_input_size)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ int conf_req_flag;
+ gss_qop_t qop_req;
+ OM_uint32 req_output_size;
+ OM_uint32 *max_input_size;
+{
+ return(krb5_gss_wrap_size_limit(minor_status, context_handle,
+ conf_req_flag, qop_req,
+ req_output_size, max_input_size));
+}
diff --git a/src/lib/gssapi/krb5/process_context_token.c b/src/lib/gssapi/krb5/process_context_token.c
index 80affbd27..4639108d5 100644
--- a/src/lib/gssapi/krb5/process_context_token.c
+++ b/src/lib/gssapi/krb5/process_context_token.c
@@ -22,18 +22,24 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_process_context_token(ct, minor_status, context_handle,
+krb5_gss_process_context_token(minor_status, context_handle,
token_buffer)
- void *ct;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t token_buffer;
{
- krb5_context context = ct;
+ krb5_context context;
krb5_gss_ctx_id_rec *ctx;
OM_uint32 majerr;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
/* validate the context handle */
if (! kg_validate_ctx_id(context_handle)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
@@ -56,6 +62,6 @@ krb5_gss_process_context_token(ct, minor_status, context_handle,
/* that's it. delete the context */
- return(krb5_gss_delete_sec_context(context, minor_status, &context_handle,
+ return(krb5_gss_delete_sec_context(minor_status, &context_handle,
GSS_C_NO_BUFFER));
}
diff --git a/src/lib/gssapi/krb5/rel_cred.c b/src/lib/gssapi/krb5/rel_cred.c
index 297699fe1..df301987b 100644
--- a/src/lib/gssapi/krb5/rel_cred.c
+++ b/src/lib/gssapi/krb5/rel_cred.c
@@ -23,15 +23,17 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_release_cred(ctx, minor_status, cred_handle)
- void *ctx;
+krb5_gss_release_cred(minor_status, cred_handle)
OM_uint32 *minor_status;
gss_cred_id_t *cred_handle;
{
- krb5_context context = ctx;
+ krb5_context context;
krb5_gss_cred_id_t cred;
krb5_error_code code1, code2;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if (*cred_handle == GSS_C_NO_CREDENTIAL)
return(kg_release_defcred(minor_status));
diff --git a/src/lib/gssapi/krb5/rel_name.c b/src/lib/gssapi/krb5/rel_name.c
index 40ff0d2d3..56f56d060 100644
--- a/src/lib/gssapi/krb5/rel_name.c
+++ b/src/lib/gssapi/krb5/rel_name.c
@@ -23,13 +23,15 @@
#include "gssapiP_krb5.h"
OM_uint32
-krb5_gss_release_name(ctx, minor_status, input_name)
- void *ctx;
+krb5_gss_release_name(minor_status, input_name)
OM_uint32 *minor_status;
gss_name_t *input_name;
{
- krb5_context context = ctx;
+ krb5_context context;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
if (! kg_validate_name(*input_name)) {
*minor_status = (OM_uint32) G_VALIDATE_FAILED;
return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
diff --git a/src/lib/gssapi/krb5/rel_oid.c b/src/lib/gssapi/krb5/rel_oid.c
index 32e697ace..d5ec7bcc7 100644
--- a/src/lib/gssapi/krb5/rel_oid.c
+++ b/src/lib/gssapi/krb5/rel_oid.c
@@ -73,6 +73,7 @@ krb5_gss_internal_release_oid(ct, minor_status, oid)
*/
if ((*oid != gss_mech_krb5) &&
+ (*oid != gss_mech_krb5_old) &&
(*oid != gss_nt_krb5_name) &&
(*oid != gss_nt_krb5_principal)) {
/* We don't know about this OID */
diff --git a/src/lib/gssapi/krb5/seal.c b/src/lib/gssapi/krb5/seal.c
index ca52a60af..818de191f 100644
--- a/src/lib/gssapi/krb5/seal.c
+++ b/src/lib/gssapi/krb5/seal.c
@@ -22,11 +22,14 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_seal(ctx, minor_status, context_handle, conf_req_flag,
+krb5_gss_seal(minor_status, context_handle, conf_req_flag,
qop_req, input_message_buffer, conf_state,
output_message_buffer)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int conf_req_flag;
@@ -35,7 +38,11 @@ krb5_gss_seal(ctx, minor_status, context_handle, conf_req_flag,
int *conf_state;
gss_buffer_t output_message_buffer;
{
- krb5_context context = ctx;
+ krb5_context context;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
return(kg_seal(context, minor_status, context_handle, conf_req_flag,
qop_req, input_message_buffer, conf_state,
output_message_buffer, KG_TOK_SEAL_MSG));
@@ -43,10 +50,9 @@ krb5_gss_seal(ctx, minor_status, context_handle, conf_req_flag,
/* V2 interface */
OM_uint32
-krb5_gss_wrap(ctx, minor_status, context_handle, conf_req_flag,
+krb5_gss_wrap(minor_status, context_handle, conf_req_flag,
qop_req, input_message_buffer, conf_state,
output_message_buffer)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int conf_req_flag;
@@ -55,28 +61,13 @@ krb5_gss_wrap(ctx, minor_status, context_handle, conf_req_flag,
int *conf_state;
gss_buffer_t output_message_buffer;
{
- krb5_context context = ctx;
+ krb5_context context;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
return(kg_seal(context, minor_status, context_handle, conf_req_flag,
(int) qop_req, input_message_buffer, conf_state,
output_message_buffer, KG_TOK_WRAP_MSG));
}
-/* V2 interface */
-OM_uint32
-krb5_gss_wrap_size_limit(ctx, minor_status, context_handle, conf_req_flag,
- qop_req, req_output_size, max_input_size)
- void *ctx;
- OM_uint32 *minor_status;
- gss_ctx_id_t context_handle;
- int conf_req_flag;
- gss_qop_t qop_req;
- OM_uint32 req_output_size;
- OM_uint32 *max_input_size;
-{
- krb5_context context = ctx;
-
- /* XXX - should just put this in k5seal.c */
- return(kg_seal_size(context, minor_status, context_handle, conf_req_flag,
- qop_req, req_output_size, max_input_size));
-}
diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c
index 5acfd5c67..2a8cd0dd0 100644
--- a/src/lib/gssapi/krb5/ser_sctx.c
+++ b/src/lib/gssapi/krb5/ser_sctx.c
@@ -28,264 +28,17 @@
#include "gssapiP_krb5.h"
/*
- * This module contains routines to [de]serialize krb5_gss_cred_id_t,
+ * This module contains routines to [de]serialize
* krb5_gss_enc_desc and krb5_gss_ctx_id_t.
+ * XXX This whole serialization abstraction is unnecessary in a
+ * non-messaging environment, which krb5 is. Someday, this should
+ * all get redone without the extra level of indirection. I've done
+ * some of this work here, since adding new serializers is an internal
+ * krb5 interface, and I won't use those. There is some more
+ * deobfuscation (no longer anonymizing pointers, mostly) which could
+ * still be done. --marc
*/
-
-/* Windows needs these prototypes since the structure they're assigned
- * into is prototyped.
- */
-static krb5_error_code kg_cred_size
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer arg,
- size_t *sizep));
-
-static krb5_error_code kg_cred_externalize
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer arg,
- krb5_octet **buffer,
- size_t *lenremain));
-
-static krb5_error_code kg_cred_internalize
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer *argp,
- krb5_octet **buffer,
- size_t *lenremain));
-
-static krb5_error_code kg_enc_desc_size
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer arg,
- size_t *sizep));
-
-static krb5_error_code kg_enc_desc_externalize
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer arg,
- krb5_octet **buffer,
- size_t *lenremain));
-
-static krb5_error_code kg_enc_desc_internalize
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer *argp,
- krb5_octet **buffer,
- size_t *lenremain));
-
-static krb5_error_code kg_ctx_size
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer arg,
- size_t *sizep));
-
-static krb5_error_code kg_ctx_externalize
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer arg,
- krb5_octet **buffer,
- size_t *lenremain));
-
-static krb5_error_code kg_ctx_internalize
- PROTOTYPE((krb5_context kcontext,
- krb5_pointer *argp,
- krb5_octet **buffer,
- size_t *lenremain));
-
-/*
- * Determine the size required for this krb5_gss_cred_id_t.
- */
-static krb5_error_code
-kg_cred_size(kcontext, arg, sizep)
- krb5_context kcontext;
- krb5_pointer arg;
- size_t *sizep;
-{
- krb5_error_code kret;
- krb5_gss_cred_id_t cred;
- size_t required;
-
- /*
- * krb5_gss_cred_id_t requires:
- * krb5_int32 for KG_CRED
- * krb5_int32 for usage.
- * krb5_int32 for tgt_expire.
- * krb5_int32 for trailer.
- */
- kret = EINVAL;
- if ((cred = (krb5_gss_cred_id_t) arg)) {
- required = 4*sizeof(krb5_int32);
- kret = 0;
- if (cred->princ)
- kret = krb5_size_opaque(kcontext,
- KV5M_PRINCIPAL,
- (krb5_pointer) cred->princ,
- &required);
- if (!kret && cred->keytab)
- kret = krb5_size_opaque(kcontext,
- KV5M_KEYTAB,
- (krb5_pointer) cred->keytab,
- &required);
-
- if (!kret && cred->ccache)
- kret = krb5_size_opaque(kcontext,
- KV5M_CCACHE,
- (krb5_pointer) cred->ccache,
- &required);
- if (!kret)
- *sizep += required;
- }
- return(kret);
-}
-
-/*
- * Externalize this krb5_gss_cred_id_t.
- */
-static krb5_error_code
-kg_cred_externalize(kcontext, arg, buffer, lenremain)
- krb5_context kcontext;
- krb5_pointer arg;
- krb5_octet **buffer;
- size_t *lenremain;
-{
- krb5_error_code kret;
- krb5_gss_cred_id_t cred;
- size_t required;
- krb5_octet *bp;
- size_t remain;
-
- required = 0;
- bp = *buffer;
- remain = *lenremain;
- kret = EINVAL;
- if ((cred = (krb5_gss_cred_id_t) arg)) {
- kret = ENOMEM;
- if (!kg_cred_size(kcontext, arg, &required) &&
- (required <= remain)) {
- /* Our identifier */
- (void) krb5_ser_pack_int32(KG_CRED, &bp, &remain);
-
- /* Now static data */
- (void) krb5_ser_pack_int32((krb5_int32) cred->usage, &bp, &remain);
- (void) krb5_ser_pack_int32((krb5_int32) cred->tgt_expire,
- &bp, &remain);
-
- /* Now pack up dynamic data */
- if (cred->princ)
- kret = krb5_externalize_opaque(kcontext,
- KV5M_PRINCIPAL,
- (krb5_pointer) cred->princ,
- &bp, &remain);
- else
- kret = 0;
-
- if (!kret && cred->keytab)
- kret = krb5_externalize_opaque(kcontext,
- KV5M_KEYTAB,
- (krb5_pointer) cred->keytab,
- &bp, &remain);
-
- if (!kret && cred->ccache)
- kret = krb5_externalize_opaque(kcontext,
- KV5M_CCACHE,
- (krb5_pointer) cred->ccache,
- &bp, &remain);
-
- if (!kret) {
- (void) krb5_ser_pack_int32(KG_CRED, &bp, &remain);
- *buffer = bp;
- *lenremain = remain;
- }
- }
- }
- return(kret);
-}
-
-/*
- * Internalize this krb5_gss_cred_id_t.
- */
-static krb5_error_code
-kg_cred_internalize(kcontext, argp, buffer, lenremain)
- krb5_context kcontext;
- krb5_pointer *argp;
- krb5_octet **buffer;
- size_t *lenremain;
-{
- krb5_error_code kret;
- krb5_gss_cred_id_t cred;
- krb5_int32 ibuf;
- krb5_octet *bp;
- size_t remain;
-
- bp = *buffer;
- remain = *lenremain;
- kret = EINVAL;
- /* Read our magic number */
- if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
- ibuf = 0;
- if (ibuf == KG_CRED) {
- kret = ENOMEM;
-
- /* Get a cred */
- if ((remain >= (2*sizeof(krb5_int32))) &&
- (cred = (krb5_gss_cred_id_t)
- xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
- memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
-
- /* Get the static data */
- (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
- cred->usage = (int) ibuf;
- (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
- cred->tgt_expire = (krb5_timestamp) ibuf;
-
- /* cred->princ */
- if ((kret = krb5_internalize_opaque(kcontext,
- KV5M_PRINCIPAL,
- (krb5_pointer *) &cred->princ,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
-
- /* cred->keytab */
- if (!kret &&
- (kret = krb5_internalize_opaque(kcontext,
- KV5M_KEYTAB,
- (krb5_pointer *) &cred->keytab,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
-
- /* cred->ccache */
- if (!kret &&
- (kret = krb5_internalize_opaque(kcontext,
- KV5M_CCACHE,
- (krb5_pointer *) &cred->ccache,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
-
- /* trailer */
- if (!kret &&
- !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
- (ibuf == KG_CRED)) {
- *buffer = bp;
- *lenremain = remain;
- *argp = (krb5_pointer) cred;
- }
- else {
- if (!kret && (ibuf != KG_CRED))
- kret = EINVAL;
- if (cred->ccache)
- krb5_cc_close(kcontext, cred->ccache);
- if (cred->keytab)
- krb5_kt_close(kcontext, cred->keytab);
- if (cred->princ)
- krb5_free_principal(kcontext, cred->princ);
- xfree(cred);
- }
- }
- }
- return(kret);
-}
-
/*
* Determine the size required for this krb5_gss_enc_desc.
*/
@@ -332,7 +85,7 @@ kg_enc_desc_size(kcontext, arg, sizep)
}
return(kret);
}
-
+
/*
* Externalize this krb5_gss_enc_desc.
*/
@@ -387,7 +140,7 @@ kg_enc_desc_externalize(kcontext, arg, buffer, lenremain)
}
return(kret);
}
-
+
/*
* Internalize this krb5_gss_enc_desc.
*/
@@ -471,27 +224,88 @@ kg_enc_desc_internalize(kcontext, argp, buffer, lenremain)
}
return(kret);
}
-
+
+static krb5_error_code
+kg_oid_externalize(kcontext, arg, buffer, lenremain)
+ krb5_context kcontext;
+ krb5_pointer arg;
+ krb5_octet **buffer;
+ size_t *lenremain;
+{
+ gss_OID oid = (gss_OID) arg;
+
+ (void) krb5_ser_pack_int32((krb5_int32) oid->length,
+ buffer, lenremain);
+ (void) krb5_ser_pack_bytes((krb5_octet *) oid->elements,
+ oid->length, buffer, lenremain);
+}
+
+static krb5_error_code
+kg_oid_internalize(kcontext, argp, buffer, lenremain)
+ krb5_context kcontext;
+ krb5_pointer *argp;
+ krb5_octet **buffer;
+ size_t *lenremain;
+{
+ gss_OID oid;
+ krb5_int32 ibuf;
+
+ oid = (gss_OID) malloc(sizeof(gss_OID_desc));
+ if (oid == NULL)
+ return ENOMEM;
+ (void) krb5_ser_unpack_int32(&ibuf, buffer, lenremain);
+ oid->length = ibuf;
+ (void) krb5_ser_unpack_bytes((krb5_octet *) oid->elements,
+ oid->length, buffer, lenremain);
+ return 0;
+}
+
+krb5_error_code
+kg_oid_size(kcontext, arg, sizep)
+ krb5_context kcontext;
+ krb5_pointer arg;
+ size_t *sizep;
+{
+ krb5_error_code kret;
+ gss_OID oid;
+ size_t required;
+
+ kret = EINVAL;
+ if ((oid = (gss_OID) arg)) {
+ required = sizeof(krb5_int32);
+ required += oid->length;
+
+ kret = 0;
+
+ *sizep += required;
+ }
+
+ return(kret);
+}
+
/*
- * Determine the size required for this krb5_gss_ctx_id_t.
+ * Determine the size required for this krb5_gss_ctx_id_rec.
*/
-static krb5_error_code
+krb5_error_code
kg_ctx_size(kcontext, arg, sizep)
krb5_context kcontext;
krb5_pointer arg;
size_t *sizep;
{
krb5_error_code kret;
- krb5_gss_ctx_id_t *ctx;
+ krb5_gss_ctx_id_rec *ctx;
size_t required;
/*
- * krb5_gss_ctx_id_t requires:
+ * krb5_gss_ctx_id_rec requires:
* krb5_int32 for KG_CONTEXT
* krb5_int32 for initiate.
* krb5_int32 for mutual.
* krb5_int32 for seed_init.
* sizeof(seed) for seed
+ * krb5_int32 for signalg.
+ * krb5_int32 for cksum_size.
+ * krb5_int32 for sealalg.
* krb5_int32 for endtime.
* krb5_int32 for flags.
* krb5_int32 for seq_send.
@@ -501,8 +315,8 @@ kg_ctx_size(kcontext, arg, sizep)
* krb5_int32 for trailer.
*/
kret = EINVAL;
- if ((ctx = (krb5_gss_ctx_id_t *) arg)) {
- required = 11*sizeof(krb5_int32);
+ if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
+ required = 14*sizeof(krb5_int32);
required += sizeof(ctx->seed);
kret = 0;
@@ -525,33 +339,30 @@ kg_ctx_size(kcontext, arg, sizep)
&required);
if (!kret)
- kret = krb5_size_opaque(kcontext,
- KG_ENC_DESC,
+ kret = kg_enc_desc_size(kcontext,
(krb5_pointer) &ctx->enc,
&required);
if (!kret)
- kret = krb5_size_opaque(kcontext,
- KG_ENC_DESC,
+ kret = kg_enc_desc_size(kcontext,
(krb5_pointer) &ctx->seq,
&required);
- if (!kret && ctx->auth_context)
- kret = krb5_size_opaque(kcontext,
- KV5M_AUTH_CONTEXT,
- (krb5_pointer) ctx->auth_context,
- &required);
+ if (!kret)
+ kret = kg_oid_size(kcontext,
+ (krb5_pointer) ctx->mech_used,
+ &required);
if (!kret)
*sizep += required;
}
return(kret);
}
-
+
/*
- * Externalize this krb5_gss_ctx_id_t.
+ * Externalize this krb5_gss_ctx_id_ret.
*/
-static krb5_error_code
+krb5_error_code
kg_ctx_externalize(kcontext, arg, buffer, lenremain)
krb5_context kcontext;
krb5_pointer arg;
@@ -559,7 +370,7 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
size_t *lenremain;
{
krb5_error_code kret;
- krb5_gss_ctx_id_t *ctx;
+ krb5_gss_ctx_id_rec *ctx;
size_t required;
krb5_octet *bp;
size_t remain;
@@ -568,7 +379,7 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
bp = *buffer;
remain = *lenremain;
kret = EINVAL;
- if ((ctx = (krb5_gss_ctx_id_t *) arg)) {
+ if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
kret = ENOMEM;
if (!kg_ctx_size(kcontext, arg, &required) &&
(required <= remain)) {
@@ -585,6 +396,12 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
(void) krb5_ser_pack_bytes((krb5_octet *) ctx->seed,
sizeof(ctx->seed),
&bp, &remain);
+ (void) krb5_ser_pack_int32((krb5_int32) ctx->signalg,
+ &bp, &remain);
+ (void) krb5_ser_pack_int32((krb5_int32) ctx->cksum_size,
+ &bp, &remain);
+ (void) krb5_ser_pack_int32((krb5_int32) ctx->sealalg,
+ &bp, &remain);
(void) krb5_ser_pack_int32((krb5_int32) ctx->endtime,
&bp, &remain);
(void) krb5_ser_pack_int32((krb5_int32) ctx->flags,
@@ -601,6 +418,10 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
/* Now dynamic data */
kret = 0;
+ if (!kret && ctx->mech_used)
+ kret = kg_oid_externalize(kcontext, ctx->mech_used,
+ &bp, &remain);
+
if (!kret && ctx->here)
kret = krb5_externalize_opaque(kcontext,
KV5M_PRINCIPAL,
@@ -620,23 +441,15 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
&bp, &remain);
if (!kret)
- kret = krb5_externalize_opaque(kcontext,
- KG_ENC_DESC,
+ kret = kg_enc_desc_externalize(kcontext,
(krb5_pointer) &ctx->enc,
&bp, &remain);
if (!kret)
- kret = krb5_externalize_opaque(kcontext,
- KG_ENC_DESC,
+ kret = kg_enc_desc_externalize(kcontext,
(krb5_pointer) &ctx->seq,
&bp, &remain);
- if (!kret && ctx->auth_context)
- kret = krb5_externalize_opaque(kcontext,
- KV5M_AUTH_CONTEXT,
- (krb5_pointer)ctx->auth_context,
- &bp, &remain);
-
if (!kret) {
(void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
*buffer = bp;
@@ -646,11 +459,11 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
}
return(kret);
}
-
+
/*
* Internalize this krb5_gss_ctx_id_t.
*/
-static krb5_error_code
+krb5_error_code
kg_ctx_internalize(kcontext, argp, buffer, lenremain)
krb5_context kcontext;
krb5_pointer *argp;
@@ -658,7 +471,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
size_t *lenremain;
{
krb5_error_code kret;
- krb5_gss_ctx_id_t *ctx;
+ krb5_gss_ctx_id_rec *ctx;
krb5_int32 ibuf;
krb5_octet *bp;
size_t remain;
@@ -675,9 +488,9 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
/* Get a context */
if ((remain >= ((10*sizeof(krb5_int32))+sizeof(ctx->seed))) &&
- (ctx = (krb5_gss_ctx_id_t *)
- xmalloc(sizeof(krb5_gss_ctx_id_t)))) {
- memset(ctx, 0, sizeof(krb5_gss_ctx_id_t));
+ (ctx = (krb5_gss_ctx_id_rec *)
+ xmalloc(sizeof(krb5_gss_ctx_id_rec)))) {
+ memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
/* Get static data */
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
@@ -690,9 +503,15 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
sizeof(ctx->seed),
&bp, &remain);
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+ ctx->signalg = (int) ibuf;
+ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+ ctx->cksum_size = (int) ibuf;
+ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+ ctx->sealalg = (int) ibuf;
+ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
ctx->endtime = (krb5_timestamp) ibuf;
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
- ctx->flags = (krb5_timestamp) ibuf;
+ ctx->flags = (krb5_flags) ibuf;
(void) krb5_ser_unpack_int32(&ctx->seq_send, &bp, &remain);
(void) krb5_ser_unpack_int32(&ctx->seq_recv, &bp, &remain);
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
@@ -700,6 +519,11 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
ctx->big_endian = (int) ibuf;
+ if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp,
+ &remain))) {
+ if (kret == EINVAL)
+ kret = 0;
+ }
/* Now get substructure data */
if ((kret = krb5_internalize_opaque(kcontext,
KV5M_PRINCIPAL,
@@ -725,8 +549,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
kret = 0;
}
if (!kret) {
- if ((kret = krb5_internalize_opaque(kcontext,
- KG_ENC_DESC,
+ if ((kret = kg_enc_desc_internalize(kcontext,
(krb5_pointer *) &edp,
&bp, &remain))) {
if (kret == EINVAL)
@@ -738,8 +561,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
}
}
if (!kret) {
- if ((kret = krb5_internalize_opaque(kcontext,
- KG_ENC_DESC,
+ if ((kret = kg_enc_desc_internalize(kcontext,
(krb5_pointer *) &edp,
&bp, &remain))) {
if (kret == EINVAL)
@@ -750,15 +572,6 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
xfree(edp);
}
}
- if (!kret &&
- (kret = krb5_internalize_opaque(kcontext,
- KV5M_AUTH_CONTEXT,
- (krb5_pointer *)
- &ctx->auth_context,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
/* Get trailer */
if (!kret &&
@@ -771,8 +584,6 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
else {
if (!kret && (ibuf != KG_CONTEXT))
kret = EINVAL;
- if (ctx->auth_context)
- krb5_auth_con_free(kcontext, ctx->auth_context);
if (ctx->seq.eblock.key)
krb5_free_keyblock(kcontext, ctx->seq.eblock.key);
if (ctx->seq.eblock.priv && ctx->seq.eblock.priv_size)
@@ -797,36 +608,3 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
}
return(kret);
}
-
-static const krb5_ser_entry kg_cred_ser_entry = {
- KG_CRED, /* Type */
- kg_cred_size, /* Sizer routine */
- kg_cred_externalize, /* Externalize routine */
- kg_cred_internalize /* Internalize routine */
-};
-static const krb5_ser_entry kg_enc_desc_ser_entry = {
- KG_ENC_DESC, /* Type */
- kg_enc_desc_size, /* Sizer routine */
- kg_enc_desc_externalize, /* Externalize routine */
- kg_enc_desc_internalize /* Internalize routine */
-};
-static const krb5_ser_entry kg_ctx_ser_entry = {
- KG_CONTEXT, /* Type */
- kg_ctx_size, /* Sizer routine */
- kg_ctx_externalize, /* Externalize routine */
- kg_ctx_internalize /* Internalize routine */
-};
-
-krb5_error_code
-kg_ser_context_init(kcontext)
- krb5_context kcontext;
-{
- krb5_error_code kret;
-
- kret = krb5_register_serializer(kcontext, &kg_cred_ser_entry);
- if (!kret)
- kret = krb5_register_serializer(kcontext, &kg_enc_desc_ser_entry);
- if (!kret)
- kret = krb5_register_serializer(kcontext, &kg_ctx_ser_entry);
- return(kret);
-}
diff --git a/src/lib/gssapi/krb5/sign.c b/src/lib/gssapi/krb5/sign.c
index c3b6ebf4b..0177f40d4 100644
--- a/src/lib/gssapi/krb5/sign.c
+++ b/src/lib/gssapi/krb5/sign.c
@@ -22,19 +22,25 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_sign(ctx, minor_status, context_handle,
+krb5_gss_sign(minor_status, context_handle,
qop_req, message_buffer,
message_token)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
int qop_req;
gss_buffer_t message_buffer;
gss_buffer_t message_token;
{
- krb5_context context = ctx;
+ krb5_context context;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
return(kg_seal(context, minor_status, context_handle, 0,
qop_req, message_buffer, NULL,
message_token, KG_TOK_SIGN_MSG));
@@ -42,17 +48,19 @@ krb5_gss_sign(ctx, minor_status, context_handle,
/* V2 interface */
OM_uint32
-krb5_gss_get_mic(ctx, minor_status, context_handle, qop_req,
+krb5_gss_get_mic(minor_status, context_handle, qop_req,
message_buffer, message_token)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_qop_t qop_req;
gss_buffer_t message_buffer;
gss_buffer_t message_token;
{
- krb5_context context = ctx;
+ krb5_context context;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
return(kg_seal(context, minor_status, context_handle, 0,
(int) qop_req, message_buffer, NULL,
message_token, KG_TOK_MIC_MSG));
diff --git a/src/lib/gssapi/krb5/unseal.c b/src/lib/gssapi/krb5/unseal.c
index da71fa4f4..546521e1b 100644
--- a/src/lib/gssapi/krb5/unseal.c
+++ b/src/lib/gssapi/krb5/unseal.c
@@ -22,11 +22,14 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_unseal(ctx, minor_status, context_handle,
+krb5_gss_unseal(minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, qop_state)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t input_message_buffer;
@@ -34,7 +37,11 @@ krb5_gss_unseal(ctx, minor_status, context_handle,
int *conf_state;
int *qop_state;
{
- krb5_context context = ctx;
+ krb5_context context;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
return(kg_unseal(context, minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, qop_state, KG_TOK_SEAL_MSG));
@@ -42,10 +49,9 @@ krb5_gss_unseal(ctx, minor_status, context_handle,
/* V2 interface */
OM_uint32
-krb5_gss_unwrap(ctx, minor_status, context_handle,
+krb5_gss_unwrap(minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, qop_state)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t input_message_buffer;
@@ -53,10 +59,13 @@ krb5_gss_unwrap(ctx, minor_status, context_handle,
int *conf_state;
gss_qop_t *qop_state;
{
- krb5_context context = ctx;
+ krb5_context context;
OM_uint32 rstat;
int qstate;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
rstat = kg_unseal(context, minor_status, context_handle,
input_message_buffer, output_message_buffer,
conf_state, &qstate, KG_TOK_WRAP_MSG);
diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c
index 0b46d0e5e..ee3e1aafa 100644
--- a/src/lib/gssapi/krb5/util_cksum.c
+++ b/src/lib/gssapi/krb5/util_cksum.c
@@ -20,11 +20,16 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * $Id$
+ */
+
#include "gssapiP_krb5.h"
#include <memory.h>
krb5_error_code
-kg_checksum_channel_bindings(cb, cksum, bigend)
+kg_checksum_channel_bindings(context, cb, cksum, bigend)
+ krb5_context context;
gss_channel_bindings_t cb;
krb5_checksum *cksum;
int bigend;
@@ -33,20 +38,18 @@ kg_checksum_channel_bindings(cb, cksum, bigend)
char *buf, *ptr;
krb5_error_code code;
- if (!kg_context && (code=kg_get_context()))
- return code;
-
+ /* initialize the the cksum and allocate the contents buffer */
+ cksum->checksum_type = CKSUMTYPE_RSA_MD5;
+ cksum->length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
+ if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) {
+ free(buf);
+ return(ENOMEM);
+ }
+
/* generate a buffer full of zeros if no cb specified */
if (cb == GSS_C_NO_CHANNEL_BINDINGS) {
- /* allocate the cksum contents buffer */
- if ((cksum->contents = (krb5_octet *)
- xmalloc(krb5_checksum_size(context, CKSUMTYPE_RSA_MD5))) == NULL)
- return(ENOMEM);
-
- cksum->checksum_type = CKSUMTYPE_RSA_MD5;
- memset(cksum->contents, '\0',
- (cksum->length = krb5_checksum_size(kg_context, CKSUMTYPE_RSA_MD5)));
+ memset(cksum->contents, '\0', cksum->length);
return(0);
}
@@ -60,13 +63,6 @@ kg_checksum_channel_bindings(cb, cksum, bigend)
if ((buf = (char *) xmalloc(len)) == NULL)
return(ENOMEM);
- /* allocate the cksum contents buffer */
- cksum->length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
- if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) {
- free(buf);
- return(ENOMEM);
- }
-
/* helper macros. This code currently depends on a long being 32
bits, and htonl dtrt. */
@@ -80,7 +76,7 @@ kg_checksum_channel_bindings(cb, cksum, bigend)
/* checksum the data */
- if (code = krb5_calculate_checksum(kg_context, CKSUMTYPE_RSA_MD5,
+ if (code = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5,
buf, len, NULL, 0, cksum)) {
xfree(cksum->contents);
xfree(buf);
diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c
index 89028270e..bf49de41d 100644
--- a/src/lib/gssapi/krb5/util_crypt.c
+++ b/src/lib/gssapi/krb5/util_crypt.c
@@ -23,6 +23,10 @@
#include "gssapiP_krb5.h"
#include <memory.h>
+/*
+ * $Id$
+ */
+
static unsigned char zeros[8] = {0,0,0,0,0,0,0,0};
int
@@ -39,7 +43,7 @@ kg_make_confounder(ed, buf)
krb5_gss_enc_desc *ed;
unsigned char *buf;
{
- return(krb5_random_confounder( ed->eblock.crypto_entry->block_length, buf));
+ return(krb5_random_confounder(ed->eblock.crypto_entry->block_length, buf));
}
int
@@ -51,7 +55,8 @@ kg_encrypt_size(ed, n)
}
krb5_error_code
-kg_encrypt(ed, iv, in, out, length)
+kg_encrypt(context, ed, iv, in, out, length)
+ krb5_context context;
krb5_gss_enc_desc *ed;
krb5_pointer iv;
krb5_pointer in;
@@ -59,18 +64,29 @@ kg_encrypt(ed, iv, in, out, length)
int length;
{
krb5_error_code code;
+ krb5_pointer tmp;
- if (!kg_context && (code=kg_get_context()))
- return code;
-
if (! ed->processed) {
- if (code = krb5_process_key(kg_context, &ed->eblock, ed->key))
+ if (code = krb5_process_key(context, &ed->eblock, ed->key))
return(code);
ed->processed = 1;
}
- if (code = krb5_encrypt(kg_context, in, out, length, &ed->eblock,
- iv?iv:(krb5_pointer)zeros))
+ /* this is lame. the krb5 encryption interfaces no longer allow
+ you to encrypt in place. perhaps this should be fixed, but
+ dealing here is easier for now --marc */
+
+ if ((tmp = (krb5_pointer) xmalloc(length)) == NULL)
+ return(ENOMEM);
+
+ memcpy(tmp, in, length);
+
+ code = krb5_encrypt(context, tmp, out, length, &ed->eblock,
+ iv?iv:(krb5_pointer)zeros);
+
+ xfree(tmp);
+
+ if (code)
return(code);
return(0);
@@ -79,7 +95,8 @@ kg_encrypt(ed, iv, in, out, length)
/* length is the length of the cleartext. */
krb5_error_code
-kg_decrypt(ed, iv, in, out, length)
+kg_decrypt(context, ed, iv, in, out, length)
+ krb5_context context;
krb5_gss_enc_desc *ed;
krb5_pointer iv;
krb5_pointer in;
@@ -90,11 +107,8 @@ kg_decrypt(ed, iv, in, out, length)
int elen;
char *buf;
- if (!kg_context && (code=kg_get_context()))
- return code;
-
if (! ed->processed) {
- if (code = krb5_process_key(kg_context, &ed->eblock, ed->key))
+ if (code = krb5_process_key(context, &ed->eblock, ed->key))
return(code);
ed->processed = 1;
}
@@ -103,7 +117,7 @@ kg_decrypt(ed, iv, in, out, length)
if ((buf = (char *) xmalloc(elen)) == NULL)
return(ENOMEM);
- if (code = krb5_decrypt(kg_context, in, buf, elen, &ed->eblock,
+ if (code = krb5_decrypt(context, in, buf, elen, &ed->eblock,
iv?iv:(krb5_pointer)zeros)) {
xfree(buf);
return(code);
diff --git a/src/lib/gssapi/krb5/util_seed.c b/src/lib/gssapi/krb5/util_seed.c
index ed60922d5..14f365245 100644
--- a/src/lib/gssapi/krb5/util_seed.c
+++ b/src/lib/gssapi/krb5/util_seed.c
@@ -23,10 +23,15 @@
#include "gssapiP_krb5.h"
#include <memory.h>
+/*
+ * $Id$
+ */
+
static unsigned char zeros[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
krb5_error_code
-kg_make_seed(key, seed)
+kg_make_seed(context, key, seed)
+ krb5_context context;
krb5_keyblock *key;
unsigned char *seed;
{
@@ -34,10 +39,7 @@ kg_make_seed(key, seed)
krb5_gss_enc_desc ed;
int i;
- if (!kg_context && (code=kg_get_context()))
- return code;
-
- if (code = krb5_copy_keyblock(kg_context, key, &ed.key))
+ if (code = krb5_copy_keyblock(context, key, &ed.key))
return(code);
/* reverse the key bytes, as per spec */
@@ -45,13 +47,13 @@ kg_make_seed(key, seed)
for (i=0; i<ed.key->length; i++)
ed.key->contents[i] = key->contents[key->length - 1 - i];
- krb5_use_enctype(kg_context, &ed.eblock, ENCTYPE_DES_CBC_RAW);
+ krb5_use_enctype(context, &ed.eblock, ENCTYPE_DES_CBC_RAW);
ed.processed = 0;
- code = kg_encrypt(&ed, NULL, zeros, seed, 16);
+ code = kg_encrypt(context, &ed, NULL, zeros, seed, 16);
- krb5_finish_key(kg_context, &ed.eblock);
- krb5_free_keyblock(kg_context, ed.key);
+ krb5_finish_key(context, &ed.eblock);
+ krb5_free_keyblock(context, ed.key);
return(code);
}
diff --git a/src/lib/gssapi/krb5/util_seqnum.c b/src/lib/gssapi/krb5/util_seqnum.c
index 67bcda6db..ed9293f77 100644
--- a/src/lib/gssapi/krb5/util_seqnum.c
+++ b/src/lib/gssapi/krb5/util_seqnum.c
@@ -22,8 +22,13 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
krb5_error_code
-kg_make_seq_num(ed, direction, seqnum, cksum, buf)
+kg_make_seq_num(context, ed, direction, seqnum, cksum, buf)
+ krb5_context context;
krb5_gss_enc_desc *ed;
int direction;
krb5_int32 seqnum;
@@ -42,5 +47,34 @@ kg_make_seq_num(ed, direction, seqnum, cksum, buf)
plain[6] = direction;
plain[7] = direction;
- return(kg_encrypt(ed, cksum, plain, buf, 8));
+ return(kg_encrypt(context, ed, cksum, plain, buf, 8));
+}
+
+krb5_error_code kg_get_seq_num(context, ed, cksum, buf, direction, seqnum)
+ krb5_context context;
+ krb5_gss_enc_desc *ed;
+ unsigned char *cksum;
+ unsigned char *buf;
+ int *direction;
+ krb5_int32 *seqnum;
+{
+ krb5_error_code code;
+ unsigned char plain[8];
+
+ if (code = kg_decrypt(context, ed, cksum, buf, plain, 8))
+ return(code);
+
+ if ((plain[4] != plain[5]) ||
+ (plain[4] != plain[6]) ||
+ (plain[4] != plain[7]))
+ return((krb5_error_code) KG_BAD_SEQ);
+
+ *direction = plain[4];
+
+ *seqnum = ((plain[0]) |
+ (plain[1]<<8) |
+ (plain[2]<<16) |
+ (plain[3]<<24));
+
+ return(0);
}
diff --git a/src/lib/gssapi/krb5/verify.c b/src/lib/gssapi/krb5/verify.c
index 33ee8fb8c..0e7305640 100644
--- a/src/lib/gssapi/krb5/verify.c
+++ b/src/lib/gssapi/krb5/verify.c
@@ -22,39 +22,50 @@
#include "gssapiP_krb5.h"
+/*
+ * $Id$
+ */
+
OM_uint32
-krb5_gss_verify(ctx, minor_status, context_handle,
+krb5_gss_verify(minor_status, context_handle,
message_buffer, token_buffer,
qop_state)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t message_buffer;
gss_buffer_t token_buffer;
int *qop_state;
{
- krb5_context context = ctx;
- return(kg_unseal(context, minor_status, context_handle,
- token_buffer, message_buffer,
- NULL, qop_state, KG_TOK_SIGN_MSG));
+ krb5_context context;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
+
+ return(kg_unseal(context, minor_status, context_handle,
+ token_buffer, message_buffer,
+ NULL, qop_state, KG_TOK_SIGN_MSG));
}
/* V2 interface */
OM_uint32
-krb5_gss_verify_mic(ctx, minor_status, context_handle,
+krb5_gss_verify_mic(minor_status, context_handle,
message_buffer, token_buffer,
qop_state)
- void *ctx;
OM_uint32 *minor_status;
gss_ctx_id_t context_handle;
gss_buffer_t message_buffer;
gss_buffer_t token_buffer;
gss_qop_t *qop_state;
{
- krb5_context context = ctx;
+ krb5_context context;
OM_uint32 rstat;
int qstate;
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
+
rstat = kg_unseal(context, minor_status, context_handle,
token_buffer, message_buffer,
NULL, &qstate, KG_TOK_MIC_MSG);
diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c
new file mode 100644
index 000000000..8c47d0fa6
--- /dev/null
+++ b/src/lib/gssapi/krb5/wrap_size_limit.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 1993 by OpenVision Technologies, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appears in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of OpenVision not be used
+ * in advertising or publicity pertaining to distribution of the software
+ * without specific, written prior permission. OpenVision makes no
+ * representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied warranty.
+ *
+ * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/*
+ * $Id$
+ */
+
+/* V2 interface */
+OM_uint32
+krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
+ qop_req, req_output_size, max_input_size)
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ int conf_req_flag;
+ gss_qop_t qop_req;
+ OM_uint32 req_output_size;
+ OM_uint32 *max_input_size;
+{
+ krb5_context context;
+ krb5_gss_ctx_id_rec *ctx;
+ OM_uint32 cfsize;
+ OM_uint32 ohlen;
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
+ /* only default qop is allowed */
+ if (qop_req != GSS_C_QOP_DEFAULT) {
+ *minor_status = (OM_uint32) G_UNKNOWN_QOP;
+ return(GSS_S_FAILURE);
+ }
+
+ /* validate the context handle */
+ if (! kg_validate_ctx_id(context_handle)) {
+ *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ return(GSS_S_NO_CONTEXT);
+ }
+
+ ctx = (krb5_gss_ctx_id_rec *) context_handle;
+ if (! ctx->established) {
+ *minor_status = KG_CTX_INCOMPLETE;
+ return(GSS_S_NO_CONTEXT);
+ }
+
+ /* Calculate the token size and subtract that from the output size */
+ cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
+ ohlen = g_token_size((gss_OID) ctx->mech_used,
+ (unsigned int) cfsize + ctx->cksum_size + 14);
+
+ /* Cannot have trailer length that will cause us to pad over our length */
+ *max_input_size = (req_output_size - ohlen) & (~7);
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+}
diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h
index e82cfbba0..22b8c5bdb 100644
--- a/src/lib/gssapi/mechglue/mglueP.h
+++ b/src/lib/gssapi/mechglue/mglueP.h
@@ -74,6 +74,17 @@ typedef struct gss_union_cred_t {
/* define one of these and provide a function to return */
/* it to initialize the GSSAPI library */
+/* ultrix cc doesn't understand prototypes in structures.
+ we could autoconf test for this --marc */
+
+#ifndef NPROTOTYPE
+#if defined(__ultrix) && !defined (__GNUC__)
+#define NPROTOTYPE(x) ()
+#else
+#define NPROTOTYPE(x) PROTOTYPE(x)
+#endif
+#endif
+
/*
* This is the definition of the mechs_array struct, which is used to
* define the mechs array table. This table is used to indirectly
diff --git a/src/lib/kadm/ChangeLog b/src/lib/kadm/ChangeLog
index 6e9e4d64e..ac07e1981 100644
--- a/src/lib/kadm/ChangeLog
+++ b/src/lib/kadm/ChangeLog
@@ -13,6 +13,11 @@ Tue May 21 20:51:06 1996 Sam Hartman <hartmans@mit.edu>
* Makefile.in (check-unix): Use KRB5_RUN_FLAGS
+Sun May 12 00:46:57 1996 Marc Horowitz <marc@mit.edu>
+
+ * alt_prof.c (krb5_read_realm_params): added "acl_file" variable
+ for the admin server.
+
Wed Mar 13 17:37:00 1996 Ken Raeburn <raeburn@cygnus.com>
* configure.in: Use AC_HEADER_STDARG.
diff --git a/src/lib/kadm/alt_prof.c b/src/lib/kadm/alt_prof.c
index d4512c41c..9556ac450 100644
--- a/src/lib/kadm/alt_prof.c
+++ b/src/lib/kadm/alt_prof.c
@@ -305,6 +305,11 @@ krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp)
if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
rparams->realm_kdc_ports = svalue;
+ /* Get the name of the acl file */
+ hierarchy[2] = "acl_file";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+ rparams->realm_acl_file = svalue;
+
/* Get the value for the kadmind port */
hierarchy[2] = "kadmind_port";
if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
diff --git a/src/lib/kadm5/ChangeLog b/src/lib/kadm5/ChangeLog
new file mode 100644
index 000000000..a10d351d1
--- /dev/null
+++ b/src/lib/kadm5/ChangeLog
@@ -0,0 +1,81 @@
+Mon Jul 22 04:17:23 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in (LIBS): add -lgen to LIBS whenever compile is
+ found. Solaris requires it.
+
+ * chpass_util.c (_kadm5_chpass_principal_util): the calls to
+ kadm5_free_{princicpal,policy}_ent used server_handle instead of
+ lhandle, which caused problems in the api versioning code.
+
+Thu Jul 18 19:50:39 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in: removed ET_RULES, replaced with AC_PROG_AWK
+
+Mon Jul 15 16:52:44 1996 Barry Jaspan <bjaspan@mit.edu>
+
+ * client_init.c (_kadm5_init_any): use krb5_get_in_tkt_keytab
+ instead of changing krb5_defkeyname
+
+Mon Jul 15 16:36:02 1996 Marc Horowitz <marc@mit.edu>
+
+ * Makefile.in (CLNTOBJS), AC_REPLACE_FUNCS: check for setenv, and
+ link against setenv.o if it's needed.
+
+Fri Jul 12 15:06:48 1996 Marc Horowitz <marc@mit.edu>
+
+ * svr_iters.c (glob_to_regexp:append_realm): the semantics and
+ code were somewhat confused. they are now fixed.
+
+ * logger.c (HAVE_*): turn all the "#if HAVE_*" into
+ "#ifdef HAVE_*"
+
+ * configure.in (AC_CHECK_FUNCS): check for the functions which
+ logger.c checks for.
+
+ * svr_principal.c (kadm5_get_principal): due to the the api
+ versioning, it is possible for this function to be called with a
+ three argument prototype. in this case, do not modify mask,
+ because this will clobber the stack on some platforms.
+
+ * client_principal.c (kadm5_create_principal): be more careful
+ about what sorts of things are referenced, passed down, and passed
+ back if the caller is api v1.
+
+Wed Jul 10 01:29:34 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in: added autoconf support
+
+Tue Jul 9 17:38:43 1996 Marc Horowitz <marc@mit.edu>
+
+ * svr_iters.c (*_REGEXPS): rework the conditionals to operate
+ as functions of function symbols tested by configure.
+ * client_init.c (setenv, unsetenv declarations): make them the
+ same as the stdlib declarations, if they're going to be here at
+ all.
+ * Makefile.in: reworked to support building both libraries. this
+ required a bunch of changes, including some coordinating ones in
+ aclocal.m4
+
+Tue Jul 9 16:26:26 1996 Barry Jaspan <bjaspan@mit.edu>
+
+ * svr_principal.c (kadm5_decrypt_key): add kadm5_decrypt_key
+
+Mon Jul 8 16:55:22 1996 Barry Jaspan <bjaspan@mit.edu>
+
+ * svr_iters.c (kadm5_get_either): append local ream to globs with
+ no realm
+
+ * alt_prof.c: fix dbname, admin_dbname, and admin_lockfile to
+ derive from each other as in spec
+
+ * adb_policy.c: add create_db/destroy_db
+
+ * adb_openclose.c: add create_db/destroy_db, fix handling of
+ permanent locks, handle multiple lock files via static linked list
+
+ * adb.h: update create_db/destroy_db to make params instead of
+ explicit values
+
+ * Makefile.ov (TOP): Use ../../kadmin, not kadmin.ov
+
+
diff --git a/src/lib/kadm5/Makefile.in b/src/lib/kadm5/Makefile.in
new file mode 100644
index 000000000..ef500d3f2
--- /dev/null
+++ b/src/lib/kadm5/Makefile.in
@@ -0,0 +1,165 @@
+CFLAGS = $(CCOPTS) $(DEFS)
+
+##DOSBUILDTOP = ..\..
+##DOSLIBNAME=libkadm5srv.lib
+
+.c.o:
+ $(CC) $(CFLAGS) -c $(srcdir)/$*.c
+@SHARED_RULE@
+
+kadm_err.$(OBJEXT): kadm_err.c
+ $(CC) $(CFLAGS) -c $*.c
+@SHARED_RULE_LOCAL@
+
+adb_err.$(OBJEXT): adb_err.c
+ $(CC) $(CFLAGS) -c $*.c
+@SHARED_RULE_LOCAL@
+
+chpass_util_strings.$(OBJEXT): chpass_util_strings.c
+ $(CC) $(CFLAGS) -c $*.c
+@SHARED_RULE_LOCAL@
+
+kadm_err.c kadm_err.h: $(srcdir)/kadm_err.et
+adb_err.c adb_err.h: $(srcdir)/adb_err.et
+chpass_util_strings.c chpass_util_strings.h: $(srcdir)/chpass_util_strings.et
+
+clean::
+ $(RM) kadm_err.c kadm_err.h kadm_err.o
+ $(RM) adb_err.c adb_err.h adb_err.o
+ $(RM) chpass_util_strings.c chpass_util_strings.h chpass_util_strings.o
+
+GENSRCS = kadm_err.c \
+ adb_err.c \
+ chpass_util_strings.c \
+ $(srcdir)/ovsec_glue.c \
+ $(srcdir)/misc_free.c \
+ $(srcdir)/kadm_rpc_xdr.c \
+ $(srcdir)/chpass_util.c \
+ $(srcdir)/alt_prof.c \
+ $(srcdir)/str_conv.c \
+ $(srcdir)/logger.c \
+
+SRVSRCS = $(GENSRCS) \
+ $(srcdir)/svr_policy.c \
+ $(srcdir)/svr_principal.c \
+ $(srcdir)/server_acl.c \
+ $(srcdir)/server_kdb.c \
+ $(srcdir)/server_misc.c \
+ $(srcdir)/server_init.c \
+ $(srcdir)/server_dict.c \
+ $(srcdir)/svr_iters.c \
+ $(srcdir)/svr_chpass_util.c \
+ $(srcdir)/adb_xdr.c \
+ $(srcdir)/adb_policy.c \
+ $(srcdir)/adb_free.c \
+ $(srcdir)/adb_openclose.c
+
+CLNTSRCS = $(GENSRCS) \
+ $(srcdir)/clnt_policy.c \
+ $(srcdir)/client_rpc.c \
+ $(srcdir)/client_principal.c \
+ $(srcdir)/client_init.c \
+ $(srcdir)/clnt_privs.c \
+ $(srcdir)/clnt_chpass_util.c
+
+GENOBJS = kadm_err.$(OBJEXT) \
+ adb_err.$(OBJEXT) \
+ chpass_util_strings.$(OBJEXT) \
+ ovsec_glue.$(OBJEXT) \
+ misc_free.$(OBJEXT) \
+ kadm_rpc_xdr.$(OBJEXT) \
+ chpass_util.$(OBJEXT) \
+ alt_prof.$(OBJEXT) \
+ str_conv.$(OBJEXT) \
+ logger.$(OBJEXT) \
+
+SRVOBJS = $(GENOBJS) \
+ svr_policy.$(OBJEXT) \
+ svr_principal.$(OBJEXT) \
+ server_acl.$(OBJEXT) \
+ server_kdb.$(OBJEXT) \
+ server_misc.$(OBJEXT) \
+ server_init.$(OBJEXT) \
+ server_dict.$(OBJEXT) \
+ svr_iters.$(OBJEXT) \
+ svr_chpass_util.$(OBJEXT) \
+ adb_xdr.$(OBJEXT) \
+ adb_policy.$(OBJEXT) \
+ adb_free.$(OBJEXT) \
+ adb_openclose.$(OBJEXT)
+
+CLNTOBJS = $(GENOBJS) @LIBOBJS@ \
+ clnt_policy.$(OBJEXT) \
+ client_rpc.$(OBJEXT) \
+ client_principal.$(OBJEXT) \
+ client_init.$(OBJEXT) \
+ clnt_privs.$(OBJEXT) \
+ clnt_chpass_util.$(OBJEXT)
+
+#
+# Depends on libkdb5, libkrb5, libcrypto, libcom_err, libdyn
+#
+KDB5_VER=@KDB5_SH_VERS@
+KRB5_VER=@KRB5_SH_VERS@
+CRYPTO_VER=@CRYPTO_SH_VERS@
+COMERR_VER=@COMERR_SH_VERS@
+DYN_VER=@DYN_SH_VERS@
+DEPLIBS=$(TOPLIBD)/libkdb5.$(SHEXT).$(KDB5_VER) \
+ $(TOPLIBD)/libkrb5.$(SHEXT).$(KRB5_VER) \
+ $(TOPLIBD)/libcrypto.$(SHEXT).$(CRYPTO_VER) \
+ $(TOPLIBD)/libcom_err.$(SHEXT).$(COMERR_VER) \
+ $(TOPLIBD)/libdyn.$(SHEXT).$(DYN_VER)
+
+SHLIB_LIBS=-lkdb5 -lkrb5 -lcrypto -lcom_err -ldyn
+SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@
+SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
+
+all-unix:: shared includes $(OBJS)
+all-mac:: $(OBJS)
+all-windows:: $(OBJS)
+
+# don't think about this very hard. when the build system goes away,
+# so will this.
+LIBDONE = srv/DONE clnt/DONE
+LIB_SUBDIRS=
+shared:
+ -mkdir shared srv clnt
+ ln -s ../shared srv/shared
+ ln -s ../shared clnt/shared
+
+srv/DONE: $(SRVOBJS)
+ $(RM) srv/DONE
+ echo $(SRVOBJS) > srv/DONE
+
+clnt/DONE: $(CLNTOBJS)
+ $(RM) clnt/DONE
+ echo $(CLNTOBJS) > clnt/DONE
+
+check-windows::
+
+clean-unix::
+ $(RM) shared/* srv/* clnt/*
+ -rmdir shared srv clnt
+
+clean-mac::
+clean-windows::
+
+libkadm5srv.a: $(SRVOBJS)
+ $(RM) $@
+ $(ARADD) $@ $(SRVOBJS)
+ $(RANLIB) $@
+
+libkadm5clnt.a: $(CLNTOBJS)
+ $(RM) $@
+ $(ARADD) $@ $(CLNTOBJS)
+ $(RANLIB) $@
+
+install:: libkadm5srv.a libkadm5clnt.a
+ $(INSTALL_DATA) libkadm5srv.a $(DESTDIR)$(KRB5_LIBDIR)/libkadm5srv.a
+ $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libkadm5srv.a
+ $(INSTALL_DATA) libkadm5clnt.a $(DESTDIR)$(KRB5_LIBDIR)/libkadm5clnt.a
+ $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libkadm5clnt.a
+
+clean::
+ $(RM) libkadm5srv.a libkadm5srv.bak DONESRV
+ $(RM) libkadm5clnt.a libkadm5clnt.bak DONECLNT
diff --git a/src/lib/kadm5/Makefile.ov b/src/lib/kadm5/Makefile.ov
new file mode 100644
index 000000000..6b078f777
--- /dev/null
+++ b/src/lib/kadm5/Makefile.ov
@@ -0,0 +1,61 @@
+TOP = ../../kadmin
+include $(TOP)/config.mk/template
+
+# All but D_REGEXP_TYPE are needed only for logger.c
+CFLAGS += $(D_REGEXP_TYPE) $(D_HAVE_SYSLOG_H) $(D_HAVE_STDARG_H) \
+ $(D_HAVE_SYSLOG) $(D_HAVE_VSPRINTF) $(D_HAVE_OPENLOG) \
+ $(D_HAVE_CLOSELOG) $(D_HAVE_STRFTIME)
+
+ifdef D_NO_SETENV
+SETENVC = setenv.c
+SETENVO = setenv.o
+endif
+
+SUBDIRS = unit-test
+
+COMMON_SRCS := kadm_err.c adb_err.c chpass_util_strings.c ovsec_glue.c \
+ misc_free.c kadm_rpc_xdr.c chpass_util.c alt_prof.c str_conv.c \
+ logger.c $(SETENVC)
+COMMON_OBJS := kadm_err.o adb_err.o chpass_util_strings.o ovsec_glue.o \
+ misc_free.o kadm_rpc_xdr.o chpass_util.o alt_prof.o str_conv.o \
+ logger.o $(SETENVO)
+
+SERVER_SRCS := svr_policy.c svr_principal.c server_kdb.c server_misc.c \
+ server_init.c server_dict.c server_acl.c svr_iters.c \
+ svr_chpass_util.c
+SERVER_OBJS := svr_policy.o svr_principal.o server_kdb.o server_misc.o \
+ server_init.o server_dict.o server_acl.o svr_iters.o \
+ svr_chpass_util.o
+DB_SRCS := adb_xdr.c adb_policy.c adb_free.c adb_openclose.c
+DB_OBJS := adb_xdr.o adb_policy.o adb_free.o adb_openclose.o
+
+CLIENT_SRCS := clnt_policy.c client_rpc.c client_principal.c \
+ client_init.c clnt_privs.c clnt_chpass_util.c
+CLIENT_OBJS := clnt_policy.o client_rpc.o client_principal.o \
+ client_init.o clnt_privs.o clnt_chpass_util.o
+
+HDRS := kadm_rpc.h admin.h admin_xdr.h adb.h admin_internal.h \
+ server_internal.h server_acl.h
+HDRS_DIR := kadm5
+ETABLES := chpass_util_strings.et kadm_err.et adb_err.et
+
+SRCS := $(COMMON_SRCS) $(SERVER_SRCS) $(DB_SRCS)
+OBJS := $(COMMON_OBJS) $(SERVER_OBJS) $(DB_OBJS)
+LIB := libkadm5srv.a
+
+expand StageLibrary
+expand Depend
+
+SRCS = $(COMMON_SRCS) $(CLIENT_SRCS)
+OBJS = $(COMMON_OBJS) $(CLIENT_OBJS)
+LIB = libkadm5clnt.a
+
+expand StageLibrary
+expand Depend
+
+expand SubdirTarget
+expand StageIncludes
+expand StageErrorTables
+
+# Not sure if/why this is needed...
+chpass_util.c: chpass_util_strings.h
diff --git a/src/lib/kadm5/adb.h b/src/lib/kadm5/adb.h
new file mode 100644
index 000000000..b73553575
--- /dev/null
+++ b/src/lib/kadm5/adb.h
@@ -0,0 +1,141 @@
+/*
+ * Data Types for policys, and principal information that
+ * exist in the respective databases.
+ *
+ * $Header$
+ *
+ * This file was originally created with rpcgen.
+ * It has been hacked up since then.
+ */
+
+#ifndef __ADB_H__
+#define __ADB_H__
+#include <sys/types.h>
+#include <rpc/types.h>
+#include "k5-int.h"
+#include <krb5/kdb.h>
+#include <db.h>
+#include <kadm5/admin.h>
+#include <kadm5/adb_err.h>
+#include <com_err.h>
+
+typedef long osa_adb_ret_t;
+
+#define OSA_ADB_POLICY_DB_MAGIC 0x12345A00
+#define OSA_ADB_PRINC_DB_MAGIC 0x12345B00
+
+#define OSA_ADB_SHARED 0x7001
+#define OSA_ADB_EXCLUSIVE 0x7002
+#define OSA_ADB_PERMANENT 0x7003
+
+#define OSA_ADB_PRINC_VERSION_MASK 0x12345C00
+#define OSA_ADB_PRINC_VERSION_1 0x12345C01
+#define OSA_ADB_POLICY_VERSION_MASK 0x12345D00
+#define OSA_ADB_POLICY_VERSION_1 0x12345D01
+
+typedef struct _osa_adb_db_lock_ent_t {
+ FILE *lockfile;
+ char *filename;
+ int refcnt, lockmode, lockcnt;
+ krb5_context context;
+} osa_adb_lock_ent, *osa_adb_lock_t;
+
+typedef struct _osa_adb_db_ent_t {
+ int magic;
+ DB *db;
+ HASHINFO info;
+ char *filename;
+ osa_adb_lock_t lock;
+} osa_adb_db_ent, *osa_adb_db_t, *osa_adb_princ_t, *osa_adb_policy_t;
+
+/* an osa_pw_hist_ent stores all the key_datas for a single password */
+typedef struct _osa_pw_hist_t {
+ int n_key_data;
+ krb5_key_data *key_data;
+} osa_pw_hist_ent, *osa_pw_hist_t;
+
+typedef struct _osa_princ_ent_t {
+ int version;
+ char *policy;
+ long aux_attributes;
+ unsigned int old_key_len;
+ unsigned int old_key_next;
+ krb5_kvno admin_history_kvno;
+ osa_pw_hist_ent *old_keys;
+} osa_princ_ent_rec, *osa_princ_ent_t;
+
+typedef struct _osa_policy_ent_t {
+ int version;
+ char *name;
+ rpc_u_int32 pw_min_life;
+ rpc_u_int32 pw_max_life;
+ rpc_u_int32 pw_min_length;
+ rpc_u_int32 pw_min_classes;
+ rpc_u_int32 pw_history_num;
+ rpc_u_int32 policy_refcnt;
+} osa_policy_ent_rec, *osa_policy_ent_t;
+
+typedef void (*osa_adb_iter_princ_func) (void *, osa_princ_ent_t);
+typedef void (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
+
+
+/*
+ * Return Code (the rest are in adb_err.h)
+ */
+
+#define OSA_ADB_OK 0
+
+/*
+ * xdr functions
+ */
+bool_t xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp);
+bool_t xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp);
+
+/*
+ * Functions
+ */
+
+osa_adb_ret_t osa_adb_create_db(char *filename, char *lockfile, int magic);
+osa_adb_ret_t osa_adb_destroy_db(char *filename, char *lockfile, int magic);
+osa_adb_ret_t osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+ char *lockfile, int magic);
+osa_adb_ret_t osa_adb_fini_db(osa_adb_db_t db, int magic);
+osa_adb_ret_t osa_adb_get_lock(osa_adb_db_t db, int mode);
+osa_adb_ret_t osa_adb_release_lock(osa_adb_db_t db);
+osa_adb_ret_t osa_adb_open_and_lock(osa_adb_princ_t db, int locktype);
+osa_adb_ret_t osa_adb_close_and_unlock(osa_adb_princ_t db);
+
+osa_adb_ret_t osa_adb_create_policy_db(kadm5_config_params *params);
+osa_adb_ret_t osa_adb_destroy_policy_db(kadm5_config_params *params);
+osa_adb_ret_t osa_adb_open_princ(osa_adb_princ_t *db, char *filename);
+osa_adb_ret_t osa_adb_open_policy(osa_adb_policy_t *db,
+ kadm5_config_params *rparams);
+osa_adb_ret_t osa_adb_close_princ(osa_adb_princ_t db);
+osa_adb_ret_t osa_adb_close_policy(osa_adb_policy_t db);
+osa_adb_ret_t osa_adb_create_princ(osa_adb_princ_t db,
+ osa_princ_ent_t entry);
+osa_adb_ret_t osa_adb_create_policy(osa_adb_policy_t db,
+ osa_policy_ent_t entry);
+osa_adb_ret_t osa_adb_destroy_princ(osa_adb_princ_t db,
+ kadm5_princ_t name);
+osa_adb_ret_t osa_adb_destroy_policy(osa_adb_policy_t db,
+ kadm5_policy_t name);
+osa_adb_ret_t osa_adb_get_princ(osa_adb_princ_t db,
+ kadm5_princ_t name,
+ osa_princ_ent_t *entry);
+osa_adb_ret_t osa_adb_get_policy(osa_adb_policy_t db,
+ kadm5_policy_t name,
+ osa_policy_ent_t *entry);
+osa_adb_ret_t osa_adb_put_princ(osa_adb_princ_t db,
+ osa_princ_ent_t entry);
+osa_adb_ret_t osa_adb_put_policy(osa_adb_policy_t db,
+ osa_policy_ent_t entry);
+osa_adb_ret_t osa_adb_iter_policy(osa_adb_policy_t db,
+ osa_adb_iter_policy_func func,
+ void * data);
+osa_adb_ret_t osa_adb_iter_princ(osa_adb_princ_t db,
+ osa_adb_iter_princ_func func,
+ void *data);
+void osa_free_policy_ent(osa_policy_ent_t val);
+void osa_free_princ_ent(osa_princ_ent_t val);
+#endif /* __ADB_H__ */
diff --git a/src/lib/kadm5/adb_err.et b/src/lib/kadm5/adb_err.et
new file mode 100644
index 000000000..394802571
--- /dev/null
+++ b/src/lib/kadm5/adb_err.et
@@ -0,0 +1,16 @@
+error_table adb
+error_code OSA_ADB_NOERR, "No Error"
+error_code OSA_ADB_DUP, "Principal or policy already exists"
+error_code OSA_ADB_NOENT, "Principal or policy does not exist"
+error_code OSA_ADB_DBINIT, "Database not initialized"
+error_code OSA_ADB_BAD_POLICY, "Invalid policy name"
+error_code OSA_ADB_BAD_PRINC, "Invalid principal name"
+error_code OSA_ADB_BAD_DB, "Database inconsistency detected"
+error_code OSA_ADB_XDR_FAILURE, "XDR encoding error"
+error_code OSA_ADB_FAILURE, "Failure!"
+error_code OSA_ADB_BADLOCKMODE, "Bad lock mode"
+error_code OSA_ADB_CANTLOCK_DB, "Cannot lock database"
+error_code OSA_ADB_NOTLOCKED, "Database not locked"
+error_code OSA_ADB_NOLOCKFILE, "KADM5 administration database lock file missing"
+error_code OSA_ADB_NOEXCL_PERM, "Insufficient permission to lock file"
+end
diff --git a/src/lib/kadm5/adb_free.c b/src/lib/kadm5/adb_free.c
new file mode 100644
index 000000000..4c6f8a66d
--- /dev/null
+++ b/src/lib/kadm5/adb_free.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.8 1996/07/22 20:35:16 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.7.4.1 1996/07/18 03:08:07 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.7.2.1 1996/06/20 02:16:25 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.7 1996/05/12 06:21:57 marc
+ * don't use <absolute paths> for "internal header files"
+ *
+ * Revision 1.6 1993/12/13 21:15:56 shanzer
+ * fixed memory leak
+ * .,
+ *
+ * Revision 1.5 1993/12/06 22:20:37 marc
+ * fixup free functions to use xdr to free the underlying struct
+ *
+ * Revision 1.4 1993/11/15 00:29:46 shanzer
+ * check to make sure pointers are somewhat vaid before freeing.
+ *
+ * Revision 1.3 1993/11/09 04:02:24 shanzer
+ * added some includefiles
+ * changed bzero to memset
+ *
+ * Revision 1.2 1993/11/04 01:54:24 shanzer
+ * added rcs header ..
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include "adb.h"
+#include <memory.h>
+#include <malloc.h>
+
+void
+osa_free_princ_ent(osa_princ_ent_t val)
+{
+ XDR xdrs;
+
+ xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+
+ xdr_osa_princ_ent_rec(&xdrs, val);
+ free(val);
+}
+
+void
+osa_free_policy_ent(osa_policy_ent_t val)
+{
+ XDR xdrs;
+
+ xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+
+ xdr_osa_policy_ent_rec(&xdrs, val);
+ free(val);
+}
+
diff --git a/src/lib/kadm5/adb_openclose.c b/src/lib/kadm5/adb_openclose.c
new file mode 100644
index 000000000..627a6b410
--- /dev/null
+++ b/src/lib/kadm5/adb_openclose.c
@@ -0,0 +1,338 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "adb.h"
+#include <stdlib.h>
+
+#define MAX_LOCK_TRIES 5
+
+struct _locklist {
+ osa_adb_lock_ent lockinfo;
+ struct _locklist *next;
+};
+
+osa_adb_ret_t osa_adb_create_db(char *filename, char *lockfilename,
+ int magic)
+{
+ FILE *lf;
+ DB *db;
+ HASHINFO info;
+
+ lf = fopen(lockfilename, "w+");
+ if (lf == NULL)
+ return errno;
+ (void) fclose(lf);
+
+ memset(&info, 0, sizeof(info));
+ info.hash = NULL;
+ info.bsize = 256;
+ info.ffactor = 8;
+ info.nelem = 25000;
+ info.lorder = 0;
+ db = dbopen(filename, O_RDWR | O_CREAT | O_EXCL, 0600, DB_HASH, &info);
+ if (db == NULL)
+ return errno;
+ if (db->close(db) < 0)
+ return errno;
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_destroy_db(char *filename, char *lockfilename,
+ int magic)
+{
+ /* the admin databases do not contain security-critical data */
+ if (unlink(filename) < 0 ||
+ unlink(lockfilename) < 0)
+ return errno;
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_init_db(osa_adb_db_t *dbp, char *filename,
+ char *lockfilename, int magic)
+{
+ osa_adb_db_t db;
+ static struct _locklist *locklist = NULL;
+ struct _locklist *lockp;
+ krb5_error_code code;
+
+ if (dbp == NULL || filename == NULL)
+ return EINVAL;
+
+ db = (osa_adb_princ_t) malloc(sizeof(osa_adb_db_ent));
+ if (db == NULL)
+ return ENOMEM;
+
+ memset(db, 0, sizeof(*db));
+ db->info.hash = NULL;
+ db->info.bsize = 256;
+ db->info.ffactor = 8;
+ db->info.nelem = 25000;
+ db->info.lorder = 0;
+
+ /*
+ * A process is allowed to open the same database multiple times
+ * and access it via different handles. If the handles use
+ * distinct lockinfo structures, things get confused: lock(A),
+ * lock(B), release(B) will result in the kernel unlocking the
+ * lock file but handle A will still think the file is locked.
+ * Therefore, all handles using the same lock file must share a
+ * single lockinfo structure.
+ *
+ * It is not sufficient to have a single lockinfo structure,
+ * however, because a single process may also wish to open
+ * multiple different databases simultaneously, with different
+ * lock files. This code used to use a single static lockinfo
+ * structure, which means that the second database opened used
+ * the first database's lock file. This was Bad.
+ *
+ * We now maintain a linked list of lockinfo structures, keyed by
+ * lockfilename. An entry is added when this function is called
+ * with a new lockfilename, and all subsequent calls with that
+ * lockfilename use the existing entry, updating the refcnt.
+ * When the database is closed with fini_db(), the refcnt is
+ * decremented, and when it is zero the lockinfo structure is
+ * freed and reset. The entry in the linked list, however, is
+ * never removed; it will just be reinitialized the next time
+ * init_db is called with the right lockfilename.
+ */
+
+ /* find or create the lockinfo structure for lockfilename */
+ lockp = locklist;
+ while (lockp) {
+ if (strcmp(lockp->lockinfo.filename, lockfilename) == 0)
+ break;
+ else
+ lockp = lockp->next;
+ }
+ if (lockp == NULL) {
+ /* doesn't exist, create it, add to list */
+ lockp = (struct _locklist *) malloc(sizeof(*lockp));
+ if (lockp == NULL) {
+ free(db);
+ return ENOMEM;
+ }
+ memset(lockp, 0, sizeof(*lockp));
+ lockp->next = locklist;
+ locklist = lockp;
+ }
+
+ /* now initialize lockp->lockinfo if necessary */
+ if (lockp->lockinfo.lockfile == NULL) {
+ if (code = krb5_init_context(&lockp->lockinfo.context)) {
+ free(db);
+ return((osa_adb_ret_t) code);
+ }
+
+ /*
+ * needs be open read/write so that write locking can work with
+ * POSIX systems
+ */
+ lockp->lockinfo.filename = strdup(lockfilename);
+ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r+")) == NULL) {
+ /*
+ * maybe someone took away write permission so we could only
+ * get shared locks?
+ */
+ if ((lockp->lockinfo.lockfile = fopen(lockfilename, "r"))
+ == NULL) {
+ free(db);
+ return OSA_ADB_NOLOCKFILE;
+ }
+ }
+ lockp->lockinfo.lockmode = lockp->lockinfo.lockcnt = 0;
+ }
+
+ /* lockp is set, lockinfo is initialized, update the reference count */
+ db->lock = &lockp->lockinfo;
+ db->lock->refcnt++;
+
+ db->filename = strdup(filename);
+ db->magic = magic;
+
+ *dbp = db;
+
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_fini_db(osa_adb_db_t db, int magic)
+{
+ if (db->magic != magic)
+ return EINVAL;
+ if (db->lock->refcnt == 0) {
+ /* barry says this can't happen */
+ return OSA_ADB_FAILURE;
+ } else {
+ db->lock->refcnt--;
+ }
+
+ if (db->lock->refcnt == 0) {
+ /*
+ * Don't free db->lock->filename, it is used as a key to
+ * find the lockinfo entry in the linked list. If the
+ * lockfile doesn't exist, we must be closing the database
+ * after trashing it. This has to be allowed, so don't
+ * generate an error.
+ */
+ (void) fclose(db->lock->lockfile);
+ db->lock->lockfile = NULL;
+ krb5_free_context(db->lock->context);
+ }
+
+ db->magic = 0;
+ free(db->filename);
+ free(db);
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_get_lock(osa_adb_db_t db, int mode)
+{
+ int tries, gotlock, perm, krb5_mode, ret;
+
+ if (db->lock->lockmode >= mode) {
+ /* No need to upgrade lock, just incr refcnt and return */
+ db->lock->lockcnt++;
+ return(OSA_ADB_OK);
+ }
+
+ perm = 0;
+ switch (mode) {
+ case OSA_ADB_PERMANENT:
+ perm = 1;
+ case OSA_ADB_EXCLUSIVE:
+ krb5_mode = KRB5_LOCKMODE_EXCLUSIVE;
+ break;
+ case OSA_ADB_SHARED:
+ krb5_mode = KRB5_LOCKMODE_SHARED;
+ break;
+ default:
+ return(EINVAL);
+ }
+
+ for (gotlock = tries = 0; tries < MAX_LOCK_TRIES; tries++) {
+ if ((ret = krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ krb5_mode|KRB5_LOCKMODE_DONTBLOCK)) == 0) {
+ gotlock++;
+ break;
+ } else if (ret == EBADF && mode == OSA_ADB_EXCLUSIVE)
+ /* tried to exclusive-lock something we don't have */
+ /* write access to */
+ return OSA_ADB_NOEXCL_PERM;
+
+ sleep(1);
+ }
+
+ /* test for all the likely "can't get lock" error codes */
+ if (ret == EACCES || ret == EAGAIN || ret == EWOULDBLOCK)
+ return OSA_ADB_CANTLOCK_DB;
+ else if (ret != 0)
+ return ret;
+
+ /*
+ * If the file no longer exists, someone acquired a permanent
+ * lock. If that process terminates its exclusive lock is lost,
+ * but if we already had the file open we can (probably) lock it
+ * even though it has been unlinked. So we need to insist that
+ * it exist.
+ */
+ if (access(db->lock->filename, F_OK) < 0) {
+ (void) krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ KRB5_LOCKMODE_UNLOCK);
+ return OSA_ADB_NOLOCKFILE;
+ }
+
+ /* we have the shared/exclusive lock */
+
+ if (perm) {
+ if (unlink(db->lock->filename) < 0) {
+ int ret;
+
+ /* somehow we can't delete the file, but we already */
+ /* have the lock, so release it and return */
+
+ ret = errno;
+ (void) krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ KRB5_LOCKMODE_UNLOCK);
+
+ /* maybe we should return CANTLOCK_DB.. but that would */
+ /* look just like the db was already locked */
+ return ret;
+ }
+
+ /* this releases our exclusive lock.. which is okay because */
+ /* now no one else can get one either */
+ (void) fclose(db->lock->lockfile);
+ }
+
+ db->lock->lockmode = mode;
+ db->lock->lockcnt++;
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_release_lock(osa_adb_db_t db)
+{
+ int ret;
+
+ if (!db->lock->lockcnt) /* lock already unlocked */
+ return OSA_ADB_NOTLOCKED;
+
+ if (--db->lock->lockcnt == 0) {
+ if (db->lock->lockmode == OSA_ADB_PERMANENT) {
+ /* now we need to create the file since it does not exist */
+ if ((db->lock->lockfile = fopen(db->lock->filename,
+ "w+")) == NULL)
+ return OSA_ADB_NOLOCKFILE;
+ } else if (ret = krb5_lock_file(db->lock->context,
+ fileno(db->lock->lockfile),
+ KRB5_LOCKMODE_UNLOCK))
+ return ret;
+
+ db->lock->lockmode = 0;
+ }
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_open_and_lock(osa_adb_princ_t db, int locktype)
+{
+ int ret;
+
+ ret = osa_adb_get_lock(db, locktype);
+ if (ret != OSA_ADB_OK)
+ return ret;
+
+ db->db = dbopen(db->filename, O_RDWR, 0600, DB_HASH, &db->info);
+ if (db->db == NULL) {
+ (void) osa_adb_release_lock(db);
+ if(errno == EINVAL)
+ return OSA_ADB_BAD_DB;
+ return errno;
+ }
+ return OSA_ADB_OK;
+}
+
+osa_adb_ret_t osa_adb_close_and_unlock(osa_adb_princ_t db)
+{
+ int ret;
+
+ if(db->db->close(db->db) == -1) {
+ (void) osa_adb_release_lock(db);
+ return OSA_ADB_FAILURE;
+ }
+
+ db->db = NULL;
+
+ return(osa_adb_release_lock(db));
+}
+
diff --git a/src/lib/kadm5/adb_policy.c b/src/lib/kadm5/adb_policy.c
new file mode 100644
index 000000000..ff0117bac
--- /dev/null
+++ b/src/lib/kadm5/adb_policy.c
@@ -0,0 +1,401 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include "adb.h"
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+
+extern int errno;
+
+#define OPENLOCK(db, mode) \
+{ \
+ int ret; \
+ if (db == NULL) \
+ return EINVAL; \
+ else if (db->magic != OSA_ADB_POLICY_DB_MAGIC) \
+ return OSA_ADB_DBINIT; \
+ else if ((ret = osa_adb_open_and_lock(db, mode)) != OSA_ADB_OK) \
+ return ret; \
+ }
+
+#define CLOSELOCK(db) \
+{ \
+ int ret; \
+ if ((ret = osa_adb_close_and_unlock(db)) != OSA_ADB_OK) \
+ return ret; \
+}
+
+osa_adb_ret_t osa_adb_create_policy_db(kadm5_config_params *params)
+{
+ return osa_adb_create_db(params->admin_dbname,
+ params->admin_lockfile,
+ OSA_ADB_POLICY_DB_MAGIC);
+}
+
+osa_adb_ret_t osa_adb_destroy_policy_db(kadm5_config_params *params)
+{
+ return osa_adb_destroy_db(params->admin_dbname,
+ params->admin_lockfile,
+ OSA_ADB_POLICY_DB_MAGIC);
+}
+
+osa_adb_ret_t osa_adb_open_policy(osa_adb_princ_t *dbp,
+ kadm5_config_params *rparams)
+{
+ return osa_adb_init_db(dbp, rparams->admin_dbname,
+ rparams->admin_lockfile,
+ OSA_ADB_POLICY_DB_MAGIC);
+}
+
+osa_adb_ret_t osa_adb_close_policy(osa_adb_princ_t db)
+{
+ return osa_adb_fini_db(db, OSA_ADB_POLICY_DB_MAGIC);
+}
+
+/*
+ * Function: osa_adb_create_policy
+ *
+ * Purpose: create a policy entry in the policy db.
+ *
+ * Arguments:
+ * entry (input) pointer to the entry to be added
+ * <return value> OSA_ADB_OK on sucsess, else error code.
+ *
+ * Requires:
+ * entry have a valid name.
+ *
+ * Effects:
+ * creates the entry in the db
+ *
+ * Modifies:
+ * the policy db.
+ *
+ */
+osa_adb_ret_t
+osa_adb_create_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ XDR xdrs;
+ int ret;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE);
+
+ if(entry->name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = entry->name;
+ dbkey.size = (strlen(entry->name) + 1);
+
+ switch(db->db->get(db->db, &dbkey, &dbdata, 0)) {
+ case 0:
+ ret = OSA_ADB_DUP;
+ goto error;
+ case 1:
+ break;
+ default:
+ ret = errno;
+ goto error;
+ }
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ ret = OSA_ADB_XDR_FAILURE;
+ goto error;
+ }
+ dbdata.data = xdralloc_getdata(&xdrs);
+ dbdata.size = xdr_getpos(&xdrs);
+ switch(db->db->put(db->db, &dbkey, &dbdata, R_NOOVERWRITE)) {
+ case 0:
+ if((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ ret = OSA_ADB_OK;
+ break;
+ case 1:
+ ret = OSA_ADB_DUP;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ xdr_destroy(&xdrs);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_destroy_policy
+ *
+ * Purpose: destroy a policy entry
+ *
+ * Arguments:
+ * db (input) database handle
+ * name (input) name of policy
+ * <return value> OSA_ADB_OK on sucsess, or error code.
+ *
+ * Requires:
+ * db being valid.
+ * name being non-null.
+ * Effects:
+ * deletes policy from db.
+ *
+ * Modifies:
+ * policy db.
+ *
+ */
+osa_adb_ret_t
+osa_adb_destroy_policy(osa_adb_policy_t db, kadm5_policy_t name)
+{
+ DBT dbkey;
+ int status, ret;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE);
+
+ if(name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = name;
+ dbkey.size = (strlen(name) + 1);
+
+ status = db->db->del(db->db, &dbkey, 0);
+ switch(status) {
+ case 1:
+ ret = OSA_ADB_NOENT;
+ goto error;
+ case 0:
+ if ((db->db->sync(db->db, 0)) == -1) {
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ ret = OSA_ADB_OK;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_get_policy
+ *
+ * Purpose: retrieve policy
+ *
+ * Arguments:
+ * db (input) db handle
+ * name (input) name of policy
+ * entry (output) policy entry
+ * <return value> 0 on sucsess, error code on failure.
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+osa_adb_ret_t
+osa_adb_get_policy(osa_adb_policy_t db, kadm5_policy_t name,
+ osa_policy_ent_t *entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ XDR xdrs;
+ int ret;
+ char *aligned_data;
+
+ OPENLOCK(db, OSA_ADB_SHARED);
+
+ if(name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = name;
+ dbkey.size = (strlen(dbkey.data) + 1);
+ dbdata.data = NULL;
+ dbdata.size = 0;
+ switch((db->db->get(db->db, &dbkey, &dbdata, 0))) {
+ case 1:
+ ret = OSA_ADB_NOENT;
+ goto error;
+ case 0:
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ if (!(*(entry) = (osa_policy_ent_t)malloc(sizeof(osa_policy_ent_rec)))) {
+ ret = ENOMEM;
+ goto error;
+ }
+ if (!(aligned_data = (char *) malloc(dbdata.size))) {
+ ret = ENOMEM;
+ goto error;
+ }
+ memcpy(aligned_data, dbdata.data, dbdata.size);
+ memset(*entry, 0, sizeof(osa_policy_ent_rec));
+ xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+ if (!xdr_osa_policy_ent_rec(&xdrs, *entry))
+ ret = OSA_ADB_FAILURE;
+ else ret = OSA_ADB_OK;
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_put_policy
+ *
+ * Purpose: update a policy in the dababase
+ *
+ * Arguments:
+ * db (input) db handle
+ * entry (input) policy entry
+ * <return value> 0 on sucsess error code on failure.
+ *
+ * Requires:
+ * [requires]
+ *
+ * Effects:
+ * [effects]
+ *
+ * Modifies:
+ * [modifies]
+ *
+ */
+osa_adb_ret_t
+osa_adb_put_policy(osa_adb_policy_t db, osa_policy_ent_t entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ DBT tmpdb;
+ XDR xdrs;
+ int ret;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE);
+
+ if(entry->name == NULL) {
+ ret = EINVAL;
+ goto error;
+ }
+ dbkey.data = entry->name;
+ dbkey.size = (strlen(entry->name) + 1);
+ switch(db->db->get(db->db, &dbkey, &tmpdb, 0)) {
+ case 0:
+ break;
+ case 1:
+ ret = OSA_ADB_NOENT;
+ goto error;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ ret = OSA_ADB_XDR_FAILURE;
+ goto error;
+ }
+ dbdata.data = xdralloc_getdata(&xdrs);
+ dbdata.size = xdr_getpos(&xdrs);
+ switch(db->db->put(db->db, &dbkey, &dbdata, 0)) {
+ case 0:
+ if((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ ret = OSA_ADB_OK;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ xdr_destroy(&xdrs);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+/*
+ * Function: osa_adb_iter_policy
+ *
+ * Purpose: iterate over the policy database.
+ *
+ * Arguments:
+ * db (input) db handle
+ * func (input) fucntion pointer to call
+ * data opaque data type
+ * <return value> 0 on sucsess error code on failure
+ *
+ * Requires:
+ * Effects:
+ * Modifies:
+ */
+osa_adb_ret_t
+osa_adb_iter_policy(osa_adb_policy_t db, osa_adb_iter_policy_func func,
+ void *data)
+{
+ DBT dbkey,
+ dbdata;
+ XDR xdrs;
+ int ret;
+ osa_policy_ent_t entry;
+ char *aligned_data;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE); /* hmmm */
+
+ if((ret = db->db->seq(db->db, &dbkey, &dbdata, R_FIRST)) == -1) {
+ ret = errno;
+ goto error;
+ }
+
+ while (ret == 0) {
+ if (!(entry = (osa_policy_ent_t) malloc(sizeof(osa_policy_ent_rec)))) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ if(!(aligned_data = (char *) malloc(dbdata.size))) {
+ ret = ENOMEM;
+ goto error;
+ }
+ memcpy(aligned_data, dbdata.data, dbdata.size);
+
+ memset(entry, 0, sizeof(osa_policy_ent_rec));
+ xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+ if(!xdr_osa_policy_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ (*func)(data, entry);
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ osa_free_policy_ent(entry);
+ ret = db->db->seq(db->db, &dbkey, &dbdata, R_NEXT);
+ }
+ if(ret == -1)
+ ret = errno;
+ else ret = OSA_ADB_OK;
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
diff --git a/src/lib/kadm5/adb_principal.c b/src/lib/kadm5/adb_principal.c
new file mode 100644
index 000000000..8ee9aab30
--- /dev/null
+++ b/src/lib/kadm5/adb_principal.c
@@ -0,0 +1,408 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.24 1996/07/22 20:35:23 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.23.4.1 1996/07/18 03:08:17 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.23.2.1 1996/06/20 02:16:30 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.23 1996/05/16 21:44:35 bjaspan
+ * this file is no longer used, #if the whole thing out
+ *
+ * Revision 1.22 1996/05/08 20:51:44 bjaspan
+ * marc's changes
+ *
+ * Revision 1.21 1995/08/24 20:23:43 bjaspan
+ * marc is a bonehead
+ *
+ * Revision 1.20 1995/08/23 19:16:02 marc
+ * check for db == NULL in OPENLOCK()
+ *
+ * Revision 1.19 1995/08/08 18:31:30 bjaspan
+ * [secure/3394] first cut at admin db locking support
+ *
+ * Revision 1.18 1995/08/02 15:26:57 bjaspan
+ * check db==NULL in iter
+ *
+ * Revision 1.17 1994/05/09 17:52:36 shanzer
+ * fixed some include files
+ *
+ * Revision 1.16 1994/03/17 01:25:58 shanzer
+ * include fcntl.h
+ *
+ * Revision 1.15 1993/12/17 18:54:06 jik
+ * [secure-admin/1040]
+ *
+ * open_princ should return errno, rather than BAD_DB, if errno is
+ * something other than BAD_DB.
+ *
+ * Revision 1.14 1993/12/13 18:55:58 marc
+ * remove bogus free()'s
+ *
+ * Revision 1.13 1993/12/08 22:29:27 marc
+ * fixed another xdrmem alignment thing]
+ *
+ * Revision 1.12 1993/12/06 22:22:22 bjaspan
+ * fix alignment and free-memory-read bugs
+ *
+ * Revision 1.11 1993/12/05 04:15:16 shanzer
+ * removed data size hack.
+ *
+ * Revision 1.10 1993/11/15 00:29:24 shanzer
+ * added filenme to open
+ *
+ * Revision 1.9 1993/11/10 20:10:06 shanzer
+ * now uses xdralloc instead of xdrmem
+ *
+ * Revision 1.8 1993/11/09 21:43:24 shanzer
+ * added check to see if we overflowed our xdr buffer.
+ *
+ * Revision 1.7 1993/11/09 04:00:19 shanzer
+ * changed bzero to memset
+ *
+ * Revision 1.6 1993/11/05 23:16:21 shanzer
+ * return ENOMEM instead of ovsec_kadm_mem
+ *
+ * Revision 1.5 1993/11/05 22:17:03 shanzer
+ * added principal db interative function
+ *
+ * Revision 1.4 1993/11/04 23:20:24 shanzer
+ * made HASHINFO static.
+ *
+ * Revision 1.3 1993/11/04 01:52:30 shanzer
+ * Restructred some code .. fixed some bugs/leaks
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#if 0
+/* XXX THIS FILE IS NO LONGER USED, and should be deleted when we're done */
+
+#include <sys/file.h>
+#include <fcntl.h>
+#include "adb.h"
+#include <stdlib.h>
+#include <memory.h>
+
+#define OPENLOCK(db, mode) \
+{ \
+ int ret; \
+ if (db == NULL) \
+ return EINVAL; \
+ else if (db->magic != OSA_ADB_PRINC_DB_MAGIC) \
+ return OSA_ADB_DBINIT; \
+ else if ((ret = osa_adb_open_and_lock(db, mode)) != OSA_ADB_OK) \
+ return ret; \
+ }
+
+#define CLOSELOCK(db) \
+{ \
+ int ret; \
+ if ((ret = osa_adb_close_and_unlock(db)) != OSA_ADB_OK) \
+ return ret; \
+}
+
+osa_adb_ret_t osa_adb_open_princ(osa_adb_princ_t *dbp, char *filename)
+{
+ return osa_adb_init_db(dbp, filename, OSA_ADB_PRINC_DB_MAGIC);
+}
+
+osa_adb_ret_t osa_adb_close_princ(osa_adb_princ_t db)
+{
+ return osa_adb_fini_db(db, OSA_ADB_PRINC_DB_MAGIC);
+}
+
+osa_adb_ret_t
+osa_adb_create_princ(osa_adb_princ_t db, osa_princ_ent_t entry)
+{
+
+ DBT dbkey;
+ DBT dbdata;
+ XDR xdrs;
+ int ret;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE);
+
+ if(krb5_unparse_name(db->lock->context,
+ entry->name, (char **) &dbkey.data)) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+ if((dbkey.size = strlen(dbkey.data)) == 0) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+
+ switch(db->db->get(db->db, &dbkey, &dbdata, 0)) {
+ case 0:
+ ret = OSA_ADB_DUP;
+ goto error;
+ case 1:
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(!xdr_osa_princ_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ ret = OSA_ADB_XDR_FAILURE;
+ goto error;
+ }
+ dbdata.data = xdralloc_getdata(&xdrs);
+ dbdata.size = xdr_getpos(&xdrs);
+ switch(db->db->put(db->db, &dbkey, &dbdata, R_NOOVERWRITE)) {
+ case 0:
+ if((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ else
+ ret = OSA_ADB_OK;
+ break;
+ case 1:
+ ret = OSA_ADB_DUP;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ xdralloc_release(&xdrs);
+ free(dbkey.data);
+
+error:
+ CLOSELOCK(db);
+
+ return ret;
+}
+
+osa_adb_ret_t
+osa_adb_destroy_princ(osa_adb_princ_t db, ovsec_kadm_princ_t name)
+{
+ DBT dbkey;
+ int status;
+ int ret;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE);
+
+ if(krb5_unparse_name(db->lock->context, name, (char **) &dbkey.data)) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+ if ((dbkey.size = strlen(dbkey.data)) == 0) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+ status = db->db->del(db->db, &dbkey, 0);
+ switch(status) {
+ case 1:
+ ret = OSA_ADB_NOENT;
+ break;
+ case 0:
+ if ((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ else
+ ret = OSA_ADB_OK;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ free(dbkey.data);
+
+error:
+ CLOSELOCK(db);
+
+ return ret;
+}
+
+osa_adb_ret_t
+osa_adb_get_princ(osa_adb_princ_t db, ovsec_kadm_princ_t name,
+ osa_princ_ent_t *entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ XDR xdrs;
+ int ret = 0;
+ char *aligned_data;
+
+ OPENLOCK(db, OSA_ADB_SHARED);
+
+ if(krb5_unparse_name(db->lock->context, name, (char **) &dbkey.data)) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+ if((dbkey.size = strlen(dbkey.data)) == 0) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+ dbdata.size = 0;
+ dbdata.data = NULL;
+ switch(db->db->get(db->db, &dbkey, &dbdata, 0)) {
+ case 1:
+ ret = OSA_ADB_NOENT;
+ break;
+ case 0:
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ free(dbkey.data);
+ if (ret)
+ goto error;
+
+ if (!(*(entry) = (osa_princ_ent_t)malloc(sizeof(osa_princ_ent_rec)))) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ aligned_data = (char *) malloc(dbdata.size);
+ if (aligned_data == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ memcpy(aligned_data, dbdata.data, dbdata.size);
+
+ memset(*entry, 0, sizeof(osa_princ_ent_rec));
+ xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+ if (!xdr_osa_princ_ent_rec(&xdrs, *entry)) {
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ ret = OSA_ADB_OK;
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+osa_adb_ret_t
+osa_adb_put_princ(osa_adb_princ_t db, osa_princ_ent_t entry)
+{
+ DBT dbkey;
+ DBT dbdata;
+ DBT tmpdb;
+ XDR xdrs;
+ int ret;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE);
+
+ if(krb5_unparse_name(db->lock->context,
+ entry->name, (char **) &dbkey.data)) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+ if((dbkey.size = strlen(dbkey.data)) == 0) {
+ ret = OSA_ADB_BAD_PRINC;
+ goto error;
+ }
+
+ switch(db->db->get(db->db, &dbkey, &tmpdb, 0)) {
+ case 0:
+ break;
+ case 1:
+ ret = OSA_ADB_NOENT;
+ goto error;
+ default:
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(!xdr_osa_princ_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ ret = OSA_ADB_XDR_FAILURE;
+ goto error;
+ }
+ dbdata.data = xdralloc_getdata(&xdrs);
+ dbdata.size = xdr_getpos(&xdrs);
+ switch(db->db->put(db->db, &dbkey, &dbdata, 0)) {
+ case 0:
+ if((db->db->sync(db->db, 0)) == -1)
+ ret = OSA_ADB_FAILURE;
+ else
+ ret = OSA_ADB_OK;
+ break;
+ default:
+ ret = OSA_ADB_FAILURE;
+ break;
+ }
+ xdralloc_release(&xdrs);
+ free(dbkey.data);
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+osa_adb_ret_t
+osa_adb_iter_princ(osa_adb_princ_t db, osa_adb_iter_princ_func func,
+ void *data)
+{
+ DBT dbkey,
+ dbdata;
+ XDR xdrs;
+ int ret;
+ osa_princ_ent_t entry;
+ char *aligned_data;
+
+ OPENLOCK(db, OSA_ADB_EXCLUSIVE); /* hmmmm */
+
+ if((ret = db->db->seq(db->db, &dbkey, &dbdata, R_FIRST)) == -1) {
+ ret = errno;
+ goto error;
+ }
+ while (ret == 0) {
+ if (!(entry = (osa_princ_ent_t) malloc(sizeof(osa_princ_ent_rec)))) {
+ ret = ENOMEM;
+ goto error;
+ }
+
+ aligned_data = (char *) malloc(dbdata.size);
+ if (aligned_data == NULL) {
+ ret = ENOMEM;
+ goto error;
+ }
+ memcpy(aligned_data, dbdata.data, dbdata.size);
+
+ memset(entry, 0, sizeof(osa_princ_ent_rec));
+ xdrmem_create(&xdrs, aligned_data, dbdata.size, XDR_DECODE);
+ if(!xdr_osa_princ_ent_rec(&xdrs, entry)) {
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ ret = OSA_ADB_FAILURE;
+ goto error;
+ }
+ (*func)(data, entry);
+ xdr_destroy(&xdrs);
+ free(aligned_data);
+ osa_free_princ_ent(entry);
+ ret = db->db->seq(db->db, &dbkey, &dbdata, R_NEXT);
+ }
+ if(ret == -1)
+ ret = errno;
+ else
+ ret = OSA_ADB_OK;
+
+error:
+ CLOSELOCK(db);
+ return ret;
+}
+
+#endif /* 0 */
diff --git a/src/lib/kadm5/adb_xdr.c b/src/lib/kadm5/adb_xdr.c
new file mode 100644
index 000000000..944fb04b3
--- /dev/null
+++ b/src/lib/kadm5/adb_xdr.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/types.h>
+#include <krb5.h>
+#include <rpc/rpc.h>
+#include "adb.h"
+#include "admin_xdr.h"
+#include <memory.h>
+
+bool_t
+xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp)
+{
+ unsigned int tmp;
+
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_ver))
+ return(FALSE);
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_kvno))
+ return(FALSE);
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0]))
+ return(FALSE);
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_type[1]))
+ return(FALSE);
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_length[0]))
+ return(FALSE);
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_length[1]))
+ return(FALSE);
+
+ tmp = (unsigned int) objp->key_data_length[0];
+ if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[0],
+ &tmp, ~0))
+ return FALSE;
+
+ tmp = (unsigned int) objp->key_data_length[1];
+ if (!xdr_bytes(xdrs, (char **) &objp->key_data_contents[1],
+ &tmp, ~0))
+ return FALSE;
+
+ /* don't need to copy tmp out, since key_data_length will be set
+ by the above encoding. */
+
+ return(TRUE);
+}
+
+bool_t
+xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp)
+{
+ if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+ (u_int *) &objp->n_key_data, ~0,
+ sizeof(krb5_key_data),
+ xdr_krb5_key_data))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp)
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ objp->version = OSA_ADB_PRINC_VERSION_1;
+ /* fall through */
+ case XDR_FREE:
+ if (!xdr_int(xdrs, &objp->version))
+ return FALSE;
+ break;
+ case XDR_DECODE:
+ if (!xdr_int(xdrs, &objp->version))
+ return FALSE;
+ if (objp->version != OSA_ADB_PRINC_VERSION_1)
+ return FALSE;
+ break;
+ }
+
+ if (!xdr_nullstring(xdrs, &objp->policy))
+ return (FALSE);
+ if (!xdr_long(xdrs, &objp->aux_attributes))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &objp->old_key_next))
+ return (FALSE);
+ if (!xdr_krb5_kvno(xdrs, &objp->admin_history_kvno))
+ return (FALSE);
+ if (!xdr_array(xdrs, (caddr_t *) &objp->old_keys,
+ (unsigned int *) &objp->old_key_len, ~0,
+ sizeof(osa_pw_hist_ent),
+ xdr_osa_pw_hist_ent))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_osa_policy_ent_rec(XDR *xdrs, osa_policy_ent_t objp)
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ objp->version = OSA_ADB_POLICY_VERSION_1;
+ /* fall through */
+ case XDR_FREE:
+ if (!xdr_int(xdrs, &objp->version))
+ return FALSE;
+ break;
+ case XDR_DECODE:
+ if (!xdr_int(xdrs, &objp->version))
+ return FALSE;
+ if (objp->version != OSA_ADB_POLICY_VERSION_1)
+ return FALSE;
+ break;
+ }
+
+ if(!xdr_nullstring(xdrs, &objp->name))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_min_life))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_max_life))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_min_length))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_min_classes))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->pw_history_num))
+ return (FALSE);
+ if (!xdr_u_int32(xdrs, &objp->policy_refcnt))
+ return (FALSE);
+ return (TRUE);
+}
diff --git a/src/lib/kadm5/admin.h b/src/lib/kadm5/admin.h
new file mode 100644
index 000000000..1e98430db
--- /dev/null
+++ b/src/lib/kadm5/admin.h
@@ -0,0 +1,649 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#ifndef __KADM5_ADMIN_H__
+#define __KADM5_ADMIN_H__
+
+#if !defined(USE_KADM5_API_VERSION)
+#define USE_KADM5_API_VERSION 2
+#endif
+
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <krb5.h>
+#include <k5-int.h>
+#include <com_err.h>
+#include <kadm5/kadm_err.h>
+#include <kadm5/adb_err.h>
+#include <kadm5/chpass_util_strings.h>
+
+#define KADM5_ADMIN_SERVICE "kadmin/admin"
+#define KADM5_CHANGEPW_SERVICE "kadmin/changepw"
+#define KADM5_HIST_PRINCIPAL "kadmin/history"
+
+typedef krb5_principal kadm5_princ_t;
+typedef char *kadm5_policy_t;
+typedef long kadm5_ret_t;
+
+#define KADM5_PW_FIRST_PROMPT \
+ ((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT))
+#define KADM5_PW_SECOND_PROMPT \
+ ((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT))
+
+/*
+ * Succsessfull return code
+ */
+#define KADM5_OK 0
+
+/*
+ * XXX This should be in kdb.h; it is here so that I do not have to
+ * change that file yet, but this should be *very* temporary.
+ * --- bjaspan, 5/23/96
+ */
+#define KRB5_TL_KADM5_E_DATA 0x0004
+
+/*
+ * Field masks
+ */
+
+/* kadm5_principal_ent_t */
+#define KADM5_PRINCIPAL 0x000001
+#define KADM5_PRINC_EXPIRE_TIME 0x000002
+#define KADM5_PW_EXPIRATION 0x000004
+#define KADM5_LAST_PWD_CHANGE 0x000008
+#define KADM5_ATTRIBUTES 0x000010
+#define KADM5_MAX_LIFE 0x000020
+#define KADM5_MOD_TIME 0x000040
+#define KADM5_MOD_NAME 0x000080
+#define KADM5_KVNO 0x000100
+#define KADM5_MKVNO 0x000200
+#define KADM5_AUX_ATTRIBUTES 0x000400
+#define KADM5_POLICY 0x000800
+#define KADM5_POLICY_CLR 0x001000
+/* version 2 masks */
+#define KADM5_MAX_RLIFE 0x002000
+#define KADM5_LAST_SUCCESS 0x004000
+#define KADM5_LAST_FAILED 0x008000
+#define KADM5_FAIL_AUTH_COUNT 0x010000
+#define KADM5_KEY_DATA 0x020000
+#define KADM5_TL_DATA 0x040000
+/* all but KEY_DATA and TL_DATA */
+#define KADM5_PRINCIPAL_NORMAL_MASK 0x01ffff
+
+/* kadm5_policy_ent_t */
+#define KADM5_PW_MAX_LIFE 0x004000
+#define KADM5_PW_MIN_LIFE 0x008000
+#define KADM5_PW_MIN_LENGTH 0x010000
+#define KADM5_PW_MIN_CLASSES 0x020000
+#define KADM5_PW_HISTORY_NUM 0x040000
+#define KADM5_REF_COUNT 0x080000
+
+/* kadm5_config_params */
+#define KADM5_CONFIG_REALM 0x000001
+#define KADM5_CONFIG_DBNAME 0x000002
+#define KADM5_CONFIG_MKEY_NAME 0x000004
+#define KADM5_CONFIG_MAX_LIFE 0x000008
+#define KADM5_CONFIG_MAX_RLIFE 0x000010
+#define KADM5_CONFIG_EXPIRATION 0x000020
+#define KADM5_CONFIG_FLAGS 0x000040
+#define KADM5_CONFIG_ADMIN_KEYTAB 0x000080
+#define KADM5_CONFIG_STASH_FILE 0x000100
+#define KADM5_CONFIG_ENCTYPE 0x000200
+#define KADM5_CONFIG_ADBNAME 0x000400
+#define KADM5_CONFIG_ADB_LOCKFILE 0x000800
+#define KADM5_CONFIG_PROFILE 0x001000
+#define KADM5_CONFIG_ACL_FILE 0x002000
+#define KADM5_CONFIG_KADMIND_PORT 0x004000
+#define KADM5_CONFIG_ENCTYPES 0x008000
+#define KADM5_CONFIG_ADMIN_SERVER 0x010000
+#define KADM5_CONFIG_DICT_FILE 0x020000
+#define KADM5_CONFIG_MKEY_FROM_KBD 0x040000
+
+/*
+ * permission bits
+ */
+#define KADM5_PRIV_GET 0x01
+#define KADM5_PRIV_ADD 0x02
+#define KADM5_PRIV_MODIFY 0x04
+#define KADM5_PRIV_DELETE 0x08
+
+/*
+ * API versioning constants
+ */
+#define KADM5_MASK_BITS 0xffffff00
+
+#define KADM5_STRUCT_VERSION_MASK 0x12345600
+#define KADM5_STRUCT_VERSION_1 (KADM5_STRUCT_VERSION_MASK|0x01)
+#define KADM5_STRUCT_VERSION KADM5_STRUCT_VERSION_1
+
+#define KADM5_API_VERSION_MASK 0x12345700
+#define KADM5_API_VERSION_1 (KADM5_API_VERSION_MASK|0x01)
+#define KADM5_API_VERSION_2 (KADM5_API_VERSION_MASK|0x02)
+
+typedef struct _kadm5_principal_ent_t_v2 {
+ krb5_principal principal;
+ krb5_timestamp princ_expire_time;
+ krb5_timestamp last_pwd_change;
+ krb5_timestamp pw_expiration;
+ krb5_deltat max_life;
+ krb5_principal mod_name;
+ krb5_timestamp mod_date;
+ krb5_flags attributes;
+ krb5_kvno kvno;
+ krb5_kvno mkvno;
+ char *policy;
+ long aux_attributes;
+
+ /* version 2 fields */
+ krb5_deltat max_renewable_life;
+ krb5_timestamp last_success;
+ krb5_timestamp last_failed;
+ krb5_kvno fail_auth_count;
+ krb5_int16 n_key_data;
+ krb5_int16 n_tl_data;
+ krb5_tl_data *tl_data;
+ krb5_key_data *key_data;
+} kadm5_principal_ent_rec_v2, *kadm5_principal_ent_t_v2;
+
+typedef struct _kadm5_principal_ent_t_v1 {
+ krb5_principal principal;
+ krb5_timestamp princ_expire_time;
+ krb5_timestamp last_pwd_change;
+ krb5_timestamp pw_expiration;
+ krb5_deltat max_life;
+ krb5_principal mod_name;
+ krb5_timestamp mod_date;
+ krb5_flags attributes;
+ krb5_kvno kvno;
+ krb5_kvno mkvno;
+ char *policy;
+ long aux_attributes;
+} kadm5_principal_ent_rec_v1, *kadm5_principal_ent_t_v1;
+
+#if USE_KADM5_API_VERSION == 1
+typedef struct _kadm5_principal_ent_t_v1
+ kadm5_principal_ent_rec, *kadm5_principal_ent_t;
+#else
+typedef struct _kadm5_principal_ent_t_v2
+ kadm5_principal_ent_rec, *kadm5_principal_ent_t;
+#endif
+
+typedef struct _kadm5_policy_ent_t {
+ char *policy;
+ long pw_min_life;
+ long pw_max_life;
+ long pw_min_length;
+ long pw_min_classes;
+ long pw_history_num;
+ long policy_refcnt;
+} kadm5_policy_ent_rec, *kadm5_policy_ent_t;
+
+typedef struct __krb5_key_salt_tuple {
+ krb5_enctype ks_enctype;
+ krb5_int32 ks_salttype;
+} krb5_key_salt_tuple;
+
+/*
+ * Data structure returned by kadm5_get_config_params()
+ */
+typedef struct _kadm5_config_params {
+ long mask;
+ char * realm;
+ char * profile;
+ int kadmind_port;
+
+ char * admin_server;
+
+ char * dbname;
+ char * admin_dbname;
+ char * admin_lockfile;
+ char * admin_keytab;
+ char * acl_file;
+ char * dict_file;
+
+ int mkey_from_kbd;
+ char * stash_file;
+ char * mkey_name;
+ krb5_enctype enctype;
+ krb5_deltat max_life;
+ krb5_deltat max_rlife;
+ krb5_timestamp expiration;
+ krb5_flags flags;
+ krb5_key_salt_tuple *keysalts;
+ krb5_int32 num_keysalts;
+} kadm5_config_params;
+
+/***********************************************************************
+ * This is the old krb5_realm_read_params, which I mutated into
+ * kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
+ * still uses.
+ ***********************************************************************/
+
+/*
+ * Data structure returned by krb5_read_realm_params()
+ */
+typedef struct __krb5_realm_params {
+ char * realm_profile;
+ char * realm_dbname;
+ char * realm_mkey_name;
+ char * realm_stash_file;
+ char * realm_kdc_ports;
+ char * realm_acl_file;
+ krb5_int32 realm_kadmind_port;
+ krb5_enctype realm_enctype;
+ krb5_deltat realm_max_life;
+ krb5_deltat realm_max_rlife;
+ krb5_timestamp realm_expiration;
+ krb5_flags realm_flags;
+ krb5_key_salt_tuple *realm_keysalts;
+ unsigned int realm_kadmind_port_valid:1;
+ unsigned int realm_enctype_valid:1;
+ unsigned int realm_max_life_valid:1;
+ unsigned int realm_max_rlife_valid:1;
+ unsigned int realm_expiration_valid:1;
+ unsigned int realm_flags_valid:1;
+ unsigned int realm_filler:7;
+ krb5_int32 realm_num_keysalts;
+} krb5_realm_params;
+
+/*
+ * functions
+ */
+
+#if USE_KADM5_API_VERSION > 1
+krb5_error_code kadm5_get_config_params(krb5_context context,
+ char *kdcprofile, char *kdcenv,
+ kadm5_config_params *params_in,
+ kadm5_config_params *params_out);
+krb5_error_code kadm5_free_realm_params(krb5_context kcontext,
+ kadm5_config_params *params);
+#endif
+
+kadm5_ret_t kadm5_init(char *client_name, char *pass,
+ char *service_name,
+#if USE_KADM5_API_VERSION == 1
+ char *realm,
+#else
+ kadm5_config_params *params,
+#endif
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+kadm5_ret_t kadm5_init_with_password(char *client_name,
+ char *pass,
+ char *service_name,
+#if USE_KADM5_API_VERSION == 1
+ char *realm,
+#else
+ kadm5_config_params *params,
+#endif
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+kadm5_ret_t kadm5_init_with_skey(char *client_name,
+ char *keytab,
+ char *service_name,
+#if USE_KADM5_API_VERSION == 1
+ char *realm,
+#else
+ kadm5_config_params *params,
+#endif
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+#if USE_KADM5_API_VERSION > 1
+kadm5_ret_t kadm5_init_with_creds(char *client_name,
+ krb5_ccache cc,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+#endif
+kadm5_ret_t kadm5_flush(void *server_handle);
+kadm5_ret_t kadm5_destroy(void *server_handle);
+kadm5_ret_t kadm5_create_principal(void *server_handle,
+ kadm5_principal_ent_t ent,
+ long mask, char *pass);
+kadm5_ret_t kadm5_delete_principal(void *server_handle,
+ krb5_principal principal);
+kadm5_ret_t kadm5_modify_principal(void *server_handle,
+ kadm5_principal_ent_t ent,
+ long mask);
+kadm5_ret_t kadm5_rename_principal(void *server_handle,
+ krb5_principal,krb5_principal);
+#if USE_KADM5_API_VERSION == 1
+kadm5_ret_t kadm5_get_principal(void *server_handle,
+ krb5_principal principal,
+ kadm5_principal_ent_t *ent);
+#else
+kadm5_ret_t kadm5_get_principal(void *server_handle,
+ krb5_principal principal,
+ kadm5_principal_ent_t ent,
+ long mask);
+#endif
+kadm5_ret_t kadm5_chpass_principal(void *server_handle,
+ krb5_principal principal,
+ char *pass);
+#if USE_KADM5_API_VERSION == 1
+kadm5_ret_t kadm5_randkey_principal(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock **keyblock);
+#else
+kadm5_ret_t kadm5_randkey_principal(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock **keyblocks,
+ int *n_keys);
+#endif
+kadm5_ret_t kadm5_create_policy(void *server_handle,
+ kadm5_policy_ent_t ent,
+ long mask);
+/*
+ * kadm5_create_policy_internal is not part of the supported,
+ * exposed API. It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from kadm5_create_policy.
+ */
+kadm5_ret_t kadm5_create_policy_internal(void *server_handle,
+ kadm5_policy_ent_t
+ entry, long mask);
+kadm5_ret_t kadm5_delete_policy(void *server_handle,
+ kadm5_policy_t policy);
+kadm5_ret_t kadm5_modify_policy(void *server_handle,
+ kadm5_policy_ent_t ent,
+ long mask);
+/*
+ * kadm5_modify_policy_internal is not part of the supported,
+ * exposed API. It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from kadm5_modify_policy.
+ */
+kadm5_ret_t kadm5_modify_policy_internal(void *server_handle,
+ kadm5_policy_ent_t
+ entry, long mask);
+#if USE_KADM5_API_VERSION == 1
+kadm5_ret_t kadm5_get_policy(void *server_handle,
+ kadm5_policy_t policy,
+ kadm5_policy_ent_t *ent);
+#else
+kadm5_ret_t kadm5_get_policy(void *server_handle,
+ kadm5_policy_t policy,
+ kadm5_policy_ent_t ent);
+#endif
+kadm5_ret_t kadm5_get_privs(void *server_handle,
+ long *privs);
+
+kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret);
+
+kadm5_ret_t kadm5_free_principal_ent(void *server_handle,
+ kadm5_principal_ent_t
+ ent);
+kadm5_ret_t kadm5_free_policy_ent(void *server_handle,
+ kadm5_policy_ent_t ent);
+
+kadm5_ret_t kadm5_get_principals(void *server_handle,
+ char *exp, char ***princs,
+ int *count);
+
+kadm5_ret_t kadm5_get_policies(void *server_handle,
+ char *exp, char ***pols,
+ int *count);
+
+#if USE_KADM5_API_VERSION > 1
+kadm5_ret_t kadm5_free_key_data(void *server_handle,
+ krb5_int16 *n_key_data,
+ krb5_key_data *key_data);
+#endif
+
+#if USE_KADM5_API_VERSION == 1
+/*
+ * OVSEC_KADM_API_VERSION_1 should be, if possible, compile-time
+ * compatible with KADM5_API_VERSION_2. Basically, this means we have
+ * to continue to provide all the old ovsec_kadm function and symbol
+ * names.
+ */
+
+#define OVSEC_KADM_ACLFILE "/krb5/ovsec_adm.acl"
+#define OVSEC_KADM_WORDFILE "/krb5/ovsec_adm.dict"
+
+#define OVSEC_KADM_ADMIN_SERVICE "ovsec_adm/admin"
+#define OVSEC_KADM_CHANGEPW_SERVICE "ovsec_adm/changepw"
+#define OVSEC_KADM_HIST_PRINCIPAL "ovsec_adm/history"
+
+typedef krb5_principal ovsec_kadm_princ_t;
+typedef krb5_keyblock ovsec_kadm_keyblock;
+typedef char *ovsec_kadm_policy_t;
+typedef long ovsec_kadm_ret_t;
+
+enum ovsec_kadm_salttype { OVSEC_KADM_SALT_V4, OVSEC_KADM_SALT_NORMAL };
+enum ovsec_kadm_saltmod { OVSEC_KADM_MOD_KEEP, OVSEC_KADM_MOD_V4, OVSEC_KADM_MOD_NORMAL };
+
+#define OVSEC_KADM_PW_FIRST_PROMPT \
+ ((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_PROMPT))
+#define OVSEC_KADM_PW_SECOND_PROMPT \
+ ((char *) error_message(CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT))
+
+/*
+ * Succsessfull return code
+ */
+#define OVSEC_KADM_OK 0
+
+/*
+ * Create/Modify masks
+ */
+/* principal */
+#define OVSEC_KADM_PRINCIPAL 0x000001
+#define OVSEC_KADM_PRINC_EXPIRE_TIME 0x000002
+#define OVSEC_KADM_PW_EXPIRATION 0x000004
+#define OVSEC_KADM_LAST_PWD_CHANGE 0x000008
+#define OVSEC_KADM_ATTRIBUTES 0x000010
+#define OVSEC_KADM_MAX_LIFE 0x000020
+#define OVSEC_KADM_MOD_TIME 0x000040
+#define OVSEC_KADM_MOD_NAME 0x000080
+#define OVSEC_KADM_KVNO 0x000100
+#define OVSEC_KADM_MKVNO 0x000200
+#define OVSEC_KADM_AUX_ATTRIBUTES 0x000400
+#define OVSEC_KADM_POLICY 0x000800
+#define OVSEC_KADM_POLICY_CLR 0x001000
+/* policy */
+#define OVSEC_KADM_PW_MAX_LIFE 0x004000
+#define OVSEC_KADM_PW_MIN_LIFE 0x008000
+#define OVSEC_KADM_PW_MIN_LENGTH 0x010000
+#define OVSEC_KADM_PW_MIN_CLASSES 0x020000
+#define OVSEC_KADM_PW_HISTORY_NUM 0x040000
+#define OVSEC_KADM_REF_COUNT 0x080000
+
+/*
+ * permission bits
+ */
+#define OVSEC_KADM_PRIV_GET 0x01
+#define OVSEC_KADM_PRIV_ADD 0x02
+#define OVSEC_KADM_PRIV_MODIFY 0x04
+#define OVSEC_KADM_PRIV_DELETE 0x08
+
+/*
+ * API versioning constants
+ */
+#define OVSEC_KADM_MASK_BITS 0xffffff00
+
+#define OVSEC_KADM_STRUCT_VERSION_MASK 0x12345600
+#define OVSEC_KADM_STRUCT_VERSION_1 (OVSEC_KADM_STRUCT_VERSION_MASK|0x01)
+#define OVSEC_KADM_STRUCT_VERSION OVSEC_KADM_STRUCT_VERSION_1
+
+#define OVSEC_KADM_API_VERSION_MASK 0x12345700
+#define OVSEC_KADM_API_VERSION_1 (OVSEC_KADM_API_VERSION_MASK|0x01)
+
+
+typedef struct _ovsec_kadm_principal_ent_t {
+ krb5_principal principal;
+ krb5_timestamp princ_expire_time;
+ krb5_timestamp last_pwd_change;
+ krb5_timestamp pw_expiration;
+ krb5_deltat max_life;
+ krb5_principal mod_name;
+ krb5_timestamp mod_date;
+ krb5_flags attributes;
+ krb5_kvno kvno;
+ krb5_kvno mkvno;
+ char *policy;
+ long aux_attributes;
+} ovsec_kadm_principal_ent_rec, *ovsec_kadm_principal_ent_t;
+
+typedef struct _ovsec_kadm_policy_ent_t {
+ char *policy;
+ long pw_min_life;
+ long pw_max_life;
+ long pw_min_length;
+ long pw_min_classes;
+ long pw_history_num;
+ long policy_refcnt;
+} ovsec_kadm_policy_ent_rec, *ovsec_kadm_policy_ent_t;
+
+/*
+ * functions
+ */
+ovsec_kadm_ret_t ovsec_kadm_init(char *client_name, char *pass,
+ char *service_name, char *realm,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+ovsec_kadm_ret_t ovsec_kadm_init_with_password(char *client_name,
+ char *pass,
+ char *service_name,
+ char *realm,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+ovsec_kadm_ret_t ovsec_kadm_init_with_skey(char *client_name,
+ char *keytab,
+ char *service_name,
+ char *realm,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+ovsec_kadm_ret_t ovsec_kadm_flush(void *server_handle);
+ovsec_kadm_ret_t ovsec_kadm_destroy(void *server_handle);
+ovsec_kadm_ret_t ovsec_kadm_create_principal(void *server_handle,
+ ovsec_kadm_principal_ent_t ent,
+ long mask, char *pass);
+ovsec_kadm_ret_t ovsec_kadm_delete_principal(void *server_handle,
+ krb5_principal principal);
+ovsec_kadm_ret_t ovsec_kadm_modify_principal(void *server_handle,
+ ovsec_kadm_principal_ent_t ent,
+ long mask);
+ovsec_kadm_ret_t ovsec_kadm_rename_principal(void *server_handle,
+ krb5_principal,krb5_principal);
+ovsec_kadm_ret_t ovsec_kadm_get_principal(void *server_handle,
+ krb5_principal principal,
+ ovsec_kadm_principal_ent_t *ent);
+ovsec_kadm_ret_t ovsec_kadm_chpass_principal(void *server_handle,
+ krb5_principal principal,
+ char *pass);
+ovsec_kadm_ret_t ovsec_kadm_randkey_principal(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock **keyblock);
+ovsec_kadm_ret_t ovsec_kadm_create_policy(void *server_handle,
+ ovsec_kadm_policy_ent_t ent,
+ long mask);
+/*
+ * ovsec_kadm_create_policy_internal is not part of the supported,
+ * exposed API. It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from ovsec_kadm_create_policy.
+ */
+ovsec_kadm_ret_t ovsec_kadm_create_policy_internal(void *server_handle,
+ ovsec_kadm_policy_ent_t
+ entry, long mask);
+ovsec_kadm_ret_t ovsec_kadm_delete_policy(void *server_handle,
+ ovsec_kadm_policy_t policy);
+ovsec_kadm_ret_t ovsec_kadm_modify_policy(void *server_handle,
+ ovsec_kadm_policy_ent_t ent,
+ long mask);
+/*
+ * ovsec_kadm_modify_policy_internal is not part of the supported,
+ * exposed API. It is available only in the server library, and you
+ * shouldn't use it unless you know why it's there and how it's
+ * different from ovsec_kadm_modify_policy.
+ */
+ovsec_kadm_ret_t ovsec_kadm_modify_policy_internal(void *server_handle,
+ ovsec_kadm_policy_ent_t
+ entry, long mask);
+ovsec_kadm_ret_t ovsec_kadm_get_policy(void *server_handle,
+ ovsec_kadm_policy_t policy,
+ ovsec_kadm_policy_ent_t *ent);
+ovsec_kadm_ret_t ovsec_kadm_get_privs(void *server_handle,
+ long *privs);
+
+ovsec_kadm_ret_t ovsec_kadm_chpass_principal_util(void *server_handle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret);
+
+ovsec_kadm_ret_t ovsec_kadm_free_principal_ent(void *server_handle,
+ ovsec_kadm_principal_ent_t
+ ent);
+ovsec_kadm_ret_t ovsec_kadm_free_policy_ent(void *server_handle,
+ ovsec_kadm_policy_ent_t ent);
+
+ovsec_kadm_ret_t ovsec_kadm_get_principals(void *server_handle,
+ char *exp, char ***princs,
+ int *count);
+
+ovsec_kadm_ret_t ovsec_kadm_get_policies(void *server_handle,
+ char *exp, char ***pols,
+ int *count);
+
+#define OVSEC_KADM_FAILURE KADM5_FAILURE
+#define OVSEC_KADM_AUTH_GET KADM5_AUTH_GET
+#define OVSEC_KADM_AUTH_ADD KADM5_AUTH_ADD
+#define OVSEC_KADM_AUTH_MODIFY KADM5_AUTH_MODIFY
+#define OVSEC_KADM_AUTH_DELETE KADM5_AUTH_DELETE
+#define OVSEC_KADM_AUTH_INSUFFICIENT KADM5_AUTH_INSUFFICIENT
+#define OVSEC_KADM_BAD_DB KADM5_BAD_DB
+#define OVSEC_KADM_DUP KADM5_DUP
+#define OVSEC_KADM_RPC_ERROR KADM5_RPC_ERROR
+#define OVSEC_KADM_NO_SRV KADM5_NO_SRV
+#define OVSEC_KADM_BAD_HIST_KEY KADM5_BAD_HIST_KEY
+#define OVSEC_KADM_NOT_INIT KADM5_NOT_INIT
+#define OVSEC_KADM_UNK_PRINC KADM5_UNK_PRINC
+#define OVSEC_KADM_UNK_POLICY KADM5_UNK_POLICY
+#define OVSEC_KADM_BAD_MASK KADM5_BAD_MASK
+#define OVSEC_KADM_BAD_CLASS KADM5_BAD_CLASS
+#define OVSEC_KADM_BAD_LENGTH KADM5_BAD_LENGTH
+#define OVSEC_KADM_BAD_POLICY KADM5_BAD_POLICY
+#define OVSEC_KADM_BAD_PRINCIPAL KADM5_BAD_PRINCIPAL
+#define OVSEC_KADM_BAD_AUX_ATTR KADM5_BAD_AUX_ATTR
+#define OVSEC_KADM_BAD_HISTORY KADM5_BAD_HISTORY
+#define OVSEC_KADM_BAD_MIN_PASS_LIFE KADM5_BAD_MIN_PASS_LIFE
+#define OVSEC_KADM_PASS_Q_TOOSHORT KADM5_PASS_Q_TOOSHORT
+#define OVSEC_KADM_PASS_Q_CLASS KADM5_PASS_Q_CLASS
+#define OVSEC_KADM_PASS_Q_DICT KADM5_PASS_Q_DICT
+#define OVSEC_KADM_PASS_REUSE KADM5_PASS_REUSE
+#define OVSEC_KADM_PASS_TOOSOON KADM5_PASS_TOOSOON
+#define OVSEC_KADM_POLICY_REF KADM5_POLICY_REF
+#define OVSEC_KADM_INIT KADM5_INIT
+#define OVSEC_KADM_BAD_PASSWORD KADM5_BAD_PASSWORD
+#define OVSEC_KADM_PROTECT_PRINCIPAL KADM5_PROTECT_PRINCIPAL
+#define OVSEC_KADM_BAD_SERVER_HANDLE KADM5_BAD_SERVER_HANDLE
+#define OVSEC_KADM_BAD_STRUCT_VERSION KADM5_BAD_STRUCT_VERSION
+#define OVSEC_KADM_OLD_STRUCT_VERSION KADM5_OLD_STRUCT_VERSION
+#define OVSEC_KADM_NEW_STRUCT_VERSION KADM5_NEW_STRUCT_VERSION
+#define OVSEC_KADM_BAD_API_VERSION KADM5_BAD_API_VERSION
+#define OVSEC_KADM_OLD_LIB_API_VERSION KADM5_OLD_LIB_API_VERSION
+#define OVSEC_KADM_OLD_SERVER_API_VERSION KADM5_OLD_SERVER_API_VERSION
+#define OVSEC_KADM_NEW_LIB_API_VERSION KADM5_NEW_LIB_API_VERSION
+#define OVSEC_KADM_NEW_SERVER_API_VERSION KADM5_NEW_SERVER_API_VERSION
+#define OVSEC_KADM_SECURE_PRINC_MISSING KADM5_SECURE_PRINC_MISSING
+#define OVSEC_KADM_NO_RENAME_SALT KADM5_NO_RENAME_SALT
+
+#endif /* USE_KADM5_API_VERSION == 1 */
+
+#endif /* __KADM5_ADMIN_H__ */
diff --git a/src/lib/kadm5/admin_internal.h b/src/lib/kadm5/admin_internal.h
new file mode 100644
index 000000000..d73837e67
--- /dev/null
+++ b/src/lib/kadm5/admin_internal.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#ifndef __KADM5_ADMIN_INTERNAL_H__
+#define __KADM5_ADMIN_INTERNAL_H__
+
+#include <kadm5/admin.h>
+
+#define KADM5_SERVER_HANDLE_MAGIC 0x12345800
+
+#define GENERIC_CHECK_HANDLE(handle, old_api_version, new_api_version) \
+{ \
+ kadm5_server_handle_t srvr = \
+ (kadm5_server_handle_t) handle; \
+ \
+ if (! srvr) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ if (srvr->magic_number != KADM5_SERVER_HANDLE_MAGIC) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ if ((srvr->struct_version & KADM5_MASK_BITS) != \
+ KADM5_STRUCT_VERSION_MASK) \
+ return KADM5_BAD_STRUCT_VERSION; \
+ if (srvr->struct_version < KADM5_STRUCT_VERSION_1) \
+ return KADM5_OLD_STRUCT_VERSION; \
+ if (srvr->struct_version > KADM5_STRUCT_VERSION_1) \
+ return KADM5_NEW_STRUCT_VERSION; \
+ if ((srvr->api_version & KADM5_MASK_BITS) != \
+ KADM5_API_VERSION_MASK) \
+ return KADM5_BAD_API_VERSION; \
+ if (srvr->api_version < KADM5_API_VERSION_1) \
+ return old_api_version; \
+ if (srvr->api_version > KADM5_API_VERSION_2) \
+ return new_api_version; \
+}
+
+/*
+ * _KADM5_CHECK_HANDLE calls the function _kadm5_check_handle and
+ * returns any non-zero error code that function returns.
+ * _kadm5_check_handle, in client_handle.c and server_handle.c, exists
+ * in both the server- and client- side libraries. In each library,
+ * it calls CHECK_HANDLE, which is defined by the appropriate
+ * _internal.h header file to call GENERIC_CHECK_HANDLE as well as
+ * CLIENT_CHECK_HANDLE and SERVER_CHECK_HANDLE.
+ *
+ * _KADM5_CHECK_HANDLE should be used by a function that needs to
+ * check the handle but wants to be the same code in both the client
+ * and server library; it makes a function call to the right handle
+ * checker. Code that only exists in one library can call the
+ * CHECK_HANDLE macro, which inlines the test instead of making
+ * another function call.
+ *
+ * Got that?
+ */
+#define _KADM5_CHECK_HANDLE(handle) \
+{ int code; if (code = _kadm5_check_handle((void *)handle)) return code; }
+
+kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
+ void *lhandle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret);
+
+/* this is needed by the alt_prof code I stole. The functions
+ maybe shouldn't be named krb5_*, but they are. */
+
+krb5_error_code
+krb5_string_to_keysalts(char *string, const char *tupleseps,
+ const char *ksaltseps, krb5_boolean dups,
+ krb5_key_salt_tuple **ksaltp, krb5_int32 *nksaltp);
+
+krb5_error_code
+krb5_string_to_flags(char* string, const char* positive, const char* negative,
+ krb5_flags *flagsp);
+
+#endif /* __KADM5_ADMIN_INTERNAL_H__ */
diff --git a/src/lib/kadm5/admin_xdr.h b/src/lib/kadm5/admin_xdr.h
new file mode 100644
index 000000000..3e4f48f7a
--- /dev/null
+++ b/src/lib/kadm5/admin_xdr.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.5 1996/07/22 20:35:33 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.4.4.1 1996/07/18 03:08:25 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.4.2.1 1996/06/20 02:16:37 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.4 1996/05/30 16:36:34 bjaspan
+ * finish updating to kadm5 naming (oops)
+ *
+ * Revision 1.3 1996/05/22 00:28:19 bjaspan
+ * rename to kadm5
+ *
+ * Revision 1.2 1996/05/12 06:30:10 marc
+ * - fixup includes and data types to match beta6
+ *
+ * Revision 1.1 1993/11/09 04:06:01 shanzer
+ * Initial revision
+ *
+ */
+
+#include <kadm5/admin.h>
+#include "kadm_rpc.h"
+
+bool_t xdr_nullstring(XDR *xdrs, char **objp);
+bool_t xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp);
+bool_t xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp);
+bool_t xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp);
+bool_t xdr_krb5_flags(XDR *xdrs, krb5_flags *objp);
+bool_t xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp);
+bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp);
+bool_t xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp);
+bool_t xdr_kadm5_policy_ent_t(XDR *xdrs, kadm5_policy_ent_t *objp);
+bool_t xdr_kadm5_principal_ent_t(XDR *xdrs, kadm5_principal_ent_t *objp);
+bool_t xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp);
+bool_t xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp);
+bool_t xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp);
+bool_t xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp);
+bool_t xdr_chpass_arg(XDR *xdrs, chpass_arg *objp);
+bool_t xdr_chrand_arg(XDR *xdrs, chrand_arg *objp);
+bool_t xdr_chrand_ret(XDR *xdrs, chrand_ret *objp);
+bool_t xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp);
+bool_t xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp);
+bool_t xdr_cpol_arg(XDR *xdrs, cpol_arg *objp);
+bool_t xdr_dpol_arg(XDR *xdrs, dpol_arg *objp);
+bool_t xdr_mpol_arg(XDR *xdrs, mpol_arg *objp);
+bool_t xdr_gpol_arg(XDR *xdrs, gpol_arg *objp);
+bool_t xdr_gpol_ret(XDR *xdrs, gpol_ret *objp);
+bool_t xdr_krb5_principal(XDR *xdrs, krb5_principal *objp);
+bool_t xdr_krb5_octet(XDR *xdrs, krb5_octet *objp);
+bool_t xdr_krb5_int32(XDR *xdrs, krb5_int32 *objp);
+bool_t xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp);
+bool_t xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp);
diff --git a/src/lib/kadm5/alt_prof.c b/src/lib/kadm5/alt_prof.c
new file mode 100644
index 000000000..2f36f76fa
--- /dev/null
+++ b/src/lib/kadm5/alt_prof.c
@@ -0,0 +1,861 @@
+/*
+ * lib/kadm/alt_prof.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * alt_prof.c - Implement alternate profile file handling.
+ */
+#include "k5-int.h"
+#include <kadm5/admin.h>
+#include <stdio.h>
+#include <ctype.h>
+
+/*
+ * krb5_aprof_init() - Initialize alternate profile context.
+ *
+ * Parameters:
+ * fname - default file name of the profile.
+ * envname - environment variable name which can override fname.
+ * acontextp - Pointer to opaque context for alternate profile.
+ *
+ * Returns:
+ * error codes from profile_init()
+ */
+krb5_error_code
+krb5_aprof_init(fname, envname, acontextp)
+ char *fname;
+ char *envname;
+ krb5_pointer *acontextp;
+{
+ krb5_error_code kret;
+ const char *namelist[2];
+ profile_t profile;
+
+ namelist[1] = (char *) NULL;
+ profile = (profile_t) NULL;
+ if (envname) {
+ if ((namelist[0] = getenv(envname))) {
+ if (!(kret = profile_init(namelist, &profile))) {
+ *acontextp = (krb5_pointer) profile;
+ return(0);
+ }
+ }
+ }
+ namelist[0] = fname;
+ profile = (profile_t) NULL;
+ if (!(kret = profile_init(namelist, &profile))) {
+ *acontextp = (krb5_pointer) profile;
+ return(0);
+ }
+ return(kret);
+}
+
+/*
+ * krb5_aprof_getvals() - Get values from alternate profile.
+ *
+ * Parameters:
+ * acontext - opaque context for alternate profile.
+ * hierarchy - hierarchy of value to retrieve.
+ * retdata - Returned data values.
+ *
+ * Returns:
+ * error codes from profile_get_values()
+ */
+krb5_error_code
+krb5_aprof_getvals(acontext, hierarchy, retdata)
+ krb5_pointer acontext;
+ const char **hierarchy;
+ char ***retdata;
+{
+ return(profile_get_values((profile_t) acontext,
+ hierarchy,
+ retdata));
+}
+
+/*
+ * krb5_aprof_get_deltat() - Get a delta time value from the alternate
+ * profile.
+ *
+ * Parameters:
+ * acontext - opaque context for alternate profile.
+ * hierarchy - hierarchy of value to retrieve.
+ * uselast - if true, use last value, otherwise use
+ * first value found.
+ * deltatp - returned delta time value.
+ *
+ * Returns:
+ * error codes from profile_get_values()
+ * error codes from krb5_string_to_deltat()
+ */
+krb5_error_code
+krb5_aprof_get_deltat(acontext, hierarchy, uselast, deltatp)
+ krb5_pointer acontext;
+ const char **hierarchy;
+ krb5_boolean uselast;
+ krb5_deltat *deltatp;
+{
+ krb5_error_code kret;
+ char **values;
+ char *valp;
+ int index;
+
+ if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
+ index = 0;
+ if (uselast) {
+ for (index=0; values[index]; index++);
+ index--;
+ }
+ valp = values[index];
+ kret = krb5_string_to_deltat(valp, deltatp);
+
+ /* Free the string storage */
+ for (index=0; values[index]; index++)
+ krb5_xfree(values[index]);
+ krb5_xfree(values);
+ }
+ return(kret);
+}
+
+/*
+ * krb5_aprof_get_string() - Get a string value from the alternate
+ * profile.
+ *
+ * Parameters:
+ * acontext - opaque context for alternate profile.
+ * hierarchy - hierarchy of value to retrieve.
+ * uselast - if true, use last value, otherwise use
+ * first value found.
+ * stringp - returned string value.
+ *
+ * Returns:
+ * error codes from profile_get_values()
+ */
+krb5_error_code
+krb5_aprof_get_string(acontext, hierarchy, uselast, stringp)
+ krb5_pointer acontext;
+ const char **hierarchy;
+ krb5_boolean uselast;
+ char **stringp;
+{
+ krb5_error_code kret;
+ char **values;
+ int index, i;
+
+ if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
+ index = 0;
+ if (uselast) {
+ for (index=0; values[index]; index++);
+ index--;
+ }
+
+ *stringp = values[index];
+
+ /* Free the string storage */
+ for (i=0; values[i]; i++)
+ if (i != index)
+ krb5_xfree(values[i]);
+ krb5_xfree(values);
+ }
+ return(kret);
+}
+
+/*
+ * krb5_aprof_get_int32() - Get a 32-bit integer value from the alternate
+ * profile.
+ *
+ * Parameters:
+ * acontext - opaque context for alternate profile.
+ * hierarchy - hierarchy of value to retrieve.
+ * uselast - if true, use last value, otherwise use
+ * first value found.
+ * intp - returned 32-bit integer value.
+ *
+ * Returns:
+ * error codes from profile_get_values()
+ * EINVAL - value is not an integer
+ */
+krb5_error_code
+krb5_aprof_get_int32(acontext, hierarchy, uselast, intp)
+ krb5_pointer acontext;
+ const char **hierarchy;
+ krb5_boolean uselast;
+ krb5_int32 *intp;
+{
+ krb5_error_code kret;
+ char **values;
+ int index;
+
+ if (!(kret = krb5_aprof_getvals(acontext, hierarchy, &values))) {
+ index = 0;
+ if (uselast) {
+ for (index=0; values[index]; index++);
+ index--;
+ }
+
+ if (sscanf(values[index], "%d", intp) != 1)
+ kret = EINVAL;
+
+ /* Free the string storage */
+ for (index=0; values[index]; index++)
+ krb5_xfree(values[index]);
+ krb5_xfree(values);
+ }
+ return(kret);
+}
+
+/*
+ * krb5_aprof_finish() - Finish alternate profile context.
+ *
+ * Parameter:
+ * acontext - opaque context for alternate profile.
+ *
+ * Returns:
+ * 0 on success, something else on failure.
+ */
+krb5_error_code
+krb5_aprof_finish(acontext)
+ krb5_pointer acontext;
+{
+ profile_release(acontext);
+ return(0);
+}
+
+/*
+ * Function: kadm5_get_config_params
+ *
+ * Purpose: Merge configuration parameters provided by the caller with
+ * values specified in configuration files and with default values.
+ *
+ * Arguments:
+ *
+ * context (r) krb5_context to use
+ * profile (r) profile file to use
+ * envname (r) envname that contains a profile name to
+ * override profile
+ * params_in (r) params structure containing user-supplied
+ * values, or NULL
+ * params_out (w) params structure to be filled in
+ *
+ * Effects:
+ *
+ * The fields and mask of params_out are filled in with values
+ * obtained from params_in, the specified profile, and default
+ * values. Only and all fields specified in params_out->mask are
+ * set. The context of params_out must be freed with
+ * kadm5_free_config_params.
+ *
+ * params_in and params_out may be the same pointer. However, all pointers
+ * in params_in for which the mask is set will be re-assigned to newly copied
+ * versions, overwriting the old pointer value.
+ */
+krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv,
+ params_in, params_out)
+ krb5_context context;
+ char *kdcprofile;
+ char *kdcenv;
+ kadm5_config_params *params_in, *params_out;
+{
+ char *filename;
+ char *envname;
+ char *lrealm;
+ krb5_pointer aprofile = 0;
+ const char *hierarchy[4];
+ char *svalue;
+ krb5_int32 ivalue;
+ krb5_deltat dtvalue;
+ kadm5_config_params params, empty_params;
+
+ krb5_error_code kret;
+
+ memset((char *) &params, 0, sizeof(params));
+ memset((char *) &empty_params, 0, sizeof(empty_params));
+
+ if (params_in == NULL) params_in = &empty_params;
+
+ if (params_in->mask & KADM5_CONFIG_REALM) {
+ lrealm = params.realm = strdup(params_in->realm);
+ params.mask |= KADM5_CONFIG_REALM;
+ } else {
+ kret = krb5_get_default_realm(context, &lrealm);
+ if (kret)
+ goto cleanup;
+ params.realm = lrealm;
+ params.mask |= KADM5_CONFIG_REALM;
+ }
+ if (params_in->mask & KADM5_CONFIG_PROFILE) {
+ filename = params.profile = strdup(params_in->profile);
+ params.mask |= KADM5_CONFIG_PROFILE;
+ envname = NULL;
+ } else {
+ /* XXX ummm... these defaults should to work on both sides */
+ filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
+ envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
+ if (context->profile_secure == TRUE) envname = 0;
+ }
+
+ kret = krb5_aprof_init(filename, envname, &aprofile);
+ if (kret)
+ goto cleanup;
+
+ /* Initialize realm parameters */
+ hierarchy[0] = "realms";
+ hierarchy[1] = lrealm;
+ hierarchy[3] = (char *) NULL;
+
+ /* Get the value for the admin server */
+ hierarchy[2] = "admin_server";
+ if (params_in->mask & KADM5_CONFIG_ADMIN_SERVER) {
+ params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+ params.admin_server = strdup(params_in->admin_server);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.admin_server = svalue;
+ params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+ }
+ if (params.mask & KADM5_CONFIG_ADMIN_SERVER) {
+ char *p;
+ if (p = strchr(params.admin_server, ':')) {
+ params.kadmind_port = atoi(p+1);
+ params.mask |= KADM5_CONFIG_KADMIND_PORT;
+ *p = '\0';
+ }
+ }
+
+ /* Get the value for the database */
+ hierarchy[2] = "database_name";
+ if (params_in->mask & KADM5_CONFIG_DBNAME) {
+ params.mask |= KADM5_CONFIG_DBNAME;
+ params.dbname = strdup(params_in->dbname);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.dbname = svalue;
+ params.mask |= KADM5_CONFIG_DBNAME;
+ }
+
+ /*
+ * Get the value for the admin (policy) database and lockfile.
+ * The logic here is slightly tricky. DBNAME, ADBNAME, and
+ * ADB_LOCKFILE are dependent on the earlier items in the
+ * sequence. If an earlier item was specified via the input
+ * parameters, that value overrides the variables in the config
+ * file and causes the later item to be set to ".kadm5" or
+ * ".lock", respectively. However, if no earlier item was
+ * specified, the variables in the config file are used, and the
+ * ".kadm5" and ".lock" suffixes are only added as a no-variable
+ * default.
+ *
+ * Read the spec.
+ */
+ hierarchy[2] = "admin_database_name";
+ if (params_in->mask & KADM5_CONFIG_ADBNAME) {
+ params.mask |= KADM5_CONFIG_ADBNAME;
+ params.admin_dbname = strdup(params_in->admin_dbname);
+ } else if (params_in->mask & KADM5_CONFIG_DBNAME) {
+ params.admin_dbname = (char *) malloc(strlen(params.dbname) + 6);
+ if (params.admin_dbname) {
+ sprintf(params.admin_dbname, "%s.kadm5", params.dbname);
+ params.mask |= KADM5_CONFIG_ADBNAME;
+ }
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.admin_dbname = svalue;
+ params.mask |= KADM5_CONFIG_ADBNAME;
+ } else if (params.mask & KADM5_CONFIG_DBNAME) {
+ params.admin_dbname = (char *) malloc(strlen(params.dbname) + 6);
+ if (params.admin_dbname) {
+ sprintf(params.admin_dbname, "%s.kadm5", params.dbname);
+ params.mask |= KADM5_CONFIG_ADBNAME;
+ }
+ }
+
+ /* Get the value for the admin (policy) database lock file*/
+ hierarchy[2] = "admin_database_lockfile";
+ if (params_in->mask & KADM5_CONFIG_ADB_LOCKFILE) {
+ params.mask |= KADM5_CONFIG_ADB_LOCKFILE;
+ params.admin_lockfile = strdup(params_in->admin_lockfile);
+ } else if ((params_in->mask & KADM5_CONFIG_ADBNAME) ||
+ (params_in->mask & KADM5_CONFIG_DBNAME)) {
+ /* if DBNAME is set but ADBNAME is not, then admin_database
+ * will already have been set above */
+ params.admin_lockfile = (char *) malloc(strlen(params.admin_dbname)
+ + 6);
+ if (params.admin_lockfile) {
+ sprintf(params.admin_lockfile, "%s.lock", params.admin_dbname);
+ params.mask |= KADM5_CONFIG_ADB_LOCKFILE;
+ }
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.mask |= KADM5_CONFIG_ADB_LOCKFILE;
+ params.admin_lockfile = svalue;
+ } else if (params.mask & KADM5_CONFIG_ADBNAME) {
+ params.admin_lockfile = (char *) malloc(strlen(params.admin_dbname)
+ + 6);
+ if (params.admin_lockfile) {
+ sprintf(params.admin_lockfile, "%s.lock", params.admin_dbname);
+ params.mask |= KADM5_CONFIG_ADB_LOCKFILE;
+ }
+ }
+
+ /* Get the value for the admin (policy) database lock file*/
+ hierarchy[2] = "admin_keytab";
+ if (params_in->mask & KADM5_CONFIG_ADMIN_KEYTAB) {
+ params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+ params.admin_keytab = strdup(params_in->admin_keytab);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+ params.admin_keytab = svalue;
+ } else {
+ params.admin_keytab = (char *) getenv("KRB5_KTNAME");
+ if (params.admin_keytab) {
+ params.admin_keytab = strdup(params.admin_keytab);
+ if (params.admin_keytab)
+ params.mask |= KADM5_CONFIG_ADMIN_KEYTAB;
+ }
+ }
+
+ /* Get the name of the acl file */
+ hierarchy[2] = "acl_file";
+ if (params_in->mask & KADM5_CONFIG_ACL_FILE) {
+ params.mask |= KADM5_CONFIG_ACL_FILE;
+ params.acl_file = strdup(params_in->acl_file);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.mask |= KADM5_CONFIG_ACL_FILE;
+ params.acl_file = svalue;
+ }
+
+ /* Get the name of the dict file */
+ hierarchy[2] = "dict_file";
+ if (params_in->mask & KADM5_CONFIG_DICT_FILE) {
+ params.mask |= KADM5_CONFIG_DICT_FILE;
+ params.dict_file = strdup(params_in->dict_file);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.mask |= KADM5_CONFIG_DICT_FILE;
+ params.dict_file = svalue;
+ }
+
+ /* Get the value for the kadmind port */
+ if (! (params.mask & KADM5_CONFIG_KADMIND_PORT)) {
+ hierarchy[2] = "kadmind_port";
+ if (params_in->mask & KADM5_CONFIG_KADMIND_PORT) {
+ params.mask |= KADM5_CONFIG_KADMIND_PORT;
+ params.kadmind_port = params_in->kadmind_port;
+ } else if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE,
+ &ivalue)) {
+ params.kadmind_port = ivalue;
+ params.mask |= KADM5_CONFIG_KADMIND_PORT;
+ } else {
+ params.kadmind_port = 749; /* assigned by IANA */
+ params.mask |= KADM5_CONFIG_KADMIND_PORT;
+ }
+ }
+
+ /* Get the value for the master key name */
+ hierarchy[2] = "master_key_name";
+ if (params_in->mask & KADM5_CONFIG_MKEY_NAME) {
+ params.mask |= KADM5_CONFIG_MKEY_NAME;
+ params.mkey_name = strdup(params_in->mkey_name);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.mask |= KADM5_CONFIG_MKEY_NAME;
+ params.mkey_name = svalue;
+ }
+
+ /* Get the value for the master key type */
+ hierarchy[2] = "master_key_type";
+ if (params_in->mask & KADM5_CONFIG_ENCTYPE) {
+ params.mask |= KADM5_CONFIG_ENCTYPE;
+ params.enctype = params_in->enctype;
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ if (!krb5_string_to_enctype(svalue, &params.enctype)) {
+ params.mask |= KADM5_CONFIG_ENCTYPE;
+ krb5_xfree(svalue);
+ }
+ }
+
+ /* Get the value for mkey_from_kbd */
+ if (params_in->mask & KADM5_CONFIG_MKEY_FROM_KBD) {
+ params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+ params.mkey_from_kbd = params_in->mkey_from_kbd;
+ }
+
+ /* Get the value for the stashfile */
+ hierarchy[2] = "key_stash_file";
+ if (params_in->mask & KADM5_CONFIG_STASH_FILE) {
+ params.mask |= KADM5_CONFIG_STASH_FILE;
+ params.stash_file = strdup(params_in->stash_file);
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.mask |= KADM5_CONFIG_STASH_FILE;
+ params.stash_file = svalue;
+ }
+
+ /* Get the value for maximum ticket lifetime. */
+ hierarchy[2] = "max_life";
+ if (params_in->mask & KADM5_CONFIG_MAX_LIFE) {
+ params.mask |= KADM5_CONFIG_MAX_LIFE;
+ params.max_life = params_in->max_life;
+ } else if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+ params.max_life = dtvalue;
+ params.mask |= KADM5_CONFIG_MAX_LIFE;
+ } else {
+ params.max_life = 0;
+ params.mask |= KADM5_CONFIG_MAX_LIFE;
+ }
+
+ /* Get the value for maximum renewable ticket lifetime. */
+ hierarchy[2] = "max_renewable_life";
+ if (params_in->mask & KADM5_CONFIG_MAX_RLIFE) {
+ params.mask |= KADM5_CONFIG_MAX_RLIFE;
+ params.max_rlife = params_in->max_rlife;
+ } else if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+ params.max_rlife = dtvalue;
+ params.mask |= KADM5_CONFIG_MAX_RLIFE;
+ } else {
+ params.max_rlife = 0;
+ params.mask |= KADM5_CONFIG_MAX_RLIFE;
+ }
+
+ /* Get the value for the default principal expiration */
+ hierarchy[2] = "default_principal_expiration";
+ if (params_in->mask & KADM5_CONFIG_EXPIRATION) {
+ params.mask |= KADM5_CONFIG_EXPIRATION;
+ params.expiration = params_in->expiration;
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ if (!krb5_string_to_timestamp(svalue, &params.expiration)) {
+ params.mask |= KADM5_CONFIG_EXPIRATION;
+ krb5_xfree(svalue);
+ }
+ } else {
+ params.mask |= KADM5_CONFIG_EXPIRATION;
+ params.expiration = 0;
+ }
+
+ /* Get the value for the default principal flags */
+ hierarchy[2] = "default_principal_flags";
+ if (params_in->mask & KADM5_CONFIG_FLAGS) {
+ params.mask |= KADM5_CONFIG_FLAGS;
+ params.flags = params_in->flags;
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ char *sp, *ep, *tp;
+
+ sp = svalue;
+ params.flags = 0;
+ while (sp) {
+ if ((ep = strchr(sp, (int) ',')) ||
+ (ep = strchr(sp, (int) ' ')) ||
+ (ep = strchr(sp, (int) '\t'))) {
+ /* Fill in trailing whitespace of sp */
+ tp = ep - 1;
+ while (isspace(*tp) && (tp < sp)) {
+ *tp = '\0';
+ tp--;
+ }
+ *ep = '\0';
+ ep++;
+ /* Skip over trailing whitespace of ep */
+ while (isspace(*ep) && (*ep)) ep++;
+ }
+ /* Convert this flag */
+ if (krb5_string_to_flags(sp,
+ "+",
+ "-",
+ &params.flags))
+ break;
+ sp = ep;
+ }
+ if (!sp)
+ params.mask |= KADM5_CONFIG_FLAGS;
+ krb5_xfree(svalue);
+ } else {
+ params.mask |= KADM5_CONFIG_FLAGS;
+ params.flags = KRB5_KDB_DEF_FLAGS;
+ }
+
+ /* Get the value for the supported enctype/salttype matrix */
+ hierarchy[2] = "supported_enctypes";
+ if (params_in->mask & KADM5_CONFIG_ENCTYPES) {
+ params.mask |= KADM5_CONFIG_ENCTYPES;
+ params.keysalts = params_in->keysalts;
+ params.num_keysalts = params_in->num_keysalts;
+ } else if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ params.keysalts = NULL;
+ params.num_keysalts = 0;
+ krb5_string_to_keysalts(svalue,
+ ", \t", /* Tuple separators */
+ ":.-", /* Key/salt separators */
+ 0, /* No duplicates */
+ &params.keysalts,
+ &params.num_keysalts);
+ if (params.num_keysalts)
+ params.mask |= KADM5_CONFIG_ENCTYPES;
+ krb5_xfree(svalue);
+ }
+
+ *params_out = params;
+
+cleanup:
+ if (aprofile)
+ krb5_aprof_finish(aprofile);
+ if (kret) {
+ kadm5_free_config_params(context, &params);
+ params_out->mask = 0;
+ }
+ return(kret);
+}
+/*
+ * kadm5_free_config_params() - Free data allocated by above.
+ */
+krb5_error_code
+kadm5_free_config_params(context, params)
+ krb5_context context;
+ kadm5_config_params *params;
+{
+ if (params) {
+ if (params->profile)
+ krb5_xfree(params->profile);
+ if (params->dbname)
+ krb5_xfree(params->dbname);
+ if (params->mkey_name)
+ krb5_xfree(params->mkey_name);
+ if (params->stash_file)
+ krb5_xfree(params->stash_file);
+ if (params->keysalts)
+ krb5_xfree(params->keysalts);
+ if (params->admin_keytab)
+ free(params->admin_keytab);
+ if (params->dict_file)
+ free(params->dict_file);
+ if (params->acl_file)
+ free(params->acl_file);
+ if (params->realm)
+ free(params->realm);
+ if (params->admin_dbname)
+ free(params->admin_dbname);
+ }
+ return(0);
+}
+
+/***********************************************************************
+ * This is the old krb5_realm_read_params, which I mutated into
+ * kadm5_get_config_params but which old code (kdb5_* and krb5kdc)
+ * still uses.
+ ***********************************************************************/
+
+/*
+ * krb5_read_realm_params() - Read per-realm parameters from KDC
+ * alternate profile.
+ */
+krb5_error_code
+krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp)
+ krb5_context kcontext;
+ char *realm;
+ char *kdcprofile;
+ char *kdcenv;
+ krb5_realm_params **rparamp;
+{
+ char *filename;
+ char *envname;
+ char *lrealm;
+ krb5_pointer aprofile = 0;
+ krb5_realm_params *rparams;
+ const char *hierarchy[4];
+ char *svalue;
+ krb5_int32 ivalue;
+ krb5_deltat dtvalue;
+
+ krb5_error_code kret;
+
+ filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
+ envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
+
+ if (kcontext->profile_secure == TRUE) envname = 0;
+
+ rparams = (krb5_realm_params *) NULL;
+ if (realm)
+ lrealm = strdup(realm);
+ else {
+ kret = krb5_get_default_realm(kcontext, &lrealm);
+ if (kret)
+ goto cleanup;
+ }
+
+ kret = krb5_aprof_init(filename, envname, &aprofile);
+ if (kret)
+ goto cleanup;
+
+ rparams = (krb5_realm_params *) malloc(sizeof(krb5_realm_params));
+ if (rparams == 0) {
+ kret = ENOMEM;
+ goto cleanup;
+ }
+
+ /* Initialize realm parameters */
+ memset((char *) rparams, 0, sizeof(krb5_realm_params));
+
+ /* Get the value for the database */
+ hierarchy[0] = "realms";
+ hierarchy[1] = lrealm;
+ hierarchy[2] = "database_name";
+ hierarchy[3] = (char *) NULL;
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+ rparams->realm_dbname = svalue;
+
+ /* Get the value for the KDC port list */
+ hierarchy[2] = "kdc_ports";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+ rparams->realm_kdc_ports = svalue;
+
+ /* Get the name of the acl file */
+ hierarchy[2] = "acl_file";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+ rparams->realm_acl_file = svalue;
+
+ /* Get the value for the kadmind port */
+ hierarchy[2] = "kadmind_port";
+ if (!krb5_aprof_get_int32(aprofile, hierarchy, TRUE, &ivalue)) {
+ rparams->realm_kadmind_port = ivalue;
+ rparams->realm_kadmind_port_valid = 1;
+ }
+
+ /* Get the value for the master key name */
+ hierarchy[2] = "master_key_name";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+ rparams->realm_mkey_name = svalue;
+
+ /* Get the value for the master key type */
+ hierarchy[2] = "master_key_type";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ if (!krb5_string_to_enctype(svalue, &rparams->realm_enctype))
+ rparams->realm_enctype_valid = 1;
+ krb5_xfree(svalue);
+ }
+
+ /* Get the value for the stashfile */
+ hierarchy[2] = "key_stash_file";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue))
+ rparams->realm_stash_file = svalue;
+
+ /* Get the value for maximum ticket lifetime. */
+ hierarchy[2] = "max_life";
+ if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+ rparams->realm_max_life = dtvalue;
+ rparams->realm_max_life_valid = 1;
+ }
+
+ /* Get the value for maximum renewable ticket lifetime. */
+ hierarchy[2] = "max_renewable_life";
+ if (!krb5_aprof_get_deltat(aprofile, hierarchy, TRUE, &dtvalue)) {
+ rparams->realm_max_rlife = dtvalue;
+ rparams->realm_max_rlife_valid = 1;
+ }
+
+ /* Get the value for the default principal expiration */
+ hierarchy[2] = "default_principal_expiration";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ if (!krb5_string_to_timestamp(svalue,
+ &rparams->realm_expiration))
+ rparams->realm_expiration_valid = 1;
+ krb5_xfree(svalue);
+ }
+
+ /* Get the value for the default principal flags */
+ hierarchy[2] = "default_principal_flags";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ char *sp, *ep, *tp;
+
+ sp = svalue;
+ rparams->realm_flags = 0;
+ while (sp) {
+ if ((ep = strchr(sp, (int) ',')) ||
+ (ep = strchr(sp, (int) ' ')) ||
+ (ep = strchr(sp, (int) '\t'))) {
+ /* Fill in trailing whitespace of sp */
+ tp = ep - 1;
+ while (isspace(*tp) && (tp < sp)) {
+ *tp = '\0';
+ tp--;
+ }
+ *ep = '\0';
+ ep++;
+ /* Skip over trailing whitespace of ep */
+ while (isspace(*ep) && (*ep)) ep++;
+ }
+ /* Convert this flag */
+ if (krb5_string_to_flags(sp,
+ "+",
+ "-",
+ &rparams->realm_flags))
+ break;
+ sp = ep;
+ }
+ if (!sp)
+ rparams->realm_flags_valid = 1;
+ krb5_xfree(svalue);
+ }
+
+ /* Get the value for the supported enctype/salttype matrix */
+ hierarchy[2] = "supported_enctypes";
+ if (!krb5_aprof_get_string(aprofile, hierarchy, TRUE, &svalue)) {
+ krb5_string_to_keysalts(svalue,
+ ", \t", /* Tuple separators */
+ ":.-", /* Key/salt separators */
+ 0, /* No duplicates */
+ &rparams->realm_keysalts,
+ &rparams->realm_num_keysalts);
+ krb5_xfree(svalue);
+ }
+
+cleanup:
+ if (aprofile)
+ krb5_aprof_finish(aprofile);
+ if (lrealm)
+ free(lrealm);
+ if (kret) {
+ if (rparams)
+ krb5_free_realm_params(kcontext, rparams);
+ rparams = 0;
+ }
+ *rparamp = rparams;
+ return(kret);
+}
+
+/*
+ * krb5_free_realm_params() - Free data allocated by above.
+ */
+krb5_error_code
+krb5_free_realm_params(kcontext, rparams)
+ krb5_context kcontext;
+ krb5_realm_params *rparams;
+{
+ if (rparams) {
+ if (rparams->realm_profile)
+ krb5_xfree(rparams->realm_profile);
+ if (rparams->realm_dbname)
+ krb5_xfree(rparams->realm_dbname);
+ if (rparams->realm_mkey_name)
+ krb5_xfree(rparams->realm_mkey_name);
+ if (rparams->realm_stash_file)
+ krb5_xfree(rparams->realm_stash_file);
+ if (rparams->realm_keysalts)
+ krb5_xfree(rparams->realm_keysalts);
+ if (rparams->realm_kdc_ports)
+ krb5_xfree(rparams->realm_kdc_ports);
+ krb5_xfree(rparams);
+ }
+ return(0);
+}
+
diff --git a/src/lib/kadm5/chpass_util.c b/src/lib/kadm5/chpass_util.c
new file mode 100644
index 000000000..dbf610ce3
--- /dev/null
+++ b/src/lib/kadm5/chpass_util.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ *
+ */
+
+
+#include <stdio.h>
+#include <memory.h>
+#include <time.h>
+
+#include <kadm5/admin.h>
+#include "admin_internal.h"
+
+#include <krb5.h>
+
+#define string_text error_message
+
+/*
+ * Function: kadm5_chpass_principal_util
+ *
+ * Purpose: Wrapper around chpass_principal. We can read new pw, change pw and return useful messages
+ *
+ * Arguments:
+ *
+ * princ (input) a krb5b_principal structure for the
+ * principal whose password we should change.
+ *
+ * new_password (input) NULL or a null terminated string with the
+ * the principal's desired new password. If new_password
+ * is NULL then this routine will read a new password.
+ *
+ * pw_ret (output) if non-NULL, points to a static buffer
+ * containing the new password (if password is prompted
+ * internally), or to the new_password argument (if
+ * that is non-NULL). If the former, then the buffer
+ * is only valid until the next call to the function,
+ * and the caller should be sure to zero it when
+ * it is no longer needed.
+ *
+ * msg_ret (output) a useful message is copied here.
+ *
+ * <return value> exit status of 0 for success, else the com err code
+ * for the last significant routine called.
+ *
+ * Requires:
+ *
+ * A msg_ret should point to a buffer large enough for the messasge.
+ *
+ * Effects:
+ *
+ * Modifies:
+ *
+ *
+ */
+
+kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
+ void *lhandle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret)
+{
+ int code, code2, pwsize;
+ static char buffer[255];
+ char *new_password;
+ kadm5_principal_ent_rec princ_ent;
+ kadm5_policy_ent_rec policy_ent;
+
+ _KADM5_CHECK_HANDLE(server_handle);
+
+ if (ret_pw)
+ *ret_pw = NULL;
+
+ if (new_pw != NULL) {
+ new_password = new_pw;
+ } else { /* read the password */
+ krb5_context context;
+
+ if ((code = (int) krb5_init_context(&context)) == 0) {
+ pwsize = sizeof(buffer);
+ code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT,
+ KADM5_PW_SECOND_PROMPT,
+ buffer, &pwsize);
+ krb5_free_context(context);
+ }
+
+ if (code == 0)
+ new_password = buffer;
+ else {
+#ifdef ZEROPASSWD
+ memset(buffer, 0, sizeof(buffer));
+#endif
+ if (code == KRB5_LIBOS_BADPWDMATCH) {
+ strcpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH));
+ return(code);
+ } else {
+ sprintf(msg_ret, "%s %s\n%s\n", error_message(code),
+ string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
+ string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
+ return(code);
+ }
+ }
+ if (pwsize == 0) {
+#ifdef ZEROPASSWD
+ memset(buffer, 0, sizeof(buffer));
+#endif
+ strcpy(msg_ret, string_text(CHPASS_UTIL_NO_PASSWORD_READ));
+ return(KRB5_LIBOS_CANTREADPWD); /* could do better */
+ }
+ }
+
+ if (ret_pw)
+ *ret_pw = new_password;
+
+ code = kadm5_chpass_principal(server_handle, princ, new_password);
+
+#ifdef ZEROPASSWD
+ if (!ret_pw)
+ memset(buffer, 0, sizeof(buffer)); /* in case we read a new password */
+#endif
+
+ if (code == KADM5_OK) {
+ strcpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_CHANGED));
+ return(0);
+ }
+
+ if ((code != KADM5_PASS_Q_TOOSHORT) &&
+ (code != KADM5_PASS_REUSE) &&(code != KADM5_PASS_Q_CLASS) &&
+ (code != KADM5_PASS_Q_DICT) && (code != KADM5_PASS_TOOSOON)) {
+ /* Can't get more info for other errors */
+ sprintf(buffer, "%s %s", error_message(code),
+ string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
+ sprintf(msg_ret, "%s\n%s\n", string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
+ buffer);
+ return(code);
+ }
+
+ /* Ok, we have a password quality error. Return a good message */
+
+ if (code == KADM5_PASS_REUSE) {
+ strcpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_REUSE));
+ return(code);
+ }
+
+ if (code == KADM5_PASS_Q_DICT) {
+ strcpy(msg_ret, string_text(CHPASS_UTIL_PASSWORD_IN_DICTIONARY));
+ return(code);
+ }
+
+ /* Look up policy for the remaining messages */
+
+ code2 = kadm5_get_principal (lhandle, princ, &princ_ent,
+ KADM5_PRINCIPAL_NORMAL_MASK);
+ if (code2 != 0) {
+ sprintf(msg_ret, "%s %s\n%s %s\n\n%s\n ", error_message(code2),
+ string_text(CHPASS_UTIL_GET_PRINC_INFO),
+ error_message(code),
+ string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
+ string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
+ return(code);
+ }
+
+ if ((princ_ent.aux_attributes & KADM5_POLICY) == 0) {
+ sprintf(msg_ret, "%s %s\n\n%s", error_message(code),
+ string_text(CHPASS_UTIL_NO_POLICY_YET_Q_ERROR),
+ string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
+ (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+ return(code);
+ }
+
+ code2 = kadm5_get_policy(lhandle, princ_ent.policy,
+ &policy_ent);
+ if (code2 != 0) {
+ sprintf(msg_ret, "%s %s\n%s %s\n\n%s\n ", error_message(code2),
+ string_text(CHPASS_UTIL_GET_POLICY_INFO),
+ error_message(code),
+ string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE),
+ string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED));
+ (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+ return(code);
+ }
+
+ if (code == KADM5_PASS_Q_TOOSHORT) {
+ sprintf(msg_ret, string_text(CHPASS_UTIL_PASSWORD_TOO_SHORT),
+ policy_ent.pw_min_length);
+ (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+ (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+ return(code);
+ }
+
+/* Can't get more info for other errors */
+
+ if (code == KADM5_PASS_Q_CLASS) {
+ sprintf(msg_ret, string_text(CHPASS_UTIL_TOO_FEW_CLASSES),
+ policy_ent.pw_min_classes);
+ (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+ (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+ return(code);
+ }
+
+ if (code == KADM5_PASS_TOOSOON) {
+ time_t until;
+ char *time_string, *ptr;
+
+ until = princ_ent.last_pwd_change + policy_ent.pw_min_life;
+
+ time_string = ctime(&until);
+ if (*(ptr = &time_string[strlen(time_string)-1]) == '\n')
+ *ptr = '\0';
+
+ sprintf(msg_ret, string_text(CHPASS_UTIL_PASSWORD_TOO_SOON),
+ time_string);
+ (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+ (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+ return(code);
+ }
+
+ /* We should never get here, but just in case ... */
+ sprintf(buffer, "%s %s", error_message(code),
+ string_text(CHPASS_UTIL_WHILE_TRYING_TO_CHANGE));
+ sprintf(msg_ret, "%s\n%s\n", string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
+ buffer);
+ (void) kadm5_free_principal_ent(lhandle, &princ_ent);
+ (void) kadm5_free_policy_ent(lhandle, &policy_ent);
+ return(code);
+}
diff --git a/src/lib/kadm5/chpass_util_strings.et b/src/lib/kadm5/chpass_util_strings.et
new file mode 100644
index 000000000..032254998
--- /dev/null
+++ b/src/lib/kadm5/chpass_util_strings.et
@@ -0,0 +1,58 @@
+# this is really a string table for ovsec_kadm_chpass_principal_util
+
+error_table ovku
+
+error_code CHPASS_UTIL_GET_POLICY_INFO, "while getting policy info."
+error_code CHPASS_UTIL_GET_PRINC_INFO, "while getting principal info."
+error_code CHPASS_UTIL_NEW_PASSWORD_MISMATCH,
+ "New passwords do not match - password not changed.\n"
+
+error_code CHPASS_UTIL_NEW_PASSWORD_PROMPT, "New password:"
+error_code CHPASS_UTIL_NEW_PASSWORD_AGAIN_PROMPT, "New password (again):"
+error_code CHPASS_UTIL_NO_PASSWORD_READ, "You must type a password. Passwords must be at least one character long.\n"
+error_code CHPASS_UTIL_NO_POLICY_YET_Q_ERROR,
+"yet no policy set! Contact your system security administrator."
+
+error_code CHPASS_UTIL_PASSWORD_CHANGED, "Password changed.\n"
+
+error_code CHPASS_UTIL_PASSWORD_IN_DICTIONARY,
+"New password was found in a dictionary of possible passwords and\n\
+therefore may be easily guessed. Please choose another password.\n\
+See the ovpasswd man page for help in choosing a good password."
+
+error_code CHPASS_UTIL_PASSWORD_NOT_CHANGED, "Password not changed."
+
+error_code CHPASS_UTIL_PASSWORD_TOO_SHORT,
+"New password is too short.\n\
+Please choose a password which is at least %d characters long."
+# /* <pw-min-len> */
+
+error_code CHPASS_UTIL_TOO_FEW_CLASSES,
+"New password does not have enough character classes.\n\
+The character classes are:\n\
+ - lower-case letters,\n\
+ - upper-case letters,\n\
+ - digits,\n\
+ - punctuation, and\n\
+ - all other characters (e.g., control characters).\n\
+Please choose a password with at least %d character classes."
+# /* <min-classes> */
+
+
+error_code CHPASS_UTIL_PASSWORD_TOO_SOON,
+"Password cannot be changed because it was changed too recently.\n\
+Please wait until %s before you change it.\n\
+If you need to change your password before then, contact your system\n\
+security administrator."
+# /* <ctime(last-pw-change+pw-min-life)> */
+
+error_code CHPASS_UTIL_PASSWORD_REUSE,
+"New password was used previously. Please choose a different password."
+
+error_code CHPASS_UTIL_WHILE_TRYING_TO_CHANGE,
+"while trying to change password."
+
+error_code CHPASS_UTIL_WHILE_READING_PASSWORD, "while reading new password."
+
+end
+
diff --git a/src/lib/kadm5/client_handle.c b/src/lib/kadm5/client_handle.c
new file mode 100644
index 000000000..895777a6e
--- /dev/null
+++ b/src/lib/kadm5/client_handle.c
@@ -0,0 +1,9 @@
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include "client_internal.h"
+
+int _kadm5_check_handle(void *handle)
+{
+ CHECK_HANDLE(handle);
+ return 0;
+}
diff --git a/src/lib/kadm5/client_init.c b/src/lib/kadm5/client_init.c
new file mode 100644
index 000000000..bfc1c3a3c
--- /dev/null
+++ b/src/lib/kadm5/client_init.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <netdb.h>
+#include <memory.h>
+#include <string.h>
+#include <com_err.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <krb5.h>
+#include <k5-int.h> /* for KRB5_ADM_DEFAULT_PORT */
+#ifdef __STDC__
+#include <stdlib.h>
+#endif
+
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include "client_internal.h"
+
+#include <rpc/rpc.h>
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#include <rpc/auth_gssapi.h>
+
+#define ADM_CCACHE "/tmp/ovsec_adm.XXXXXX"
+
+#ifndef _POSIX_SOURCE /* Perhaps this should actually say __STDC__ */
+int setenv(const char *var, const char *val, int flag);
+void unsetenv(const char *var);
+#endif
+
+enum init_type { INIT_PASS, INIT_SKEY, INIT_CREDS };
+
+static kadm5_ret_t _kadm5_init_any(char *client_name,
+ enum init_type init_type,
+ char *pass,
+ krb5_ccache ccache_in,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle);
+
+kadm5_ret_t kadm5_init_with_creds(char *client_name,
+ krb5_ccache ccache,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return _kadm5_init_any(client_name, INIT_CREDS, NULL, ccache,
+ service_name, params,
+ struct_version, api_version,
+ server_handle);
+}
+
+
+kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return _kadm5_init_any(client_name, INIT_PASS, pass, NULL,
+ service_name, params, struct_version,
+ api_version, server_handle);
+}
+
+kadm5_ret_t kadm5_init(char *client_name, char *pass,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return _kadm5_init_any(client_name, INIT_PASS, pass, NULL,
+ service_name, params, struct_version,
+ api_version, server_handle);
+}
+
+kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return _kadm5_init_any(client_name, INIT_SKEY, keytab, NULL,
+ service_name, params, struct_version,
+ api_version, server_handle);
+}
+
+/*
+ * Try no preauthentication first; then try the encrypted timestamp
+ * (stolen from krb5 kinit.c)
+ */
+static int preauth_search_list[] = {
+ 0,
+ KRB5_PADATA_ENC_UNIX_TIME,
+ -1
+};
+
+static kadm5_ret_t _kadm5_init_any(char *client_name,
+ enum init_type init_type,
+ char *pass,
+ krb5_ccache ccache_in,
+ char *service_name,
+ kadm5_config_params *params_in,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ struct sockaddr_in addr;
+ struct hostent *hp;
+ struct servent *srv;
+ int fd;
+ int i;
+
+ char full_service_name[BUFSIZ], host[MAXHOSTNAMELEN], *ccname_orig;
+ char *realm;
+ krb5_creds creds;
+ krb5_ccache ccache = NULL;
+ krb5_timestamp now;
+
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc input_name;
+ gss_name_t gss_target, gss_client;
+ gss_cred_id_t gss_client_creds = GSS_C_NO_CREDENTIAL;
+
+ kadm5_server_handle_t handle;
+ kadm5_config_params params_local;
+
+ int code = 0;
+ generic_ret *r;
+
+ initialize_ovk_error_table();
+ initialize_adb_error_table();
+ initialize_ovku_error_table();
+
+ if (! server_handle) {
+ return EINVAL;
+ }
+
+ if (! (handle = malloc(sizeof(*handle)))) {
+ return ENOMEM;
+ }
+ if (! (handle->lhandle = malloc(sizeof(*handle)))) {
+ free(handle);
+ return ENOMEM;
+ }
+
+ handle->magic_number = KADM5_SERVER_HANDLE_MAGIC;
+ handle->struct_version = struct_version;
+ handle->api_version = api_version;
+ handle->clnt = 0;
+ handle->cache_name = 0;
+ handle->destroy_cache = 0;
+ *handle->lhandle = *handle;
+ handle->lhandle->api_version = KADM5_API_VERSION_2;
+ handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
+ handle->lhandle->lhandle = handle->lhandle;
+
+ krb5_init_context(&handle->context);
+ krb5_init_ets(handle->context);
+
+ if(service_name == NULL || client_name == NULL) {
+ free(handle);
+ return EINVAL;
+ }
+ memset((char *) &creds, 0, sizeof(creds));
+
+ /*
+ * Verify the version numbers before proceeding; we can't use
+ * CHECK_HANDLE because not all fields are set yet.
+ */
+ GENERIC_CHECK_HANDLE(handle, KADM5_OLD_LIB_API_VERSION,
+ KADM5_NEW_LIB_API_VERSION);
+
+ /*
+ * Acquire relevant profile entries. In version 2, merge values
+ * in params_in with values from profile, based on
+ * params_in->mask.
+ *
+ * In version 1, we've given a realm (which may be NULL) instead
+ * of params_in. So use that realm, make params_in contain an
+ * empty mask, and behave like version 2.
+ */
+ memset((char *) &params_local, 0, sizeof(params_local));
+ if (api_version == KADM5_API_VERSION_1) {
+ realm = params_local.realm = (char *) params_in;
+ if (params_in)
+ params_local.mask = KADM5_CONFIG_REALM;
+ params_in = &params_local;
+ } else {
+ if (params_in && (params_in->mask & KADM5_CONFIG_REALM))
+ realm = params_in->realm;
+ else
+ realm = NULL;
+ }
+
+#define ILLEGAL_PARAMS (KADM5_CONFIG_DBNAME | KADM5_CONFIG_ADBNAME | \
+ KADM5_CONFIG_ADB_LOCKFILE | \
+ KADM5_CONFIG_ACL_FILE | KADM5_CONFIG_DICT_FILE \
+ | KADM5_CONFIG_ADMIN_KEYTAB | \
+ KADM5_CONFIG_STASH_FILE | \
+ KADM5_CONFIG_MKEY_NAME | KADM5_CONFIG_ENCTYPE \
+ | KADM5_CONFIG_MAX_LIFE | \
+ KADM5_CONFIG_MAX_RLIFE | \
+ KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_FLAGS | \
+ KADM5_CONFIG_ENCTYPES | KADM5_CONFIG_MKEY_FROM_KBD)
+
+ if (params_in && params_in->mask & ILLEGAL_PARAMS) {
+ free(handle);
+ return KADM5_BAD_CLIENT_PARAMS;
+ }
+
+ if (code = kadm5_get_config_params(handle->context,
+ "/etc/krb5.conf",
+ "KRB5_CONFIG",
+ params_in,
+ &handle->params)) {
+ krb5_free_context(handle->context);
+ free(handle);
+ return(code);
+ }
+
+#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | \
+ KADM5_CONFIG_ADMIN_SERVER | \
+ KADM5_CONFIG_KADMIND_PORT)
+
+ if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
+ krb5_free_context(handle->context);
+ free(handle);
+ return KRB5_CONFIG_BADFORMAT;
+ }
+
+ /*
+ * Acquire a service ticket for service_name@realm in the name of
+ * client_name, using password pass (which could be NULL), and
+ * create a ccache to store them in. If INIT_CREDS, use the
+ * ccache we were provided instead.
+ */
+
+ if ((code = krb5_parse_name(handle->context, client_name, &creds.client)))
+ goto error;
+
+ if (realm) {
+ sprintf(full_service_name, "%s@%s", service_name, realm);
+ } else {
+ /* krb5_princ_realm(creds.client) is not null terminated */
+ strcpy(full_service_name, service_name);
+ strcat(full_service_name, "@");
+ strncat(full_service_name, krb5_princ_realm(handle->context,
+ creds.client)->data,
+ krb5_princ_realm(handle->context, creds.client)->length);
+ }
+
+ if ((code = krb5_parse_name(handle->context, full_service_name,
+ &creds.server)))
+ goto error;
+
+ /* XXX temporarily fix a bug in krb5_cc_get_type */
+#undef krb5_cc_get_type
+#define krb5_cc_get_type(context, cache) ((cache)->ops->prefix)
+
+
+ if (init_type == INIT_CREDS) {
+ ccache = ccache_in;
+ handle->cache_name = (char *)
+ malloc(strlen(krb5_cc_get_type(handle->context, ccache)) +
+ strlen(krb5_cc_get_name(handle->context, ccache)) + 2);
+ if (handle->cache_name == NULL) {
+ code = ENOMEM;
+ goto error;
+ }
+ sprintf(handle->cache_name, "%s:%s",
+ krb5_cc_get_type(handle->context, ccache),
+ krb5_cc_get_name(handle->context, ccache));
+ } else {
+ handle->cache_name =
+ (char *) malloc(strlen(ADM_CCACHE)+strlen("FILE:")+1);
+ if (handle->cache_name == NULL) {
+ code = ENOMEM;
+ goto error;
+ }
+ sprintf(handle->cache_name, "FILE:%s", ADM_CCACHE);
+ mktemp(handle->cache_name + strlen("FILE:"));
+
+ if ((code = krb5_cc_resolve(handle->context, handle->cache_name,
+ &ccache)))
+ goto error;
+
+ if ((code = krb5_cc_initialize (handle->context, ccache,
+ creds.client)))
+ goto error;
+
+ handle->destroy_cache = 1;
+ }
+ handle->lhandle->cache_name = handle->cache_name;
+
+ if ((code = krb5_timeofday(handle->context, &now)))
+ goto error;
+
+ /*
+ * Get a ticket, use the method specified in init_type.
+ */
+
+ creds.times.starttime = 0; /* start timer at KDC */
+ creds.times.endtime = 0; /* endtime will be limited by service */
+
+ if (init_type == INIT_PASS) {
+ for (i=0; preauth_search_list[i] >= 0; i++) {
+ code = krb5_get_in_tkt_with_password(handle->context,
+ 0, /* no options */
+ 0, /* default addresses */
+ NULL,
+ NULL, /* XXX preauth */
+ pass,
+ ccache,
+ &creds,
+ NULL);
+ if (code != KRB5KDC_ERR_PREAUTH_FAILED &&
+ code != KRB5KDC_ERR_PREAUTH_REQUIRED &&
+ code != KRB5KRB_ERR_GENERIC)
+ break;
+ }
+ } else if (init_type == INIT_SKEY) {
+ krb5_keytab kt = NULL;
+
+ if (pass && (code = krb5_kt_resolve(handle->context, pass, &kt)))
+ ;
+ else {
+ for (i=0; preauth_search_list[i] >= 0; i++) {
+ code = krb5_get_in_tkt_with_keytab(handle->context,
+ 0, /* no options */
+ 0, /* default addrs */
+ NULL,
+ NULL, /* XXX preauth */
+ kt,
+ ccache,
+ &creds,
+ NULL);
+ if (code != KRB5KDC_ERR_PREAUTH_FAILED &&
+ code != KRB5KDC_ERR_PREAUTH_REQUIRED &&
+ code != KRB5KRB_ERR_GENERIC)
+ break;
+ }
+
+ if (pass) krb5_kt_close(handle->context, kt);
+ }
+ }
+
+ /* Improved error messages */
+ if (code == KRB5KRB_AP_ERR_BAD_INTEGRITY) code = KADM5_BAD_PASSWORD;
+ if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN)
+ code = KADM5_SECURE_PRINC_MISSING;
+
+ if (code != 0) goto error;
+
+#ifdef ZEROPASSWD
+ if (pass != NULL)
+ memset(pass, 0, strlen(pass));
+#endif
+
+ /*
+ * We have ticket; open the RPC connection.
+ */
+
+ hp = gethostbyname(handle->params.admin_server);
+ if (hp == (struct hostent *) NULL) {
+ code = KRB5_CONFIG_BADFORMAT;
+ goto cleanup;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = hp->h_addrtype;
+ (void) memcpy((char *) &addr.sin_addr, (char *) hp->h_addr,
+ sizeof(addr.sin_addr));
+ addr.sin_port = htons((u_short) handle->params.kadmind_port);
+
+ fd = RPC_ANYSOCK;
+
+ handle->clnt = clnttcp_create(&addr, KADM, KADMVERS, &fd, 0, 0);
+ if (handle->clnt == NULL) {
+ code = KADM5_RPC_ERROR;
+ goto error;
+ }
+ handle->lhandle->clnt = handle->clnt;
+
+ /* now that handle->clnt is set, we can check the handle */
+ if (code = _kadm5_check_handle((void *) handle))
+ goto error;
+
+ /*
+ * The RPC connection is open; establish the GSS-API
+ * authentication context.
+ */
+
+ /* use the kadm5 cache */
+ ccname_orig = getenv("KRB5CCNAME");
+ if (ccname_orig)
+ ccname_orig = strdup(ccname_orig);
+
+ (void) setenv("KRB5CCNAME", handle->cache_name, 1);
+
+#ifndef INIT_TEST
+ input_name.value = full_service_name;
+ input_name.length = strlen((char *)input_name.value) + 1;
+ gssstat = gss_import_name(&minor_stat, &input_name,
+ gss_nt_krb5_name, &gss_target);
+ if (gssstat != GSS_S_COMPLETE) {
+ code = KADM5_GSS_ERROR;
+ goto error;
+ }
+#endif /* ! INIT_TEST */
+
+ input_name.value = client_name;
+ input_name.length = strlen((char *)input_name.value) + 1;
+ gssstat = gss_import_name(&minor_stat, &input_name,
+ gss_nt_krb5_name, &gss_client);
+ if (gssstat != GSS_S_COMPLETE) {
+ code = KADM5_GSS_ERROR;
+ goto error;
+ }
+
+ gssstat = gss_acquire_cred(&minor_stat, gss_client, 0,
+ GSS_C_NULL_OID_SET, GSS_C_INITIATE,
+ &gss_client_creds, NULL, NULL);
+ (void) gss_release_name(&minor_stat, &gss_client);
+ if (gssstat != GSS_S_COMPLETE) {
+ code = KADM5_GSS_ERROR;
+ goto error;
+ }
+
+#ifndef INIT_TEST
+ handle->clnt->cl_auth = auth_gssapi_create(handle->clnt,
+ &gssstat,
+ &minor_stat,
+ gss_client_creds,
+ gss_target,
+ GSS_C_NULL_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+ (void) gss_release_name(&minor_stat, &gss_target);
+#endif /* ! INIT_TEST */
+
+ if (ccname_orig) {
+ (void) setenv("KRB5CCNAME", ccname_orig, 1);
+ free(ccname_orig);
+ } else
+ (void) unsetenv("KRB5CCNAME");
+
+
+ if (handle->clnt->cl_auth == NULL) {
+ code = KADM5_GSS_ERROR;
+ goto error;
+ }
+
+ r = init_1(&handle->api_version, handle->clnt);
+ if (r == NULL) {
+ code = KADM5_RPC_ERROR;
+ goto error;
+ }
+ if (r->code) {
+ code = r->code;
+ goto error;
+ }
+
+ *server_handle = (void *) handle;
+
+ if (init_type != INIT_CREDS)
+ krb5_cc_close(handle->context, ccache);
+
+ goto cleanup;
+
+error:
+ /*
+ * Note that it is illegal for this code to execute if "handle"
+ * has not been allocated and initialized. I.e., don't use "goto
+ * error" before the block of code at the top of the function
+ * that allocates and initializes "handle".
+ */
+ if (handle->cache_name)
+ free(handle->cache_name);
+ if (handle->destroy_cache && ccache)
+ krb5_cc_destroy(handle->context, ccache);
+ if(handle->clnt && handle->clnt->cl_auth)
+ AUTH_DESTROY(handle->clnt->cl_auth);
+ if(handle->clnt)
+ clnt_destroy(handle->clnt);
+
+cleanup:
+ krb5_free_cred_contents(handle->context, &creds);
+ if (gss_client_creds != GSS_C_NO_CREDENTIAL)
+ (void) gss_release_cred(&minor_stat, &gss_client_creds);
+
+ if (code)
+ free(handle);
+
+ return code;
+}
+
+kadm5_ret_t
+kadm5_destroy(void *server_handle)
+{
+ krb5_ccache ccache = NULL;
+ int code = KADM5_OK;
+ kadm5_server_handle_t handle =
+ (kadm5_server_handle_t) server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if (handle->destroy_cache && handle->cache_name) {
+ if ((code = krb5_cc_resolve(handle->context,
+ handle->cache_name, &ccache)) == 0)
+ code = krb5_cc_destroy (handle->context, ccache);
+ }
+ if (handle->cache_name)
+ free(handle->cache_name);
+ if (handle->clnt && handle->clnt->cl_auth)
+ AUTH_DESTROY(handle->clnt->cl_auth);
+ if (handle->clnt)
+ clnt_destroy(handle->clnt);
+
+ handle->magic_number = 0;
+ free(handle);
+
+ return code;
+}
+
+kadm5_ret_t kadm5_flush(void *server_handle)
+{
+ return KADM5_OK;
+}
+
+int _kadm5_check_handle(void *handle)
+{
+ CHECK_HANDLE(handle);
+ return 0;
+}
diff --git a/src/lib/kadm5/client_internal.h b/src/lib/kadm5/client_internal.h
new file mode 100644
index 000000000..5a246158e
--- /dev/null
+++ b/src/lib/kadm5/client_internal.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.11 1996/07/22 20:35:46 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.10.4.1 1996/07/18 03:08:37 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.10.2.1 1996/06/20 02:16:46 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.10 1996/06/06 20:09:16 bjaspan
+ * add destroy_cache, for kadm5_init_with_creds
+ *
+ * Revision 1.9 1996/05/30 21:04:42 bjaspan
+ * add lhandle to handle
+ *
+ * Revision 1.8 1996/05/28 20:33:49 bjaspan
+ * rework kadm5_config
+ *
+ * Revision 1.7 1996/05/17 21:36:59 bjaspan
+ * rename to kadm5, begin implementing version 2
+ *
+ * Revision 1.6 1996/05/16 21:45:07 bjaspan
+ * add context
+ *
+ * Revision 1.5 1996/05/08 21:10:23 bjaspan
+ * marc's changes
+ *
+ * Revision 1.4 1996/01/16 20:54:30 grier
+ * secure/3570 use krb5_ui_4 not unsigned int
+ *
+ * Revision 1.3 1995/11/14 17:48:57 grier
+ * long to int
+ *
+ * Revision 1.2 1994/08/16 18:53:47 jik
+ * Versioning stuff.
+ *
+ * Revision 1.1 1994/08/09 21:14:38 jik
+ * Initial revision
+ *
+ */
+
+/*
+ * This header file is used internally by the Admin API client
+ * libraries. IF YOU THINK YOU NEED TO USE THIS FILE FOR ANYTHING,
+ * YOU'RE ALMOST CERTAINLY WRONG.
+ */
+
+#ifndef __KADM5_CLIENT_INTERNAL_H__
+#define __KADM5_CLIENT_INTERNAL_H__
+
+#include "admin_internal.h"
+
+typedef struct _kadm5_server_handle_t {
+ krb5_ui_4 magic_number;
+ krb5_ui_4 struct_version;
+ krb5_ui_4 api_version;
+ char * cache_name;
+ int destroy_cache;
+ CLIENT * clnt;
+ krb5_context context;
+ kadm5_config_params params;
+ struct _kadm5_server_handle_t *lhandle;
+} kadm5_server_handle_rec, *kadm5_server_handle_t;
+
+#define CLIENT_CHECK_HANDLE(handle) \
+{ \
+ kadm5_server_handle_t srvr = \
+ (kadm5_server_handle_t) handle; \
+ \
+ if (! srvr->clnt) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ if (! srvr->cache_name) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ if (! srvr->lhandle) \
+ return KADM5_BAD_SERVER_HANDLE; \
+}
+
+#define CHECK_HANDLE(handle) \
+ GENERIC_CHECK_HANDLE(handle, KADM5_OLD_LIB_API_VERSION, \
+ KADM5_NEW_LIB_API_VERSION) \
+ CLIENT_CHECK_HANDLE(handle)
+
+#endif /* __KADM5_CLIENT_INTERNAL_H__ */
diff --git a/src/lib/kadm5/client_principal.c b/src/lib/kadm5/client_principal.c
new file mode 100644
index 000000000..c41922722
--- /dev/null
+++ b/src/lib/kadm5/client_principal.c
@@ -0,0 +1,307 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/rpc.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include <memory.h>
+#include "client_internal.h"
+
+kadm5_ret_t
+kadm5_create_principal(void *server_handle,
+ kadm5_principal_ent_t princ, long mask,
+ char *pw)
+{
+ generic_ret *r;
+ cprinc_arg arg;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ arg.mask = mask;
+ arg.passwd = pw;
+ arg.api_version = handle->api_version;
+
+ if(princ == NULL)
+ return EINVAL;
+ memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ /*
+ * hack hack cough cough.
+ * krb5_unparse name dumps core if we pass it in garbage
+ * or null. So, since the client is not allowed to set mod_name
+ * anyway, we just fill it in with a dummy principal. The server of
+ * course ignores this.
+ */
+ krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
+ } else
+ arg.rec.mod_name = NULL;
+
+ if(!(mask & KADM5_POLICY))
+ arg.rec.policy = NULL;
+ if (! (mask & KADM5_KEY_DATA)) {
+ arg.rec.n_key_data = 0;
+ arg.rec.key_data = NULL;
+ }
+ if (! (mask & KADM5_TL_DATA)) {
+ arg.rec.n_tl_data = 0;
+ arg.rec.tl_data = NULL;
+ }
+
+ r = create_principal_1(&arg, handle->clnt);
+
+ if (handle->api_version == KADM5_API_VERSION_1)
+ krb5_free_principal(handle->context, arg.rec.mod_name);
+
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_delete_principal(void *server_handle, krb5_principal principal)
+{
+ dprinc_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if(principal == NULL)
+ return EINVAL;
+ arg.princ = principal;
+ arg.api_version = handle->api_version;
+ r = delete_principal_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_modify_principal(void *server_handle,
+ kadm5_principal_ent_t princ, long mask)
+{
+ mprinc_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ arg.mask = mask;
+ arg.api_version = handle->api_version;
+ /*
+ * cough cough gag gag
+ * see comment in create_principal.
+ */
+ if(princ == NULL)
+ return EINVAL;
+ memcpy(&arg.rec, princ, sizeof(kadm5_principal_ent_rec));
+ if(!(mask & KADM5_POLICY))
+ arg.rec.policy = NULL;
+ if (! (mask & KADM5_KEY_DATA)) {
+ arg.rec.n_key_data = 0;
+ arg.rec.key_data = NULL;
+ }
+ if (! (mask & KADM5_TL_DATA)) {
+ arg.rec.n_tl_data = 0;
+ arg.rec.tl_data = NULL;
+ }
+
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ /*
+ * See comment in create_principal
+ */
+ krb5_parse_name(handle->context, "bogus/bogus", &arg.rec.mod_name);
+ } else
+ arg.rec.mod_name = NULL;
+
+ r = modify_principal_1(&arg, handle->clnt);
+
+ if (handle->api_version == KADM5_API_VERSION_1)
+ krb5_free_principal(handle->context, arg.rec.mod_name);
+
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_principal(void *server_handle,
+ krb5_principal princ, kadm5_principal_ent_t ent,
+ long mask)
+{
+ gprinc_arg arg;
+ gprinc_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+ krb5_error_code retval;
+
+ CHECK_HANDLE(server_handle);
+
+ if(princ == NULL)
+ return EINVAL;
+ arg.princ = princ;
+ if (handle->api_version == KADM5_API_VERSION_1)
+ arg.mask = KADM5_PRINCIPAL_NORMAL_MASK;
+ else
+ arg.mask = mask;
+ arg.api_version = handle->api_version;
+ r = get_principal_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ kadm5_principal_ent_t_v1 *entp;
+
+ entp = (kadm5_principal_ent_t_v1 *) ent;
+ if (r->code == 0) {
+ if (!(*entp = (kadm5_principal_ent_t_v1)
+ malloc(sizeof(kadm5_principal_ent_rec_v1))))
+ return ENOMEM;
+ /* this memcpy works because the v1 structure is an initial
+ subset of the v2 struct. C guarantees that this will
+ result in the same layout in memory */
+ memcpy(*entp, &r->rec, sizeof(**entp));
+ } else {
+ *entp = NULL;
+ }
+ } else {
+ if (r->code == 0)
+ memcpy(ent, &r->rec, sizeof(r->rec));
+ }
+
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_principals(void *server_handle,
+ char *exp, char ***princs, int *count)
+{
+ gprincs_arg arg;
+ gprincs_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+ krb5_error_code retval;
+
+ CHECK_HANDLE(server_handle);
+
+ if(princs == NULL || count == NULL)
+ return EINVAL;
+ arg.exp = exp;
+ arg.api_version = handle->api_version;
+ r = get_princs_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ if(r->code == 0) {
+ *count = r->count;
+ *princs = r->princs;
+ } else {
+ *count = 0;
+ *princs = NULL;
+ }
+
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_rename_principal(void *server_handle,
+ krb5_principal source, krb5_principal dest)
+{
+ rprinc_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ arg.src = source;
+ arg.dest = dest;
+ arg.api_version = handle->api_version;
+ if (source == NULL || dest == NULL)
+ return EINVAL;
+ r = rename_principal_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_chpass_principal(void *server_handle,
+ krb5_principal princ, char *password)
+{
+ chpass_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ arg.princ = princ;
+ arg.pass = password;
+ arg.api_version = handle->api_version;
+
+ if(princ == NULL)
+ return EINVAL;
+ r = chpass_principal_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_randkey_principal(void *server_handle,
+ krb5_principal princ,
+ krb5_keyblock **key, int *n_keys)
+{
+ chrand_arg arg;
+ chrand_ret *r;
+ krb5_keyblock new;
+ kadm5_server_handle_t handle = server_handle;
+ int i, ret;
+
+ CHECK_HANDLE(server_handle);
+
+ arg.princ = princ;
+ arg.api_version = handle->api_version;
+
+ if(princ == NULL)
+ return EINVAL;
+ r = chrand_principal_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ if (key)
+ krb5_copy_keyblock(handle->context, &r->key, key);
+ } else {
+ if (n_keys)
+ *n_keys = r->n_keys;
+ if (key) {
+ *key = (krb5_keyblock *) malloc(r->n_keys*sizeof(krb5_keyblock));
+ if (*key == NULL)
+ return ENOMEM;
+ for (i = 0; i < r->n_keys; i++) {
+ ret = krb5_copy_keyblock_contents(handle->context,
+ &r->keys[i],
+ &(*key)[i]);
+ if (ret) {
+ free(*key);
+ return ENOMEM;
+ }
+ }
+ }
+ }
+
+ return r->code;
+}
+
+/* not supported on client side */
+kadm5_ret_t kadm5_decrypt_key(void *server_handle,
+ kadm5_principal_ent_t entry, krb5_int32
+ ktype, krb5_int32 stype, krb5_int32
+ kvno, krb5_keyblock *keyblock,
+ krb5_keysalt *keysalt, int *kvnop)
+{
+ return EINVAL;
+}
diff --git a/src/lib/kadm5/client_rpc.c b/src/lib/kadm5/client_rpc.c
new file mode 100644
index 000000000..547844a2c
--- /dev/null
+++ b/src/lib/kadm5/client_rpc.c
@@ -0,0 +1,221 @@
+#include <rpc/rpc.h>
+#include <kadm5/kadm_rpc.h>
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <memory.h>
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+generic_ret *
+create_principal_1(argp, clnt)
+ cprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, CREATE_PRINCIPAL, xdr_cprinc_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+delete_principal_1(argp, clnt)
+ dprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, DELETE_PRINCIPAL, xdr_dprinc_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+modify_principal_1(argp, clnt)
+ mprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, MODIFY_PRINCIPAL, xdr_mprinc_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+rename_principal_1(argp, clnt)
+ rprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, RENAME_PRINCIPAL, xdr_rprinc_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+gprinc_ret *
+get_principal_1(argp, clnt)
+ gprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static gprinc_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, GET_PRINCIPAL, xdr_gprinc_arg, argp, xdr_gprinc_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+gprincs_ret *
+get_princs_1(argp, clnt)
+ gprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static gprincs_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, GET_PRINCS, xdr_gprincs_arg, argp,
+ xdr_gprincs_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+chpass_principal_1(argp, clnt)
+ chpass_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, CHPASS_PRINCIPAL, xdr_chpass_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+chrand_ret *
+chrand_principal_1(argp, clnt)
+ chrand_arg *argp;
+ CLIENT *clnt;
+{
+ static chrand_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, CHRAND_PRINCIPAL, xdr_chrand_arg, argp, xdr_chrand_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+create_policy_1(argp, clnt)
+ cpol_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, CREATE_POLICY, xdr_cpol_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+delete_policy_1(argp, clnt)
+ dpol_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, DELETE_POLICY, xdr_dpol_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+modify_policy_1(argp, clnt)
+ mpol_arg *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, MODIFY_POLICY, xdr_mpol_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+gpol_ret *
+get_policy_1(argp, clnt)
+ gpol_arg *argp;
+ CLIENT *clnt;
+{
+ static gpol_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, GET_POLICY, xdr_gpol_arg, argp, xdr_gpol_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+gpols_ret *
+get_pols_1(argp, clnt)
+ gprinc_arg *argp;
+ CLIENT *clnt;
+{
+ static gpols_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, GET_POLS, xdr_gpols_arg, argp,
+ xdr_gpols_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+getprivs_ret *get_privs_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static getprivs_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, GET_PRIVS, xdr_u_int32, argp,
+ xdr_getprivs_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
+
+generic_ret *
+init_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static generic_ret res;
+
+ memset((char *)&res, 0, sizeof(res));
+ if (clnt_call(clnt, INIT, xdr_u_int32, argp,
+ xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&res);
+}
diff --git a/src/lib/kadm5/clnt_chpass_util.c b/src/lib/kadm5/clnt_chpass_util.c
new file mode 100644
index 000000000..d6c7f0bfb
--- /dev/null
+++ b/src/lib/kadm5/clnt_chpass_util.c
@@ -0,0 +1,15 @@
+#include <kadm5/admin.h>
+#include "client_internal.h"
+
+kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret)
+{
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+ return _kadm5_chpass_principal_util(handle, handle->lhandle, princ,
+ new_pw, ret_pw, msg_ret);
+}
diff --git a/src/lib/kadm5/clnt_policy.c b/src/lib/kadm5/clnt_policy.c
new file mode 100644
index 000000000..f81cf7471
--- /dev/null
+++ b/src/lib/kadm5/clnt_policy.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/rpc.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include "client_internal.h"
+#include <stdlib.h>
+#include <string.h>
+
+kadm5_ret_t
+kadm5_create_policy(void *server_handle,
+ kadm5_policy_ent_t policy, long mask)
+{
+ cpol_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if(policy == (kadm5_policy_ent_t) NULL)
+ return EINVAL;
+
+ arg.mask = mask;
+ arg.api_version = handle->api_version;
+ memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec));
+ r = create_policy_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_delete_policy(void *server_handle, char *name)
+{
+ dpol_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if(name == NULL)
+ return EINVAL;
+
+ arg.name = name;
+ arg.api_version = handle->api_version;
+
+ r = delete_policy_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_modify_policy(void *server_handle,
+ kadm5_policy_ent_t policy, long mask)
+
+{
+ mpol_arg arg;
+ generic_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if(policy == (kadm5_policy_ent_t) NULL)
+ return EINVAL;
+
+ arg.mask = mask;
+ arg.api_version = handle->api_version;
+
+ memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec));
+ r = modify_policy_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_policy(void *server_handle, char *name, kadm5_policy_ent_t ent)
+
+{
+ gpol_arg arg;
+ gpol_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ arg.name = name;
+ arg.api_version = handle->api_version;
+
+ if(name == NULL)
+ return EINVAL;
+
+ r = get_policy_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ kadm5_policy_ent_t *entp;
+
+ entp = (kadm5_policy_ent_t *) ent;
+ if(r->code == 0) {
+ if (!(*entp = (kadm5_policy_ent_t)
+ malloc(sizeof(kadm5_policy_ent_rec))))
+ return ENOMEM;
+ memcpy(*entp, &r->rec, sizeof(**entp));
+ } else {
+ *entp = NULL;
+ }
+ } else {
+ if (r->code == 0)
+ memcpy(ent, &r->rec, sizeof(r->rec));
+ }
+
+ return r->code;
+}
+
+kadm5_ret_t
+kadm5_get_policies(void *server_handle,
+ char *exp, char ***pols, int *count)
+{
+ gpols_arg arg;
+ gpols_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+ krb5_error_code retval;
+
+ CHECK_HANDLE(server_handle);
+
+ if(pols == NULL || count == NULL)
+ return EINVAL;
+ arg.exp = exp;
+ arg.api_version = handle->api_version;
+ r = get_pols_1(&arg, handle->clnt);
+ if(r == NULL)
+ return KADM5_RPC_ERROR;
+ if(r->code == 0) {
+ *count = r->count;
+ *pols = r->pols;
+ } else {
+ *count = 0;
+ *pols = NULL;
+ }
+
+ return r->code;
+}
diff --git a/src/lib/kadm5/clnt_privs.c b/src/lib/kadm5/clnt_privs.c
new file mode 100644
index 000000000..93ea199e2
--- /dev/null
+++ b/src/lib/kadm5/clnt_privs.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.6 1996/07/22 20:35:57 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.5.4.1 1996/07/18 03:08:45 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.5.2.1 1996/06/20 02:16:53 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.5 1996/05/17 21:36:50 bjaspan
+ * rename to kadm5, begin implementing version 2
+ *
+ * Revision 1.4 1996/05/16 21:45:51 bjaspan
+ * u_int32 -> long, add krb5_context
+ *
+ * Revision 1.3 1994/09/20 16:25:05 bjaspan
+ * [secure-admin/2436: API versioning fixes to various admin files]
+ * [secure-releng/2502: audit secure-admin/2436: random API versioning fixes]
+ *
+ * Sandbox:
+ *
+ * Unnecessary variable initialization removed.
+ *
+ * Revision 1.3 1994/09/12 20:26:39 jik
+ * Unnecessary variable initialization removed.
+ *
+ * Revision 1.2 1994/08/16 18:52:02 jik
+ * Versioning changes.
+ *
+ * Revision 1.1 1993/11/10 23:10:39 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/rpc.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include "client_internal.h"
+
+kadm5_ret_t kadm5_get_privs(void *server_handle, long *privs)
+{
+ getprivs_ret *r;
+ kadm5_server_handle_t handle = server_handle;
+
+ r = get_privs_1(&handle->api_version, handle->clnt);
+ if (r == NULL)
+ return KADM5_RPC_ERROR;
+ else if (r->code == KADM5_OK)
+ *privs = r->privs;
+ return r->code;
+}
diff --git a/src/lib/kadm5/configure.in b/src/lib/kadm5/configure.in
new file mode 100644
index 000000000..6466673a8
--- /dev/null
+++ b/src/lib/kadm5/configure.in
@@ -0,0 +1,49 @@
+AC_INIT(configure.in)
+CONFIG_RULES
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+AC_PROG_LEX
+AC_PROG_AWK
+AC_CHECK_HEADERS(syslog.h)
+AC_REPLACE_FUNCS(setenv)
+save_LIBS="$LIBS"
+LIBS=-lgen
+AC_CHECK_FUNCS(compile step)
+[if test "$krb5_cv_func_compile" = true ; then
+ LIBS="$save_LIBS -lgen"
+else
+ LIBS="$save_LIBS"
+fi]
+AC_CHECK_FUNCS(re_comp re_exec regcomp regexec openlog syslog closelog strftime vsprintf)
+V5_SHARED_LIB_OBJS
+V5_MAKE_SHARED_LIB(libkadm5srv,1.0,.., ./kadm5,srv)
+V5_MAKE_SHARED_LIB(libkadm5clnt,1.0,.., ./kadm5,clnt)
+GSSRPC_SH_VERS=$krb5_cv_shlib_version_libgssrpc
+AC_SUBST(GSSRPC_SH_VERS)
+GSSAPI_KRB5_SH_VERS=$krb5_cv_shlib_version_libgssapi_krb5
+AC_SUBST(GSSAPI_KRB5_SH_VERS)
+KDB5_SH_VERS=$krb5_cv_shlib_version_libkdb5
+AC_SUBST(KDB5_SH_VERS)
+KRB5_SH_VERS=$krb5_cv_shlib_version_libkrb5
+AC_SUBST(KRB5_SH_VERS)
+CRYPTO_SH_VERS=$krb5_cv_shlib_version_libcrypto
+AC_SUBST(CRYPTO_SH_VERS)
+COMERR_SH_VERS=$krb5_cv_shlib_version_libcom_err
+AC_SUBST(COMERR_SH_VERS)
+DYN_SH_VERS=$krb5_cv_shlib_version_libdyn
+AC_SUBST(DYN_SH_VERS)
+CopySrcHeader(adb.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(admin.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(admin_internal.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(admin_xdr.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(client_internal.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(kadm_rpc.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(server_acl.h,[$](BUILDTOP)/include/kadm5)
+CopySrcHeader(server_internal.h,[$](BUILDTOP)/include/kadm5)
+CopyHeader(adb_err.h,[$](BUILDTOP)/include/kadm5)
+CopyHeader(chpass_util_strings.h,[$](BUILDTOP)/include/kadm5)
+CopyHeader(kadm_err.h,[$](BUILDTOP)/include/kadm5)
+AppendRule([all:: all-$(WHAT)])
+V5_AC_OUTPUT_MAKEFILE
diff --git a/src/lib/kadm5/get_admhst.c b/src/lib/kadm5/get_admhst.c
new file mode 100644
index 000000000..a398997d6
--- /dev/null
+++ b/src/lib/kadm5/get_admhst.c
@@ -0,0 +1,89 @@
+/*
+ * $Source$
+ * $Author$
+ *
+ * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
+ * of Technology.
+ *
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
+ */
+
+#ifndef lint
+static char *rcsid =
+"$Header$";
+#endif /* lint */
+
+#include <stdio.h>
+#include <krb5/osconf.h>
+#include <string.h>
+
+/*
+ * Given a Kerberos realm, find a host on which the Kerberos database
+ * administration server can be found.
+ *
+ * krb5_get_admhst takes a pointer to be filled in, a pointer to the name
+ * of the realm for which a server is desired, and an integer n, and
+ * returns (in h) the nth administrative host entry from the configuration
+ * file DEFAULT_CONFIG_FILENAME.
+ *
+ * If the realm is NULL, the default realm is used.
+ *
+ * On error, get_admhst returns 0. If all goes well, the routine
+ * returns 1.
+ *
+ * This is a temporary hack to allow us to find the nearest system running
+ * a Kerberos admin server. In the long run, this functionality will be
+ * provided by a nameserver.
+ */
+int
+krb5_get_admhst(char *h, char *r, int n)
+{
+ FILE *cnffile;
+ char *realm = NULL;
+ char tr[BUFSIZ];
+ char linebuf[BUFSIZ];
+ char scratch[64];
+ register int i;
+ int ret;
+
+ if(r == NULL) {
+ if((ret = krb5_get_default_realm(&realm)) != 0)
+ return ret;
+ r = realm;
+ }
+ if ((cnffile = fopen(DEFAULT_CONFIG_FILENAME, "r")) == NULL) {
+ return(0);
+ }
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ /* error reading */
+ (void) fclose(cnffile);
+ return(0);
+ }
+ if (!strchr(linebuf, '\n')) {
+ /* didn't all fit into buffer, punt */
+ (void) fclose(cnffile);
+ if(realm)
+ free(realm);
+ return(0);
+ }
+ for (i = 0; i < n; ) {
+ /* run through the file, looking for admin host */
+ if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
+ (void) fclose(cnffile);
+ if(realm)
+ free(realm);
+ return(0);
+ }
+ /* need to scan for a token after 'admin' to make sure that
+ admin matched correctly */
+ if (sscanf(linebuf, "%s %s admin %s", tr, h, scratch) != 3)
+ continue;
+ if (!strcmp(tr,r))
+ i++;
+ }
+ (void) fclose(cnffile);
+ if(realm)
+ free(realm);
+ return(1);
+}
diff --git a/src/lib/kadm5/kadm_err.et b/src/lib/kadm5/kadm_err.et
new file mode 100644
index 000000000..446a38de1
--- /dev/null
+++ b/src/lib/kadm5/kadm_err.et
@@ -0,0 +1,54 @@
+# This is the KADM5 error table. The order of error codes
+# defined in this file MUST match that specified in the API
+# functionality specification, which is the master version.
+#
+error_table ovk
+# vv 0
+error_code KADM5_FAILURE, "Operation failed for unspecified reason"
+error_code KADM5_AUTH_GET, "Operation requires ``get'' privilege"
+error_code KADM5_AUTH_ADD, "Operation requires ``add'' privilege"
+error_code KADM5_AUTH_MODIFY, "Operation requires ``modify'' privilege"
+error_code KADM5_AUTH_DELETE, "Operation requires ``delete'' privilege"
+error_code KADM5_AUTH_INSUFFICIENT, "Insufficient authorization for operation"
+error_code KADM5_BAD_DB, "Database inconsistency detected"
+error_code KADM5_DUP, "Principal or policy already exists"
+error_code KADM5_RPC_ERROR, "Communication failure with server"
+error_code KADM5_NO_SRV, "No administration server found for realm"
+error_code KADM5_BAD_HIST_KEY, "Password history principal key version mismatch"
+error_code KADM5_NOT_INIT, "Connection to server not initialized"
+error_code KADM5_UNK_PRINC, "Principal does not exist"
+error_code KADM5_UNK_POLICY, "Policy does not exist"
+error_code KADM5_BAD_MASK, "Invalid field mask for operation"
+error_code KADM5_BAD_CLASS, "Invalid number of character classes"
+error_code KADM5_BAD_LENGTH, "Invalid password length"
+error_code KADM5_BAD_POLICY, "Illegal policy name"
+error_code KADM5_BAD_PRINCIPAL, "Illegal principal name"
+error_code KADM5_BAD_AUX_ATTR, "Invalid auxillary attributes"
+error_code KADM5_BAD_HISTORY, "Invalid password history count"
+error_code KADM5_BAD_MIN_PASS_LIFE, "Password minimum life is greater than password maximum life"
+error_code KADM5_PASS_Q_TOOSHORT, "Password is too short"
+error_code KADM5_PASS_Q_CLASS, "Password does not contain enough character classes"
+error_code KADM5_PASS_Q_DICT, "Password is in the password dictionary"
+error_code KADM5_PASS_REUSE, "Cannot reuse password"
+error_code KADM5_PASS_TOOSOON, "Current password's minimum life has not expired"
+error_code KADM5_POLICY_REF, "Policy is in use"
+error_code KADM5_INIT, "Connection to server already initialized"
+error_code KADM5_BAD_PASSWORD, "Incorrect password"
+error_code KADM5_PROTECT_PRINCIPAL, "Cannot change protected principal"
+error_code KADM5_BAD_SERVER_HANDLE, "Programmer error! Bad Admin server handle"
+error_code KADM5_BAD_STRUCT_VERSION, "Programmer error! Bad API structure version"
+error_code KADM5_OLD_STRUCT_VERSION, "API structure version specified by application is no longer supported (to fix, recompile application against current KADM5 API header files and libraries)"
+error_code KADM5_NEW_STRUCT_VERSION, "API structure version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)"
+error_code KADM5_BAD_API_VERSION, "Programmer error! Bad API version"
+error_code KADM5_OLD_LIB_API_VERSION, "API version specified by application is no longer supported by libraries (to fix, update application to adhere to current API version and recompile)"
+error_code KADM5_OLD_SERVER_API_VERSION, "API version specified by application is no longer supported by server (to fix, update application to adhere to current API version and recompile)"
+error_code KADM5_NEW_LIB_API_VERSION, "API version specified by application is unknown to libraries (to fix, obtain current KADM5 API header files and libraries and recompile application)"
+error_code KADM5_NEW_SERVER_API_VERSION, "API version specified by application is unknown to server (to fix, obtain and install newest KADM5 Admin Server)"
+error_code KADM5_SECURE_PRINC_MISSING, "Database error! Required KADM5 principal missing"
+error_code KADM5_NO_RENAME_SALT, "The salt type of the specified principal does not support renaming"
+error_code KADM5_BAD_CLIENT_PARAMS, "Illegal configuration parameter for remote KADM5 client"
+error_code KADM5_BAD_SERVER_PARAMS, "Illegal configuration parameter for local KADM5 client"
+error_code KADM5_AUTH_LIST, "Operation requires ``list'' privilege"
+error_code KADM5_AUTH_CHANGEPW, "Operation requires ``change-password'' privilege"
+error_code KADM5_GSS_ERROR, "GSS-API (or Kerberos) error"
+end
diff --git a/src/lib/kadm5/kadm_rpc.h b/src/lib/kadm5/kadm_rpc.h
new file mode 100644
index 000000000..b0f97e6cb
--- /dev/null
+++ b/src/lib/kadm5/kadm_rpc.h
@@ -0,0 +1,205 @@
+#include <rpc/types.h>
+
+#include <krb5.h>
+#include <kadm5/admin.h>
+
+struct cprinc_arg {
+ krb5_ui_4 api_version;
+ kadm5_principal_ent_rec rec;
+ long mask;
+ char *passwd;
+};
+typedef struct cprinc_arg cprinc_arg;
+bool_t xdr_cprinc_arg();
+
+struct generic_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+};
+typedef struct generic_ret generic_ret;
+bool_t xdr_generic_ret();
+
+struct dprinc_arg {
+ krb5_ui_4 api_version;
+ krb5_principal princ;
+};
+typedef struct dprinc_arg dprinc_arg;
+bool_t xdr_dprinc_arg();
+
+struct mprinc_arg {
+ krb5_ui_4 api_version;
+ kadm5_principal_ent_rec rec;
+ long mask;
+};
+typedef struct mprinc_arg mprinc_arg;
+bool_t xdr_mprinc_arg();
+
+struct rprinc_arg {
+ krb5_ui_4 api_version;
+ krb5_principal src;
+ krb5_principal dest;
+};
+typedef struct rprinc_arg rprinc_arg;
+bool_t xdr_rprinc_arg();
+
+struct gprincs_arg {
+ krb5_ui_4 api_version;
+ char *exp;
+};
+typedef struct gprincs_arg gprincs_arg;
+bool_t xdr_gprincs_arg();
+
+struct gprincs_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+ char **princs;
+ int count;
+};
+typedef struct gprincs_ret gprincs_ret;
+bool_t xdr_gprincs_ret();
+
+struct chpass_arg {
+ krb5_ui_4 api_version;
+ krb5_principal princ;
+ char *pass;
+};
+typedef struct chpass_arg chpass_arg;
+bool_t xdr_chpass_arg();
+
+struct chrand_arg {
+ krb5_ui_4 api_version;
+ krb5_principal princ;
+};
+typedef struct chrand_arg chrand_arg;
+bool_t xdr_chrand_arg();
+
+struct chrand_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+ krb5_keyblock key;
+ krb5_keyblock *keys;
+ int n_keys;
+};
+typedef struct chrand_ret chrand_ret;
+bool_t xdr_chrand_ret();
+
+struct gprinc_arg {
+ krb5_ui_4 api_version;
+ krb5_principal princ;
+ long mask;
+};
+typedef struct gprinc_arg gprinc_arg;
+bool_t xdr_gprinc_arg();
+
+struct gprinc_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+ kadm5_principal_ent_rec rec;
+};
+typedef struct gprinc_ret gprinc_ret;
+bool_t xdr_gprinc_ret();
+bool_t xdr_kadm5_ret_t();
+bool_t xdr_kadm5_principal_ent_rec();
+bool_t xdr_kadm5_policy_ent_rec();
+bool_t xdr_krb5_keyblock();
+bool_t xdr_krb5_principal();
+bool_t xdr_krb5_enctype();
+bool_t xdr_krb5_octet();
+bool_t xdr_krb5_int32();
+bool_t xdr_u_int32();
+
+struct cpol_arg {
+ krb5_ui_4 api_version;
+ kadm5_policy_ent_rec rec;
+ long mask;
+};
+typedef struct cpol_arg cpol_arg;
+bool_t xdr_cpol_arg();
+
+struct dpol_arg {
+ krb5_ui_4 api_version;
+ char *name;
+};
+typedef struct dpol_arg dpol_arg;
+bool_t xdr_dpol_arg();
+
+struct mpol_arg {
+ krb5_ui_4 api_version;
+ kadm5_policy_ent_rec rec;
+ long mask;
+};
+typedef struct mpol_arg mpol_arg;
+bool_t xdr_mpol_arg();
+
+struct gpol_arg {
+ krb5_ui_4 api_version;
+ char *name;
+};
+typedef struct gpol_arg gpol_arg;
+bool_t xdr_gpol_arg();
+
+struct gpol_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+ kadm5_policy_ent_rec rec;
+};
+typedef struct gpol_ret gpol_ret;
+bool_t xdr_gpol_ret();
+
+struct gpols_arg {
+ krb5_ui_4 api_version;
+ char *exp;
+};
+typedef struct gpols_arg gpols_arg;
+bool_t xdr_gpols_arg();
+
+struct gpols_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+ char **pols;
+ int count;
+};
+typedef struct gpols_ret gpols_ret;
+bool_t xdr_gpols_ret();
+
+struct getprivs_ret {
+ krb5_ui_4 api_version;
+ kadm5_ret_t code;
+ long privs;
+};
+typedef struct getprivs_ret getprivs_ret;
+bool_t xdr_getprivs_ret();
+
+#define KADM ((krb5_ui_4)2112)
+#define KADMVERS ((krb5_ui_4)2)
+#define CREATE_PRINCIPAL ((krb5_ui_4)1)
+extern generic_ret *create_principal_1();
+#define DELETE_PRINCIPAL ((krb5_ui_4)2)
+extern generic_ret *delete_principal_1();
+#define MODIFY_PRINCIPAL ((krb5_ui_4)3)
+extern generic_ret *modify_principal_1();
+#define RENAME_PRINCIPAL ((krb5_ui_4)4)
+extern generic_ret *rename_principal_1();
+#define GET_PRINCIPAL ((krb5_ui_4)5)
+extern gprinc_ret *get_principal_1();
+#define CHPASS_PRINCIPAL ((krb5_ui_4)6)
+extern generic_ret *chpass_principal_1();
+#define CHRAND_PRINCIPAL ((krb5_ui_4)7)
+extern chrand_ret *chrand_principal_1();
+#define CREATE_POLICY ((krb5_ui_4)8)
+extern generic_ret *create_policy_1();
+#define DELETE_POLICY ((krb5_ui_4)9)
+extern generic_ret *delete_policy_1();
+#define MODIFY_POLICY ((krb5_ui_4)10)
+extern generic_ret *modify_policy_1();
+#define GET_POLICY ((krb5_ui_4)11)
+extern gpol_ret *get_policy_1();
+#define GET_PRIVS ((krb5_ui_4)12)
+extern getprivs_ret *get_privs_1();
+#define INIT ((krb5_ui_4)13)
+extern generic_ret *init_1();
+#define GET_PRINCS ((krb5_ui_4) 14)
+extern gprincs_ret *get_princs_1();
+#define GET_POLS ((krb5_ui_4) 15)
+extern gpols_ret *get_pols_1();
+
diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c
new file mode 100644
index 000000000..6cce9391e
--- /dev/null
+++ b/src/lib/kadm5/kadm_rpc_xdr.c
@@ -0,0 +1,830 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/rpc.h>
+#include <krb5.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm_rpc.h>
+#include <malloc.h>
+#include <string.h>
+
+static bool_t
+_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
+ int v);
+
+/*
+ * Function: xdr_ui_4
+ *
+ * Purpose: XDR function which serves as a wrapper for xdr_u_int32,
+ * to prevent compiler warnings about type clashes between u_int32
+ * and krb5_ui_4.
+ */
+bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp)
+{
+ /* Assumes that krb5_ui_4 and u_int32 are both four bytes long.
+ This should not be a harmful assumption. */
+ return xdr_u_int32(xdrs, (rpc_u_int32 *) objp);
+}
+
+
+/*
+ * Function: xdr_nullstring
+ *
+ * Purpose: XDR function for "strings" that are either NULL-terminated
+ * or NULL.
+ */
+bool_t xdr_nullstring(XDR *xdrs, char **objp)
+{
+ u_int size;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (*objp == NULL)
+ size = 0;
+ else
+ size = strlen(*objp) + 1;
+ }
+ if (! xdr_u_int(xdrs, &size)) {
+ return FALSE;
+ }
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (size == 0) {
+ *objp = NULL;
+ return TRUE;
+ } else if (*objp == NULL) {
+ *objp = (char *) mem_alloc(size);
+ if (*objp == NULL) {
+ errno = ENOMEM;
+ return FALSE;
+ }
+ }
+ return (xdr_opaque(xdrs, *objp, size));
+
+ case XDR_ENCODE:
+ if (size != 0)
+ return (xdr_opaque(xdrs, *objp, size));
+ return TRUE;
+
+ case XDR_FREE:
+ if (*objp != NULL)
+ mem_free(*objp, size);
+ *objp = NULL;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/*
+ * Function: xdr_nulltype
+ *
+ * Purpose: XDR function for arbitrary pointer types that are either
+ * NULL or contain data.
+ */
+bool_t xdr_nulltype(XDR *xdrs, void **objp, xdrproc_t proc)
+{
+ bool_t null;
+
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (!xdr_bool(xdrs, &null))
+ return FALSE;
+ if (null) {
+ *objp = NULL;
+ return TRUE;
+ }
+ return (*proc)(xdrs, objp);
+
+ case XDR_ENCODE:
+ if (*objp == NULL)
+ null = TRUE;
+ else
+ null = FALSE;
+ if (!xdr_bool(xdrs, &null))
+ return FALSE;
+ if (null == FALSE)
+ return (*proc)(xdrs, objp);
+ return TRUE;
+
+ case XDR_FREE:
+ if (*objp)
+ return (*proc)(xdrs, objp);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+bool_t
+xdr_krb5_timestamp(XDR *xdrs, krb5_timestamp *objp)
+{
+ /* This assumes that int32 and krb5_timestamp are the same size.
+ This shouldn't be a problem, since we've got a unit test which
+ checks for this. */
+ if (!xdr_int32(xdrs, (rpc_int32 *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_kvno(XDR *xdrs, krb5_kvno *objp)
+{
+ unsigned char tmp;
+
+ if (xdrs->x_op == XDR_ENCODE)
+ tmp = (unsigned char) *objp;
+
+ if (!xdr_u_char(xdrs, &tmp))
+ return (FALSE);
+
+ if (xdrs->x_op == XDR_DECODE)
+ *objp = (krb5_kvno) tmp;
+
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_deltat(XDR *xdrs, krb5_deltat *objp)
+{
+ /* This assumes that int32 and krb5_deltat are the same size.
+ This shouldn't be a problem, since we've got a unit test which
+ checks for this. */
+ if (!xdr_int32(xdrs, (rpc_int32 *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_flags(XDR *xdrs, krb5_flags *objp)
+{
+ /* This assumes that int32 and krb5_flags are the same size.
+ This shouldn't be a problem, since we've got a unit test which
+ checks for this. */
+ if (!xdr_int32(xdrs, (rpc_int32 *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_ui_4(XDR *xdrs, krb5_ui_4 *objp)
+{
+ if (!xdr_u_int32(xdrs, (rpc_u_int32 *) objp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_int16(XDR *xdrs, krb5_int16 *objp)
+{
+ int tmp;
+
+ tmp = (int) *objp;
+
+ if (!xdr_int(xdrs, &tmp))
+ return(FALSE);
+
+ *objp = (krb5_int16) tmp;
+
+ return(TRUE);
+}
+
+bool_t xdr_krb5_key_data_nocontents(XDR *xdrs, krb5_key_data *objp)
+{
+ /*
+ * Note that this function intentionally DOES NOT tranfer key
+ * length or contents! xdr_krb5_key_data in adb_xdr.c does.
+ */
+
+ if (xdrs->x_op == XDR_DECODE)
+ memset((char *) objp, 0, sizeof(krb5_key_data));
+
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_ver)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_kvno)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) {
+ return (FALSE);
+ }
+ if (objp->key_data_ver > 1) {
+ if (!xdr_krb5_int16(xdrs, &objp->key_data_type[0])) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+bool_t xdr_krb5_tl_data(XDR *xdrs, krb5_tl_data **tl_data_head)
+{
+ krb5_tl_data *tl, *tl2;
+ bool_t more;
+ int len;
+
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ case XDR_ENCODE:
+ tl = *tl_data_head;
+ while (1) {
+ more = (tl != NULL);
+ if (!xdr_bool(xdrs, &more))
+ return FALSE;
+ if (tl == NULL)
+ break;
+ if (!xdr_krb5_int16(xdrs, &tl->tl_data_type))
+ return FALSE;
+ len = tl->tl_data_length;
+ if (!xdr_bytes(xdrs, (char **) &tl->tl_data_contents, &len, ~0))
+ return FALSE;
+ tl = tl->tl_data_next;
+ }
+ break;
+
+ case XDR_DECODE:
+ tl = NULL;
+ while (1) {
+ if (!xdr_bool(xdrs, &more))
+ return FALSE;
+ if (more == FALSE)
+ break;
+ tl2 = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
+ if (tl2 == NULL)
+ return FALSE;
+ memset((char *) tl2, 0, sizeof(krb5_tl_data));
+ if (!xdr_krb5_int16(xdrs, &tl2->tl_data_type))
+ return FALSE;
+ if (!xdr_bytes(xdrs, (char **)&tl2->tl_data_contents, &len, ~0))
+ return FALSE;
+ tl2->tl_data_length = len;
+
+ tl2->tl_data_next = tl;
+ tl = tl2;
+ }
+
+ *tl_data_head = tl;
+ break;
+ }
+
+ return TRUE;
+}
+
+bool_t
+xdr_kadm5_ret_t(XDR *xdrs, kadm5_ret_t *objp)
+{
+ rpc_u_int32 tmp;
+
+ if (xdrs->x_op == XDR_ENCODE)
+ tmp = (rpc_u_int32) *objp;
+
+ if (!xdr_u_int32(xdrs, &tmp))
+ return (FALSE);
+
+ if (xdrs->x_op == XDR_DECODE)
+ *objp = (kadm5_ret_t) tmp;
+
+ return (TRUE);
+}
+
+bool_t xdr_kadm5_principal_ent_rec_v1(XDR *xdrs,
+ kadm5_principal_ent_rec *objp)
+{
+ return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_1);
+}
+
+bool_t xdr_kadm5_principal_ent_rec(XDR *xdrs,
+ kadm5_principal_ent_rec *objp)
+{
+ return _xdr_kadm5_principal_ent_rec(xdrs, objp, KADM5_API_VERSION_2);
+}
+
+static bool_t
+_xdr_kadm5_principal_ent_rec(XDR *xdrs, kadm5_principal_ent_rec *objp,
+ int v)
+{
+ unsigned int n;
+
+ if (!xdr_krb5_principal(xdrs, &objp->principal)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_timestamp(xdrs, &objp->princ_expire_time)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_timestamp(xdrs, &objp->last_pwd_change)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_timestamp(xdrs, &objp->pw_expiration)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_deltat(xdrs, &objp->max_life)) {
+ return (FALSE);
+ }
+ if (v == KADM5_API_VERSION_1) {
+ if (!xdr_krb5_principal(xdrs, &objp->mod_name)) {
+ return (FALSE);
+ }
+ } else {
+ if (!xdr_nulltype(xdrs, (void **) &objp->mod_name,
+ xdr_krb5_principal)) {
+ return (FALSE);
+ }
+ }
+ if (!xdr_krb5_timestamp(xdrs, &objp->mod_date)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_flags(xdrs, &objp->attributes)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_kvno(xdrs, &objp->kvno)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_kvno(xdrs, &objp->mkvno)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->policy)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->aux_attributes)) {
+ return (FALSE);
+ }
+ if (v != KADM5_API_VERSION_1) {
+ if (!xdr_krb5_deltat(xdrs, &objp->max_renewable_life)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_timestamp(xdrs, &objp->last_success)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_timestamp(xdrs, &objp->last_failed)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_kvno(xdrs, &objp->fail_auth_count)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_int16(xdrs, &objp->n_key_data)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_int16(xdrs, &objp->n_tl_data)) {
+ return (FALSE);
+ }
+ if (!xdr_nulltype(xdrs, (void **) &objp->tl_data,
+ xdr_krb5_tl_data)) {
+ return FALSE;
+ }
+ n = objp->n_key_data;
+ if (!xdr_array(xdrs, (caddr_t *) &objp->key_data,
+ &n, ~0, sizeof(krb5_key_data),
+ xdr_krb5_key_data_nocontents)) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_kadm5_policy_ent_rec(XDR *xdrs, kadm5_policy_ent_rec *objp)
+{
+ if (!xdr_nullstring(xdrs, &objp->policy)) {
+ return (FALSE);
+ }
+ /* these all used to be u_int32, but it's stupid for sized types
+ to be exposed at the api, and they're the same as longs on the
+ wire. */
+ if (!xdr_long(xdrs, &objp->pw_min_life)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->pw_max_life)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->pw_min_length)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->pw_min_classes)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->pw_history_num)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->policy_refcnt)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_cprinc_arg(XDR *xdrs, cprinc_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (objp->api_version == KADM5_API_VERSION_1) {
+ if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ } else {
+ if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ }
+ if (!xdr_long(xdrs, &objp->mask)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->passwd)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_generic_ret(XDR *xdrs, generic_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+ return (FALSE);
+ }
+ return(TRUE);
+}
+
+bool_t
+xdr_dprinc_arg(XDR *xdrs, dprinc_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mprinc_arg(XDR *xdrs, mprinc_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (objp->api_version == KADM5_API_VERSION_1) {
+ if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ } else {
+ if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ }
+ if (!xdr_long(xdrs, &objp->mask)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_rprinc_arg(XDR *xdrs, rprinc_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_principal(xdrs, &objp->src)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_principal(xdrs, &objp->dest)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gprincs_arg(XDR *xdrs, gprincs_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->exp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+ return (FALSE);
+ }
+ if (objp->code == KADM5_OK) {
+ if (!xdr_int(xdrs, &objp->count)) {
+ return (FALSE);
+ }
+ if (!xdr_array(xdrs, (caddr_t *) &objp->princs,
+ (unsigned int *) &objp->count, ~0,
+ sizeof(char *), xdr_nullstring)) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_chpass_arg(XDR *xdrs, chpass_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->pass)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_chrand_arg(XDR *xdrs, chrand_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_chrand_ret(XDR *xdrs, chrand_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+ return (FALSE);
+ }
+ if (objp->api_version == KADM5_API_VERSION_1) {
+ if(objp->code == KADM5_OK) {
+ if (!xdr_krb5_keyblock(xdrs, &objp->key)) {
+ return (FALSE);
+ }
+ }
+ } else {
+ if (objp->code == KADM5_OK) {
+ if (!xdr_array(xdrs, (char **)&objp->keys, &objp->n_keys, ~0,
+ sizeof(krb5_keyblock),
+ xdr_krb5_keyblock))
+ return FALSE;
+ }
+ }
+
+ return (TRUE);
+}
+
+bool_t
+xdr_gprinc_arg(XDR *xdrs, gprinc_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_krb5_principal(xdrs, &objp->princ)) {
+ return (FALSE);
+ }
+ if ((objp->api_version > KADM5_API_VERSION_1) &&
+ !xdr_long(xdrs, &objp->mask)) {
+ return FALSE;
+ }
+
+ return (TRUE);
+}
+
+bool_t
+xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+ return (FALSE);
+ }
+ if(objp->code == KADM5_OK) {
+ if (objp->api_version == KADM5_API_VERSION_1) {
+ if (!xdr_kadm5_principal_ent_rec_v1(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ } else {
+ if (!xdr_kadm5_principal_ent_rec(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ }
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_cpol_arg(XDR *xdrs, cpol_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->mask)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_dpol_arg(XDR *xdrs, dpol_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->name)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mpol_arg(XDR *xdrs, mpol_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec)) {
+ return (FALSE);
+ }
+ if (!xdr_long(xdrs, &objp->mask)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gpol_arg(XDR *xdrs, gpol_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->name)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gpol_ret(XDR *xdrs, gpol_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+ return (FALSE);
+ }
+ if(objp->code == KADM5_OK) {
+ if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec))
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gpols_arg(XDR *xdrs, gpols_arg *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_nullstring(xdrs, &objp->exp)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_gpols_ret(XDR *xdrs, gpols_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
+ return (FALSE);
+ }
+ if (objp->code == KADM5_OK) {
+ if (!xdr_int(xdrs, &objp->count)) {
+ return (FALSE);
+ }
+ if (!xdr_array(xdrs, (caddr_t *) &objp->pols,
+ (unsigned int *) &objp->count, ~0,
+ sizeof(char *), xdr_nullstring)) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp)
+{
+ if (!xdr_ui_4(xdrs, &objp->api_version)) {
+ return (FALSE);
+ }
+ if (! xdr_kadm5_ret_t(xdrs, &objp->code) ||
+ ! xdr_long(xdrs, &objp->privs))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t
+xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
+{
+ int ret;
+ char *p = NULL;
+ krb5_principal pr = NULL;
+ static krb5_context context = NULL;
+
+ /* using a static context here is ugly, but should work
+ ok, and the other solutions are even uglier */
+
+ if (!context &&
+ krb5_init_context(&context))
+ return(FALSE);
+
+ switch(xdrs->x_op) {
+ case XDR_ENCODE:
+ if((ret = krb5_unparse_name(context, *objp, &p)) != 0)
+ return FALSE;
+ if(!xdr_nullstring(xdrs, &p))
+ return FALSE;
+ free(p);
+ break;
+ case XDR_DECODE:
+ if(!xdr_nullstring(xdrs, &p))
+ return FALSE;
+ ret = krb5_parse_name(context, p, &pr);
+ if(ret != 0)
+ return FALSE;
+ *objp = pr;
+ free(p);
+ break;
+ case XDR_FREE:
+ if(*objp != NULL)
+ krb5_free_principal(context, *objp);
+ break;
+ }
+ return TRUE;
+}
+
+bool_t
+xdr_krb5_octet(XDR *xdrs, krb5_octet *objp)
+{
+ if (!xdr_u_char(xdrs, objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp)
+{
+ /*
+ * This used to be xdr_krb5_keytype, but keytypes and enctypes have
+ * been merged into only enctypes. However, randkey_principal
+ * already ensures that only a key of ENCTYPE_DES_CBC_CRC will be
+ * returned to v1 clients, and ENCTYPE_DES_CBC_CRC has the same
+ * value as KEYTYPE_DES used too, which is what all v1 clients
+ * expect. Therefore, IMHO, just encoding whatever enctype we get
+ * is safe.
+ */
+
+ if (!xdr_u_int(xdrs, (unsigned int *) objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp)
+{
+ /* XXX This only works because free_keyblock assumes ->contents
+ is allocated by malloc() */
+
+ if(!xdr_krb5_enctype(xdrs, &objp->enctype))
+ return FALSE;
+ if(!xdr_bytes(xdrs, (char **) &objp->contents, (unsigned int *)
+ &objp->length, ~0))
+ return FALSE;
+ return TRUE;
+}
+
diff --git a/src/lib/kadm5/logger.c b/src/lib/kadm5/logger.c
new file mode 100644
index 000000000..924fb9a23
--- /dev/null
+++ b/src/lib/kadm5/logger.c
@@ -0,0 +1,940 @@
+/*
+ * lib/kadm/logger.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#if !defined(_MSDOS)
+
+/*
+ * logger.c - Handle logging functions for those who want it.
+ */
+#include "k5-int.h"
+#include "adm_proto.h"
+#include "com_err.h"
+#include <stdio.h>
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+#endif /* HAVE_SYSLOG_H */
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#else /* HAVE_STDARG_H */
+#include <varargs.h>
+#endif /* HAVE_STDARG_H */
+
+#define KRB5_KLOG_MAX_ERRMSG_SIZE 1024
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif /* MAXHOSTNAMELEN */
+
+/* This is to assure that we have at least one match in the syslog stuff */
+#ifndef LOG_AUTH
+#define LOG_AUTH 0
+#endif /* LOG_AUTH */
+#ifndef LOG_ERR
+#define LOG_ERR 0
+#endif /* LOG_ERR */
+
+static const char lspec_parse_err_1[] = "%s: cannot parse <%s>\n";
+static const char lspec_parse_err_2[] = "%s: warning - logging entry syntax error\n";
+static const char log_file_err[] = "%s: error writing to %s\n";
+static const char log_device_err[] = "%s: error writing to %s device\n";
+static const char log_ufo_string[] = "???";
+static const char log_emerg_string[] = "EMERGENCY";
+static const char log_alert_string[] = "ALERT";
+static const char log_crit_string[] = "CRITICAL";
+static const char log_err_string[] = "Error";
+static const char log_warning_string[] = "Warning";
+static const char log_notice_string[] = "Notice";
+static const char log_info_string[] = "info";
+static const char log_debug_string[] = "debug";
+
+/*
+ * Output logging.
+ *
+ * Output logging is now controlled by the configuration file. We can specify
+ * the following syntaxes under the [logging]->entity specification.
+ * FILE<opentype><pathname>
+ * SYSLOG[=<severity>[:<facility>]]
+ * STDERR
+ * CONSOLE
+ * DEVICE=<device-spec>
+ *
+ * Where:
+ * <opentype> is ":" for open/append, "=" for open/create.
+ * <pathname> is a valid path name.
+ * <severity> is one of: (default = ERR)
+ * EMERG
+ * ALERT
+ * CRIT
+ * ERR
+ * WARNING
+ * NOTICE
+ * INFO
+ * DEBUG
+ * <facility> is one of: (default = AUTH)
+ * KERN
+ * USER
+ * MAIL
+ * DAEMON
+ * AUTH
+ * LPR
+ * NEWS
+ * UUCP
+ * CRON
+ * LOCAL0..LOCAL7
+ * <device-spec> is a valid device specification.
+ */
+struct log_entry {
+ enum log_type { K_LOG_FILE,
+ K_LOG_SYSLOG,
+ K_LOG_STDERR,
+ K_LOG_CONSOLE,
+ K_LOG_DEVICE,
+ K_LOG_NONE } log_type;
+ krb5_pointer log_2free;
+ union log_union {
+ struct log_file {
+ FILE *lf_filep;
+ char *lf_fname;
+ } log_file;
+ struct log_syslog {
+ int ls_facility;
+ int ls_severity;
+ } log_syslog;
+ struct log_device {
+ FILE *ld_filep;
+ char *ld_devname;
+ } log_device;
+ } log_union;
+};
+#define lfu_filep log_union.log_file.lf_filep
+#define lfu_fname log_union.log_file.lf_fname
+#define lsu_facility log_union.log_syslog.ls_facility
+#define lsu_severity log_union.log_syslog.ls_severity
+#define ldu_filep log_union.log_device.ld_filep
+#define ldu_devname log_union.log_device.ld_devname
+
+struct log_control {
+ struct log_entry *log_entries;
+ int log_nentries;
+ char *log_whoami;
+ char *log_hostname;
+ krb5_boolean log_opened;
+};
+
+static struct log_control log_control = {
+ (struct log_entry *) NULL,
+ 0,
+ (char *) NULL,
+ (char *) NULL,
+ 0
+};
+static struct log_entry def_log_entry;
+
+/*
+ * These macros define any special processing that needs to happen for
+ * devices. For unix, of course, this is hardly anything.
+ */
+#define DEVICE_OPEN(d, m) fopen(d, m)
+#define CONSOLE_OPEN(m) fopen("/dev/console", m)
+#define DEVICE_PRINT(f, m) ((fprintf(f, m) >= 0) ? \
+ (fprintf(f, "\r\n"), fflush(f), 0) : \
+ -1)
+#define DEVICE_CLOSE(d) fclose(d)
+
+
+/*
+ * klog_com_err_proc() - Handle com_err(3) messages as specified by the
+ * profile.
+ */
+static void
+klog_com_err_proc(whoami, code, format, ap)
+ const char *whoami;
+ long code;
+ const char *format;
+ va_list ap;
+{
+ char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
+ int lindex;
+ char *actual_format;
+#ifdef HAVE_SYSLOG
+ int log_pri = -1;
+#endif /* HAVE_SYSLOG */
+ char *cp;
+ char *syslogp;
+
+ /* Make the header */
+ sprintf(outbuf, "%s: ", whoami);
+ /*
+ * Squirrel away address after header for syslog since syslog makes
+ * a header
+ */
+ syslogp = &outbuf[strlen(outbuf)];
+
+ /* If reporting an error message, separate it. */
+ if (code) {
+ strcat(outbuf, error_message(code));
+ strcat(outbuf, " - ");
+ }
+ cp = &outbuf[strlen(outbuf)];
+
+ actual_format = (char *) format;
+#ifdef HAVE_SYSLOG
+ /*
+ * This is an unpleasant hack. If the first character is less than
+ * 8, then we assume that it is a priority.
+ *
+ * Since it is not guaranteed that there is a direct mapping between
+ * syslog priorities (e.g. Ultrix and old BSD), we resort to this
+ * intermediate representation.
+ */
+ if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) {
+ actual_format = (char *) (format + 1);
+ switch ((unsigned char) *format) {
+#ifdef LOG_EMERG
+ case 1:
+ log_pri = LOG_EMERG;
+ break;
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
+ case 2:
+ log_pri = LOG_ALERT;
+ break;
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
+ case 3:
+ log_pri = LOG_CRIT;
+ break;
+#endif /* LOG_CRIT */
+ default:
+ case 4:
+ log_pri = LOG_ERR;
+ break;
+#ifdef LOG_WARNING
+ case 5:
+ log_pri = LOG_WARNING;
+ break;
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
+ case 6:
+ log_pri = LOG_NOTICE;
+ break;
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
+ case 7:
+ log_pri = LOG_INFO;
+ break;
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
+ case 8:
+ log_pri = LOG_DEBUG;
+ break;
+#endif /* LOG_DEBUG */
+ }
+ }
+#endif /* HAVE_SYSLOG */
+
+ /* Now format the actual message */
+#if HAVE_VSPRINTF
+ vsprintf(cp, actual_format, ap);
+#else /* HAVE_VSPRINTF */
+ sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1],
+ ((int *) ap)[2], ((int *) ap)[3],
+ ((int *) ap)[4], ((int *) ap)[5]);
+#endif /* HAVE_VSPRINTF */
+
+ /*
+ * Now that we have the message formatted, perform the output to each
+ * logging specification.
+ */
+ for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+ switch (log_control.log_entries[lindex].log_type) {
+ case K_LOG_FILE:
+ case K_LOG_STDERR:
+ /*
+ * Files/standard error.
+ */
+ if (fprintf(log_control.log_entries[lindex].lfu_filep,
+ outbuf) < 0) {
+ /* Attempt to report error */
+ fprintf(stderr, log_file_err, whoami,
+ log_control.log_entries[lindex].lfu_fname);
+ }
+ else {
+ fprintf(log_control.log_entries[lindex].lfu_filep, "\n");
+ fflush(log_control.log_entries[lindex].lfu_filep);
+ }
+ break;
+ case K_LOG_CONSOLE:
+ case K_LOG_DEVICE:
+ /*
+ * Devices (may need special handling)
+ */
+ if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
+ outbuf) < 0) {
+ /* Attempt to report error */
+ fprintf(stderr, log_device_err, whoami,
+ log_control.log_entries[lindex].ldu_devname);
+ }
+ break;
+#ifdef HAVE_SYSLOG
+ case K_LOG_SYSLOG:
+ /*
+ * System log.
+ */
+ /*
+ * If we have specified a priority through our hackery, then
+ * use it, otherwise use the default.
+ */
+ if (log_pri >= 0)
+ log_pri |= log_control.log_entries[lindex].lsu_facility;
+ else
+ log_pri = log_control.log_entries[lindex].lsu_facility |
+ log_control.log_entries[lindex].lsu_severity;
+
+ /* Log the message with our header trimmed off */
+ syslog(log_pri, syslogp);
+ break;
+#endif /* HAVE_SYSLOG */
+ default:
+ break;
+ }
+ }
+}
+
+/*
+ * krb5_klog_init() - Initialize logging.
+ *
+ * This routine parses the syntax described above to specify destinations for
+ * com_err(3) or krb5_klog_syslog() messages generated by the caller.
+ *
+ * Parameters:
+ * kcontext - Kerberos context.
+ * ename - Entity name as it is to appear in the profile.
+ * whoami - Entity name as it is to appear in error output.
+ * do_com_err - Take over com_err(3) processing.
+ *
+ * Implicit inputs:
+ * stderr - This is where STDERR output goes.
+ *
+ * Implicit outputs:
+ * log_nentries - Number of log entries, both valid and invalid.
+ * log_control - List of entries (log_nentries long) which contains
+ * data for klog_com_err_proc() to use to determine
+ * where/how to send output.
+ */
+krb5_error_code
+krb5_klog_init(kcontext, ename, whoami, do_com_err)
+ krb5_context kcontext;
+ char *ename;
+ char *whoami;
+ krb5_boolean do_com_err;
+{
+ const char *logging_profent[3];
+ const char *logging_defent[3];
+ char **logging_specs;
+ int i, ngood;
+ char *cp, *cp2;
+ char savec;
+ int error;
+ int do_openlog, log_facility;
+ FILE *f;
+
+ /* Initialize */
+ do_openlog = 0;
+ log_facility = 0;
+
+ /*
+ * Look up [logging]-><ename> in the profile. If that doesn't
+ * succeed, then look for [logging]->default.
+ */
+ logging_profent[0] = "logging";
+ logging_profent[1] = ename;
+ logging_profent[2] = (char *) NULL;
+ logging_defent[0] = "logging";
+ logging_defent[1] = "default";
+ logging_defent[2] = (char *) NULL;
+ logging_specs = (char **) NULL;
+ ngood = 0;
+ log_control.log_nentries = 0;
+ if (!profile_get_values(kcontext->profile,
+ logging_profent,
+ &logging_specs) ||
+ !profile_get_values(kcontext->profile,
+ logging_defent,
+ &logging_specs)) {
+ /*
+ * We have a match, so we first count the number of elements
+ */
+ for (log_control.log_nentries = 0;
+ logging_specs[log_control.log_nentries];
+ log_control.log_nentries++);
+
+ /*
+ * Now allocate our structure.
+ */
+ log_control.log_entries = (struct log_entry *)
+ malloc(log_control.log_nentries * sizeof(struct log_entry));
+ if (log_control.log_entries) {
+ /*
+ * Scan through the list.
+ */
+ for (i=0; i<log_control.log_nentries; i++) {
+ log_control.log_entries[i].log_type = K_LOG_NONE;
+ log_control.log_entries[i].log_2free = logging_specs[i];
+ /*
+ * The format is:
+ * <whitespace><data><whitespace>
+ * so, trim off the leading and trailing whitespace here.
+ */
+ for (cp = logging_specs[i]; isspace(*cp); cp++);
+ for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
+ isspace(*cp2); cp2--);
+ cp2++;
+ *cp2 = '\0';
+ /*
+ * Is this a file?
+ */
+ if (!strncasecmp(cp, "FILE", 4)) {
+ /*
+ * Check for append/overwrite, then open the file.
+ */
+ if (cp[4] == ':' || cp[4] == '=') {
+ f = fopen(&cp[5], (cp[4] == ':') ? "a+" : "w");
+ if (f) {
+ log_control.log_entries[i].lfu_filep = f;
+ log_control.log_entries[i].log_type = K_LOG_FILE;
+ log_control.log_entries[i].lfu_fname = &cp[5];
+ } else {
+ fprintf(stderr,"Couldn't open log file %s: %s\n",
+ &cp[5], error_message(errno));
+ continue;
+ }
+ }
+ }
+#ifdef HAVE_SYSLOG
+ /*
+ * Is this a syslog?
+ */
+ else if (!strncasecmp(cp, "SYSLOG", 6)) {
+ error = 0;
+ log_control.log_entries[i].lsu_facility = LOG_AUTH;
+ log_control.log_entries[i].lsu_severity = LOG_ERR;
+ /*
+ * Is there a severify specified?
+ */
+ if (cp[6] == ':') {
+ /*
+ * Find the end of the severity.
+ */
+ if (cp2 = strchr(&cp[7], ':')) {
+ savec = *cp2;
+ *cp2 = '\0';
+ cp2++;
+ }
+
+ /*
+ * Match a severity.
+ */
+ if (!strcasecmp(&cp[7], "ERR")) {
+ log_control.log_entries[i].lsu_severity = LOG_ERR;
+ }
+#ifdef LOG_EMERG
+ else if (!strcasecmp(&cp[7], "EMERG")) {
+ log_control.log_entries[i].lsu_severity =
+ LOG_EMERG;
+ }
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
+ else if (!strcasecmp(&cp[7], "ALERT")) {
+ log_control.log_entries[i].lsu_severity =
+ LOG_ALERT;
+ }
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
+ else if (!strcasecmp(&cp[7], "CRIT")) {
+ log_control.log_entries[i].lsu_severity = LOG_CRIT;
+ }
+#endif /* LOG_CRIT */
+#ifdef LOG_WARNING
+ else if (!strcasecmp(&cp[7], "WARNING")) {
+ log_control.log_entries[i].lsu_severity =
+ LOG_WARNING;
+ }
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
+ else if (!strcasecmp(&cp[7], "NOTICE")) {
+ log_control.log_entries[i].lsu_severity =
+ LOG_NOTICE;
+ }
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
+ else if (!strcasecmp(&cp[7], "INFO")) {
+ log_control.log_entries[i].lsu_severity = LOG_INFO;
+ }
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
+ else if (!strcasecmp(&cp[7], "DEBUG")) {
+ log_control.log_entries[i].lsu_severity =
+ LOG_DEBUG;
+ }
+#endif /* LOG_DEBUG */
+ else
+ error = 1;
+
+ /*
+ * If there is a facility present, then parse that.
+ */
+ if (cp2) {
+ if (!strcasecmp(cp2, "AUTH")) {
+ log_control.log_entries[i].lsu_facility = LOG_AUTH;
+ }
+#ifdef LOG_KERN
+ else if (!strcasecmp(cp2, "KERN")) {
+ log_control.log_entries[i].lsu_facility = LOG_KERN;
+ }
+#endif /* LOG_KERN */
+#ifdef LOG_USER
+ else if (!strcasecmp(cp2, "USER")) {
+ log_control.log_entries[i].lsu_facility = LOG_USER;
+ }
+#endif /* LOG_USER */
+#ifdef LOG_MAIL
+ else if (!strcasecmp(cp2, "MAIL")) {
+ log_control.log_entries[i].lsu_facility = LOG_MAIL;
+ }
+#endif /* LOG_MAIL */
+#ifdef LOG_DAEMON
+ else if (!strcasecmp(cp2, "DAEMON")) {
+ log_control.log_entries[i].lsu_facility = LOG_DAEMON;
+ }
+#endif /* LOG_DAEMON */
+#ifdef LOG_LPR
+ else if (!strcasecmp(cp2, "LPR")) {
+ log_control.log_entries[i].lsu_facility = LOG_LPR;
+ }
+#endif /* LOG_LPR */
+#ifdef LOG_NEWS
+ else if (!strcasecmp(cp2, "NEWS")) {
+ log_control.log_entries[i].lsu_facility = LOG_NEWS;
+ }
+#endif /* LOG_NEWS */
+#ifdef LOG_UUCP
+ else if (!strcasecmp(cp2, "UUCP")) {
+ log_control.log_entries[i].lsu_facility = LOG_UUCP;
+ }
+#endif /* LOG_UUCP */
+#ifdef LOG_CRON
+ else if (!strcasecmp(cp2, "CRON")) {
+ log_control.log_entries[i].lsu_facility = LOG_CRON;
+ }
+#endif /* LOG_CRON */
+#ifdef LOG_LOCAL0
+ else if (!strcasecmp(cp2, "LOCAL0")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL0;
+ }
+#endif /* LOG_LOCAL0 */
+#ifdef LOG_LOCAL1
+ else if (!strcasecmp(cp2, "LOCAL1")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL1;
+ }
+#endif /* LOG_LOCAL1 */
+#ifdef LOG_LOCAL2
+ else if (!strcasecmp(cp2, "LOCAL2")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL2;
+ }
+#endif /* LOG_LOCAL2 */
+#ifdef LOG_LOCAL3
+ else if (!strcasecmp(cp2, "LOCAL3")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL3;
+ }
+#endif /* LOG_LOCAL3 */
+#ifdef LOG_LOCAL4
+ else if (!strcasecmp(cp2, "LOCAL4")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL4;
+ }
+#endif /* LOG_LOCAL4 */
+#ifdef LOG_LOCAL5
+ else if (!strcasecmp(cp2, "LOCAL5")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL5;
+ }
+#endif /* LOG_LOCAL5 */
+#ifdef LOG_LOCAL6
+ else if (!strcasecmp(cp2, "LOCAL6")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL6;
+ }
+#endif /* LOG_LOCAL6 */
+#ifdef LOG_LOCAL7
+ else if (!strcasecmp(cp2, "LOCAL7")) {
+ log_control.log_entries[i].lsu_facility = LOG_LOCAL7;
+ }
+#endif /* LOG_LOCAL7 */
+ cp2--;
+ *cp2 = savec;
+ }
+ }
+ if (!error) {
+ log_control.log_entries[i].log_type = K_LOG_SYSLOG;
+ do_openlog = 1;
+ log_facility = log_control.log_entries[i].lsu_facility;
+ }
+ }
+#endif /* HAVE_SYSLOG */
+ /*
+ * Is this a standard error specification?
+ */
+ else if (!strcasecmp(cp, "STDERR")) {
+ if (log_control.log_entries[i].lfu_filep =
+ fdopen(fileno(stderr), "a+")) {
+ log_control.log_entries[i].log_type = K_LOG_STDERR;
+ log_control.log_entries[i].lfu_fname =
+ "standard error";
+ }
+ }
+ /*
+ * Is this a specification of the console?
+ */
+ else if (!strcasecmp(cp, "CONSOLE")) {
+ if (log_control.log_entries[i].ldu_filep =
+ CONSOLE_OPEN("a+")) {
+ log_control.log_entries[i].log_type = K_LOG_CONSOLE;
+ log_control.log_entries[i].ldu_devname = "console";
+ }
+ }
+ /*
+ * Is this a specification of a device?
+ */
+ else if (!strncasecmp(cp, "DEVICE", 6)) {
+ /*
+ * We handle devices very similarly to files.
+ */
+ if (cp[6] == '=') {
+ if (log_control.log_entries[i].ldu_filep =
+ DEVICE_OPEN(&cp[7], "w")) {
+ log_control.log_entries[i].log_type = K_LOG_DEVICE;
+ log_control.log_entries[i].ldu_devname = &cp[7];
+ }
+ }
+ }
+ /*
+ * See if we successfully parsed this specification.
+ */
+ if (log_control.log_entries[i].log_type == K_LOG_NONE) {
+ fprintf(stderr, lspec_parse_err_1, whoami, cp);
+ fprintf(stderr, lspec_parse_err_2, whoami);
+ }
+ else
+ ngood++;
+ }
+ }
+ /*
+ * If we didn't find anything, then free our lists.
+ */
+ if (ngood == 0) {
+ for (i=0; i<log_control.log_nentries; i++)
+ free(logging_specs[i]);
+ }
+ free(logging_specs);
+ }
+ /*
+ * If we didn't find anything, go for the default which is to log to
+ * the system log.
+ */
+ if (ngood == 0) {
+ if (log_control.log_entries)
+ free(log_control.log_entries);
+ log_control.log_entries = &def_log_entry;
+ log_control.log_entries->log_type = K_LOG_SYSLOG;
+ log_control.log_entries->log_2free = (krb5_pointer) NULL;
+ log_control.log_entries->lsu_facility = LOG_AUTH;
+ log_control.log_entries->lsu_severity = LOG_ERR;
+ log_control.log_nentries = 1;
+ }
+ if (log_control.log_nentries) {
+ if (log_control.log_whoami = (char *) malloc(strlen(whoami)+1))
+ strcpy(log_control.log_whoami, whoami);
+ if (log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN))
+ gethostname(log_control.log_hostname, MAXHOSTNAMELEN);
+#ifdef HAVE_OPENLOG
+ if (do_openlog) {
+ openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
+ log_control.log_opened = 1;
+ }
+#endif /* HAVE_OPENLOG */
+ if (do_com_err)
+ (void) set_com_err_hook(klog_com_err_proc);
+ }
+ return((log_control.log_nentries) ? 0 : ENOENT);
+}
+
+/*
+ * krb5_klog_close() - Close the logging context and free all data.
+ */
+void
+krb5_klog_close(kcontext)
+ krb5_context kcontext;
+{
+ int lindex;
+ (void) reset_com_err_hook();
+ for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+ switch (log_control.log_entries[lindex].log_type) {
+ case K_LOG_FILE:
+ case K_LOG_STDERR:
+ /*
+ * Files/standard error.
+ */
+ fclose(log_control.log_entries[lindex].lfu_filep);
+ break;
+ case K_LOG_CONSOLE:
+ case K_LOG_DEVICE:
+ /*
+ * Devices (may need special handling)
+ */
+ DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
+ break;
+#ifdef HAVE_SYSLOG
+ case K_LOG_SYSLOG:
+ /*
+ * System log.
+ */
+ break;
+#endif /* HAVE_SYSLOG */
+ default:
+ break;
+ }
+ if (log_control.log_entries[lindex].log_2free)
+ free(log_control.log_entries[lindex].log_2free);
+ }
+ if (log_control.log_entries != &def_log_entry)
+ free(log_control.log_entries);
+ log_control.log_entries = (struct log_entry *) NULL;
+ log_control.log_nentries = 0;
+ if (log_control.log_whoami)
+ free(log_control.log_whoami);
+ log_control.log_whoami = (char *) NULL;
+ if (log_control.log_hostname)
+ free(log_control.log_hostname);
+ log_control.log_hostname = (char *) NULL;
+#ifdef HAVE_CLOSELOG
+ if (log_control.log_opened)
+ closelog();
+#endif /* HAVE_CLOSELOG */
+}
+
+/*
+ * severity2string() - Convert a severity to a string.
+ */
+static char *
+severity2string(severity)
+ int severity;
+{
+ int s;
+ const char *ss;
+
+ s = severity & LOG_PRIMASK;
+ ss = log_ufo_string;
+ switch (s) {
+#ifdef LOG_EMERG
+ case LOG_EMERG:
+ ss = log_emerg_string;
+ break;
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
+ case LOG_ALERT:
+ ss = log_alert_string;
+ break;
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
+ case LOG_CRIT:
+ ss = log_crit_string;
+ break;
+#endif /* LOG_CRIT */
+ case LOG_ERR:
+ ss = log_err_string;
+ break;
+#ifdef LOG_WARNING
+ case LOG_WARNING:
+ ss = log_warning_string;
+ break;
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
+ case LOG_NOTICE:
+ ss = log_notice_string;
+ break;
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
+ case LOG_INFO:
+ ss = log_info_string;
+ break;
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
+ case LOG_DEBUG:
+ ss = log_debug_string;
+ break;
+#endif /* LOG_DEBUG */
+ }
+ return((char *) ss);
+}
+
+/*
+ * krb5_klog_syslog() - Simulate the calling sequence of syslog(3), while
+ * also performing the logging redirection as specified
+ * by krb5_klog_init().
+ */
+static int
+klog_vsyslog(priority, format, arglist)
+ int priority;
+ const char *format;
+ va_list arglist;
+{
+ char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
+ int lindex;
+ char *syslogp;
+ char *cp;
+ time_t now;
+#ifdef HAVE_STRFTIME
+ size_t soff;
+#endif /* HAVE_STRFTIME */
+
+ /*
+ * Format a syslog-esque message of the format:
+ *
+ * (verbose form)
+ * <date> <hostname> <id>[<pid>](<priority>): <message>
+ *
+ * (short form)
+ * <date> <message>
+ */
+ cp = outbuf;
+ (void) time(&now);
+#ifdef HAVE_STRFTIME
+ /*
+ * Format the date: mon dd hh:mm:ss
+ */
+ soff = strftime(outbuf, sizeof(outbuf), "%b %d %H:%M:%S", localtime(&now));
+ if (soff > 0)
+ cp += soff;
+ else
+ return(-1);
+#else /* HAVE_STRFTIME */
+ /*
+ * Format the date:
+ * We ASSUME here that the output of ctime is of the format:
+ * dow mon dd hh:mm:ss tzs yyyy\n
+ * 012345678901234567890123456789
+ */
+ strncpy(outbuf, ctime(&now) + 4, 15);
+ cp += 15;
+#endif /* HAVE_STRFTIME */
+#ifdef VERBOSE_LOGS
+ sprintf(cp, " %s %s[%d](%s): ",
+ log_control.log_hostname, log_control.log_whoami, getpid(),
+ severity2string(priority));
+#else
+ sprintf(cp, " ");
+#endif
+ syslogp = &outbuf[strlen(outbuf)];
+
+ /* Now format the actual message */
+#ifdef HAVE_VSPRINTF
+ vsprintf(syslogp, format, arglist);
+#else /* HAVE_VSPRINTF */
+ sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1],
+ ((int *) arglist)[2], ((int *) arglist)[3],
+ ((int *) arglist)[4], ((int *) arglist)[5]);
+#endif /* HAVE_VSPRINTF */
+
+ /*
+ * Now that we have the message formatted, perform the output to each
+ * logging specification.
+ */
+ for (lindex = 0; lindex < log_control.log_nentries; lindex++) {
+ switch (log_control.log_entries[lindex].log_type) {
+ case K_LOG_FILE:
+ case K_LOG_STDERR:
+ /*
+ * Files/standard error.
+ */
+ if (fprintf(log_control.log_entries[lindex].lfu_filep,
+ outbuf) < 0) {
+ /* Attempt to report error */
+ fprintf(stderr, log_file_err,
+ log_control.log_entries[lindex].lfu_fname);
+ }
+ else {
+ fprintf(log_control.log_entries[lindex].lfu_filep, "\n");
+ fflush(log_control.log_entries[lindex].lfu_filep);
+ }
+ break;
+ case K_LOG_CONSOLE:
+ case K_LOG_DEVICE:
+ /*
+ * Devices (may need special handling)
+ */
+ if (DEVICE_PRINT(log_control.log_entries[lindex].ldu_filep,
+ outbuf) < 0) {
+ /* Attempt to report error */
+ fprintf(stderr, log_device_err,
+ log_control.log_entries[lindex].ldu_devname);
+ }
+ break;
+#ifdef HAVE_SYSLOG
+ case K_LOG_SYSLOG:
+ /*
+ * System log.
+ */
+
+ /* Log the message with our header trimmed off */
+ syslog(priority, syslogp);
+ break;
+#endif /* HAVE_SYSLOG */
+ default:
+ break;
+ }
+ }
+ return(0);
+}
+
+#ifdef HAVE_STDARG_H
+int
+krb5_klog_syslog(int priority, const char *format, ...)
+#else /* HAVE_STDARG_H */
+int
+krb5_klog_syslog(priority, format, va_alist)
+ int priority;
+ const char *format;
+ va_dcl
+#endif /* HAVE_STDARG_H */
+{
+ int retval;
+ va_list pvar;
+
+#ifdef HAVE_STDARG_H
+ va_start(pvar, format);
+#else /* HAVE_STDARG_H */
+ va_start(pvar);
+#endif /* HAVE_STDARG_H */
+ retval = klog_vsyslog(priority, format, pvar);
+ va_end(pvar);
+ return(retval);
+}
+#endif /* !defined(_MSDOS) */
diff --git a/src/lib/kadm5/misc_free.c b/src/lib/kadm5/misc_free.c
new file mode 100644
index 000000000..cfe28a411
--- /dev/null
+++ b/src/lib/kadm5/misc_free.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+#include <kadm5/admin.h>
+#include <malloc.h>
+#include "server_internal.h"
+
+kadm5_ret_t
+kadm5_free_policy_ent(void *server_handle, kadm5_policy_ent_t val)
+{
+ kadm5_server_handle_t handle = server_handle;
+
+ _KADM5_CHECK_HANDLE(server_handle);
+
+ if(val) {
+ if (val->policy)
+ free(val->policy);
+ if (handle->api_version == KADM5_API_VERSION_1)
+ free(val);
+ }
+ return KADM5_OK;
+}
+
+kadm5_ret_t
+ kadm5_free_name_list(void *server_handle, char **names, int count)
+{
+ _KADM5_CHECK_HANDLE(server_handle);
+
+ while (count--)
+ free(names[count]);
+ free(names);
+}
+
+
+/* XXX this ought to be in libkrb5.a, but isn't */
+kadm5_ret_t krb5_free_key_data_contents(context, key)
+ krb5_context context;
+ krb5_key_data *key;
+{
+ int i, idx;
+
+ idx = (key->key_data_ver == 1 ? 1 : 2);
+ for (i = 0; i < idx; i++) {
+ if (key->key_data_contents[i]) {
+ memset(key->key_data_contents[i], 0, key->key_data_length[i]);
+ free(key->key_data_contents[i]);
+ }
+ }
+}
+
+kadm5_ret_t
+kadm5_free_principal_ent(void *server_handle,
+ kadm5_principal_ent_t val)
+{
+ kadm5_server_handle_t handle = server_handle;
+ int i;
+
+ _KADM5_CHECK_HANDLE(server_handle);
+
+ if(val) {
+ if(val->principal)
+ krb5_free_principal(handle->context, val->principal);
+ if(val->mod_name)
+ krb5_free_principal(handle->context, val->mod_name);
+ if(val->policy)
+ free(val->policy);
+ if (handle->api_version > KADM5_API_VERSION_1) {
+ if (val->n_key_data) {
+ for (i = 0; i < val->n_key_data; i++)
+ krb5_free_key_data_contents(handle->context,
+ &val->key_data[i]);
+ free(val->key_data);
+ }
+ if (val->tl_data) {
+ krb5_tl_data *tl;
+
+ while (val->tl_data) {
+ tl = val->tl_data->tl_data_next;
+ free(val->tl_data->tl_data_contents);
+ free(val->tl_data);
+ val->tl_data = tl;
+ }
+ }
+ }
+
+ if (handle->api_version == KADM5_API_VERSION_1)
+ free(val);
+ }
+ return KADM5_OK;
+}
diff --git a/src/lib/kadm5/ovsec_glue.c b/src/lib/kadm5/ovsec_glue.c
new file mode 100644
index 000000000..6118282df
--- /dev/null
+++ b/src/lib/kadm5/ovsec_glue.c
@@ -0,0 +1,188 @@
+#define USE_KADM5_API_VERSION 1
+#include <kadm5/admin.h>
+
+ovsec_kadm_ret_t ovsec_kadm_init_with_password(char *client_name, char *pass,
+ char *service_name,
+ char *realm,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return kadm5_init_with_password(client_name, pass, service_name,
+ realm, struct_version, api_version,
+ server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_init_with_skey(char *client_name, char *keytab,
+ char *service_name,
+ char *realm,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return kadm5_init_with_skey(client_name, keytab, service_name, realm,
+ struct_version, api_version,
+ server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_init(char *client_name, char *from_stash,
+ char *service_name,
+ char *realm,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return kadm5_init(client_name, from_stash, service_name,
+ realm, struct_version, api_version,
+ server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_destroy(void *server_handle)
+{
+ return kadm5_destroy(server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_flush(void *server_handle)
+{
+ return kadm5_flush(server_handle);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_create_principal(void *server_handle,
+ ovsec_kadm_principal_ent_t entry,
+ long mask,
+ char *password)
+{
+ return kadm5_create_principal(server_handle,
+ (kadm5_principal_ent_t)
+ entry, mask, password);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_delete_principal(void *server_handle,
+ krb5_principal principal)
+{
+ return kadm5_delete_principal(server_handle, principal);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_modify_principal(void *server_handle,
+ ovsec_kadm_principal_ent_t entry,
+ long mask)
+{
+ return kadm5_modify_principal(server_handle,
+ (kadm5_principal_ent_t) entry, mask);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_rename_principal(void *server_handle,
+ krb5_principal source,
+ krb5_principal target)
+{
+ return kadm5_rename_principal(server_handle, source, target);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_principal(void *server_handle,
+ krb5_principal principal,
+ ovsec_kadm_principal_ent_t *entry)
+{
+ return kadm5_get_principal(server_handle, principal,
+ (kadm5_principal_ent_t *) entry);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_chpass_principal(void *server_handle,
+ krb5_principal principal,
+ char *password)
+{
+ return kadm5_chpass_principal(server_handle, principal, password);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_chpass_principal_util(void *server_handle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret)
+{
+ return kadm5_chpass_principal_util(server_handle, princ, new_pw,
+ ret_pw, msg_ret);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_randkey_principal(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock **key)
+{
+ return kadm5_randkey_principal(server_handle, principal, key);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_create_policy(void *server_handle,
+ ovsec_kadm_policy_ent_t entry,
+ long mask)
+{
+ return kadm5_create_policy(server_handle,
+ (kadm5_policy_ent_t) entry, mask);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_delete_policy(void *server_handle,
+ ovsec_kadm_policy_t name)
+{
+ return kadm5_delete_policy(server_handle, (kadm5_policy_t) name);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_modify_policy(void *server_handle,
+ ovsec_kadm_policy_ent_t entry,
+ long mask)
+{
+ return kadm5_modify_policy(server_handle,
+ (kadm5_policy_ent_t) entry, mask);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_get_policy(void *server_handle,
+ ovsec_kadm_policy_t name,
+ ovsec_kadm_policy_ent_t *entry)
+{
+ return kadm5_get_policy(server_handle, (kadm5_policy_t) name,
+ (kadm5_policy_ent_t *) entry);
+}
+
+
+ovsec_kadm_ret_t ovsec_kadm_free_policy_ent(void *server_handle,
+ ovsec_kadm_policy_ent_t val)
+{
+ return kadm5_free_policy_ent(server_handle, (kadm5_policy_ent_t) val);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_free_name_list(void *server_handle,
+ char **names, int count)
+{
+ return kadm5_free_name_list(server_handle, names, count);
+}
+
+ovsec_kadm_ret_t
+ovsec_kadm_free_principal_ent(void *server_handle,
+ ovsec_kadm_principal_ent_t val)
+{
+ return kadm5_free_principal_ent(server_handle,
+ (kadm5_principal_ent_t) val);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_privs(void *server_handle, long *privs)
+{
+ return kadm5_get_privs(server_handle, privs);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_principals(void *server_handle,
+ char *exp,
+ char ***princs,
+ int *count)
+{
+ return kadm5_get_principals(server_handle, exp, princs, count);
+}
+
+ovsec_kadm_ret_t ovsec_kadm_get_policies(void *server_handle,
+ char *exp,
+ char ***pols,
+ int *count)
+{
+ return kadm5_get_policies(server_handle, exp, pols, count);
+}
+
diff --git a/src/lib/kadm5/server_acl.c b/src/lib/kadm5/server_acl.c
new file mode 100644
index 000000000..16a7f4e40
--- /dev/null
+++ b/src/lib/kadm5/server_acl.c
@@ -0,0 +1,511 @@
+/*
+ * kadmin/v5server/srv_acl.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * srv_acl.c - Handle Kerberos ACL related functions.
+ */
+#include <stdio.h>
+#include <sys/param.h>
+#include <gssapi/gssapi_generic.h>
+#include "k5-int.h"
+#include "server_acl.h"
+#include <kadm5/server_internal.h>
+
+typedef struct _acl_op_table {
+ char ao_op;
+ krb5_int32 ao_mask;
+} aop_t;
+
+typedef struct _acl_entry {
+ struct _acl_entry *ae_next;
+ char *ae_name;
+ krb5_boolean ae_name_bad;
+ krb5_principal ae_principal;
+ krb5_int32 ae_op_allowed;
+ char *ae_target;
+ krb5_boolean ae_target_bad;
+ krb5_principal ae_target_princ;
+} aent_t;
+
+static const aop_t acl_op_table[] = {
+ { 'a', ACL_ADD },
+ { 'd', ACL_DELETE },
+ { 'm', ACL_MODIFY },
+ { 'c', ACL_CHANGEPW },
+ { 'i', ACL_INQUIRE },
+ { 'l', ACL_LIST },
+ { 'x', ACL_ALL_MASK },
+ { '*', ACL_ALL_MASK },
+ { '\0', 0 }
+};
+
+static aent_t *acl_list_head = (aent_t *) NULL;
+static aent_t *acl_list_tail = (aent_t *) NULL;
+
+static const char *acl_acl_file = (char *) NULL;
+static int acl_inited = 0;
+static int acl_debug_level = 0;
+/*
+ * This is the catchall entry. If nothing else appropriate is found, or in
+ * the case where the ACL file is not present, this entry controls what can
+ * be done.
+ */
+static const char *acl_catchall_entry = NULL;
+
+static const char *acl_line2long_msg = "%s: line %d too long, truncated\n";
+static const char *acl_op_bad_msg = "Unrecognized ACL operation '%c' in %s\n";
+static const char *acl_syn_err_msg = "%s: syntax error at line %d <%10s...>\n";
+static const char *acl_cantopen_msg = "\007cannot open ACL file";
+
+/*
+ * acl_get_line() - Get a line from the ACL file.
+ */
+static char *
+acl_get_line(fp, lnp)
+ FILE *fp;
+ int *lnp;
+{
+ int i, domore;
+ static char acl_buf[BUFSIZ];
+
+ for (domore = 1; domore && !feof(fp); ) {
+ /* Copy in the line */
+ for (i=0;
+ ((i<BUFSIZ) &&
+ (!feof(fp)) &&
+ ((acl_buf[i] = fgetc(fp)) != '\n'));
+ i++);
+
+ /* Check if we exceeded our buffer size */
+ if ((i == BUFSIZ) && (!feof(fp)) && (acl_buf[i] != '\n')) {
+ fprintf(stderr, acl_line2long_msg, acl_acl_file, *lnp);
+ while (fgetc(fp) != '\n');
+ }
+ acl_buf[i] = '\0';
+ if (acl_buf[0] == (char) EOF) /* ptooey */
+ acl_buf[0] = '\0';
+ else
+ (*lnp)++;
+ if ((acl_buf[0] != '#') && (acl_buf[0] != '\0'))
+ domore = 0;
+ }
+ if (domore || (strlen(acl_buf) == 0))
+ return((char *) NULL);
+ else
+ return(acl_buf);
+}
+
+/*
+ * acl_parse_line() - Parse the contents of an ACL line.
+ */
+static aent_t *
+acl_parse_line(lp)
+ char *lp;
+{
+ static char acle_principal[BUFSIZ];
+ static char acle_ops[BUFSIZ];
+ static char acle_object[BUFSIZ];
+ aent_t *acle;
+ char *op;
+ int t, found, opok, nmatch;
+
+ DPRINT(DEBUG_CALLS, acl_debug_level,
+ ("* acl_parse_line(line=%20s)\n", lp));
+ /*
+ * Format is very simple:
+ * entry ::= <whitespace> <principal> <whitespace> <opstring> <whitespace>
+ * [<target> <whitespace>]
+ */
+ acle = (aent_t *) NULL;
+ acle_object[0] = '\0';
+ nmatch = sscanf(lp, "%s %s %s", acle_principal, acle_ops, acle_object);
+ if (nmatch >= 2) {
+ acle = (aent_t *) malloc(sizeof(aent_t));
+ if (acle) {
+ acle->ae_next = (aent_t *) NULL;
+ acle->ae_op_allowed = (krb5_int32) 0;
+ acle->ae_target =
+ (nmatch >= 3) ? strdup(acle_object) : (char *) NULL;
+ acle->ae_target_bad = 0;
+ acle->ae_target_princ = (krb5_principal) NULL;
+ opok = 1;
+ for (op=acle_ops; *op; op++) {
+ char rop;
+
+ rop = (isupper(*op)) ? tolower(*op) : *op;
+ found = 0;
+ for (t=0; acl_op_table[t].ao_op; t++) {
+ if (rop == acl_op_table[t].ao_op) {
+ found = 1;
+ if (rop == *op)
+ acle->ae_op_allowed |= acl_op_table[t].ao_mask;
+ else
+ acle->ae_op_allowed &= ~acl_op_table[t].ao_mask;
+ }
+ }
+ if (!found) {
+ fprintf(stderr, acl_op_bad_msg, *op, lp);
+ opok = 0;
+ }
+ }
+ if (opok) {
+ acle->ae_name = (char *) malloc(strlen(acle_principal)+1);
+ if (acle->ae_name) {
+ strcpy(acle->ae_name, acle_principal);
+ acle->ae_principal = (krb5_principal) NULL;
+ acle->ae_name_bad = 0;
+ DPRINT(DEBUG_ACL, acl_debug_level,
+ ("A ACL entry %s -> opmask %x\n",
+ acle->ae_name, acle->ae_op_allowed));
+ }
+ else {
+ if (acle->ae_target)
+ free(acle->ae_target);
+ free(acle);
+ acle = (aent_t *) NULL;
+ }
+ }
+ else {
+ if (acle->ae_target)
+ free(acle->ae_target);
+ free(acle);
+ acle = (aent_t *) NULL;
+ }
+ }
+ }
+ DPRINT(DEBUG_CALLS, acl_debug_level,
+ ("X acl_parse_line() = %x\n", (long) acle));
+ return(acle);
+}
+
+/*
+ * acl_free_entries() - Free all ACL entries.
+ */
+static void
+acl_free_entries()
+{
+ aent_t *ap;
+ aent_t *np;
+
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_free_entries()\n"));
+ for (ap=acl_list_head; ap; ap = np) {
+ if (ap->ae_name)
+ free(ap->ae_name);
+ if (ap->ae_principal)
+ krb5_free_principal((krb5_context) NULL, ap->ae_principal);
+ if (ap->ae_target)
+ free(ap->ae_target);
+ if (ap->ae_target_princ)
+ krb5_free_principal((krb5_context) NULL, ap->ae_target_princ);
+ np = ap->ae_next;
+ free(ap);
+ }
+ acl_list_head = acl_list_tail = (aent_t *) NULL;
+ acl_inited = 0;
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_free_entries()\n"));
+}
+
+/*
+ * acl_load_acl_file() - Open and parse the ACL file.
+ */
+static int
+acl_load_acl_file()
+{
+char tmpbuf[10];
+ FILE *afp;
+ char *alinep;
+ aent_t **aentpp;
+ int alineno;
+ int retval = 1;
+
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_load_acl_file()\n"));
+ /* Open the ACL file for read */
+ if (afp = fopen(acl_acl_file, "r")) {
+ alineno = 1;
+ aentpp = &acl_list_head;
+
+ /* Get a non-comment line */
+ while (alinep = acl_get_line(afp, &alineno)) {
+ /* Parse it */
+ *aentpp = acl_parse_line(alinep);
+ /* If syntax error, then fall out */
+ if (!*aentpp) {
+ fprintf(stderr, acl_syn_err_msg,
+ acl_acl_file, alineno, alinep);
+ retval = 0;
+ break;
+ }
+ acl_list_tail = *aentpp;
+ aentpp = &(*aentpp)->ae_next;
+ }
+
+ if (acl_catchall_entry) {
+ strcpy(tmpbuf, acl_catchall_entry);
+ if (*aentpp = acl_parse_line(tmpbuf)) {
+ acl_list_tail = *aentpp;
+ }
+ else {
+ retval = 0;
+ DPRINT(DEBUG_OPERATION, acl_debug_level,
+ ("> catchall acl entry (%s) load failed\n",
+ acl_catchall_entry));
+ }
+ fclose(afp);
+ }
+ }
+ else {
+ com_err(acl_acl_file, errno, acl_cantopen_msg);
+ if (acl_list_head = acl_parse_line(acl_catchall_entry)) {
+ acl_list_tail = acl_list_head;
+ }
+ else {
+ retval = 0;
+ DPRINT(DEBUG_OPERATION, acl_debug_level,
+ ("> catchall acl entry (%s) load failed\n",
+ acl_catchall_entry));
+ }
+ }
+
+ if (!retval) {
+ acl_free_entries();
+ }
+ DPRINT(DEBUG_CALLS, acl_debug_level,
+ ("X acl_load_acl_file() = %d\n", retval));
+ return(retval);
+}
+
+/*
+ * acl_match_data() - See if two data entries match.
+ *
+ * Wildcarding is only supported for a whole component.
+ */
+static krb5_boolean
+acl_match_data(e1, e2)
+ krb5_data *e1, *e2;
+{
+ krb5_boolean retval;
+
+ DPRINT(DEBUG_CALLS, acl_debug_level,
+ ("* acl_match_entry(%s, %s)\n", e1->data, e2->data));
+ retval = 0;
+ if (!strncmp(e1->data, "*", e1->length) ||
+ !strncmp(e2->data, "*", e2->length)) {
+ retval = 1;
+ }
+ else {
+ if ((e1->length == e2->length) &&
+ (!strncmp(e1->data, e2->data, e1->length)))
+ retval = 1;
+ }
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_match_entry()=%d\n",retval));
+ return(retval);
+}
+
+/*
+ * acl_find_entry() - Find a matching entry.
+ */
+static aent_t *
+acl_find_entry(kcontext, principal, dest_princ)
+ krb5_context kcontext;
+ krb5_principal principal;
+ krb5_principal dest_princ;
+{
+ aent_t *entry;
+ krb5_error_code kret;
+ int i;
+ int matchgood;
+
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_find_entry()\n"));
+ for (entry=acl_list_head; entry; entry = entry->ae_next) {
+ if (!strcmp(entry->ae_name, "*")) {
+ DPRINT(DEBUG_ACL, acl_debug_level, ("A wildcard ACL match\n"));
+ break;
+ }
+ if (!entry->ae_principal && !entry->ae_name_bad) {
+ kret = krb5_parse_name(kcontext,
+ entry->ae_name,
+ &entry->ae_principal);
+ if (kret)
+ entry->ae_name_bad = 1;
+ }
+ if (entry->ae_name_bad) {
+ DPRINT(DEBUG_ACL, acl_debug_level,
+ ("A Bad ACL entry %s\n", entry->ae_name));
+ continue;
+ }
+ if (entry->ae_target &&
+ !entry->ae_target_princ &&
+ !entry->ae_target_bad) {
+ kret = krb5_parse_name(kcontext,
+ entry->ae_target,
+ &entry->ae_target_princ);
+ if (kret)
+ entry->ae_target_bad = 1;
+ }
+ if (entry->ae_target_bad) {
+ DPRINT(DEBUG_ACL, acl_debug_level,
+ ("A Bad target in an ACL entry for %s\n", entry->ae_name));
+ entry->ae_name_bad = 1;
+ continue;
+ }
+ matchgood = 0;
+ if (acl_match_data(&entry->ae_principal->realm,
+ &principal->realm) &&
+ (entry->ae_principal->length == principal->length)) {
+ matchgood = 1;
+ for (i=0; i<principal->length; i++) {
+ if (!acl_match_data(&entry->ae_principal->data[i],
+ &principal->data[i])) {
+ matchgood = 0;
+ break;
+ }
+ }
+ }
+ if (!matchgood)
+ continue;
+
+ /* We've matched the principal. If we have a target, then try it */
+ if (entry->ae_target && entry->ae_target_princ && dest_princ) {
+ if (acl_match_data(&entry->ae_target_princ->realm,
+ &dest_princ->realm) &&
+ (entry->ae_target_princ->length == dest_princ->length)) {
+ for (i=0; i<dest_princ->length; i++) {
+ if (!acl_match_data(&entry->ae_target_princ->data[i],
+ &dest_princ->data[i])) {
+ matchgood = 0;
+ break;
+ }
+ }
+ }
+ else
+ matchgood = 0;
+ }
+
+ if (matchgood)
+ break;
+ }
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_find_entry()=%x\n",entry));
+ return(entry);
+}
+
+/*
+ * acl_init() - Initialize ACL context.
+ */
+krb5_error_code
+acl_init(kcontext, debug_level, acl_file)
+ krb5_context kcontext;
+ int debug_level;
+ char *acl_file;
+{
+ krb5_error_code kret;
+
+ kret = 0;
+ acl_debug_level = debug_level;
+ DPRINT(DEBUG_CALLS, acl_debug_level,
+ ("* acl_init(afile=%s)\n",
+ ((acl_file) ? acl_file : "(null)")));
+ acl_acl_file = (acl_file) ? acl_file : (char *) KRB5_DEFAULT_ADMIN_ACL;
+ acl_inited = acl_load_acl_file();
+
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_init() = %d\n", kret));
+ return(kret);
+}
+
+/*
+ * acl_finish - Terminate ACL context.
+ */
+void
+acl_finish(kcontext, debug_level)
+ krb5_context kcontext;
+ int debug_level;
+{
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_finish()\n"));
+ acl_free_entries();
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_finish()\n"));
+}
+
+/*
+ * acl_op_permitted() - Is this operation permitted for this principal?
+ * this code used not to be based on gssapi. In order
+ * to minimize porting hassles, I've put all the
+ * gssapi hair in this function. This might not be
+ * the best medium-term solution. (The best long-term
+ * solution is, of course, a real authorization service.)
+ */
+krb5_boolean
+acl_check(kcontext, caller, opmask, principal)
+ krb5_context kcontext;
+ gss_name_t caller;
+ krb5_int32 opmask;
+ krb5_principal principal;
+{
+ krb5_boolean retval;
+ aent_t *aentry;
+ gss_buffer_desc caller_buf;
+ gss_OID caller_oid;
+ OM_uint32 emaj, emin;
+ krb5_error_code code;
+ krb5_principal caller_princ;
+
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n"));
+
+ if (GSS_ERROR(emaj = gss_display_name(&emin, caller, &caller_buf,
+ &caller_oid)))
+ return(0);
+
+ code = krb5_parse_name(kcontext, (char *) caller_buf.value,
+ &caller_princ);
+
+ gss_release_buffer(&emin, &caller_buf);
+
+ if (code)
+ return(code);
+
+ retval = 0;
+ if (aentry = acl_find_entry(kcontext, caller_princ, principal)) {
+ if ((aentry->ae_op_allowed & opmask) == opmask)
+ retval = 1;
+ }
+
+ krb5_free_principal(kcontext, caller_princ);
+
+ DPRINT(DEBUG_CALLS, acl_debug_level, ("X acl_op_permitted()=%d\n",
+ retval));
+ return(retval);
+}
+
+kadm5_ret_t kadm5_get_privs(void *server_handle, long *privs)
+{
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ /* this is impossible to do with the current interface. For now,
+ return all privs, which will confuse some clients, but not
+ deny any access to users of "smart" clients which try to cache */
+
+ *privs = ~0;
+
+ return KADM5_OK;
+}
diff --git a/src/lib/kadm5/server_acl.h b/src/lib/kadm5/server_acl.h
new file mode 100644
index 000000000..9dfc8daba
--- /dev/null
+++ b/src/lib/kadm5/server_acl.h
@@ -0,0 +1,81 @@
+/*
+ * kadmin/v5server/kadm5_defs.h
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+#ifndef SERVER_ACL_H__
+#define SERVER_ACL_H__
+
+/*
+ * Debug definitions.
+ */
+#define DEBUG_SPROC 1
+#define DEBUG_OPERATION 2
+#define DEBUG_HOST 4
+#define DEBUG_REALM 8
+#define DEBUG_REQUESTS 16
+#define DEBUG_ACL 32
+#define DEBUG_PROTO 64
+#define DEBUG_CALLS 128
+#define DEBUG_NOSLAVES 256
+#ifdef DEBUG
+#define DPRINT(l1, cl, al) if ((cl & l1) != 0) xprintf al
+#else /* DEBUG */
+#define DPRINT(l1, cl, al)
+#endif /* DEBUG */
+#define DLOG(l1, cl, msg) if ((cl & l1) != 0) \
+ com_err(programname, 0, msg)
+
+/*
+ * Access control bits.
+ */
+#define ACL_ADD 1
+#define ACL_DELETE 2
+#define ACL_MODIFY 4
+#define ACL_CHANGEPW 8
+/* #define ACL_CHANGE_OWN_PW 16 */
+#define ACL_INQUIRE 32
+/* #define ACL_EXTRACT 64 */
+#define ACL_LIST 128
+#define ACL_RENAME (ACL_ADD+ACL_DELETE)
+
+#define ACL_ALL_MASK (ACL_ADD | \
+ ACL_DELETE | \
+ ACL_MODIFY | \
+ ACL_CHANGEPW | \
+ ACL_INQUIRE | \
+ ACL_LIST)
+
+krb5_error_code acl_init
+ KRB5_PROTOTYPE((krb5_context,
+ int,
+ char *));
+void acl_finish
+ KRB5_PROTOTYPE((krb5_context,
+ int));
+krb5_boolean acl_check
+ KRB5_PROTOTYPE((krb5_context,
+ gss_name_t,
+ krb5_int32,
+ krb5_principal));
+
+#endif /* SERVER_ACL_H__ */
diff --git a/src/lib/kadm5/server_dict.c b/src/lib/kadm5/server_dict.c
new file mode 100644
index 000000000..6c0bcef03
--- /dev/null
+++ b/src/lib/kadm5/server_dict.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <kadm5/admin.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include <memory.h>
+#include <syslog.h>
+#include "server_internal.h"
+
+static char **word_list = NULL; /* list of word pointers */
+static char *word_block = NULL; /* actual word data */
+static int word_count = 0; /* number of words */
+extern int errno;
+
+/*
+ * Function: word_compare
+ *
+ * Purpose: compare two words in the dictionary.
+ *
+ * Arguments:
+ * w1 (input) pointer to first word
+ * w2 (input) pointer to second word
+ * <return value> result of strcmp
+ *
+ * Requires:
+ * w1 and w2 to point to valid memory
+ *
+ */
+
+static int
+word_compare(const void *s1, const void *s2)
+{
+ return (strcasecmp(*(char **)s1, *(char **)s2));
+}
+
+/*
+ * Function: init-dict
+ *
+ * Purpose: Initialize in memory word dictionary
+ *
+ * Arguments:
+ * none
+ * <return value> KADM5_OK on sucsess errno on failure;
+ * (but success on ENOENT)
+ *
+ * Requires:
+ * If WORDFILE exists, it must contain a list of words,
+ * one word per-line.
+ *
+ * Effects:
+ * If WORDFILE exists, it is read into memory sorted for future
+ * use. If it does not exist, it syslogs an error message and returns
+ * success.
+ *
+ * Modifies:
+ * word_list to point to a chunck of allocated memory containing
+ * pointers to words
+ * word_block to contain the dictionary.
+ *
+ */
+
+int init_dict(kadm5_config_params *params)
+{
+ int fd,
+ len,
+ i;
+ char *p,
+ *t;
+ struct stat sb;
+
+ if(word_list != NULL && word_block != NULL)
+ return KADM5_OK;
+ if (! (params->mask & KADM5_CONFIG_DICT_FILE)) {
+ syslog(LOG_INFO, "No dictionary file specified, continuing "
+ "without one.");
+ return KADM5_OK;
+ }
+ if ((fd = open(params->dict_file, O_RDONLY)) == -1) {
+ if (errno == ENOENT) {
+ syslog(LOG_ERR, "WARNING! Cannot find dictionary file %s, "
+ "continuing without one.", params->dict_file);
+ return KADM5_OK;
+ } else
+ return errno;
+ }
+ if (fstat(fd, &sb) == -1)
+ return errno;
+ if ((word_block = (char *) malloc(sb.st_size + 1)) == NULL)
+ return errno;
+ if (read(fd, word_block, sb.st_size) != sb.st_size)
+ return errno;
+ (void) close(fd);
+ word_block[sb.st_size] = '\0';
+
+ p = word_block;
+ len = sb.st_size;
+ while(len > 0 && (t = memchr(p, '\n', len)) != NULL) {
+ *t = '\0';
+ len -= t - p + 1;
+ p = t + 1;
+ word_count++;
+ }
+ if ((word_list = (char **) malloc(word_count * sizeof(char *))) == NULL)
+ return errno;
+ p = word_block;
+ for (i = 0; i < word_count; i++) {
+ word_list[i] = p;
+ p += strlen(p) + 1;
+ }
+ qsort(word_list, word_count, sizeof(char *), word_compare);
+ return KADM5_OK;
+}
+
+/*
+ * Function: find_word
+ *
+ * Purpose: See if the specified word exists in the in-core dictionary
+ *
+ * Arguments:
+ * word (input) word to search for.
+ * <return value> WORD_NOT_FOUND if not in dictionary,
+ * KADM5_OK if if found word
+ * errno if init needs to be called and returns an
+ * error
+ *
+ * Requires:
+ * word to be a null terminated string.
+ * That word_list and word_block besetup
+ *
+ * Effects:
+ * finds word in dictionary.
+ * Modifies:
+ * nothing.
+ *
+ */
+
+int
+find_word(const char *word)
+{
+ char **value;
+
+ if(word_list == NULL || word_block == NULL)
+ return WORD_NOT_FOUND;
+ if ((value = (char **) bsearch(&word, word_list, word_count, sizeof(char *),
+ word_compare)) == NULL)
+ return WORD_NOT_FOUND;
+ else
+ return KADM5_OK;
+}
+
+/*
+ * Function: destroy_dict
+ *
+ * Purpose: destroy in-core copy of dictionary.
+ *
+ * Arguments:
+ * none
+ * <return value> none
+ * Requires:
+ * nothing
+ * Effects:
+ * frees up memory occupied by word_list and word_block
+ * sets count back to 0, and resets the pointers to NULL
+ *
+ * Modifies:
+ * word_list, word_block, and word_count.
+ *
+ */
+
+void
+destroy_dict(void)
+{
+ if(word_list) {
+ free(word_list);
+ word_list = NULL;
+ }
+ if(word_block) {
+ free(word_block);
+ word_block = NULL;
+ }
+ if(word_count)
+ word_count = 0;
+ return;
+}
diff --git a/src/lib/kadm5/server_handle.c b/src/lib/kadm5/server_handle.c
new file mode 100644
index 000000000..53abe94dd
--- /dev/null
+++ b/src/lib/kadm5/server_handle.c
@@ -0,0 +1,9 @@
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include "server_internal.h"
+
+int _kadm5_check_handle(void *handle)
+{
+ CHECK_HANDLE(handle);
+ return 0;
+}
diff --git a/src/lib/kadm5/server_init.c b/src/lib/kadm5/server_init.c
new file mode 100644
index 000000000..653f6d896
--- /dev/null
+++ b/src/lib/kadm5/server_init.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <com_err.h>
+#include <kadm5/admin.h>
+#include <krb5.h>
+#include "server_internal.h"
+
+/*
+ * Function check_handle
+ *
+ * Purpose: Check a server handle and return a com_err code if it is
+ * invalid or 0 if it is valid.
+ *
+ * Arguments:
+ *
+ * handle The server handle.
+ */
+
+static int check_handle(void *handle)
+{
+ CHECK_HANDLE(handle);
+ return 0;
+}
+
+kadm5_ret_t kadm5_init_with_password(char *client_name, char *pass,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ return kadm5_init(client_name, pass, service_name, params,
+ struct_version, api_version,
+ server_handle);
+}
+
+kadm5_ret_t kadm5_init_with_creds(char *client_name,
+ krb5_ccache ccache,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ /*
+ * A program calling init_with_creds *never* expects to prompt the
+ * user. Therefore, always pass a dummy password in case this is
+ * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and
+ * MKEY_FROM_KBD is non-zero, return an error.
+ */
+ if (api_version == KADM5_API_VERSION_2 && params &&
+ (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) &&
+ params->mkey_from_kbd)
+ return KADM5_BAD_SERVER_PARAMS;
+ return kadm5_init(client_name, NULL, service_name, params,
+ struct_version, api_version,
+ server_handle);
+}
+
+
+kadm5_ret_t kadm5_init_with_skey(char *client_name, char *keytab,
+ char *service_name,
+ kadm5_config_params *params,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ /*
+ * A program calling init_with_skey *never* expects to prompt the
+ * user. Therefore, always pass a dummy password in case this is
+ * KADM5_API_VERSION_1. If this is KADM5_API_VERSION_2 and
+ * MKEY_FROM_KBD is non-zero, return an error.
+ */
+ if (api_version == KADM5_API_VERSION_2 && params &&
+ (params->mask & KADM5_CONFIG_MKEY_FROM_KBD) &&
+ params->mkey_from_kbd)
+ return KADM5_BAD_SERVER_PARAMS;
+ return kadm5_init(client_name, NULL, service_name, params,
+ struct_version, api_version,
+ server_handle);
+}
+
+kadm5_ret_t kadm5_init(char *client_name, char *pass,
+ char *service_name,
+ kadm5_config_params *params_in,
+ krb5_ui_4 struct_version,
+ krb5_ui_4 api_version,
+ void **server_handle)
+{
+ int ret;
+ kadm5_server_handle_t handle;
+ kadm5_config_params params_local; /* for v1 compat */
+
+ if (! server_handle)
+ return EINVAL;
+
+ if (! client_name)
+ return EINVAL;
+
+ if (! (handle = (kadm5_server_handle_t) malloc(sizeof *handle)))
+ return ENOMEM;
+ memset(handle, 0, sizeof(*handle));
+
+ if (ret = (int) krb5_init_context(&(handle->context))) {
+ free(handle);
+ return(ret);
+ }
+
+ initialize_ovk_error_table();
+ initialize_adb_error_table();
+ initialize_ovku_error_table();
+ krb5_init_ets(handle->context);
+
+ handle->magic_number = KADM5_SERVER_HANDLE_MAGIC;
+ handle->struct_version = struct_version;
+ handle->api_version = api_version;
+
+ /*
+ * Verify the version numbers before proceeding; we can't use
+ * CHECK_HANDLE because not all fields are set yet.
+ */
+ GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION,
+ KADM5_NEW_SERVER_API_VERSION);
+
+ /*
+ * Acquire relevant profile entries. In version 2, merge values
+ * in params_in with values from profile, based on
+ * params_in->mask.
+ *
+ * In version 1, we've given a realm (which may be NULL) instead
+ * of params_in. So use that realm, make params_in contain an
+ * empty mask, and behave like version 2.
+ */
+ memset((char *) &params_local, 0, sizeof(params_local));
+ if (api_version == KADM5_API_VERSION_1) {
+ params_local.realm = (char *) params_in;
+ if (params_in)
+ params_local.mask = KADM5_CONFIG_REALM;
+ params_in = &params_local;
+ }
+
+#define ILLEGAL_PARAMS (KADM5_CONFIG_ADMIN_SERVER)
+ if (params_in && (params_in->mask & ILLEGAL_PARAMS)) {
+ krb5_free_context(handle->context);
+ free(handle);
+ return KADM5_BAD_SERVER_PARAMS;
+ }
+
+ if (ret = kadm5_get_config_params(handle->context,
+ (char *) NULL,
+ (char *) NULL,
+ params_in,
+ &handle->params)) {
+ krb5_free_context(handle->context);
+ free(handle);
+ return(ret);
+ }
+
+#define REQUIRED_PARAMS (KADM5_CONFIG_REALM | KADM5_CONFIG_DBNAME | \
+ KADM5_CONFIG_ADBNAME | \
+ KADM5_CONFIG_ADB_LOCKFILE | \
+ KADM5_CONFIG_ENCTYPE | \
+ KADM5_CONFIG_FLAGS | \
+ KADM5_CONFIG_MAX_LIFE | KADM5_CONFIG_MAX_RLIFE | \
+ KADM5_CONFIG_EXPIRATION | KADM5_CONFIG_ENCTYPES)
+
+ if ((handle->params.mask & REQUIRED_PARAMS) != REQUIRED_PARAMS) {
+ krb5_free_context(handle->context);
+ free(handle);
+ return KRB5_CONFIG_BADFORMAT;
+ }
+
+ /*
+ * Set the db_name based on configuration before calling
+ * krb5_db_init, so it will get used.
+ */
+ if (ret = krb5_dbm_db_set_name(handle->context,
+ handle->params.dbname)) {
+ free(handle);
+ return(ret);
+ }
+
+ if (ret = krb5_db_init(handle->context)) {
+ krb5_free_context(handle->context);
+ free(handle);
+ return(ret);
+ }
+
+ if ((ret = krb5_parse_name(handle->context, client_name,
+ &handle->current_caller))) {
+ krb5_db_fini(handle->context);
+ krb5_free_context(handle->context);
+ free(handle);
+ return ret;
+ }
+
+ if (! (handle->lhandle = malloc(sizeof(*handle)))) {
+ krb5_db_fini(handle->context);
+ krb5_free_context(handle->context);
+ free(handle);
+ return ENOMEM;
+ }
+ *handle->lhandle = *handle;
+ handle->lhandle->api_version = KADM5_API_VERSION_2;
+ handle->lhandle->struct_version = KADM5_STRUCT_VERSION;
+ handle->lhandle->lhandle = handle->lhandle;
+
+ /* can't check the handle until current_caller is set */
+ if (ret = check_handle((void *) handle)) {
+ free(handle);
+ return ret;
+ }
+
+ /*
+ * The KADM5_API_VERSION_1 spec said "If pass (or keytab) is NULL
+ * or an empty string, reads the master password from [the stash
+ * file]. Otherwise, the non-NULL password is ignored and the
+ * user is prompted for it via the tty." However, the code was
+ * implemented the other way: when a non-NULL password was
+ * provided, the stash file was used. This is somewhat more
+ * sensible, as then a local or remote client that provides a
+ * password does not prompt the user. This code maintains the
+ * previous actual behavior, and not the old spec behavior,
+ * because that is how the unit tests are written.
+ *
+ * In KADM5_API_VERSION_2, this decision is controlled by
+ * params.
+ *
+ * kdb_init_master's third argument is "from_keyboard".
+ */
+ if (ret = kdb_init_master(handle, handle->params.realm,
+ (handle->api_version == KADM5_API_VERSION_1 ?
+ ((pass == NULL) || !(strlen(pass))) :
+ ((handle->params.mask &
+ KADM5_CONFIG_MKEY_FROM_KBD) &&
+ handle->params.mkey_from_kbd))
+ )) {
+ krb5_db_fini(handle->context);
+ krb5_free_context(handle->context);
+ free(handle);
+ return ret;
+ }
+
+ if ((ret = kdb_init_hist(handle, handle->params.realm))) {
+ krb5_db_fini(handle->context);
+ krb5_free_context(handle->context);
+ free(handle);
+ return ret;
+ }
+
+ if (ret = init_dict(&handle->params)) {
+ krb5_db_fini(handle->context);
+ krb5_free_principal(handle->context, handle->current_caller);
+ krb5_free_context(handle->context);
+ free(handle);
+ return ret;
+ }
+
+ if (ret = adb_policy_init(handle)) {
+ krb5_db_fini(handle->context);
+ krb5_free_principal(handle->context, handle->current_caller);
+ krb5_free_context(handle->context);
+ free(handle);
+ return ret;
+ }
+ handle->lhandle->policy_db = handle->policy_db;
+
+ *server_handle = (void *) handle;
+
+ return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_destroy(void *server_handle)
+{
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ destroy_dict();
+
+ adb_policy_close(handle);
+ krb5_db_fini(handle->context);
+ krb5_free_principal(handle->context, handle->current_caller);
+ krb5_free_context(handle->context);
+ handle->magic_number = 0;
+ free(handle->lhandle);
+ free(handle);
+
+ return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_flush(void *server_handle)
+{
+ kadm5_server_handle_t handle = server_handle;
+ kadm5_ret_t ret;
+
+ CHECK_HANDLE(server_handle);
+
+ if ((ret = krb5_db_fini(handle->context)) ||
+ /*
+ * Set the db_name based on configuration before calling
+ * krb5_db_init, so it will get used.
+ */
+ (ret = krb5_dbm_db_set_name(handle->context,
+ handle->params.dbname)) ||
+ (ret = krb5_db_init(handle->context)) ||
+ (ret = adb_policy_close(handle)) ||
+ (ret = adb_policy_init(handle))) {
+ (void) kadm5_destroy(server_handle);
+ return ret;
+ }
+ return KADM5_OK;
+}
+
+int _kadm5_check_handle(void *handle)
+{
+ CHECK_HANDLE(handle);
+ return 0;
+}
diff --git a/src/lib/kadm5/server_internal.h b/src/lib/kadm5/server_internal.h
new file mode 100644
index 000000000..415f6d7d7
--- /dev/null
+++ b/src/lib/kadm5/server_internal.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+/*
+ * This header file is used internally by the Admin API server
+ * libraries and Admin server. IF YOU THINK YOU NEED TO USE THIS FILE
+ * FOR ANYTHING, YOU'RE ALMOST CERTAINLY WRONG.
+ */
+
+#ifndef __KADM5_SERVER_INTERNAL_H__
+#define __KADM5_SERVER_INTERNAL_H__
+
+#include <memory.h>
+#include <malloc.h>
+#include "k5-int.h"
+#include <krb5/kdb.h>
+#include <kadm5/admin.h>
+#include "admin_internal.h"
+#include "adb.h"
+
+typedef struct _kadm5_server_handle_t {
+ krb5_ui_4 magic_number;
+ krb5_ui_4 struct_version;
+ krb5_ui_4 api_version;
+ krb5_context context;
+ krb5_principal current_caller;
+ kadm5_config_params params;
+ struct _kadm5_server_handle_t *lhandle;
+ osa_adb_policy_t policy_db;
+} kadm5_server_handle_rec, *kadm5_server_handle_t;
+
+kadm5_ret_t adb_policy_init(kadm5_server_handle_t handle);
+kadm5_ret_t adb_policy_close(kadm5_server_handle_t handle);
+kadm5_ret_t passwd_check(kadm5_server_handle_t handle,
+ char *pass, int use_policy,
+ kadm5_policy_ent_t policy,
+ krb5_principal principal);
+kadm5_ret_t principal_exists(krb5_principal principal);
+krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
+ char *r, int from_keyboard);
+krb5_error_code kdb_init_hist(kadm5_server_handle_t handle,
+ char *r);
+krb5_error_code kdb_get_entry(kadm5_server_handle_t handle,
+ krb5_principal principal, krb5_db_entry *kdb,
+ osa_princ_ent_rec *adb);
+krb5_error_code kdb_free_entry(kadm5_server_handle_t handle,
+ krb5_db_entry *kdb, osa_princ_ent_rec *adb);
+krb5_error_code kdb_put_entry(kadm5_server_handle_t handle,
+ krb5_db_entry *kdb, osa_princ_ent_rec *adb);
+krb5_error_code kdb_delete_entry(kadm5_server_handle_t handle,
+ krb5_principal name);
+
+int init_dict(kadm5_config_params *);
+int find_word(const char *word);
+void destroy_dict(void);
+
+/*
+ * *Warning*
+ * *Warning* This is going to break if we
+ * *Warning* ever go multi-threaded
+ * *Warning*
+ */
+extern krb5_principal current_caller;
+
+/*
+ * Why is this (or something similar) not defined *anywhere* in krb5?
+ */
+#define KSUCCESS 0
+#define WORD_NOT_FOUND 1
+
+/*
+ * all the various mask bits or'd together
+ */
+
+#define ALL_PRINC_MASK (KADM5_PRINCIPAL | KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION | \
+ KADM5_LAST_PWD_CHANGE | KADM5_ATTRIBUTES | KADM5_MAX_LIFE | \
+ KADM5_MOD_TIME | KADM5_MOD_NAME | KADM5_KVNO | KADM5_MKVNO | \
+ KADM5_AUX_ATTRIBUTES | KADM5_POLICY_CLR | KADM5_POLICY)
+
+#define ALL_POLICY_MASK (KADM5_POLICY | KADM5_PW_MAX_LIFE | KADM5_PW_MIN_LIFE | \
+ KADM5_PW_MIN_LENGTH | KADM5_PW_MIN_CLASSES | KADM5_PW_HISTORY_NUM | \
+ KADM5_REF_COUNT)
+
+#define SERVER_CHECK_HANDLE(handle) \
+{ \
+ kadm5_server_handle_t srvr = \
+ (kadm5_server_handle_t) handle; \
+ \
+ if (! srvr->current_caller) \
+ return KADM5_BAD_SERVER_HANDLE; \
+ if (! srvr->lhandle) \
+ return KADM5_BAD_SERVER_HANDLE; \
+}
+
+#define CHECK_HANDLE(handle) \
+ GENERIC_CHECK_HANDLE(handle, KADM5_OLD_SERVER_API_VERSION, \
+ KADM5_NEW_SERVER_API_VERSION) \
+ SERVER_CHECK_HANDLE(handle)
+
+#endif /* __KADM5_SERVER_INTERNAL_H__ */
diff --git a/src/lib/kadm5/server_kdb.c b/src/lib/kadm5/server_kdb.c
new file mode 100644
index 000000000..1a900a380
--- /dev/null
+++ b/src/lib/kadm5/server_kdb.c
@@ -0,0 +1,424 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "k5-int.h"
+#include <kadm5/admin.h>
+#include "server_internal.h"
+
+krb5_principal master_princ;
+krb5_encrypt_block master_encblock;
+krb5_keyblock master_keyblock;
+krb5_db_entry master_db;
+
+krb5_principal hist_princ;
+krb5_encrypt_block hist_encblock;
+krb5_keyblock hist_key;
+krb5_db_entry hist_db;
+krb5_kvno hist_kvno;
+
+/* much of this code is stolen from the kdc. there should be some
+ library code to deal with this. */
+
+krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
+ char *r, int from_keyboard)
+{
+ int ret = 0;
+ char *realm;
+ krb5_keyblock tmk;
+
+ if (r == NULL) {
+ if ((ret = krb5_get_default_realm(handle->context, &realm)))
+ return ret;
+ } else {
+ realm = r;
+ }
+
+ if ((ret = krb5_db_setup_mkey_name(handle->context,
+ handle->params.mkey_name,
+ realm, NULL, &master_princ)))
+ goto done;
+
+ master_keyblock.enctype = handle->params.enctype;
+
+ krb5_use_enctype(handle->context, &master_encblock,
+ master_keyblock.enctype);
+
+ if (ret = krb5_db_fetch_mkey(handle->context, master_princ,
+ &master_encblock, from_keyboard,
+ FALSE /* only prompt once */,
+ handle->params.stash_file,
+ NULL /* I'm not sure about this,
+ but it's what the kdc does --marc */,
+ &master_keyblock))
+ goto done;
+
+ if ((ret = krb5_db_init(handle->context)) != KSUCCESS)
+ goto done;
+
+ if ((ret = krb5_db_verify_master_key(handle->context, master_princ,
+ &master_keyblock,
+ &master_encblock))) {
+ krb5_db_fini(handle->context);
+ return ret;
+ }
+
+ /* the kdc gets the db mkvno here. The admin server never uses this
+ bit of information, so there's no reason to retrieve it. */
+
+ if ((ret = krb5_process_key(handle->context, &master_encblock,
+ &master_keyblock))) {
+ krb5_db_fini(handle->context);
+ goto done;
+ }
+
+done:
+ if (r == NULL)
+ free(realm);
+
+ return(ret);
+}
+
+/*
+ * Function: kdb_init_hist
+ *
+ * Purpose: Initializes the global history variables.
+ *
+ * Arguments:
+ *
+ * handle (r) kadm5 api server handle
+ * r (r) realm of history principal to use, or NULL
+ *
+ * Effects: This function sets the value of the following global
+ * variables:
+ *
+ * hist_princ krb5_principal holding the history principal
+ * hist_db krb5_db_entry of the history principal
+ * hist_key krb5_keyblock holding the history principal's key
+ * hist_encblock krb5_encrypt_block holding the procssed hist_key
+ * hist_kvno the version number of the history key
+ *
+ * If the history principal does not already exist, this function
+ * attempts to create it with kadm5_create_principal. WARNING!
+ * If the history principal is deleted and this function is executed
+ * (by kadmind, or kadmin.local, or anything else with permission),
+ * the principal will be assigned a new random key and all existing
+ * password history information will become useless.
+ */
+krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
+{
+ int ret = 0;
+ char *realm, *hist_name;
+ krb5_key_data *key_data;
+
+ if (r == NULL) {
+ if ((ret = krb5_get_default_realm(handle->context, &realm)))
+ return ret;
+ } else {
+ realm = r;
+ }
+
+ if ((hist_name = (char *) malloc(strlen(KADM5_HIST_PRINCIPAL) +
+ strlen(realm) + 2)) == NULL)
+ goto done;
+
+ (void) sprintf(hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm);
+
+ if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ)))
+ goto done;
+
+ if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL))) {
+ kadm5_principal_ent_rec ent;
+
+ if (ret != KADM5_UNK_PRINC)
+ goto done;
+
+ /* try to create the principal */
+
+ memset(&ent, 0, sizeof(ent));
+
+ ent.principal = hist_princ;
+ ent.max_life = KRB5_KDB_DISALLOW_ALL_TIX;
+ ent.attributes = 0;
+
+ /* this uses hist_kvno. So we set it to 2, which will be the
+ correct value once the principal is created and randomized.
+ Of course, it doesn't make sense to keep a history for the
+ history principal, anyway. */
+
+ hist_kvno = 2;
+
+ if (ret = kadm5_create_principal(handle, &ent,
+ (KADM5_PRINCIPAL |
+ KADM5_MAX_LIFE |
+ KADM5_ATTRIBUTES),
+ "to-be-random"))
+ goto done;
+
+ /* this won't let us randomize the hist_princ. So we cheat. */
+
+ hist_princ = NULL;
+
+ ret = kadm5_randkey_principal(handle, ent.principal, NULL, NULL);
+
+ hist_princ = ent.principal;
+
+ if (ret)
+ goto done;
+
+ /* now read the newly-created kdb record out of the
+ database. */
+
+ if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL)))
+ goto done;
+
+ }
+
+ if (ret = krb5_dbe_find_enctype(handle->context,
+ &hist_db,
+ handle->params.enctype,
+ -1,
+ -1,
+ &key_data))
+ goto done;
+
+ if (ret = krb5_dbekd_decrypt_key_data(handle->context, &master_encblock,
+ key_data, &hist_key, NULL))
+ goto done;
+
+ krb5_use_enctype(handle->context, &hist_encblock, hist_key.enctype);
+
+ if ((ret = krb5_process_key(handle->context, &hist_encblock,
+ &hist_key)) != KSUCCESS)
+ goto done;
+
+ hist_kvno = key_data->key_data_kvno;
+
+done:
+ free(hist_name);
+ if (r == NULL)
+ free(realm);
+ return ret;
+}
+
+/*
+ * Function: kdb_get_entry
+ *
+ * Purpose: Gets an entry from the kerberos database and breaks
+ * it out into a krb5_db_entry and an osa_princ_ent_t.
+ *
+ * Arguments:
+ *
+ * handle (r) the server_handle
+ * principal (r) the principal to get
+ * kdb (w) krb5_db_entry to fill in
+ * adb (w) osa_princ_ent_rec to fill in
+ *
+ * when the caller is done with kdb and adb, kdb_free_entry must be
+ * called to release them. The adb record is filled in with the
+ * contents of the KRB5_TL_KADM_DATA record; if that record doesn't
+ * exist, an empty but valid adb record is returned.
+ */
+krb5_error_code
+kdb_get_entry(kadm5_server_handle_t handle,
+ krb5_principal principal, krb5_db_entry *kdb,
+ osa_princ_ent_rec *adb)
+{
+ krb5_error_code ret;
+ int nprincs;
+ krb5_boolean more;
+ krb5_tl_data tl_data;
+ XDR xdrs;
+
+ if (ret = krb5_db_get_principal(handle->context, principal, kdb, &nprincs,
+ &more))
+ return(ret);
+
+ if (more) {
+ krb5_db_free_principal(handle->context, kdb, nprincs);
+ return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE);
+ } else if (nprincs != 1) {
+ krb5_db_free_principal(handle->context, kdb, nprincs);
+ return(KADM5_UNK_PRINC);
+ }
+
+ if (adb) {
+ memset(adb, 0, sizeof(*adb));
+
+ tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+ /*
+ * XXX Currently, lookup_tl_data always returns zero; it sets
+ * tl_data->tl_data_length to zero if the type isn't found.
+ * This should be fixed...
+ */
+ if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data))
+ || (tl_data.tl_data_length == 0)) {
+ /* there's no admin data. this can happen, if the admin
+ server is put into production after some principals
+ are created. In this case, return valid admin
+ data (which is all zeros with the hist_kvno filled
+ in), and when the entry is written, the admin
+ data will get stored correctly. */
+
+ adb->admin_history_kvno = hist_kvno;
+
+ return(ret);
+ }
+
+ xdrmem_create(&xdrs, tl_data.tl_data_contents,
+ tl_data.tl_data_length, XDR_DECODE);
+ if (! xdr_osa_princ_ent_rec(&xdrs, adb)) {
+ xdr_destroy(&xdrs);
+ krb5_db_free_principal(handle->context, kdb, 1);
+ return(OSA_ADB_XDR_FAILURE);
+ }
+ xdr_destroy(&xdrs);
+ }
+
+ return(0);
+}
+
+/*
+ * Function: kdb_free_entry
+ *
+ * Purpose: frees the resources allocated by kdb_get_entry
+ *
+ * Arguments:
+ *
+ * handle (r) the server_handle
+ * kdb (w) krb5_db_entry to fill in
+ * adb (w) osa_princ_ent_rec to fill in
+ *
+ * when the caller is done with kdb and adb, kdb_free_entry must be
+ * called to release them.
+ */
+
+krb5_error_code
+kdb_free_entry(kadm5_server_handle_t handle,
+ krb5_db_entry *kdb, osa_princ_ent_rec *adb)
+{
+ XDR xdrs;
+
+
+ if (kdb)
+ krb5_db_free_principal(handle->context, kdb, 1);
+
+ if (adb) {
+ xdrmem_create(&xdrs, NULL, 0, XDR_FREE);
+ xdr_osa_princ_ent_rec(&xdrs, adb);
+ xdr_destroy(&xdrs);
+ }
+
+ return(0);
+}
+
+/*
+ * Function: kdb_put_entry
+ *
+ * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to
+ * database.
+ *
+ * Arguments:
+ *
+ * handle (r) the server_handle
+ * kdb (r/w) the krb5_db_entry to store
+ * adb (r) the osa_princ_db_ent to store
+ *
+ * Effects:
+ *
+ * The last modifier field of the kdb is set to the caller at now.
+ * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as
+ * KRB5_TL_KADM_DATA. kdb is then written to the database.
+ */
+krb5_error_code
+kdb_put_entry(kadm5_server_handle_t handle,
+ krb5_db_entry *kdb, osa_princ_ent_rec *adb)
+{
+ krb5_error_code ret;
+ krb5_int32 now;
+ XDR xdrs;
+ krb5_tl_data tl_data;
+ int one;
+
+ if (ret = krb5_timeofday(handle->context, &now))
+ return(ret);
+
+ if (ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now,
+ handle->current_caller))
+ return(ret);
+
+ xdralloc_create(&xdrs, XDR_ENCODE);
+ if(! xdr_osa_princ_ent_rec(&xdrs, adb)) {
+ xdr_destroy(&xdrs);
+ return(OSA_ADB_XDR_FAILURE);
+ }
+ tl_data.tl_data_type = KRB5_TL_KADM_DATA;
+ tl_data.tl_data_length = xdr_getpos(&xdrs);
+ tl_data.tl_data_contents = xdralloc_getdata(&xdrs);
+
+ ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);
+
+ xdr_destroy(&xdrs);
+
+ if (ret)
+ return(ret);
+
+ one = 1;
+
+ if (ret = krb5_db_put_principal(handle->context, kdb, &one))
+ return(ret);
+
+ return(0);
+}
+
+krb5_error_code
+kdb_delete_entry(kadm5_server_handle_t handle, krb5_principal name)
+{
+ int one = 1;
+ krb5_error_code ret;
+
+ ret = krb5_db_delete_principal(handle->context, name, &one);
+
+ return ret;
+}
+
+typedef struct _iter_data {
+ void (*func)(void *, krb5_principal);
+ void *data;
+} iter_data;
+
+static krb5_error_code
+kdb_iter_func(krb5_pointer data, krb5_db_entry *kdb)
+{
+ iter_data *id = (iter_data *) data;
+
+ (*(id->func))(id->data, kdb->princ);
+
+ return(0);
+}
+
+krb5_error_code
+kdb_iter_entry(kadm5_server_handle_t handle,
+ void (*iter_fct)(void *, krb5_principal), void *data)
+{
+ iter_data id;
+ krb5_error_code ret;
+
+ id.func = iter_fct;
+ id.data = data;
+
+ if (ret = krb5_db_iterate(handle->context, kdb_iter_func, &id))
+ return(ret);
+
+ return(0);
+}
+
+
diff --git a/src/lib/kadm5/server_misc.c b/src/lib/kadm5/server_misc.c
new file mode 100644
index 000000000..24f101ce5
--- /dev/null
+++ b/src/lib/kadm5/server_misc.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include "k5-int.h"
+#include <krb5/kdb.h>
+#include <ctype.h>
+#include "adb.h"
+
+/* for strcasecmp */
+#include <string.h>
+
+#include "server_internal.h"
+
+kadm5_ret_t
+adb_policy_init(kadm5_server_handle_t handle)
+{
+ osa_adb_ret_t ret;
+ if(handle->policy_db == (osa_adb_policy_t) NULL)
+ if((ret = osa_adb_open_policy(&handle->policy_db,
+ &handle->params)) != OSA_ADB_OK)
+ return ret;
+ return KADM5_OK;
+}
+
+kadm5_ret_t
+adb_policy_close(kadm5_server_handle_t handle)
+{
+ osa_adb_ret_t ret;
+ if(handle->policy_db != (osa_adb_policy_t) NULL)
+ if((ret = osa_adb_close_policy(handle->policy_db)) != OSA_ADB_OK)
+ return ret;
+ handle->policy_db = NULL;
+ return KADM5_OK;
+}
+
+/* some of this is stolen from gatekeeper ... */
+kadm5_ret_t
+passwd_check(kadm5_server_handle_t handle,
+ char *password, int use_policy, kadm5_policy_ent_t pol,
+ krb5_principal principal)
+{
+ int nupper = 0,
+ nlower = 0,
+ ndigit = 0,
+ npunct = 0,
+ nspec = 0;
+ char c, *s;
+
+ if(use_policy) {
+ if(strlen(password) < pol->pw_min_length)
+ return KADM5_PASS_Q_TOOSHORT;
+ s = password;
+ while ((c = *s++)) {
+ if (islower(c)) {
+ nlower = 1;
+ continue;
+ }
+ else if (isupper(c)) {
+ nupper = 1;
+ continue;
+ } else if (isdigit(c)) {
+ ndigit = 1;
+ continue;
+ } else if (ispunct(c)) {
+ npunct = 1;
+ continue;
+ } else {
+ nspec = 1;
+ continue;
+ }
+ }
+ if ((nupper + nlower + ndigit + npunct + nspec) < pol->pw_min_classes)
+ return KADM5_PASS_Q_CLASS;
+ if((find_word(password) == KADM5_OK))
+ return KADM5_PASS_Q_DICT;
+ else {
+ char *cp;
+ int c, n = krb5_princ_size(handle->context, principal);
+ cp = krb5_princ_realm(handle->context, principal)->data;
+ if (strcasecmp(cp, password) == 0)
+ return KADM5_PASS_Q_DICT;
+ for (c = 0; c < n ; c++) {
+ cp = krb5_princ_component(handle->context, principal, c)->data;
+ if (strcasecmp(cp, password) == 0)
+ return KADM5_PASS_Q_DICT;
+ }
+ return KADM5_OK;
+ }
+ } else {
+ if (strlen(password) < 1)
+ return KADM5_PASS_Q_TOOSHORT;
+ }
+ return KADM5_OK;
+}
diff --git a/src/lib/kadm5/setenv.c b/src/lib/kadm5/setenv.c
new file mode 100644
index 000000000..47904de1b
--- /dev/null
+++ b/src/lib/kadm5/setenv.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)setenv.c 5.2 (Berkeley) 6/27/88 */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * setenv --
+ * Set the value of the environmental variable "name" to be
+ * "value". If rewrite is set, replace any current value.
+ */
+setenv(name, value, rewrite)
+ register char *name, *value;
+ int rewrite;
+{
+ extern char **environ;
+ static int alloced; /* if allocated space before */
+ register char *C;
+ int l_value, offset;
+#if !defined(sun) && !defined(hpux)
+ char *malloc(), *realloc();
+#endif
+ char *_findenv();
+
+ if (*value == '=') /* no `=' in value */
+ ++value;
+ l_value = strlen(value);
+ if ((C = _findenv(name, &offset))) { /* find if already exists */
+ if (!rewrite)
+ return(0);
+ if (strlen(C) >= l_value) { /* old larger; copy over */
+ while (*C++ = *value++);
+ return(0);
+ }
+ }
+ else { /* create new slot */
+ register int cnt;
+ register char **P;
+
+ for (P = environ, cnt = 0; *P; ++P, ++cnt);
+ if (alloced) { /* just increase size */
+ environ = (char **)realloc((char *)environ,
+ (u_int)(sizeof(char *) * (cnt + 2)));
+ if (!environ)
+ return(-1);
+ }
+ else { /* get new space */
+ alloced = 1; /* copy old entries into it */
+ P = (char **)malloc((u_int)(sizeof(char *) *
+ (cnt + 2)));
+ if (!P)
+ return(-1);
+ memcpy(P, environ, cnt * sizeof(char *));
+ environ = P;
+ }
+ environ[cnt + 1] = NULL;
+ offset = cnt;
+ }
+ for (C = name; *C && *C != '='; ++C); /* no `=' in name */
+ if (!(environ[offset] = /* name + `=' + value */
+ malloc((u_int)((int)(C - name) + l_value + 2))))
+ return(-1);
+ for (C = environ[offset]; (*C = *name++) && *C != '='; ++C);
+ for (*C++ = '='; *C++ = *value++;);
+ return(0);
+}
+
+/*
+ * unsetenv(name) --
+ * Delete environmental variable "name".
+ */
+void
+unsetenv(name)
+ char *name;
+{
+ extern char **environ;
+ register char **P;
+ int offset;
+ char *_findenv();
+
+ while (_findenv(name, &offset)) /* if set multiple times */
+ for (P = &environ[offset];; ++P)
+ if (!(*P = *(P + 1)))
+ break;
+}
+/*
+ * Copyright (c) 1987 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* based on @(#)getenv.c 5.5 (Berkeley) 6/27/88 */
+
+/*
+ * getenv --
+ * Returns ptr to value associated with name, if any, else NULL.
+ */
+char *
+getenv(name)
+ const char *name;
+{
+ int offset;
+ char *_findenv();
+
+ return(_findenv(name, &offset));
+}
+
+/*
+ * _findenv --
+ * Returns pointer to value associated with name, if any, else NULL.
+ * Sets offset to be the offset of the name/value combination in the
+ * environmental array, for use by setenv(3) and unsetenv(3).
+ * Explicitly removes '=' in argument name.
+ *
+ * This routine *should* be a static; don't use it.
+ */
+char *
+_findenv(name, offset)
+ register char *name;
+ int *offset;
+{
+ extern char **environ;
+ register int len;
+ register char **P, *C;
+
+ for (C = name, len = 0; *C && *C != '='; ++C, ++len);
+ for (P = environ; *P; ++P)
+ if (!strncmp(*P, name, len))
+ if (*(C = *P + len) == '=') {
+ *offset = P - environ;
+ return(++C);
+ }
+ return(NULL);
+}
diff --git a/src/lib/kadm5/str_conv.c b/src/lib/kadm5/str_conv.c
new file mode 100644
index 000000000..882892933
--- /dev/null
+++ b/src/lib/kadm5/str_conv.c
@@ -0,0 +1,397 @@
+/*
+ * lib/kadm/str_conv.c
+ *
+ * Copyright 1995 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ */
+
+/*
+ * str_conv.c - Convert between strings and Kerberos internal data.
+ */
+
+/*
+ * Table of contents:
+ *
+ * String decoding:
+ * ----------------
+ * krb5_string_to_flags() - Convert string to krb5_flags.
+ *
+ * String encoding:
+ * ----------------
+ * krb5_flags_to_string() - Convert krb5_flags to string.
+ */
+
+#include "k5-int.h"
+#include "admin_internal.h"
+
+/*
+ * Local data structures.
+ */
+struct flags_lookup_entry {
+ krb5_flags fl_flags; /* Flag */
+ krb5_boolean fl_sense; /* Sense of the flag */
+ const char * fl_specifier; /* How to recognize it */
+ const char * fl_output; /* How to spit it out */
+};
+
+/*
+ * Local strings
+ */
+
+static const char default_tupleseps[] = ", \t";
+static const char default_ksaltseps[] = ":.";
+
+/* Keytype strings */
+/* Flags strings */
+static const char flags_pdate_in[] = "postdateable";
+static const char flags_fwd_in[] = "forwardable";
+static const char flags_tgtbased_in[] = "tgt-based";
+static const char flags_renew_in[] = "renewable";
+static const char flags_proxy_in[] = "proxiable";
+static const char flags_dup_skey_in[] = "dup-skey";
+static const char flags_tickets_in[] = "allow-tickets";
+static const char flags_preauth_in[] = "preauth";
+static const char flags_hwauth_in[] = "hwauth";
+static const char flags_pwchange_in[] = "pwchange";
+static const char flags_service_in[] = "service";
+static const char flags_pwsvc_in[] = "pwservice";
+static const char flags_md5_in[] = "md5";
+static const char flags_pdate_out[] = "Not Postdateable";
+static const char flags_fwd_out[] = "Not Forwardable";
+static const char flags_tgtbased_out[] = "No TGT-based requests";
+static const char flags_renew_out[] = "Not renewable";
+static const char flags_proxy_out[] = "Not proxiable";
+static const char flags_dup_skey_out[] = "No DUP_SKEY requests";
+static const char flags_tickets_out[] = "All Tickets Disallowed";
+static const char flags_preauth_out[] = "Preauthorization required";
+static const char flags_hwauth_out[] = "HW Authorization required";
+static const char flags_pwchange_out[] = "Password Change required";
+static const char flags_service_out[] = "Service Disabled";
+static const char flags_pwsvc_out[] = "Password Changing Service";
+static const char flags_md5_out[] = "RSA-MD5 supported";
+static const char flags_default_neg[] = "-";
+static const char flags_default_sep[] = " ";
+
+/*
+ * Lookup tables.
+ */
+
+static const struct flags_lookup_entry flags_table[] = {
+/* flag sense input specifier output string */
+/*----------------------------- ------- ------------------ ------------------*/
+{ KRB5_KDB_DISALLOW_POSTDATED, 0, flags_pdate_in, flags_pdate_out },
+{ KRB5_KDB_DISALLOW_FORWARDABLE,0, flags_fwd_in, flags_fwd_out },
+{ KRB5_KDB_DISALLOW_TGT_BASED, 0, flags_tgtbased_in, flags_tgtbased_out},
+{ KRB5_KDB_DISALLOW_RENEWABLE, 0, flags_renew_in, flags_renew_out },
+{ KRB5_KDB_DISALLOW_PROXIABLE, 0, flags_proxy_in, flags_proxy_out },
+{ KRB5_KDB_DISALLOW_DUP_SKEY, 0, flags_dup_skey_in, flags_dup_skey_out},
+{ KRB5_KDB_DISALLOW_ALL_TIX, 0, flags_tickets_in, flags_tickets_out },
+{ KRB5_KDB_REQUIRES_PRE_AUTH, 1, flags_preauth_in, flags_preauth_out },
+{ KRB5_KDB_REQUIRES_HW_AUTH, 1, flags_hwauth_in, flags_hwauth_out },
+{ KRB5_KDB_REQUIRES_PWCHANGE, 1, flags_pwchange_in, flags_pwchange_out},
+{ KRB5_KDB_DISALLOW_SVR, 0, flags_service_in, flags_service_out },
+{ KRB5_KDB_PWCHANGE_SERVICE, 1, flags_pwsvc_in, flags_pwsvc_out },
+{ KRB5_KDB_SUPPORT_DESMD5, 1, flags_md5_in, flags_md5_out }
+};
+static const int flags_table_nents = sizeof(flags_table)/
+ sizeof(flags_table[0]);
+
+
+krb5_error_code
+krb5_string_to_flags(string, positive, negative, flagsp)
+ char * string;
+ const char * positive;
+ const char * negative;
+ krb5_flags * flagsp;
+{
+ int i;
+ int found;
+ const char *neg;
+ size_t nsize, psize;
+ int cpos;
+ int sense;
+
+ found = 0;
+ /* We need to have a way to negate it. */
+ neg = (negative) ? negative : flags_default_neg;
+ nsize = strlen(neg);
+ psize = (positive) ? strlen(positive) : 0;
+
+ cpos = 0;
+ sense = 1;
+ /* First check for positive or negative sense */
+ if (!strncasecmp(neg, string, nsize)) {
+ sense = 0;
+ cpos += (int) nsize;
+ }
+ else if (psize && !strncasecmp(positive, string, psize)) {
+ cpos += (int) psize;
+ }
+
+ for (i=0; i<flags_table_nents; i++) {
+ if (!strcasecmp(&string[cpos], flags_table[i].fl_specifier)) {
+ found = 1;
+ if (sense == (int) flags_table[i].fl_sense)
+ *flagsp |= flags_table[i].fl_flags;
+ else
+ *flagsp &= ~flags_table[i].fl_flags;
+
+ break;
+ }
+ }
+ return((found) ? 0 : EINVAL);
+}
+
+krb5_error_code
+krb5_flags_to_string(flags, sep, buffer, buflen)
+ krb5_flags flags;
+ const char * sep;
+ char * buffer;
+ size_t buflen;
+{
+ int i;
+ krb5_flags pflags;
+ const char *sepstring;
+ char *op;
+ int initial;
+ krb5_error_code retval;
+
+ retval = 0;
+ op = buffer;
+ pflags = 0;
+ initial = 1;
+ sepstring = (sep) ? sep : flags_default_sep;
+ /* Blast through the table matching all we can */
+ for (i=0; i<flags_table_nents; i++) {
+ if (flags & flags_table[i].fl_flags) {
+ /* Found a match, see if it'll fit into the output buffer */
+ if ((op+strlen(flags_table[i].fl_output)+strlen(sepstring)) <
+ (buffer + buflen)) {
+ if (!initial) {
+ strcpy(op, sep);
+ op += strlen(sep);
+ }
+ initial = 0;
+ strcpy(op, flags_table[i].fl_output);
+ op += strlen(flags_table[i].fl_output);
+ }
+ else {
+ retval = ENOMEM;
+ break;
+ }
+ /* Keep track of what we matched */
+ pflags |= flags_table[i].fl_flags;
+ }
+ }
+ if (!retval) {
+ /* See if there's any leftovers */
+ if (flags & ~pflags)
+ retval = EINVAL;
+ else if (initial)
+ *buffer = '\0';
+ }
+ return(retval);
+}
+
+krb5_error_code
+krb5_input_flag_to_string(flag, buffer, buflen)
+ int flag;
+ char * buffer;
+ size_t buflen;
+{
+ if(flag < 0 || flag >= flags_table_nents) return ENOENT; /* End of list */
+ if(strlen(flags_table[flag].fl_specifier) > buflen) return ENOMEM;
+ strcpy(buffer, flags_table[flag].fl_specifier);
+ return 0;
+}
+
+/*
+ * krb5_keysalt_is_present() - Determine if a key/salt pair is present
+ * in a list of key/salt tuples.
+ *
+ * Salttype may be negative to indicate a search for only a enctype.
+ */
+krb5_boolean
+krb5_keysalt_is_present(ksaltlist, nksalts, enctype, salttype)
+ krb5_key_salt_tuple *ksaltlist;
+ krb5_int32 nksalts;
+ krb5_enctype enctype;
+ krb5_int32 salttype;
+{
+ krb5_boolean foundit;
+ int i;
+
+ foundit = 0;
+ if (ksaltlist) {
+ for (i=0; i<nksalts; i++) {
+ if ((ksaltlist[i].ks_enctype == enctype) &&
+ ((ksaltlist[i].ks_salttype == salttype) ||
+ (salttype < 0))) {
+ foundit = 1;
+ break;
+ }
+ }
+ }
+ return(foundit);
+}
+
+/*
+ * krb5_string_to_keysalts() - Convert a string representation to a list
+ * of key/salt tuples.
+ */
+krb5_error_code
+krb5_string_to_keysalts(string, tupleseps, ksaltseps, dups, ksaltp, nksaltp)
+ char *string;
+ const char *tupleseps;
+ const char *ksaltseps;
+ krb5_boolean dups;
+ krb5_key_salt_tuple **ksaltp;
+ krb5_int32 *nksaltp;
+{
+ krb5_error_code kret;
+ char *kp, *sp, *ep;
+ char sepchar, trailchar;
+ krb5_enctype ktype;
+ krb5_int32 stype;
+ krb5_key_salt_tuple *savep;
+ const char *tseplist;
+ const char *ksseplist;
+ const char *septmp;
+ size_t len;
+
+ kret = 0;
+ kp = string;
+ tseplist = (tupleseps) ? tupleseps : default_tupleseps;
+ ksseplist = (ksaltseps) ? ksaltseps : default_ksaltseps;
+ while (kp) {
+ /* Attempt to find a separator */
+ ep = (char *) NULL;
+ if (*tseplist) {
+ septmp = tseplist;
+ for (ep = strchr(kp, (int) *septmp);
+ *(++septmp) && !ep;
+ ep = strchr(kp, (int) *septmp));
+ }
+
+ if (ep) {
+ trailchar = *ep;
+ *ep = '\0';
+ ep++;
+ }
+ /*
+ * kp points to something (hopefully) of the form:
+ * <enctype><ksseplist><salttype>
+ * or
+ * <enctype>
+ */
+ sp = (char *) NULL;
+ /* Attempt to find a separator */
+ septmp = ksseplist;
+ for (sp = strchr(kp, (int) *septmp);
+ *(++septmp) && !sp;
+ ep = strchr(kp, (int) *septmp));
+
+ if (sp) {
+ /* Separate enctype from salttype */
+ sepchar = *sp;
+ *sp = '\0';
+ sp++;
+ }
+ else
+ stype = -1;
+
+ /*
+ * Attempt to parse enctype and salttype. If we parse well
+ * then make sure that it specifies a unique key/salt combo
+ */
+ if (!(kret = krb5_string_to_enctype(kp, &ktype)) &&
+ (!sp || !(kret = krb5_string_to_salttype(sp, &stype))) &&
+ (dups ||
+ !krb5_keysalt_is_present(*ksaltp, *nksaltp, ktype, stype))) {
+
+ /* Squirrel away old keysalt array */
+ savep = *ksaltp;
+ len = (size_t) *nksaltp;
+
+ /* Get new keysalt array */
+ if (*ksaltp = (krb5_key_salt_tuple *)
+ malloc((len + 1) * sizeof(krb5_key_salt_tuple))) {
+
+ /* Copy old keysalt if appropriate */
+ if (savep) {
+ memcpy(*ksaltp, savep,
+ len * sizeof(krb5_key_salt_tuple));
+ krb5_xfree(savep);
+ }
+
+ /* Save our values */
+ (*ksaltp)[(*nksaltp)].ks_enctype = ktype;
+ (*ksaltp)[(*nksaltp)].ks_salttype = stype;
+ (*nksaltp)++;
+ }
+ else {
+ *ksaltp = savep;
+ break;
+ }
+ }
+ if (kret)
+ return kret;
+ if (sp)
+ sp[-1] = sepchar;
+ if (ep)
+ ep[-1] = trailchar;
+ kp = ep;
+ }
+ return(kret);
+}
+
+/*
+ * krb5_keysalt_iterate() - Do something for each unique key/salt
+ * combination.
+ *
+ * If ignoresalt set, then salttype is ignored.
+ */
+krb5_error_code
+krb5_keysalt_iterate(ksaltlist, nksalt, ignoresalt, iterator, arg)
+ krb5_key_salt_tuple *ksaltlist;
+ krb5_int32 nksalt;
+ krb5_boolean ignoresalt;
+ krb5_error_code (*iterator) KRB5_NPROTOTYPE((krb5_key_salt_tuple *,
+ krb5_pointer));
+ krb5_pointer arg;
+{
+ int i;
+ krb5_error_code kret;
+ krb5_key_salt_tuple scratch;
+
+ kret = 0;
+ for (i=0; i<nksalt; i++) {
+ scratch.ks_enctype = ksaltlist[i].ks_enctype;
+ scratch.ks_salttype = (ignoresalt) ? -1 : ksaltlist[i].ks_salttype;
+ if (!krb5_keysalt_is_present(ksaltlist,
+ i,
+ scratch.ks_enctype,
+ scratch.ks_salttype)) {
+ if (kret = (*iterator)(&scratch, arg))
+ break;
+ }
+ }
+ return(kret);
+}
diff --git a/src/lib/kadm5/svr_chpass_util.c b/src/lib/kadm5/svr_chpass_util.c
new file mode 100644
index 000000000..df2bf4c47
--- /dev/null
+++ b/src/lib/kadm5/svr_chpass_util.c
@@ -0,0 +1,15 @@
+#include <kadm5/admin.h>
+#include "server_internal.h"
+
+kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
+ krb5_principal princ,
+ char *new_pw,
+ char **ret_pw,
+ char *msg_ret)
+{
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+ return _kadm5_chpass_principal_util(handle, handle->lhandle, princ,
+ new_pw, ret_pw, msg_ret);
+}
diff --git a/src/lib/kadm5/svr_iters.c b/src/lib/kadm5/svr_iters.c
new file mode 100644
index 000000000..19c900021
--- /dev/null
+++ b/src/lib/kadm5/svr_iters.c
@@ -0,0 +1,248 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#if defined(HAVE_COMPILE) && defined(HAVE_STEP)
+#define SOLARIS_REGEXPS
+#elif defined(HAVE_REGCOMP) && defined(HAVE_REGEXEC)
+#define POSIX_REGEXPS
+#elif defined(HAVE_RE_COMP) && defined(HAVE_RE_EXEC)
+#define BSD_REGEXPS
+#else
+#error I cannot find any regexp functions
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include <kadm5/admin.h>
+#include "adb.h"
+#include <dyn.h>
+#ifdef SOLARIS_REGEXPS
+#include <regexpr.h>
+#endif
+#ifdef POSIX_REGEXPS
+#include <regex.h>
+#endif
+#include <stdlib.h>
+
+#include "server_internal.h"
+
+struct iter_data {
+ krb5_context context;
+ DynObject matches;
+ char *exp;
+#ifdef SOLARIS_REGEXPS
+ char *expbuf;
+#endif
+#ifdef POSIX_REGEXPS
+ regex_t preg;
+#endif
+};
+
+/*
+ * Function: glob_to_regexp
+ *
+ * Arguments:
+ *
+ * glob (r) the shell-style glob (?*[]) to convert
+ * realm (r) the default realm to append, or NULL
+ * regexp (w) the ed-style regexp created from glob
+ *
+ * Effects:
+ *
+ * regexp is filled in with allocated memory contained a regular
+ * expression to be used with re_comp/compile that matches what the
+ * shell-style glob would match. If glob does not contain an "@"
+ * character and realm is not NULL, "@<realm>" is appended to the regexp.
+ *
+ * Conversion algorithm:
+ *
+ * quoted characters are copied quoted
+ * ? is converted to .
+ * * is converted to .*
+ * active characters are quoted: ^, $, .
+ * [ and ] are active but supported and have the same meaning, so
+ * they are copied
+ * other characters are copied
+ * regexp is anchored with ^ and $
+ */
+kadm5_ret_t glob_to_regexp(char *glob, char *realm, char **regexp)
+{
+ int append_realm;
+ char *p;
+
+ /* validate the glob */
+ if (glob[strlen(glob)-1] == '\\')
+ return EINVAL;
+
+ /* A character of glob can turn into two in regexp, plus ^ and $ */
+ /* and trailing null. If glob has no @, also allocate space for */
+ /* the realm. */
+ append_realm = (realm != NULL) && (strchr(glob, '@') == NULL);
+ p = (char *) malloc(strlen(glob)*2+ 3 +
+ (append_realm ? (strlen(realm)+1) : 0));
+ if (p == NULL)
+ return ENOMEM;
+ *regexp = p;
+
+ *p++ = '^';
+ while (*glob) {
+ switch (*glob) {
+ case '?':
+ *p++ = '.';
+ break;
+ case '*':
+ *p++ = '.';
+ *p++ = '*';
+ break;
+ case '.':
+ case '^':
+ case '$':
+ *p++ = '\\';
+ *p++ = *glob;
+ break;
+ case '\\':
+ *p++ = '\\';
+ *p++ = ++*glob;
+ break;
+ default:
+ *p++ = *glob;
+ break;
+ }
+ glob++;
+ }
+
+ if (append_realm) {
+ *p++ = '@';
+ strcpy(p, realm);
+ p += strlen(realm);
+ }
+
+ *p++ = '$';
+ *p++ = '\0';
+ return KADM5_OK;
+}
+
+void get_either_iter(struct iter_data *data, char *name)
+{
+ if (
+#ifdef SOLARIS_REGEXPS
+ (step(name, data->expbuf) != 0)
+#endif
+#ifdef POSIX_REGEXPS
+ (regexec(&data->preg, name, 0, NULL, 0) == 0)
+#endif
+#ifdef BSD_REGEXPS
+ (re_exec(name) != 0)
+#endif
+ )
+ {
+ (void) DynAdd(data->matches, &name);
+ } else
+ free(name);
+}
+
+void get_pols_iter(void *data, osa_policy_ent_t entry)
+{
+ char *name;
+
+ if ((name = strdup(entry->name)) == NULL)
+ return;
+ get_either_iter(data, name);
+}
+
+void get_princs_iter(void *data, krb5_principal princ)
+{
+ struct iter_data *id = (struct iter_data *) data;
+ char *name;
+
+ if (krb5_unparse_name(id->context, princ, &name) != 0)
+ return;
+ get_either_iter(data, name);
+}
+
+kadm5_ret_t kadm5_get_either(int princ,
+ void *server_handle,
+ char *exp,
+ char ***princs,
+ int *count)
+{
+ struct iter_data data;
+ char *msg, *regexp;
+ int ret;
+ kadm5_server_handle_t handle = server_handle;
+
+ *count = 0;
+ if (exp == NULL)
+ exp = "*";
+
+ CHECK_HANDLE(server_handle);
+
+ if ((ret = glob_to_regexp(exp, princ ? handle->params.realm : NULL,
+ &regexp)) != KADM5_OK)
+ return ret;
+
+ if (
+#ifdef SOLARIS_REGEXPS
+ ((data.expbuf = compile(regexp, NULL, NULL)) == NULL)
+#endif
+#ifdef POSIX_REGEXPS
+ ((regcomp(&data.preg, regexp, REG_NOSUB)) != 0)
+#endif
+#ifdef BSD_REGEXPS
+ ((msg = (char *) re_comp(regexp)) != NULL)
+#endif
+ )
+ {
+ /* XXX syslog msg or regerr(regerrno) */
+ free(regexp);
+ return EINVAL;
+ }
+
+ if ((data.matches = DynCreate(sizeof(char *), -4)) == NULL) {
+ free(regexp);
+ return ENOMEM;
+ }
+
+ if (princ) {
+ data.context = handle->context;
+ ret = kdb_iter_entry(handle, get_princs_iter, (void *) &data);
+ } else {
+ ret = osa_adb_iter_policy(handle->policy_db, get_pols_iter, (void *)&data);
+ }
+
+ if (ret != OSA_ADB_OK) {
+ free(regexp);
+ DynDestroy(data.matches);
+ return ret;
+ }
+
+ (*princs) = (char **) DynArray(data.matches);
+ *count = DynSize(data.matches);
+ DynRelease(data.matches);
+ free(regexp);
+ return KADM5_OK;
+}
+
+kadm5_ret_t kadm5_get_principals(void *server_handle,
+ char *exp,
+ char ***princs,
+ int *count)
+{
+ return kadm5_get_either(1, server_handle, exp, princs, count);
+}
+
+kadm5_ret_t kadm5_get_policies(void *server_handle,
+ char *exp,
+ char ***pols,
+ int *count)
+{
+ return kadm5_get_either(0, server_handle, exp, pols, count);
+}
+
diff --git a/src/lib/kadm5/svr_misc_free.c b/src/lib/kadm5/svr_misc_free.c
new file mode 100644
index 000000000..5c76a1ebc
--- /dev/null
+++ b/src/lib/kadm5/svr_misc_free.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+#include <kadm5/admin.h>
+#include <malloc.h>
+#include "server_internal.h"
+
+kadm5_ret_t
+kadm5_free_principal_ent(void *server_handle,
+ kadm5_principal_ent_t val)
+{
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if(val) {
+ if(val->principal)
+ krb5_free_principal(handle->context, val->principal);
+ if(val->mod_name)
+ krb5_free_principal(handle->context, val->mod_name);
+ if(val->policy)
+ free(val->policy);
+
+ /* XXX free key_data and tl_data */
+
+ if (handle->api_version == KADM5_API_VERSION_1)
+ free(val);
+ }
+ return KADM5_OK;
+}
diff --git a/src/lib/kadm5/svr_policy.c b/src/lib/kadm5/svr_policy.c
new file mode 100644
index 000000000..74e252115
--- /dev/null
+++ b/src/lib/kadm5/svr_policy.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/types.h>
+#include <kadm5/admin.h>
+#include "adb.h"
+#include "server_internal.h"
+#include <stdlib.h>
+
+#define MAX_PW_HISTORY 10
+#define MIN_PW_HISTORY 1
+#define MIN_PW_CLASSES 1
+#define MAX_PW_CLASSES 5
+#define MIN_PW_LENGTH 1
+
+/*
+ * Function: kadm5_create_policy
+ *
+ * Purpose: Create Policies in the policy DB.
+ *
+ * Arguments:
+ * entry (input) The policy entry to be written out to the DB.
+ * mask (input) Specifies which fields in entry are to ge written out
+ * and which get default values.
+ * <return value> 0 if sucsessfull otherwise an error code is returned.
+ *
+ * Requires:
+ * Entry must be a valid principal entry, and mask have a valid value.
+ *
+ * Effects:
+ * Verifies that mask does not specify that the refcount should
+ * be set as part of the creation, and calls
+ * kadm5_create_policy_internal. If the refcount *is*
+ * specified, returns KADM5_BAD_MASK.
+ */
+
+kadm5_ret_t
+kadm5_create_policy(void *server_handle,
+ kadm5_policy_ent_t entry, long mask)
+{
+ CHECK_HANDLE(server_handle);
+
+ if (mask & KADM5_REF_COUNT)
+ return KADM5_BAD_MASK;
+ else
+ return kadm5_create_policy_internal(server_handle, entry, mask);
+}
+
+/*
+ * Function: kadm5_create_policy_internal
+ *
+ * Purpose: Create Policies in the policy DB.
+ *
+ * Arguments:
+ * entry (input) The policy entry to be written out to the DB.
+ * mask (input) Specifies which fields in entry are to ge written out
+ * and which get default values.
+ * <return value> 0 if sucsessfull otherwise an error code is returned.
+ *
+ * Requires:
+ * Entry must be a valid principal entry, and mask have a valid value.
+ *
+ * Effects:
+ * Writes the data to the database, and does a database sync if
+ * sucsessfull.
+ *
+ */
+
+kadm5_ret_t
+kadm5_create_policy_internal(void *server_handle,
+ kadm5_policy_ent_t entry, long mask)
+{
+ kadm5_server_handle_t handle = server_handle;
+ osa_policy_ent_rec pent;
+ int ret;
+ char *p;
+
+ CHECK_HANDLE(server_handle);
+
+ if ((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
+ return EINVAL;
+ if(strlen(entry->policy) == 0)
+ return KADM5_BAD_POLICY;
+ if (!(mask & KADM5_POLICY))
+ return KADM5_BAD_MASK;
+
+ pent.name = entry->policy;
+ p = entry->policy;
+ while(*p != '\0') {
+ if(*p < ' ' || *p > '~')
+ return KADM5_BAD_POLICY;
+ else
+ p++;
+ }
+ if (!(mask & KADM5_PW_MAX_LIFE))
+ pent.pw_max_life = 0;
+ else
+ pent.pw_max_life = entry->pw_max_life;
+ if (!(mask & KADM5_PW_MIN_LIFE))
+ pent.pw_min_life = 0;
+ else {
+ if((mask & KADM5_PW_MAX_LIFE)) {
+ if(entry->pw_min_life > entry->pw_max_life && entry->pw_max_life != 0)
+ return KADM5_BAD_MIN_PASS_LIFE;
+ }
+ pent.pw_min_life = entry->pw_min_life;
+ }
+ if (!(mask & KADM5_PW_MIN_LENGTH))
+ pent.pw_min_length = MIN_PW_LENGTH;
+ else {
+ if(entry->pw_min_length < MIN_PW_LENGTH)
+ return KADM5_BAD_LENGTH;
+ pent.pw_min_length = entry->pw_min_length;
+ }
+ if (!(mask & KADM5_PW_MIN_CLASSES))
+ pent.pw_min_classes = MIN_PW_CLASSES;
+ else {
+ if(entry->pw_min_classes > MAX_PW_CLASSES || entry->pw_min_classes < MIN_PW_CLASSES)
+ return KADM5_BAD_CLASS;
+ pent.pw_min_classes = entry->pw_min_classes;
+ }
+ if (!(mask & KADM5_PW_HISTORY_NUM))
+ pent.pw_history_num = MIN_PW_HISTORY;
+ else {
+ if(entry->pw_history_num < MIN_PW_HISTORY ||
+ entry->pw_history_num > MAX_PW_HISTORY)
+ return KADM5_BAD_HISTORY;
+ else
+ pent.pw_history_num = entry->pw_history_num;
+ }
+ if (!(mask & KADM5_REF_COUNT))
+ pent.policy_refcnt = 0;
+ else
+ pent.policy_refcnt = entry->policy_refcnt;
+ if ((ret = osa_adb_create_policy(handle->policy_db, &pent)) == OSA_ADB_OK)
+ return KADM5_OK;
+ else
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_delete_policy(void *server_handle, kadm5_policy_t name)
+{
+ kadm5_server_handle_t handle = server_handle;
+ osa_policy_ent_t entry;
+ int ret;
+
+ CHECK_HANDLE(server_handle);
+
+ if(name == (kadm5_policy_t) NULL)
+ return EINVAL;
+ if(strlen(name) == 0)
+ return KADM5_BAD_POLICY;
+ if ((ret = osa_adb_get_policy(handle->policy_db, name, &entry)) != OSA_ADB_OK)
+ return ret;
+ if(entry->policy_refcnt != 0) {
+ osa_free_policy_ent(entry);
+ return KADM5_POLICY_REF;
+ }
+ osa_free_policy_ent(entry);
+ if ((ret = osa_adb_destroy_policy(handle->policy_db, name)) == OSA_ADB_OK)
+ return KADM5_OK;
+ else
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_modify_policy(void *server_handle,
+ kadm5_policy_ent_t entry, long mask)
+{
+ CHECK_HANDLE(server_handle);
+
+ if (mask & KADM5_REF_COUNT)
+ return KADM5_BAD_MASK;
+ else
+ return kadm5_modify_policy_internal(server_handle, entry, mask);
+}
+
+kadm5_ret_t
+kadm5_modify_policy_internal(void *server_handle,
+ kadm5_policy_ent_t entry, long mask)
+{
+ kadm5_server_handle_t handle = server_handle;
+ osa_policy_ent_t p;
+ int ret;
+
+ CHECK_HANDLE(server_handle);
+
+ if((entry == (kadm5_policy_ent_t) NULL) || (entry->policy == NULL))
+ return EINVAL;
+ if(strlen(entry->policy) == 0)
+ return KADM5_BAD_POLICY;
+ if((mask & KADM5_POLICY))
+ return KADM5_BAD_MASK;
+
+ switch ((ret = osa_adb_get_policy(handle->policy_db, entry->policy, &p))) {
+ case OSA_ADB_OK:
+ break;
+ case OSA_ADB_NOENT:
+ return KADM5_UNK_POLICY;
+ default:
+ break;
+ }
+ if ((mask & KADM5_PW_MAX_LIFE))
+ p->pw_max_life = entry->pw_max_life;
+ if ((mask & KADM5_PW_MIN_LIFE)) {
+ if(entry->pw_min_life > p->pw_max_life && p->pw_max_life != 0) {
+ osa_free_policy_ent(p);
+ return KADM5_BAD_MIN_PASS_LIFE;
+ }
+ p->pw_min_life = entry->pw_min_life;
+ }
+ if ((mask & KADM5_PW_MIN_LENGTH)) {
+ if(entry->pw_min_length < MIN_PW_LENGTH) {
+ osa_free_policy_ent(p);
+ return KADM5_BAD_LENGTH;
+ }
+ p->pw_min_length = entry->pw_min_length;
+ }
+ if ((mask & KADM5_PW_MIN_CLASSES)) {
+ if(entry->pw_min_classes > MAX_PW_CLASSES ||
+ entry->pw_min_classes < MIN_PW_CLASSES) {
+ osa_free_policy_ent(p);
+ return KADM5_BAD_CLASS;
+ }
+ p->pw_min_classes = entry->pw_min_classes;
+ }
+ if ((mask & KADM5_PW_HISTORY_NUM)) {
+ if(entry->pw_history_num < MIN_PW_HISTORY ||
+ entry->pw_history_num > MAX_PW_HISTORY) {
+ osa_free_policy_ent(p);
+ return KADM5_BAD_HISTORY;
+ }
+ p->pw_history_num = entry->pw_history_num;
+ }
+ if ((mask & KADM5_REF_COUNT))
+ p->policy_refcnt = entry->policy_refcnt;
+ switch ((ret = osa_adb_put_policy(handle->policy_db, p))) {
+ case OSA_ADB_OK:
+ ret = KADM5_OK;
+ break;
+ case OSA_ADB_NOENT: /* this should not happen here ... */
+ ret = KADM5_UNK_POLICY;
+ break;
+ }
+ osa_free_policy_ent(p);
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_get_policy(void *server_handle, kadm5_policy_t name,
+ kadm5_policy_ent_t entry)
+{
+ osa_policy_ent_t t;
+ kadm5_policy_ent_rec entry_local, **entry_orig, *new;
+ int ret;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ /*
+ * In version 1, entry is a pointer to a kadm5_policy_ent_t that
+ * should be filled with allocated memory.
+ */
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ entry_orig = (kadm5_policy_ent_rec **) entry;
+ *entry_orig = NULL;
+ entry = &entry_local;
+ }
+
+ if (name == (kadm5_policy_t) NULL)
+ return EINVAL;
+ if(strlen(name) == 0)
+ return KADM5_BAD_POLICY;
+ switch((ret = osa_adb_get_policy(handle->policy_db, name, &t))) {
+ case OSA_ADB_OK:
+ break;
+ case OSA_ADB_NOENT:
+ return KADM5_UNK_POLICY;
+ default:
+ return ret;
+ }
+ if ((entry->policy = (char *) malloc(strlen(t->name) + 1)) == NULL) {
+ osa_free_policy_ent(t);
+ return ENOMEM;
+ }
+ strcpy(entry->policy, t->name);
+ entry->pw_min_life = t->pw_min_life;
+ entry->pw_max_life = t->pw_max_life;
+ entry->pw_min_length = t->pw_min_length;
+ entry->pw_min_classes = t->pw_min_classes;
+ entry->pw_history_num = t->pw_history_num;
+ entry->policy_refcnt = t->policy_refcnt;
+ osa_free_policy_ent(t);
+
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ new = (kadm5_policy_ent_t) malloc(sizeof(kadm5_policy_ent_rec));
+ if (new == NULL) {
+ free(entry->policy);
+ osa_free_policy_ent(t);
+ return ENOMEM;
+ }
+ *new = *entry;
+ *entry_orig = new;
+ }
+
+ return KADM5_OK;
+}
diff --git a/src/lib/kadm5/svr_principal.c b/src/lib/kadm5/svr_principal.c
new file mode 100644
index 000000000..6f9671fcf
--- /dev/null
+++ b/src/lib/kadm5/svr_principal.c
@@ -0,0 +1,1350 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ *
+ * $Header$
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <kadm5/admin.h>
+#include "adb.h"
+#include "k5-int.h"
+#include <krb5/kdb.h>
+#include <stdio.h>
+#include <string.h>
+#include "server_internal.h"
+#include <stdarg.h>
+#include <stdlib.h>
+
+extern krb5_principal master_princ;
+extern krb5_principal hist_princ;
+extern krb5_encrypt_block master_encblock;
+extern krb5_encrypt_block hist_encblock;
+extern krb5_keyblock master_keyblock;
+extern krb5_keyblock hist_key;
+extern krb5_db_entry master_db;
+extern krb5_db_entry hist_db;
+extern krb5_kvno hist_kvno;
+
+static int decrypt_key_data(krb5_context context,
+ int n_key_data, krb5_key_data *key_data,
+ krb5_keyblock **keyblocks, int *n_keys);
+
+/*
+ * XXX Functions that ought to be in libkrb5.a, but aren't.
+ */
+int krb5_free_keyblock_contents(context, key)
+ krb5_context context;
+ krb5_keyblock *key;
+{
+ memset(key->contents, 0, key->length);
+ krb5_xfree(key->contents);
+ return 0;
+}
+
+kadm5_ret_t krb5_copy_key_data_contents(context, from, to)
+ krb5_context context;
+ krb5_key_data *from, *to;
+{
+ int i, idx;
+
+ *to = *from;
+
+ idx = (from->key_data_ver == 1 ? 1 : 2);
+
+ for (i = 0; i < idx; i++) {
+ to->key_data_contents[i] = malloc(from->key_data_length[i]);
+ if (to->key_data_contents[i] == NULL) {
+ for (i = 0; i < idx; i++) {
+ if (to->key_data_contents[i]) {
+ memset(to->key_data_contents[i], 0,
+ to->key_data_length[i]);
+ free(to->key_data_contents[i]);
+ }
+ }
+ return ENOMEM;
+ }
+ memcpy(to->key_data_contents[i], from->key_data_contents[i],
+ from->key_data_length[i]);
+ }
+ return 0;
+}
+
+static krb5_tl_data *dup_tl_data(krb5_tl_data *tl)
+{
+ krb5_tl_data *n;
+
+ n = (krb5_tl_data *) malloc(sizeof(krb5_tl_data));
+ if (n == NULL)
+ return NULL;
+ n->tl_data_contents = malloc(tl->tl_data_length);
+ if (n->tl_data_contents == NULL) {
+ free(n);
+ return NULL;
+ }
+ memcpy(n->tl_data_contents, tl->tl_data_contents, tl->tl_data_length);
+ n->tl_data_type = tl->tl_data_type;
+ n->tl_data_length = tl->tl_data_length;
+ n->tl_data_next = NULL;
+ return n;
+}
+
+kadm5_ret_t
+kadm5_create_principal(void *server_handle,
+ kadm5_principal_ent_t entry, long mask,
+ char *password)
+{
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ kadm5_policy_ent_rec polent;
+ krb5_int32 now;
+ krb5_tl_data *tl_data_orig, *tl_data_tail;
+ unsigned int ret;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ /*
+ * Argument sanity checking, and opening up the DB
+ */
+ if(!(mask & KADM5_PRINCIPAL) || (mask & KADM5_MOD_NAME) ||
+ (mask & KADM5_MOD_TIME) || (mask & KADM5_LAST_PWD_CHANGE) ||
+ (mask & KADM5_MKVNO) || (mask & KADM5_POLICY_CLR) ||
+ (mask & KADM5_AUX_ATTRIBUTES) || (mask & KADM5_KEY_DATA) ||
+ (mask & KADM5_LAST_SUCCESS) || (mask & KADM5_LAST_FAILED) ||
+ (mask & KADM5_FAIL_AUTH_COUNT))
+ return KADM5_BAD_MASK;
+ if((mask & ~ALL_PRINC_MASK))
+ return KADM5_BAD_MASK;
+ if (entry == (kadm5_principal_ent_t) NULL || password == NULL)
+ return EINVAL;
+
+ /*
+ * Check to see if the principal exists
+ */
+ ret = kdb_get_entry(handle, entry->principal, &kdb, &adb);
+
+ switch(ret) {
+ case KADM5_UNK_PRINC:
+ break;
+ case 0:
+ kdb_free_entry(handle, &kdb, &adb);
+ return KADM5_DUP;
+ default:
+ return ret;
+ }
+
+ memset(&kdb, 0, sizeof(krb5_db_entry));
+ memset(&adb, 0, sizeof(osa_princ_ent_rec));
+
+ /*
+ * If a policy was specified, load it.
+ * If we can not find the one specified return an error
+ */
+ if ((mask & KADM5_POLICY)) {
+ if ((ret = kadm5_get_policy(handle->lhandle, entry->policy,
+ &polent)) != KADM5_OK) {
+ if(ret == EINVAL)
+ return KADM5_BAD_POLICY;
+ else
+ return ret;
+ }
+ }
+ if (ret = passwd_check(handle, password, (mask & KADM5_POLICY),
+ &polent, entry->principal)) {
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return ret;
+ }
+ /*
+ * Start populating the various DB fields, using the
+ * "defaults" for fields that were not specified by the
+ * mask.
+ */
+ if (ret = krb5_timeofday(handle->context, &now)) {
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return ret;
+ }
+
+ kdb.magic = KRB5_KDB_MAGIC_NUMBER;
+ kdb.len = KRB5_KDB_V1_BASE_LENGTH; /* gag me with a chainsaw */
+
+ if ((mask & KADM5_ATTRIBUTES))
+ kdb.attributes = entry->attributes;
+ else
+ kdb.attributes = handle->params.flags;
+
+ if ((mask & KADM5_MAX_LIFE))
+ kdb.max_life = entry->max_life;
+ else
+ kdb.max_life = handle->params.max_life;
+
+ if (mask & KADM5_MAX_RLIFE)
+ kdb.max_renewable_life = entry->max_renewable_life;
+ else
+ kdb.max_renewable_life = handle->params.max_rlife;
+
+ if ((mask & KADM5_PRINC_EXPIRE_TIME))
+ kdb.expiration = entry->princ_expire_time;
+ else
+ kdb.expiration = handle->params.expiration;
+
+ kdb.pw_expiration = 0;
+ if ((mask & KADM5_POLICY)) {
+ if(polent.pw_max_life)
+ kdb.pw_expiration = now + polent.pw_max_life;
+ else
+ kdb.pw_expiration = 0;
+ }
+ if ((mask & KADM5_PW_EXPIRATION)) {
+ if(!kdb.pw_expiration)
+ kdb.pw_expiration = entry->pw_expiration;
+ else {
+ if(entry->pw_expiration != 0)
+ kdb.pw_expiration = (entry->pw_expiration < kdb.pw_expiration) ?
+ entry->pw_expiration : kdb.pw_expiration;
+ }
+ }
+
+ kdb.last_success = 0;
+ kdb.last_failed = 0;
+ kdb.fail_auth_count = 0;
+
+ /* this is kind of gross, but in order to free the tl data, I need
+ to free the entire kdb entry, and that will try to free the
+ principal. */
+
+ if (ret = krb5_copy_principal(handle->context,
+ entry->principal, &(kdb.princ))) {
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return(ret);
+ }
+
+ if (ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now)) {
+ krb5_dbe_free_contents(handle->context, &kdb);
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return(ret);
+ }
+
+ /* initialize the keys */
+
+ if (ret = krb5_dbe_cpw(handle->context, &master_encblock,
+ handle->params.keysalts,
+ handle->params.num_keysalts,
+ password,
+ (mask & KADM5_KVNO)?entry->kvno:1, &kdb)) {
+ krb5_dbe_free_contents(handle->context, &kdb);
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return(ret);
+ }
+
+ /* populate the admin-server-specific fields. In the OV server,
+ this used to be in a separate database. Since there's already
+ marshalling code for the admin fields, to keep things simple,
+ I'm going to keep it, and make all the admin stuff occupy a
+ single tl_data record, */
+
+ adb.admin_history_kvno = hist_kvno;
+ if ((mask & KADM5_POLICY)) {
+ adb.aux_attributes = KADM5_POLICY;
+
+ /* this does *not* need to be strdup'ed, because adb is xdr */
+ /* encoded in osa_adb_create_princ, and not ever freed */
+
+ adb.policy = entry->policy;
+ }
+
+ /* increment the policy ref count, if any */
+
+ if ((mask & KADM5_POLICY)) {
+ polent.policy_refcnt++;
+ if ((ret = kadm5_modify_policy_internal(handle->lhandle, &polent,
+ KADM5_REF_COUNT))
+ != KADM5_OK) {
+ krb5_dbe_free_contents(handle->context, &kdb);
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return(ret);
+ }
+ }
+
+ if (mask & KADM5_TL_DATA) {
+ /* splice entry->tl_data onto the front of kdb.tl_data */
+ tl_data_orig = kdb.tl_data;
+ for (tl_data_tail = entry->tl_data; tl_data_tail->tl_data_next;
+ tl_data_tail = tl_data_tail->tl_data_next)
+ ;
+ tl_data_tail->tl_data_next = kdb.tl_data;
+ kdb.tl_data = entry->tl_data;
+ }
+
+ /* store the new db entry */
+ ret = kdb_put_entry(handle, &kdb, &adb);
+
+ if (mask & KADM5_TL_DATA) {
+ /* remove entry->tl_data from the front of kdb.tl_data */
+ tl_data_tail->tl_data_next = NULL;
+ kdb.tl_data = tl_data_orig;
+ }
+
+ krb5_dbe_free_contents(handle->context, &kdb);
+
+ if (ret) {
+ if ((mask & KADM5_POLICY)) {
+ /* decrement the policy ref count */
+
+ polent.policy_refcnt--;
+ /*
+ * if this fails, there's nothing we can do anyway. the
+ * policy refcount wil be too high.
+ */
+ (void) kadm5_modify_policy_internal(handle->lhandle, &polent,
+ KADM5_REF_COUNT);
+ }
+
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ return(ret);
+ }
+
+ if (mask & KADM5_POLICY)
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+
+ return KADM5_OK;
+}
+
+
+kadm5_ret_t
+kadm5_delete_principal(void *server_handle, krb5_principal principal)
+{
+ unsigned int ret;
+ kadm5_policy_ent_rec polent;
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if (principal == NULL)
+ return EINVAL;
+
+ if (ret = kdb_get_entry(handle, principal, &kdb, &adb))
+ return(ret);
+
+ if ((adb.aux_attributes & KADM5_POLICY)) {
+ if ((ret = kadm5_get_policy(handle->lhandle,
+ adb.policy, &polent))
+ == KADM5_OK) {
+ polent.policy_refcnt--;
+ if ((ret = kadm5_modify_policy_internal(handle->lhandle, &polent,
+ KADM5_REF_COUNT))
+ != KADM5_OK) {
+ (void) kadm5_free_policy_ent(handle->lhandle, &polent);
+ kdb_free_entry(handle, &kdb, &adb);
+ return(ret);
+ }
+ }
+ if (ret = kadm5_free_policy_ent(handle->lhandle, &polent)) {
+ kdb_free_entry(handle, &kdb, &adb);
+ return ret;
+ }
+ }
+
+ ret = kdb_delete_entry(handle, principal);
+
+ kdb_free_entry(handle, &kdb, &adb);
+
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_modify_principal(void *server_handle,
+ kadm5_principal_ent_t entry, long mask)
+{
+ int ret, ret2, i;
+ kadm5_policy_ent_rec npol, opol;
+ int have_npol = 0, have_opol = 0;
+ krb5_db_entry kdb;
+ krb5_tl_data *tl_data_orig, *tl_data_tail;
+ osa_princ_ent_rec adb;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if((mask & KADM5_PRINCIPAL) || (mask & KADM5_LAST_PWD_CHANGE) ||
+ (mask & KADM5_MOD_TIME) || (mask & KADM5_MOD_NAME) ||
+ (mask & KADM5_MKVNO) || (mask & KADM5_AUX_ATTRIBUTES) ||
+ (mask & KADM5_KEY_DATA) || (mask & KADM5_LAST_SUCCESS) ||
+ (mask & KADM5_LAST_FAILED))
+ return KADM5_BAD_MASK;
+ if((mask & ~ALL_PRINC_MASK))
+ return KADM5_BAD_MASK;
+ if((mask & KADM5_POLICY) && (mask & KADM5_POLICY_CLR))
+ return KADM5_BAD_MASK;
+ if(entry == (kadm5_principal_ent_t) NULL)
+ return EINVAL;
+
+ if (ret = kdb_get_entry(handle, entry->principal, &kdb, &adb))
+ return(ret);
+
+ /*
+ * This is pretty much the same as create ...
+ */
+
+ if ((mask & KADM5_POLICY)) {
+ ret = kadm5_get_policy(handle->lhandle, entry->policy, &npol);
+ switch(ret) {
+ case EINVAL:
+ ret = KADM5_BAD_POLICY;
+ break;
+ case KADM5_UNK_POLICY:
+ case KADM5_BAD_POLICY:
+ ret = KADM5_UNK_POLICY;
+ goto done;
+ break;
+ case KADM5_OK:
+ have_npol = 1;
+ if(adb.aux_attributes & KADM5_POLICY) {
+ if(strcmp(adb.policy, entry->policy)) {
+ ret = kadm5_get_policy(handle->lhandle,
+ adb.policy, &opol);
+ switch(ret) {
+ case EINVAL:
+ case KADM5_BAD_POLICY:
+ case KADM5_UNK_POLICY:
+ break;
+ case KADM5_OK:
+ have_opol = 1;
+ opol.policy_refcnt--;
+ break;
+ default:
+ goto done;
+ break;
+ }
+ npol.policy_refcnt++;
+ }
+ } else npol.policy_refcnt++;
+ adb.aux_attributes |= KADM5_POLICY;
+ if (adb.policy)
+ free(adb.policy);
+ adb.policy = strdup(entry->policy);
+ if (npol.pw_max_life) {
+ if (ret =
+ krb5_dbe_lookup_last_pwd_change(handle->context, &kdb,
+ &(kdb.pw_expiration)))
+ goto done;
+ kdb.pw_expiration += npol.pw_max_life;
+ } else {
+ kdb.pw_expiration = 0;
+ }
+ break;
+ default:
+ goto done;
+ }
+ if ((mask & KADM5_PW_EXPIRATION)) {
+ if(kdb.pw_expiration == 0)
+ kdb.pw_expiration = entry->pw_expiration;
+ else if(entry->pw_expiration != 0)
+ kdb.pw_expiration = (entry->pw_expiration < kdb.pw_expiration) ?
+ entry->pw_expiration : kdb.pw_expiration;
+ }
+ }
+ if ((mask & KADM5_PW_EXPIRATION) && !(mask & KADM5_POLICY)) {
+ if(kdb.pw_expiration == 0)
+ kdb.pw_expiration = entry->pw_expiration;
+ else if(entry->pw_expiration != 0)
+ kdb.pw_expiration = (entry->pw_expiration < kdb.pw_expiration) ?
+ entry->pw_expiration : kdb.pw_expiration;
+ }
+
+ if ((mask & KADM5_POLICY_CLR)) {
+ if (adb.aux_attributes & KADM5_POLICY) {
+ adb.aux_attributes &= ~KADM5_POLICY;
+ kdb.pw_expiration = 0;
+ ret = kadm5_get_policy(handle->lhandle, adb.policy, &opol);
+ switch(ret) {
+ case EINVAL:
+ case KADM5_BAD_POLICY:
+ case KADM5_UNK_POLICY:
+ ret = KADM5_BAD_DB;
+ goto done;
+ break;
+ case KADM5_OK:
+ have_opol = 1;
+ if (adb.policy)
+ free(adb.policy);
+ adb.policy = NULL;
+ opol.policy_refcnt--;
+ break;
+ default:
+ goto done;
+ break;
+ }
+ }
+ }
+ if (((mask & KADM5_POLICY) ||
+ (mask & KADM5_POLICY_CLR)) &&
+ (((have_opol) &&
+ (ret =
+ kadm5_modify_policy_internal(handle->lhandle, &opol,
+ KADM5_REF_COUNT))) ||
+ ((have_npol) &&
+ (ret =
+ kadm5_modify_policy_internal(handle->lhandle, &npol,
+ KADM5_REF_COUNT)))))
+ goto done;
+
+ if ((mask & KADM5_ATTRIBUTES))
+ kdb.attributes = entry->attributes;
+ if ((mask & KADM5_MAX_LIFE))
+ kdb.max_life = entry->max_life;
+ if ((mask & KADM5_PRINC_EXPIRE_TIME))
+ kdb.expiration = entry->princ_expire_time;
+ /* the pw_expiration logic would go here if it wasn't spread
+ all over the policy code */
+ if (mask & KADM5_MAX_RLIFE)
+ kdb.max_renewable_life = entry->max_renewable_life;
+ if (mask & KADM5_FAIL_AUTH_COUNT)
+ kdb.fail_auth_count = entry->fail_auth_count;
+
+ if((mask & KADM5_KVNO)) {
+ for (i = 0; i < kdb.n_key_data; i++)
+ kdb.key_data[i].key_data_kvno = entry->kvno;
+ }
+
+ if (mask & KADM5_TL_DATA) {
+ /* splice entry->tl_data onto the front of kdb.tl_data */
+ tl_data_orig = kdb.tl_data;
+ for (tl_data_tail = entry->tl_data; tl_data_tail->tl_data_next;
+ tl_data_tail = tl_data_tail->tl_data_next)
+ ;
+ tl_data_tail->tl_data_next = kdb.tl_data;
+ kdb.tl_data = entry->tl_data;
+ }
+
+ if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+ goto done;
+
+ if (mask & KADM5_TL_DATA) {
+ /* remove entry->tl_data from the front of kdb.tl_data */
+ tl_data_tail->tl_data_next = NULL;
+ kdb.tl_data = tl_data_orig;
+ }
+
+ ret = KADM5_OK;
+done:
+ if (have_opol) {
+ ret2 = kadm5_free_policy_ent(handle->lhandle, &opol);
+ ret = ret ? ret : ret2;
+ }
+ if (have_npol) {
+ ret2 = kadm5_free_policy_ent(handle->lhandle, &npol);
+ ret = ret ? ret : ret2;
+ }
+ kdb_free_entry(handle, &kdb, &adb);
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_rename_principal(void *server_handle,
+ krb5_principal source, krb5_principal target)
+{
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ int ret, i;
+ kadm5_server_handle_t handle = server_handle;
+
+ CHECK_HANDLE(server_handle);
+
+ if (source == NULL || target == NULL)
+ return EINVAL;
+
+ if ((ret = kdb_get_entry(handle, target, &kdb, &adb)) == 0) {
+ kdb_free_entry(handle, &kdb, &adb);
+ return(KADM5_DUP);
+ }
+
+ if ((ret = kdb_get_entry(handle, source, &kdb, &adb)))
+ return ret;
+
+ /* this is kinda gross, but unavoidable */
+
+ for (i=0; i<kdb.n_key_data; i++) {
+ if ((kdb.key_data[i].key_data_ver == 1) ||
+ (kdb.key_data[i].key_data_type[1] == KRB5_KDB_SALTTYPE_NORMAL)) {
+ ret = KADM5_NO_RENAME_SALT;
+ goto done;
+ }
+ }
+
+ krb5_free_principal(handle->context, kdb.princ);
+ if (ret = krb5_copy_principal(handle->context, target, &kdb.princ)) {
+ kdb.princ = NULL; /* so freeing the dbe doesn't lose */
+ goto done;
+ }
+
+ if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+ goto done;
+
+ ret = kdb_delete_entry(handle, source);
+
+done:
+ kdb_free_entry(handle, &kdb, &adb);
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_get_principal(void *server_handle, krb5_principal principal,
+ kadm5_principal_ent_t entry,
+ long in_mask)
+{
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ osa_adb_ret_t ret = 0;
+ long mask;
+ int i;
+ kadm5_server_handle_t handle = server_handle;
+ kadm5_principal_ent_rec entry_local, *entry_orig;
+
+ CHECK_HANDLE(server_handle);
+
+ /*
+ * In version 1, all the defined fields are always returned.
+ * entry is a pointer to a kadm5_principal_ent_t_v1 that should be
+ * filled with allocated memory.
+ */
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ mask = KADM5_PRINCIPAL_NORMAL_MASK;
+ entry_orig = entry;
+ entry = &entry_local;
+ } else {
+ mask = in_mask;
+ }
+
+ memset((char *) entry, 0, sizeof(*entry));
+
+ if (principal == NULL)
+ return EINVAL;
+
+ if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+ return ret;
+
+ if ((mask & KADM5_POLICY) &&
+ adb.policy && (adb.aux_attributes & KADM5_POLICY)) {
+ if ((entry->policy = (char *) malloc(strlen(adb.policy) + 1)) == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ strcpy(entry->policy, adb.policy);
+ }
+
+ if (mask & KADM5_AUX_ATTRIBUTES)
+ entry->aux_attributes = adb.aux_attributes;
+
+ if ((mask & KADM5_PRINCIPAL) &&
+ (ret = krb5_copy_principal(handle->context, principal,
+ &entry->principal))) {
+ goto done;
+ }
+
+ if (mask & KADM5_PRINC_EXPIRE_TIME)
+ entry->princ_expire_time = kdb.expiration;
+
+ if ((mask & KADM5_LAST_PWD_CHANGE) &&
+ (ret = krb5_dbe_lookup_last_pwd_change(handle->context, &kdb,
+ &(entry->last_pwd_change)))) {
+ goto done;
+ }
+
+ if (mask & KADM5_PW_EXPIRATION)
+ entry->pw_expiration = kdb.pw_expiration;
+ if (mask & KADM5_MAX_LIFE)
+ entry->max_life = kdb.max_life;
+
+ /* this is a little non-sensical because the function returns two */
+ /* values that must be checked separately against the mask */
+ if ((mask & KADM5_MOD_NAME) || (mask & KADM5_MOD_TIME)) {
+ if (ret = krb5_dbe_lookup_mod_princ_data(handle->context, &kdb,
+ &(entry->mod_date),
+ &(entry->mod_name))) {
+ goto done;
+ }
+ if (! (mask & KADM5_MOD_TIME))
+ entry->mod_date = 0;
+ if (! (mask & KADM5_MOD_NAME)) {
+ krb5_free_principal(handle->context, entry->principal);
+ entry->principal = NULL;
+ }
+ }
+
+ if (mask & KADM5_ATTRIBUTES)
+ entry->attributes = kdb.attributes;
+
+ if (mask & KADM5_KVNO)
+ for (entry->kvno = 0, i=0; i<kdb.n_key_data; i++)
+ if (kdb.key_data[i].key_data_kvno > entry->kvno)
+ entry->kvno = kdb.key_data[i].key_data_kvno;
+
+ if (handle->api_version == KADM5_API_VERSION_2)
+ entry->mkvno = 0;
+ else {
+ /* XXX I'll be damned if I know how to deal with this one --marc */
+ entry->mkvno = 1;
+ }
+
+ /*
+ * The new fields that only exist in version 2 start here
+ */
+ if (handle->api_version == KADM5_API_VERSION_2) {
+ if (mask & KADM5_MAX_RLIFE)
+ entry->max_renewable_life = kdb.max_renewable_life;
+ if (mask & KADM5_LAST_SUCCESS)
+ entry->last_success = kdb.last_success;
+ if (mask & KADM5_LAST_FAILED)
+ entry->last_failed = kdb.last_failed;
+ if (mask & KADM5_FAIL_AUTH_COUNT)
+ entry->fail_auth_count = kdb.fail_auth_count;
+ if (mask & KADM5_TL_DATA) {
+ krb5_tl_data td, *tl, *tl2;
+
+ entry->n_tl_data = kdb.n_tl_data;
+ entry->tl_data = NULL;
+
+ tl = kdb.tl_data;
+ while (tl) {
+ if ((tl2 = dup_tl_data(tl)) == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ tl2->tl_data_next = entry->tl_data;
+ entry->tl_data = tl2;
+
+ tl = tl->tl_data_next;
+ }
+
+ if (kdb.e_length) {
+ td.tl_data_type = KRB5_TL_KADM5_E_DATA;
+ td.tl_data_length = kdb.e_length;
+ td.tl_data_contents = kdb.e_data;
+
+ if ((tl = dup_tl_data(&td)) == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ tl->tl_data_next = entry->tl_data;
+ entry->tl_data = tl;
+ }
+ }
+ if (mask & KADM5_KEY_DATA) {
+ entry->n_key_data = kdb.n_key_data;
+ entry->key_data = (krb5_key_data *)
+ malloc(entry->n_key_data*sizeof(krb5_key_data));
+ if (entry->key_data == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ for (i = 0; i < entry->n_key_data; i++)
+ if (ret = krb5_copy_key_data_contents(handle->context,
+ &kdb.key_data[i],
+ &entry->key_data[i]))
+ goto done;
+ }
+ }
+
+ /*
+ * If KADM5_API_VERSION_1, we return an allocated structure, and
+ * we need to convert the new structure back into the format the
+ * caller is expecting.
+ */
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ kadm5_principal_ent_t_v1 newv1;
+
+ newv1 = ((kadm5_principal_ent_t_v1) calloc(1, sizeof(*newv1)));
+ if (newv1 == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ newv1->principal = entry->principal;
+ newv1->princ_expire_time = entry->princ_expire_time;
+ newv1->last_pwd_change = entry->last_pwd_change;
+ newv1->pw_expiration = entry->pw_expiration;
+ newv1->max_life = entry->max_life;
+ newv1->mod_name = entry->mod_name;
+ newv1->mod_date = entry->mod_date;
+ newv1->attributes = entry->attributes;
+ newv1->kvno = entry->kvno;
+ newv1->mkvno = entry->mkvno;
+ newv1->policy = entry->policy;
+ newv1->aux_attributes = entry->aux_attributes;
+
+ *((kadm5_principal_ent_t_v1 *) entry_orig) = newv1;
+ }
+
+ ret = KADM5_OK;
+
+done:
+ if (ret && entry->principal)
+ krb5_free_principal(handle->context, entry->principal);
+ kdb_free_entry(handle, &kdb, &adb);
+
+ return ret;
+}
+
+/*
+ * Function: check_pw_reuse
+ *
+ * Purpose: Check if a key appears in a list of keys, in order to
+ * enforce password history.
+ *
+ * Arguments:
+ *
+ * context (r) the krb5 context
+ * histkey_encblock (r) the encblock that hist_key_data is
+ * encrypted in
+ * n_new_key_data (r) length of new_key_data
+ * new_key_data (r) keys to check against
+ * pw_hist_data, encrypted in histkey_encblock
+ * n_pw_hist_data (r) length of pw_hist_data
+ * pw_hist_data (r) passwords to check new_key_data against
+ *
+ * Effects:
+ * For each new_key in new_key_data:
+ * decrypt new_key with the master_encblock
+ * for each password in pw_hist_data:
+ * for each hist_key in password:
+ * decrypt hist_key with histkey_encblock
+ * compare the new_key and hist_key
+ *
+ * Returns krb5 errors, KADM5_PASS_RESUSE if a key in
+ * new_key_data is the same as a key in pw_hist_data, or 0.
+ */
+static kadm5_ret_t
+check_pw_reuse(krb5_context context,
+ krb5_encrypt_block *histkey_encblock,
+ int n_new_key_data, krb5_key_data *new_key_data,
+ int n_pw_hist_data, osa_pw_hist_ent *pw_hist_data)
+{
+ int x, y, z;
+ krb5_keyblock newkey, histkey;
+ krb5_error_code ret;
+
+ for (x = 0; x < n_new_key_data; x++) {
+ if (ret = krb5_dbekd_decrypt_key_data(context,
+ &master_encblock,
+ &(new_key_data[x]),
+ &newkey, NULL))
+ return(ret);
+ for (y = 0; y < n_pw_hist_data; y++) {
+ for (z = 0; z < pw_hist_data[y].n_key_data; z++) {
+ if (ret =
+ krb5_dbekd_decrypt_key_data(context,
+ histkey_encblock,
+ &pw_hist_data[y].key_data[z],
+ &histkey, NULL))
+ return(ret);
+
+ if ((newkey.length == histkey.length) &&
+ (newkey.enctype == histkey.enctype) &&
+ (memcmp(newkey.contents, histkey.contents,
+ histkey.length) == 0)) {
+ krb5_free_keyblock_contents(context, &histkey);
+ krb5_free_keyblock_contents(context, &newkey);
+
+ return(KADM5_PASS_REUSE);
+ }
+ krb5_free_keyblock_contents(context, &histkey);
+ }
+ }
+ krb5_free_keyblock_contents(context, &newkey);
+ }
+
+ return(0);
+}
+
+/*
+ * Function: create_history_entry
+ *
+ * Purpose: Creates a password history entry from an array of
+ * key_data.
+ *
+ * Arguments:
+ *
+ * context (r) krb5_context to use
+ * n_key_data (r) number of elements in key_data
+ * key_data (r) keys to add to the history entry
+ * hist (w) history entry to fill in
+ *
+ * Effects:
+ *
+ * hist->key_data is allocated to store n_key_data key_datas. Each
+ * element of key_data is decrypted with master_encblock, re-encrypted
+ * in hist_encblock, and added to hist->key_data. hist->n_key_data is
+ * set to n_key_data.
+ */
+int create_history_entry(krb5_context context, int n_key_data,
+ krb5_key_data *key_data, osa_pw_hist_ent *hist)
+{
+ int i, ret;
+ krb5_keyblock key;
+ krb5_keysalt salt;
+
+ hist->key_data = (krb5_key_data*)malloc(n_key_data*sizeof(krb5_key_data));
+ if (hist->key_data == NULL)
+ return ENOMEM;
+ memset(hist->key_data, 0, n_key_data*sizeof(krb5_key_data));
+
+ for (i = 0; i < n_key_data; i++) {
+ if (ret = krb5_dbekd_decrypt_key_data(context,
+ &master_encblock,
+ &key_data[i],
+ &key, &salt))
+ return ret;
+ if (ret = krb5_dbekd_encrypt_key_data(context,
+ &hist_encblock,
+ &key, &salt,
+ key_data[i].key_data_kvno,
+ &hist->key_data[i]))
+ return ret;
+ krb5_free_keyblock_contents(context, &key);
+ /* krb5_free_keysalt(context, &salt); */
+ }
+
+ hist->n_key_data = n_key_data;
+ return 0;
+}
+
+int free_history_entry(krb5_context context, osa_pw_hist_ent *hist)
+{
+ int i;
+
+ for (i = 0; i < hist->n_key_data; i++)
+ krb5_free_key_data_contents(context, &hist->key_data[i]);
+ free(hist->key_data);
+}
+
+/*
+ * Function: add_to_history
+ *
+ * Purpose: Adds a password to a principal's password history.
+ *
+ * Arguments:
+ *
+ * context (r) krb5_context to use
+ * adb (r/w) admin principal entry to add keys to
+ * pol (r) adb's policy
+ * pw (r) keys for the password to add to adb's key history
+ *
+ * Effects:
+ *
+ * add_to_history adds a single password to adb's password history.
+ * pw contains n_key_data keys in its key_data, in storage should be
+ * allocated but not freed by the caller (XXX blech!).
+ *
+ * This function maintains adb->old_keys as a circular queue. It
+ * starts empty, and grows each time this function is called until it
+ * is pol->pw_history_num items long. adb->old_key_len holds the
+ * number of allocated entries in the array, and must therefore be [0,
+ * pol->pw_history_num). adb->old_key_next is the index into the
+ * array where the next element should be written, and must be [0,
+ * adb->old_key_len).
+ */
+static kadm5_ret_t add_to_history(krb5_context context,
+ osa_princ_ent_t adb,
+ kadm5_policy_ent_t pol,
+ osa_pw_hist_ent *pw)
+{
+ osa_pw_hist_ent hist, *histp;
+ int ret, i;
+
+ /* A history of 1 means just check the current password */
+ if (pol->pw_history_num == 1)
+ return 0;
+
+ /* resize the adb->old_keys array if necessary */
+ if (adb->old_key_len < pol->pw_history_num-1) {
+ adb->old_keys = (osa_pw_hist_ent *)
+ realloc(adb->old_keys,
+ (adb->old_key_len+1)*sizeof(osa_pw_hist_ent));
+ if (adb->old_keys == NULL)
+ return(ENOMEM);
+
+ memset(&adb->old_keys[adb->old_key_len],0,sizeof(osa_pw_hist_ent));
+ adb->old_key_len++;
+ }
+
+ /* free the old pw history entry if it contains data */
+ histp = &adb->old_keys[adb->old_key_next];
+ for (i = 0; i < histp->n_key_data; i++)
+ krb5_free_key_data_contents(context, &histp->key_data[i]);
+
+ /* store the new entry */
+ adb->old_keys[adb->old_key_next] = *pw;
+
+ /* update the next pointer */
+ if (++adb->old_key_next == pol->pw_history_num-1)
+ adb->old_key_next = 0;
+
+ return(0);
+}
+
+kadm5_ret_t
+kadm5_chpass_principal(void *server_handle,
+ krb5_principal principal, char *password)
+{
+ krb5_int32 now;
+ kadm5_policy_ent_rec pol;
+ osa_princ_ent_rec adb;
+ krb5_db_entry kdb, kdb_save;
+ int ret, ret2, last_pwd, i, hist_added;
+ int have_pol = 0;
+ kadm5_server_handle_t handle = server_handle;
+ osa_pw_hist_ent hist;
+
+ CHECK_HANDLE(server_handle);
+
+ hist_added = 0;
+ memset(&hist, 0, sizeof(hist));
+
+ if (principal == NULL || password == NULL)
+ return EINVAL;
+ if ((krb5_principal_compare(handle->context,
+ principal, hist_princ)) == TRUE)
+ return KADM5_PROTECT_PRINCIPAL;
+
+ if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+ return(ret);
+
+ /* we are going to need the current keys after the new keys are set */
+ if ((ret = kdb_get_entry(handle, principal, &kdb_save, NULL))) {
+ kdb_free_entry(handle, &kdb, &adb);
+ return(ret);
+ }
+
+ if ((adb.aux_attributes & KADM5_POLICY)) {
+ if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, &pol)))
+ goto done;
+ have_pol = 1;
+ }
+
+ if ((ret = passwd_check(handle, password, adb.aux_attributes &
+ KADM5_POLICY, &pol, principal)))
+ goto done;
+
+ if (ret = krb5_dbe_cpw(handle->context, &master_encblock,
+ handle->params.keysalts,
+ handle->params.num_keysalts,
+ password, 0 /* increment kvno */, &kdb))
+ goto done;
+
+ kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+ if (ret = krb5_timeofday(handle->context, &now))
+ goto done;
+
+ if ((adb.aux_attributes & KADM5_POLICY)) {
+ /* the policy was loaded before */
+
+ if (ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+ &kdb, &last_pwd))
+ goto done;
+
+#if 0
+ /*
+ * The spec says this check is overridden if the caller has
+ * modify privilege. The admin server therefore makes this
+ * check itself (in chpass_principal_wrapper, misc.c). A
+ * local caller implicitly has all authorization bits.
+ */
+ if ((now - last_pwd) < pol.pw_min_life &&
+ !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+ ret = KADM5_PASS_TOOSOON;
+ goto done;
+ }
+#endif
+
+ if (ret = create_history_entry(handle->context,
+ kdb_save.n_key_data,
+ kdb_save.key_data, &hist))
+ goto done;
+
+ if (ret = check_pw_reuse(handle->context,
+ &hist_encblock,
+ kdb.n_key_data, kdb.key_data,
+ 1, &hist))
+ goto done;
+
+ if (pol.pw_history_num > 1) {
+ if (adb.admin_history_kvno != hist_kvno) {
+ ret = KADM5_BAD_HIST_KEY;
+ goto done;
+ }
+
+ if (ret = check_pw_reuse(handle->context,
+ &hist_encblock,
+ kdb.n_key_data, kdb.key_data,
+ adb.old_key_len, adb.old_keys))
+ goto done;
+
+ if (ret = add_to_history(handle->context, &adb, &pol, &hist))
+ goto done;
+ hist_added = 1;
+ }
+
+ if (pol.pw_max_life)
+ kdb.pw_expiration = now + pol.pw_max_life;
+ else
+ kdb.pw_expiration = 0;
+ } else {
+ kdb.pw_expiration = 0;
+ }
+
+ if (ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now))
+ goto done;
+
+ if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+ goto done;
+
+ ret = KADM5_OK;
+done:
+ if (!hist_added && hist.key_data)
+ free_history_entry(handle->context, &hist);
+ kdb_free_entry(handle, &kdb, &adb);
+ kdb_free_entry(handle, &kdb_save, NULL);
+ krb5_dbe_free_contents(handle->context, &kdb);
+
+ if (have_pol && (ret2 = kadm5_free_policy_ent(handle->lhandle, &pol))
+ && !ret)
+ ret = ret2;
+
+ return ret;
+}
+
+kadm5_ret_t
+kadm5_randkey_principal(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock **keyblocks,
+ int *n_keys)
+{
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ krb5_int32 now;
+ kadm5_policy_ent_rec pol;
+ krb5_key_data *key_data;
+ krb5_keyblock *keyblock;
+ int ret, last_pwd, have_pol = 0;
+ kadm5_server_handle_t handle = server_handle;
+
+ if (keyblocks)
+ *keyblocks = NULL;
+
+ CHECK_HANDLE(server_handle);
+
+ if (principal == NULL)
+ return EINVAL;
+ if (hist_princ && /* this will be NULL when initializing the databse */
+ ((krb5_principal_compare(handle->context,
+ principal, hist_princ)) == TRUE))
+ return KADM5_PROTECT_PRINCIPAL;
+
+ if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+ return(ret);
+
+ if (ret = krb5_dbe_crk(handle->context, &master_encblock,
+ handle->params.keysalts,
+ handle->params.num_keysalts,
+ &kdb))
+ goto done;
+
+ kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+ if (ret = krb5_timeofday(handle->context, &now))
+ goto done;
+
+ if ((adb.aux_attributes & KADM5_POLICY)) {
+ if ((ret = kadm5_get_policy(handle->lhandle, adb.policy,
+ &pol)) != KADM5_OK)
+ goto done;
+ have_pol = 1;
+
+ if (ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+ &kdb, &last_pwd))
+ goto done;
+
+#if 0
+ /*
+ * The spec says this check is overridden if the caller has
+ * modify privilege. The admin server therefore makes this
+ * check itself (in chpass_principal_wrapper, misc.c). A
+ * local caller implicitly has all authorization bits.
+ */
+ if((now - last_pwd) < pol.pw_min_life &&
+ !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+ ret = KADM5_PASS_TOOSOON;
+ goto done;
+ }
+#endif
+
+ if(pol.pw_history_num > 1) {
+ if(adb.admin_history_kvno != hist_kvno) {
+ ret = KADM5_BAD_HIST_KEY;
+ goto done;
+ }
+
+ if (ret = check_pw_reuse(handle->context,
+ &hist_encblock,
+ kdb.n_key_data, kdb.key_data,
+ adb.old_key_len, adb.old_keys))
+ goto done;
+ }
+ if (pol.pw_max_life)
+ kdb.pw_expiration = now + pol.pw_max_life;
+ else
+ kdb.pw_expiration = 0;
+ } else {
+ kdb.pw_expiration = 0;
+ }
+
+ if (ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now))
+ goto done;
+
+ if (keyblocks) {
+ if (handle->api_version == KADM5_API_VERSION_1) {
+ /* Version 1 clients will expect to see a DES_CRC enctype. */
+ if (ret = krb5_dbe_find_enctype(handle->context, &kdb,
+ ENCTYPE_DES_CBC_CRC,
+ -1, -1, &key_data))
+ goto done;
+
+ if (ret = decrypt_key_data(handle->context, 1, key_data,
+ keyblocks, NULL))
+ goto done;
+ } else {
+ ret = decrypt_key_data(handle->context,
+ kdb.n_key_data, kdb.key_data,
+ keyblocks, n_keys);
+ if (ret)
+ goto done;
+ }
+ }
+
+ if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+ goto done;
+
+ ret = KADM5_OK;
+done:
+ kdb_free_entry(handle, &kdb, &adb);
+ if (have_pol)
+ kadm5_free_policy_ent(handle->lhandle, &pol);
+
+ return ret;
+}
+
+/*
+ * Allocate an array of n_key_data krb5_keyblocks, fill in each
+ * element with the results of decrypting the nth key in key_data with
+ * master_encblock, and if n_keys is not NULL fill it in with the
+ * number of keys decrypted.
+ */
+static int decrypt_key_data(krb5_context context,
+ int n_key_data, krb5_key_data *key_data,
+ krb5_keyblock **keyblocks, int *n_keys)
+{
+ krb5_keyblock *keys;
+ int ret, i;
+
+ keys = (krb5_keyblock *) malloc(n_key_data*sizeof(krb5_keyblock));
+ if (keys == NULL)
+ return ENOMEM;
+ memset((char *) keys, 0, n_key_data*sizeof(krb5_keyblock));
+
+ for (i = 0; i < n_key_data; i++) {
+ if (ret = krb5_dbekd_decrypt_key_data(context,
+ &master_encblock,
+ &key_data[i],
+ &keys[i], NULL)) {
+
+ memset((char *) keys, 0, n_key_data*sizeof(krb5_keyblock));
+ free(keys);
+ return ret;
+ }
+ }
+
+ *keyblocks = keys;
+ if (n_keys)
+ *n_keys = n_key_data;
+
+ return 0;
+}
+
+/*
+ * Function: kadm5_decrypt_key
+ *
+ * Purpose: Retrieves and decrypts a principal key.
+ *
+ * Arguments:
+ *
+ * server_handle (r) kadm5 handle
+ * entry (r) principal retrieved with kadm5_get_principal
+ * ktype (r) enctype to search for, or -1 to ignore
+ * stype (r) salt type to search for, or -1 to ignore
+ * kvno (r) kvno to search for, -1 for max, 0 for max
+ * only if it also matches ktype and stype
+ * keyblock (w) keyblock to fill in
+ * keysalt (w) keysalt to fill in, or NULL
+ * kvnop (w) kvno to fill in, or NULL
+ *
+ * Effects: Searches the key_data array of entry, which must have been
+ * retrived with kadm5_get_principal with the KADM5_KEY_DATA mask, to
+ * find a key with a specified enctype, salt type, and kvno in a
+ * principal entry. If not found, return ENOENT. Otherwise, decrypt
+ * it with the master key, and return the key in keyblock, the salt
+ * in salttype, and the key version number in kvno.
+ *
+ * If ktype or stype is -1, it is ignored for the search. If kvno is
+ * -1, ktype and stype are ignored and the key with the max kvno is
+ * returned. If kvno is 0, only the key with the max kvno is returned
+ * and only if it matches the ktype and stype; otherwise, ENOENT is
+ * returned.
+ */
+kadm5_ret_t kadm5_decrypt_key(void *server_handle,
+ kadm5_principal_ent_t entry, krb5_int32
+ ktype, krb5_int32 stype, krb5_int32
+ kvno, krb5_keyblock *keyblock,
+ krb5_keysalt *keysalt, int *kvnop)
+{
+ kadm5_server_handle_t handle = server_handle;
+ krb5_db_entry dbent;
+ krb5_key_data *key_data;
+ int ret;
+
+ CHECK_HANDLE(server_handle);
+
+ if (entry->n_key_data == 0 || entry->key_data == NULL)
+ return EINVAL;
+
+ /* find_enctype only uses these two fields */
+ dbent.n_key_data = entry->n_key_data;
+ dbent.key_data = entry->key_data;
+ if (ret = krb5_dbe_find_enctype(handle->context, &dbent, ktype,
+ stype, kvno, &key_data))
+ return ret;
+
+ if (ret = krb5_dbekd_decrypt_key_data(handle->context,
+ &master_encblock, key_data,
+ keyblock, keysalt))
+ return ret;
+
+ if (kvnop)
+ *kvnop = key_data->key_data_kvno;
+
+ return KADM5_OK;
+}
diff --git a/src/lib/kadm5/unit-test/ChangeLog b/src/lib/kadm5/unit-test/ChangeLog
new file mode 100644
index 000000000..172084c20
--- /dev/null
+++ b/src/lib/kadm5/unit-test/ChangeLog
@@ -0,0 +1,18 @@
+Thu Jul 18 20:18:30 1996 Marc Horowitz <marc@mit.edu>
+
+ * api.2/init-v2.exp (test150, test151): -s flag is now -S
+
+Mon Jul 8 17:00:26 1996 Barry Jaspan <bjaspan@mit.edu>
+
+ * api.2/init-v2.exp: admin databases must now be created before
+ use (not created implicitly)
+
+ * api.1/lock.exp: lock-test 13 should be a warning, not a failure.
+
+ * api.0/rename-principal.exp: fix rename test to create principal
+ with correct salt first, and check explicitly for NO_RENAME_SALT
+ when appropriate
+
+ * lib.t: add create_principal_with_keysalts
+
+
diff --git a/src/lib/kadm5/unit-test/Makefile.ov b/src/lib/kadm5/unit-test/Makefile.ov
new file mode 100644
index 000000000..208bedeb3
--- /dev/null
+++ b/src/lib/kadm5/unit-test/Makefile.ov
@@ -0,0 +1,154 @@
+TOP = ../../../kadmin
+include $(TOP)/config.mk/template
+
+CFLAGS := $(CFLAGS) -DUSE_KADM5_API_VERSION=1
+
+LIBS := $(LIBADMCLNT) $(LIBCOM_ERR) $(LIBRPCLIB) $(LIBDYN) \
+ $(LIBGSSAPI_KRB5) $(LIBKDB5) \
+ $(LIBKRB5) $(LIBCRYPTO) $(LIBISODE) $(LIBTCL) $(LIBM) \
+ $(LIBDB) $(NDBMLIB) $(BSDLIB) $(NETLIB)
+
+INIT_SRCS = init-test.c ../client_init.c
+DESTROY_SRCS = destroy-test.c
+HANDLE_SRCS = handle-test.c
+RANDKEY_SRCS = randkey-test.c
+ITER_SRCS = iter-test.c
+LOCKTEST_SRCS = lock-test.c
+SIZE_SRCS = sizes-test.c
+
+PROG = init-test
+SRCS = $(INIT_SRCS)
+OBJS = init-test.o client_init.o
+
+client_init.o: ../client_init.c
+ $(CC) $(CFLAGS) -DUSE_KADM5_API_VERSION=2 -DINIT_TEST -c -I.. $<
+
+expand Program
+
+PROG = destroy-test
+SRCS = $(DESTROY_SRCS)
+OBJS = destroy-test.o
+
+expand Program
+
+PROG = client-handle-test
+SRCS = $(HANDLE_SRCS)
+OBJS = handle-test.o
+
+expand Program
+
+PROG = client-iter-test
+SRCS = $(ITER_SRCS)
+OBJS = iter-test.o
+
+expand Program
+
+LIBS := $(LIBADMSRV) $(LIBCOM_ERR) $(LIBRPCLIB) $(LIBDYN) \
+ $(LIBGSSAPI_KRB5) $(LIBKDB5) $(LIBKRB5) \
+ $(LIBCRYPTO) $(LIBISODE) $(LIBTCL) $(LIBM) $(LIBDB) \
+ $(NDBMLIB) $(BSDLIB) $(NETLIB)
+
+PROG = randkey-test
+SRCS = $(RANDKEY_SRCS)
+OBJS = randkey-test.o
+
+expand Program
+
+PROG = server-handle-test
+SRCS = $(HANDLE_SRCS)
+OBJS = handle-test.o
+
+expand Program
+
+PROG = lock-test
+SRCS = $(LOCKTEST_SRCS)
+OBJS = lock-test.o
+
+expand Program
+
+LIBS := $(LIBS) $(REGEXLIB)
+PROG = server-iter-test
+SRCS = $(ITER_SRCS)
+OBJS = iter-test.o
+
+expand Program
+
+PROG = sizes-test
+SRCS = $(SIZE_SRCS)
+OBJS = sizes-test.o
+
+expand Program
+
+SRCS = $(INIT_SRCS) $(DESTROY_SRCS) $(HANDLE_SRCS) \
+ $(RANDKEY_SRCS) $(LOCKTEST_SRCS) $(ITER_SRCS) \
+ $(SIZE_SRCS)
+
+expand Depend
+
+unit-test:: unit-test-client unit-test-server
+
+unit-test-client: unit-test-client-setup unit-test-client-body \
+ unit-test-client-cleanup
+
+unit-test-server: unit-test-server-setup unit-test-server-body \
+ unit-test-server-cleanup
+
+test-randkey:: randkey-test
+ ./randkey-test
+
+test-handle-server:: server-handle-test
+ ./server-handle-test
+
+test-handle-client:: client-handle-test
+ ./client-handle-test
+
+test-noauth: init-test
+ ./init-test
+
+test-destroy: destroy-test
+ ./destroy-test
+
+test-sizes: sizes-test
+ ./sizes-test
+
+unit-test-client-setup::
+ $(START_SERVERS)
+
+unit-test-client-cleanup::
+ $(STOP_SERVERS)
+
+unit-test-server-setup::
+ $(START_SERVERS_LOCAL)
+
+unit-test-server-cleanup::
+ $(STOP_SERVERS_LOCAL)
+
+capi.0: api.0
+ -rm -f capi.0
+ ln -s api.0 capi.0
+
+capi.2: api.2
+ -rm -f capi.2
+ ln -s api.2 capi.2
+
+unit-test-client-body: capi.0 capi.2 site.exp test-noauth test-destroy test-handle-client test-sizes
+ $(RUNTEST) --tool capi API=$(CLNTTCL) KDBFIVE_EDIT=$(TOP)/../admin/edit/kdb5_edit KINIT=$(TOP)/../clients/kinit/kinit KDESTROY=$(TOP)/../clients/kdestroy/kdestroy KADMIN_LOCAL=$(TOP)/cli/kadmin.local TOP=$(TOP) RPC=1
+
+sapi.0: api.0
+ -rm -f sapi.0
+ ln -s api.0 sapi.0
+
+sapi.1: api.1
+ -rm -f sapi.1
+ ln -s api.1 sapi.1
+
+sapi.2: api.2
+ -rm -f sapi.2
+ ln -s api.2 sapi.2
+
+unit-test-server-body: sapi.0 sapi.1 sapi.2 site.exp randkey-test test-handle-server \
+ lock-test test-sizes
+ $(RUNTEST) --tool sapi API=$(SRVTCL) LOCKTEST=./lock-test KDBFIVE_EDIT=$(TOP)/../admin/edit/kdb5_edit KADMIN_LOCAL=$(TOP)/cli/kadmin.local TOP=$(TOP) RPC=0
+
+clean::
+ $(CLEAN) -r *.log *.plog *.sum *.psum unit-test-log.*
diff --git a/src/lib/kadm5/unit-test/api.0/chpass-principal.exp b/src/lib/kadm5/unit-test/api.0/chpass-principal.exp
new file mode 100644
index 000000000..12fa3b9d1
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/chpass-principal.exp
@@ -0,0 +1,176 @@
+source lib.t
+api_exit
+api_start
+
+test "chpass-principal 180"
+proc test180 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_chpass_principal $server_handle "%s/a" FoobarBax
+ } $test]
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test180 }
+
+test "chpass-principal 180.5"
+proc test1805 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_chpass_principal $server_handle "%s/a" FoobarBax
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test1805 }
+
+#
+# admin with changepw service tickets try to change other principals
+# password, failes with AUTH error
+test "chpass-principal 180.625"
+proc test180625 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_chpass_principal $server_handle "%s/a" password
+ } $test] "AUTH"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test180625 }
+
+test "chpass-principal 180.75"
+proc test18075 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_chpass_principal $server_handle "%s/a" Foobar
+ } $test] "AUTH_CHANGEPW"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test18075 }
+
+test "chpass-principal 182"
+proc test182 {} {
+ global test
+
+ if { ! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_chpass_principal $server_handle kadmin/history password
+ } "PROTECT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test182
+
+test "chpass-principal 183"
+proc test183 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if { ! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_chpass_principal null "%s/a" password
+ } $test] "BAD_SERVER_HANDLE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test183
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/crte-policy.exp b/src/lib/kadm5/unit-test/api.0/crte-policy.exp
new file mode 100644
index 000000000..dbf4f1cbc
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/crte-policy.exp
@@ -0,0 +1,991 @@
+source lib.t
+api_exit
+api_start
+
+# Description: (1) Fails for mask with undefined bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 1"
+proc test1 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ 0xF01000
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test1
+
+# Description: (2) Fails if caller connected with CHANGEPW_SERVICE.
+test "create-policy 2"
+proc test2 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy";
+ return
+ }
+}
+if {$RPC} { test2 }
+
+# Description: (3) Fails for mask without POLICY bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 3"
+proc test3 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ 0x000000
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test3
+
+# Description: (4) Fails for mask with REF_COUNT bit set.
+test "create-policy 4"
+proc test4 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY OVSEC_KADM_REF_COUNT}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test4
+
+# Description: (5) Fails for invalid policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 5"
+proc test5 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "BAD_POLICY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test5
+
+# Description: (6) Fails for existing policy name.
+test "create-policy 6"
+proc test6 {} {
+ global test
+# set prms_id 777
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_create_policy $server_handle [simple_policy test-pol] \
+ {OVSEC_KADM_POLICY}
+ } "DUP"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test6
+
+# Description: (7) Fails for null policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 7"
+proc test7 {} {
+ global test
+# set prms_id 1977
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_create_policy $server_handle [simple_policy null] \
+ {OVSEC_KADM_POLICY}
+ } "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test7
+
+# Description: (8) Fails for empty-string policy name.
+test "create-policy 8"
+proc test8 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_create_policy $server_handle [simple_policy ""] \
+ {OVSEC_KADM_POLICY}
+ } "BAD_POLICY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test8
+
+# Description: (9) Accepts 0 for pw_min_life.
+test "create-policy 9"
+proc test9 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LIFE}
+ } $test]]} {
+ fail "$test: create failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+# Description: (10) Accepts non-zero for pw_min_life.
+test "create-policy 10"
+proc test10 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 32 0 0 0 0 0 } \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LIFE}
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+# Description: (11) Accepts 0 for pw_max_life.
+test "create-policy 11"
+proc test11 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MAX_LIFE}
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+# Description: (12) Accepts non-zero for pw_max_life.
+test "create-policy 12"
+proc test12 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 32 0 0 0 0 } \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MAX_LIFE}
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+# Description: (13) Rejects 0 for pw_min_length.
+test "create-policy 13"
+proc test13 {} {
+ global test
+ global prompt
+
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LENGTH}
+ } $test] "BAD_LENGTH"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+# Description: (14) Accepts non-zero for pw_min_length.
+test "create-policy 14"
+proc test14 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 8 0 0 0 } \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_LENGTH}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 3\n"
+ expect {
+ -re "8\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+# Description: (15) Rejects 0 for pw_min_classes.
+test "create-policy 15"
+proc test15 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+# Description: (16) Accepts 1 for pw_min_classes.
+test "create-policy 16"
+proc test16 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 1 0 0 } \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test16
+
+# Description: (17) Accepts 4 for pw_min_classes.
+test "create-policy 17"
+proc test17 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "5\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+# Description: (18) Rejects 5 for pw_min_classes.
+test "create-policy 18"
+proc test18 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+# Description: (19) Rejects 0 for pw_history_num.
+test "create-policy 19"
+proc test19 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+ } $test] "BAD_HISTORY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test19
+
+# Description: (20) Accepts 1 for pw_history_num.
+test "create-policy 20"
+proc test20 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test20
+
+# Description: (21) Accepts 10 for pw_history_num.
+test "create-policy 21"
+proc test21 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "10\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21
+
+# Description: (21.5) Rejects 11 for pw_history_num.
+# 01/24/94: pshuang: untried.
+
+test "create-policy 21.5"
+proc test215 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle {"%s/a" 0 0 0 0 11 0} \
+ {OVSEC_KADM_POLICY OVSEC_KADM_PW_HISTORY_NUM}
+ } $test] "BAD_HISTORY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test215
+
+
+# Description: (22) Fails for user with no access bits.
+test "create-policy 22"
+proc test22 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test22
+
+# Description: (23) Fails for user with "get" but not "add".
+test "create-policy 23"
+proc test23 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test23
+
+# Description: (24) Fails for user with "modify" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 24"
+proc test24 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test24
+
+# Description: (25) Fails for user with "delete" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 25"
+proc test25 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test25
+
+# Description: Succeeds for user with "add".
+test "create-policy 26"
+proc test26 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test26
+
+# Description: Succeeds for user with "get" and "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 27"
+proc test27 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test27
+
+# Description: (28) Rejects null policy argument.
+# 01/24/94: pshuang: untried.
+test "create-policy 28"
+proc test28 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_create_policy $server_handle null {OVSEC_KADM_POLICY}
+ } "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "create-policy 30"
+proc test30 {} {
+ global test
+ one_line_fail_test [format {
+ ovsec_kadm_create_policy null [simple_policy "%s/a"] \
+ {OVSEC_KADM_POLICY}
+ } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/crte-principal.exp b/src/lib/kadm5/unit-test/api.0/crte-principal.exp
new file mode 100644
index 000000000..12c300793
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/crte-principal.exp
@@ -0,0 +1,1330 @@
+source lib.t
+api_exit
+api_start
+
+#test "create-principal 1"
+#
+#proc test1 {} {
+# global test
+# begin_dump
+# one_line_fail_test [format {
+# ovsec_kadm_create_principal $server_handle \
+# [simple_principal "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+# } $test $test] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test1
+
+test "create-principal 2"
+
+proc test2 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_create_principal $server_handle null \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test2
+
+test "create-principal 3"
+proc test3 {} {
+ global test
+# set prms_id 777
+# setup_xfail {*-*-*} $prms_id
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} null
+ } $test] "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test3
+
+test "create-principal 4"
+proc test4 {} {
+ global test
+
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} ""
+ } $test] "_Q_TOOSHORT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test4
+
+test "create-principal 5"
+proc test5 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle \
+ [simple_principal "%s/a"] {0x100001} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test5
+
+test "create-principal 6"
+proc test6 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_LAST_PWD_CHANGE} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test6
+
+test "create-principal 7"
+proc test7 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MOD_TIME} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test7
+
+test "create-principal 8"
+proc test8 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MOD_NAME} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test8
+
+test "create-principal 9"
+proc test9 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MKVNO} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test9
+
+test "create-principal 10"
+proc test10 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_AUX_ATTRIBUTES} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test10
+
+test "create-principal 11"
+proc test11 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_POLICY_CLR} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test11
+
+test "create-principal 12"
+proc test12 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+
+}
+if {$RPC} { test12 }
+
+test "create-principal 13"
+proc test13 {} {
+ global test
+ begin_dump
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test13 }
+
+test "create-principal 14"
+proc test14 {} {
+ global test
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test14 }
+
+test "create-principal 15"
+proc test15 {} {
+ global test
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test15 }
+
+test "create-principal 16"
+proc test16 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test16 }
+
+test "create-principal 17"
+proc test17 {} {
+ global test
+
+ begin_dump
+ if {! (( [principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} testpass
+ } $test] "DUP"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test17
+
+test "create-principal 18"
+proc test18 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} tP
+ } $test] "_Q_TOOSHORT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test18
+
+test "create-principal 19"
+proc test19 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} testpassword
+ } $test] "_Q_CLASS"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test19
+
+test "create-principal 20"
+proc test20 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} Abyssinia
+ } $test] "_Q_DICT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test20
+
+test "create-principal 21"
+proc test21 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" non-existant-pol] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} NotinTheDictionary
+ } $test] "UNK_POLICY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test21
+
+test "create-principal 23"
+proc test23 {} {
+ global test
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ one_line_succeed_test \
+ [format {ovsec_kadm_get_principal $server_handle "%s/a" p} $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test23
+
+test "create-principal 24"
+proc test24 {} {
+ global test
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ one_line_succeed_test \
+ [format {ovsec_kadm_get_principal $server_handle "%s/a" p} $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test24 }
+
+
+test "create-principal 28"
+proc test28 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "create-principal 29"
+proc test29 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_PRINC_EXPIRE_TIME} \
+ inTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 1\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test29
+
+test "create-principal 30"
+proc test30 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_PW_EXPIRATION} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test30
+
+test "create-principal 31"
+proc test31 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol-nopw] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+ OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test31
+
+test "create-principal 32"
+proc test32 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+ OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+
+ send "lindex \$principal 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test32
+
+test "create-principal 33"
+proc test33 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ {"%s/a" 0 0 1234 0 null 0 0 0 0 null 0} \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_PW_EXPIRATION} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test33
+
+test "create-principal 34"
+proc test34 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ { "%s/a" 0 0 1234 0 null 0 0 0 0 test-pol-nopw 0} \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+ OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test34
+
+test "create-principal 35"
+proc test35 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ {"%s/a" 0 0 1234 0 null 0 0 0 0 test-pol 0} \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+ OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test35
+
+test "create-principal 36"
+proc test36 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle \
+ {"%s/a" 0 0 999999999 0 null 0 0 0 0 test-pol 0} \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY \
+ OVSEC_KADM_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy} ]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+
+ send "lindex \$principal 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test36
+
+test "create-principal 37"
+proc test37 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test37
+
+test "create-principal 38"
+proc test38 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol-nopw] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test38
+
+test "create-principal 39"
+proc test39 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: cannot not retrieve principal"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test39
+
+test "create-principal 40"
+proc test40 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL OVSEC_KADM_PW_EXPIRATION} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 4\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test40
+
+test "create-principal 43"
+proc test43 {} {
+ global test
+ one_line_fail_test [format {
+ ovsec_kadm_create_principal null \
+ [simple_principal "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+ } $test $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/destroy.exp b/src/lib/kadm5/unit-test/api.0/destroy.exp
new file mode 100644
index 000000000..31b844786
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/destroy.exp
@@ -0,0 +1,203 @@
+source lib.t
+api_exit
+api_start
+
+test "destroy 1"
+
+proc test1 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_destroy $server_handle}
+ end_dump_compare "no-diffs"
+}
+test1
+
+#test "destroy 2"
+#
+#proc test2 {} {
+# global test
+# begin_dump
+# if {! [cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure on init"
+# return
+# }
+# if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test \
+# {ovsec_kadm_get_principal $server_handle admin principal} \
+# "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test2
+
+#test "destroy 3"
+#proc test3 {} {
+# global test
+#
+# begin_dump
+# if {! (( ! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+# error_and_restart "$test couldn't delete principal \"$test/a\""
+# return
+# }
+# if {! [cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure on init"
+# return
+# }
+# if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test [format {
+# ovsec_kadm_create_principal $server_handle \
+# [simple_principal "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+# } $test $test] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test3
+
+#test "destroy 4"
+#proc test4 {} {
+# global test prompt
+#
+# if {! (([principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {! ([cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }] &&
+# [cmd [format {
+# ovsec_kadm_get_principal $server_handle "%s/a" principal
+# } $test]])} {
+# error_and_restart "$test: error getting principal"
+# return;
+# }
+# if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test [format {
+# ovsec_kadm_modify_principal $server_handle \
+# {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {OVSEC_KADM_KVNO}
+# } $test "77"] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test4
+
+#test "destroy 5"
+#
+#proc test5 {} {
+# global test
+#
+# if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {! [cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure on init"
+# return
+# }
+# if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test [format {
+# ovsec_kadm_delete_principal $server_handle "%s/a"
+# } $test] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test5
+
+#test "destroy 6"
+#
+#proc test6 {} {
+# global test
+# begin_dump
+# one_line_fail_test {ovsec_kadm_destroy $server_handle} "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test6
+
+
+#test "destroy 7"
+#
+#proc test7 {} {
+# global test
+# begin_dump
+# if {! [cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure in init"
+# return
+# }
+# if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# }
+# one_line_fail_test {ovsec_kadm_destroy $server_handle} "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test7
+
+test "destroy 8"
+proc test8 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+ end_dump_compare "no-diffs"
+}
+test8
+
+test "destroy 9"
+proc test9 {} {
+ global test
+ one_line_fail_test {ovsec_kadm_destroy null} "BAD_SERVER_HANDLE"
+}
+test9
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/dlte-policy.exp b/src/lib/kadm5/unit-test/api.0/dlte-policy.exp
new file mode 100644
index 000000000..7f349b02c
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/dlte-policy.exp
@@ -0,0 +1,207 @@
+source lib.t
+api_exit
+api_start
+
+test "delete-policy 2"
+proc test2 {} {
+ global test
+# set prms_id 744
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {ovsec_kadm_delete_policy $server_handle ""} "BAD_POL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test2
+
+test "delete-policy 5"
+proc test5 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_policy $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if ${RPC} test5
+
+test "delete-policy 6"
+proc test6 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_policy $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if ${RPC} test6
+
+test "delete-policy 7"
+proc test7 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_policy $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test7
+
+test "delete-policy 10"
+proc test10 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_delete_policy $server_handle "%s/a"
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if { [policy_exists "$test/a"]} {
+ fail "$test"
+ return
+ }
+}
+test10
+
+test "delete-policy 12"
+proc test12 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test unexecpted failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_create_principal $server_handle [princ_w_pol "%s/a" \
+ "%s/a"] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} \
+ NotinTheDictionary
+ } $test $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {ovsec_kadm_delete_policy $server_handle test-pol} "POLICY_REF"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "delete-policy 13"
+proc test13 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_policy null "%s/a"
+ } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/dlte-principal.exp b/src/lib/kadm5/unit-test/api.0/dlte-principal.exp
new file mode 100644
index 000000000..bb52301df
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/dlte-principal.exp
@@ -0,0 +1,329 @@
+source lib.t
+
+api_exit
+api_start
+
+#test "delete-principal 1"
+#proc test1 {} {
+# global test
+# one_line_fail_test [format {
+# ovsec_kadm_delete_principal $server_handle "%s/a"
+# } $test] "NOT_INIT"
+#}
+#test1
+
+test "delete-principal 2"
+proc test2 {} {
+ global test
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {ovsec_kadm_delete_principal $server_handle null} "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: unexpected failure in destroy"
+ return
+ }
+}
+test2
+
+test "delete-principal 5"
+proc test5 {} {
+ global test
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test] "UNK_PRINC"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test5
+
+test "delete-principal 6"
+proc test6 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" test-pol])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test6 }
+
+
+test "delete-principal 7"
+proc test7 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test7 }
+
+
+test "delete-principal 8"
+proc test8 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test8 }
+
+test "delete-principal 9"
+proc test9 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test9 }
+
+test "delete-principal 10"
+proc test10 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test10 }
+
+test "delete-principal 11"
+proc test11 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test]]} {
+ fail "$test: delete failed"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if { [principal_exists "$test/a"] } {
+ fail "$test"
+ return
+ }
+}
+test11
+
+test "delete-principal 12"
+proc test12 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" test-pol])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_delete_principal $server_handle "%s/a"
+ } $test]]} {
+ fail "$test: delete failed"
+ return
+ }
+ if { [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test]]} {
+ fail "$test: principal still exists"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref - 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ pass "$test"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+
+test12
+
+test "delete-principal 13"
+proc test13 {} {
+ global test
+ one_line_fail_test [format {
+ ovsec_kadm_delete_principal null "%s/a"
+ } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
+
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.0/get-policy.exp b/src/lib/kadm5/unit-test/api.0/get-policy.exp
new file mode 100644
index 000000000..329e7886a
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/get-policy.exp
@@ -0,0 +1,199 @@
+source lib.t
+api_exit
+api_start
+
+test "get-policy 3"
+proc test3 {} {
+ global test
+# set prms_id 744
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {ovsec_kadm_get_policy $server_handle "" p} "BAD_POLICY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test3
+
+test "get-policy 6"
+proc test6 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {ovsec_kadm_get_policy $server_handle test-pol p} \
+ "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } test6
+
+test "get-policy 7"
+proc test7 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {ovsec_kadm_get_policy $server_handle test-pol p} \
+ "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } test7
+
+test "get-policy 11"
+proc test11 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get-pol StupidAdmin $OVSEC_KADM_ADMIN_SERVICE \
+ null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_get_policy $server_handle test-pol p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+test "get-policy 12"
+proc test12 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get-pol StupidAdmin \
+ $OVSEC_KADM_CHANGEPW_SERVICE null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {ovsec_kadm_get_policy $server_handle test-pol-nopw p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "get-policy 15"
+proc test15 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/pol StupidAdmin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {ovsec_kadm_get_policy $server_handle test-pol-nopw p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "get-policy 16"
+proc test16 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/pol StupidAdmin $OVSEC_KADM_CHANGEPW_SERVICE \
+ null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {ovsec_kadm_get_policy $server_handle test-pol-nopw p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test16
+
+test "get-policy 17"
+proc test17 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_get_policy $server_handle test-pol p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+test "get-policy 18"
+proc test18 {} {
+ global test
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {ovsec_kadm_get_policy $server_handle test-pol p} \
+ "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } test18
+
+test "get-policy 21"
+proc test21 {} {
+ global test
+
+ one_line_fail_test {ovsec_kadm_get_policy null "pol1" p} "BAD_SERVER_HANDLE"
+}
+test21
diff --git a/src/lib/kadm5/unit-test/api.0/get-principal.exp b/src/lib/kadm5/unit-test/api.0/get-principal.exp
new file mode 100644
index 000000000..05937055e
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/get-principal.exp
@@ -0,0 +1,346 @@
+source lib.t
+api_exit
+api_start
+
+test "get-principal 1"
+proc test1 {} {
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {ovsec_kadm_get_principal $server_handle null p} "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test1
+
+test "get-principal 2"
+proc test2 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "UNK_PRINC"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test2
+
+test "get-principal 3"
+proc test3 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test3 }
+
+test "get-principal 4"
+proc test4 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test4 }
+
+test "get-principal 5"
+proc test5 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test5 }
+
+test "get-principal 6"
+proc test6 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test6 }
+
+test "get-principal 7"
+proc test7 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test7 }
+
+
+test "get-principal 8"
+proc test8 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" p
+ } $test] "AUTH_GET"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test8 }
+
+
+test "get-principal 9"
+proc test9 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {ovsec_kadm_get_principal $server_handle admin/none p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+test "get-principal 10"
+proc test10 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {ovsec_kadm_get_principal $server_handle admin/none p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+test "get-principal 11"
+proc test11 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/get p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+test "get-principal 12"
+proc test12 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/get p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "get-principal 13"
+proc test13 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/add p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+test "get-principal 14"
+proc test14 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin/get-mod admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {ovsec_kadm_get_principal $server_handle admin/add p}
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+test "get-principal 15"
+proc test15 {} {
+ one_line_fail_test \
+ {ovsec_kadm_get_principal null "admin" p} "BAD_SERVER_HANDLE"
+}
+test15
+
+return ""
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.0/init.exp b/src/lib/kadm5/unit-test/api.0/init.exp
new file mode 100644
index 000000000..5df5dcfc9
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/init.exp
@@ -0,0 +1,727 @@
+source lib.t
+
+# Assumptions:
+#
+# Principal "admin" exists, with "get", "add", "modify" and "delete"
+# access bits and password "admin".
+# The string "not-the-password" isn't the password of any user in the database.
+# Database master password is "mrroot".
+
+api_exit
+api_start
+test "init 1"
+
+one_line_fail_test_nochk \
+ {ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE "" \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+
+test "init 2"
+
+one_line_fail_test_nochk \
+ {ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE @ \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+
+test "init 2.5"
+
+one_line_fail_test_nochk \
+ {ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE BAD.REALM \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle}
+
+test "init 3"
+
+proc test3 {} {
+ global test
+ if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ one_line_fail_test_nochk [format {
+ ovsec_kadm_init admin admin "%s/a" null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ } $test]
+}
+if {$RPC} { test3 }
+
+test "init 4"
+
+proc test4 {} {
+ global test
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ one_line_fail_test_nochk [format {
+ ovsec_kadm_init admin admin "%s/a" null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test4 }
+
+test "init 5"
+
+if {$RPC} {
+ one_line_fail_test_nochk {
+ ovsec_kadm_init admin admin admin null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ }
+}
+
+test "init 6"
+
+proc test6 {} {
+ global test
+
+ send "ovsec_kadm_init admin null \$OVSEC_KADM_ADMIN_SERVICE null \$OVSEC_KADM_STRUCT_VERSION \$OVSEC_KADM_API_VERSION_1 server_handle\n"
+
+ expect {
+ {Enter password:} { }
+ eof {
+ fail "$test: eof instead of password prompt"
+ api_exit
+ api_start
+ return
+ }
+ timeout {
+ fail "$test: timeout instead of password prompt"
+ return
+ }
+ }
+ one_line_succeed_test "admin"
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if { $RPC } { test6 }
+
+test "init 7"
+proc test7 {} {
+ global test
+
+ send "ovsec_kadm_init admin \"\" \$OVSEC_KADM_ADMIN_SERVICE null \$OVSEC_KADM_STRUCT_VERSION \$OVSEC_KADM_API_VERSION_1 server_handle\n"
+
+ expect {
+ {Enter password:} { }
+ -re "key:$" { }
+ eof {
+ fail "$test: eof instead of password prompt"
+ api_exit
+ api_start
+ return
+ }
+ timeout {
+ fail "$test: timeout instead of password prompt"
+ return
+ }
+ }
+ one_line_succeed_test "admin"
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if { $RPC } { test7 }
+
+test "init 8"
+
+proc test8 {} {
+ global test
+ if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ one_line_fail_test_nochk [format {
+ ovsec_kadm_init "%s/a" admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test8 }
+
+test "init 9"
+
+if {$RPC} {
+ global test
+ one_line_fail_test_nochk {
+ ovsec_kadm_init admin not-the-password $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+}
+
+test "init 10"
+
+proc test10 {} {
+ global test
+# set prms_id 562
+# setup_xfail {*-*-*} $prms_id
+ one_line_fail_test_nochk {
+ ovsec_kadm_init null admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+}
+test10
+
+#test "init 11"
+#
+#proc test11 {} {
+# global test
+# set prms_id 563
+# setup_xfail {*-*-*} $prms_id
+# one_line_fail_test_nochk {
+# ovsec_kadm_init "" admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }
+#}
+#test11
+
+test "init 12"
+
+proc test12 {} {
+ global test
+ one_line_fail_test_nochk [format {
+ ovsec_kadm_init "%s/a" admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test12 }
+
+test "init 13"
+
+proc test13 {} {
+ global test
+ one_line_fail_test_nochk [format {
+ ovsec_kadm_init "%s/a@SECURE-TEST.OV.COM" admin \
+ $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ } $test]
+}
+if {$RPC} { test13 }
+
+test "init 14"
+
+proc test14 {} {
+ global test
+ one_line_fail_test_nochk [format {
+ ovsec_kadm_init "%s/a@BAD.REALM" admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test14 }
+
+test "init 15"
+
+if {$RPC} {
+ one_line_fail_test_nochk {
+ ovsec_kadm_init admin@BAD.REALM admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+}
+
+test "init 16"
+
+proc test16 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test16
+
+test "init 17"
+
+proc test17 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin@SECURE-TEST.OV.COM admin \
+ $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test17
+
+test "init 18"
+
+proc test18 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test18
+
+test "init 19"
+
+proc test19 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin@SECURE-TEST.OV.COM admin \
+ $OVSEC_KADM_ADMIN_SERVICE SECURE-TEST.OV.COM \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test19
+
+test "init 20"
+
+proc test20 {} {
+ global test
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error_and_restart "$test: couldn't init database"
+ return
+ }
+ one_line_succeed_test \
+ {ovsec_kadm_get_principal $server_handle admin principal}
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test20
+
+#test "init 21"
+#
+#proc test21 {} {
+# global test
+# if {! [cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }]} {
+# error_and_restart "$test: couldn't init database"
+# return
+# }
+# one_line_fail_test_nochk {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }
+# if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# }
+#}
+#test21
+
+
+proc test22 {} {
+ global test prompt
+ set prompting 0
+ send [string trim {
+ ovsec_kadm_init admin null null null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ }]
+ send "\n"
+ expect {
+ -re ":$" { set prompting 1}
+ -re "\nOK .*$prompt$" { fail "$test: premature success" }
+ -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+ timeout { fail "$test: timeout" }
+ eof { fail "$test: eof" }
+ }
+ if {$prompting} {
+ one_line_succeed_test mrroot
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test22 }
+
+test "init 22.5"
+proc test225 {} {
+ global test prompt
+ set prompting 0
+ send [string trim {
+ ovsec_kadm_init admin null null null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ }]
+ send "\n"
+ expect {
+ -re ":$" { set prompting 1}
+ -re "\nOK .*$prompt$" { fail "$test: premature success" }
+ -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+ timeout { fail "$test: timeout" }
+ eof { fail "$test: eof" }
+ }
+ if {$prompting} {
+ one_line_succeed_test mrroot
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test225 }
+
+test "init 23"
+
+proc test23 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin not-the-password $OVSEC_KADM_ADMIN_SERVICE \
+ null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test23 }
+
+test "init 24"
+
+proc test24 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin null null $OVSEC_KADM_STRUCT_VERSION \
+ $OVSEC_KADM_API_VERSION_1 server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test24 }
+
+test "init 25"
+
+proc test25 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin foobar null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test25 }
+
+test "init 26"
+
+#proc test26 {} {
+# global test
+#
+# api_exit
+# api_start
+# one_line_fail_test_nochk {
+# ovsec_kadm_get_principal $server_handle admin principal
+# }
+#}
+#test26
+
+#test "init 27"
+#
+#proc test27 {} {
+# global test
+#
+# if {! ((! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+# error_and_restart "$test: couldn't delete principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {[cmd [format {
+# ovsec_kadm_create_principal $server_handle [simple_principal \
+# "%s/a"] {OVSEC_KADM_PRINCIPAL} "%s/a"
+# } $test $test]]} {
+# fail "$test: unexpected success in add"
+# return
+# }
+# end_dump_compare "no-diffs"
+#}
+#test27
+
+#test "init 28"
+#
+#proc test28 {} {
+# global test prompt
+#
+# if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {! ([cmd {
+# ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+# $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+# server_handle
+# }] && [cmd [format {
+# ovsec_kadm_get_principal $server_handle "%s/a" principal
+# } $test]])} {
+# error_and_restart "$test: error getting principal"
+# return;
+# }
+# send "lindex \$principal 8\n"
+# expect {
+# -re "\n(\[0-9\]+).*$prompt$" {set kvno $expect_out(1,string) }
+# timeout {
+# error_and_restart "$test: timeout getting principal kvno"
+# return
+# }
+# eof {
+# error_and_restart "$test: eof getting principal kvno"
+# return
+# }
+# }
+# api_exit
+# api_start
+# set new_kvno [expr "$kvno + 1"]
+# if {[cmd [format {
+# ovsec_kadm_modify_principal $server_handle \
+# {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {OVSEC_KADM_KVNO}
+# } $test $new_kvno]]} {
+# fail "$test: unexpected success in modify"
+# return;
+# }
+# end_dump_compare "no-diffs"
+#}
+#test28
+
+#test "init 29"
+#
+#proc test29 {} {
+# global test
+#
+# if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {[cmd [format {
+# ovsec_kadm_delete_principal $server_handle "%s/a"
+# } $test]]} {
+# fail "$test: unexpected success in delete"
+# return
+# }
+# end_dump_compare "no-diffs"
+#}
+#test29
+
+test "init 30"
+proc test30 {} {
+ global test
+ if {[cmd {
+ ovsec_kadm_init admin foobar $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error_and_restart "$test: unexpected succsess"
+ return
+ }
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if ${RPC} { test30 }
+
+test "init 31"
+proc test31 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $bad_struct_version_mask $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } "BAD_STRUCT_VERSION"
+}
+test31
+
+test "init 32"
+proc test32 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $no_struct_version_mask $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } "BAD_STRUCT_VERSION"
+}
+test32
+
+test "init 33"
+proc test33 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $old_struct_version $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } "OLD_STRUCT_VERSION"
+}
+test33
+
+test "init 34"
+proc test34 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $new_struct_version $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } "NEW_STRUCT_VERSION"
+}
+test34
+
+test "init 35"
+proc test35 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $bad_api_version_mask \
+ server_handle
+ } "BAD_API_VERSION"
+}
+test35
+
+test "init 36"
+proc test36 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $no_api_version_mask \
+ server_handle
+ } "BAD_API_VERSION"
+}
+test36
+
+test "init 37"
+proc test37 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $old_api_version \
+ server_handle
+ } "OLD_LIB_API_VERSION"
+}
+if { $RPC } test37
+
+test "init 38"
+proc test38 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $old_api_version \
+ server_handle
+ } "OLD_SERVER_API_VERSION"
+}
+if { ! $RPC } test38
+
+test "init 39"
+proc test39 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $new_api_version \
+ server_handle
+ } "NEW_LIB_API_VERSION"
+}
+if { $RPC } test39
+
+test "init 40"
+proc test40 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $new_api_version \
+ server_handle
+ } "NEW_SERVER_API_VERSION"
+}
+if { ! $RPC } test40
+
+test "init 41"
+proc test41 {} {
+ global test
+ one_line_fail_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_API_VERSION_1 $OVSEC_KADM_STRUCT_VERSION \
+ server_handle
+ } "BAD_"
+}
+test41
+
+test "init 42"
+proc test42 {} {
+ global test
+ one_line_succeed_test {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }
+ if {! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test42
+
+
+proc test45_46 {service} {
+ global test kdb5_edit env
+
+ spawn $kdb5_edit -R "del $service"
+ expect {
+ {Type 'yes' to confirm:} {
+ send "yes\n"
+ }
+ default {
+ error "kdb5_edit del failed\n";
+ }
+ }
+ expect eof
+ wait
+
+ one_line_fail_test [concat {ovsec_kadm_init admin admin } \
+ $service \
+ { null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle}] "SECURE_PRINC_MISSING"
+
+ # this leaves the keytab with an incorrect entry
+ exec $kdb5_edit -R "ark $service"
+
+ # restart the api so it gets a new ccache
+ api_exit
+ api_start
+}
+
+if {$RPC} {
+ test "init 45"
+
+ test45_46 ovsec_adm/admin
+
+ test "init 46"
+
+ test45_46 ovsec_adm/changepw
+
+ # re-extract the keytab so it is right
+ exec rm /krb5/ovsec_adm.srvtab
+ exec $env(MAKE_KEYTAB) -princ ovsec_adm/admin -princ ovsec_adm/changepw \
+ -princ kadmin/admin -princ kadmin/changepw /krb5/ovsec_adm.srvtab
+}
+
+return ""
+
diff --git a/src/lib/kadm5/unit-test/api.0/mod-policy.exp b/src/lib/kadm5/unit-test/api.0/mod-policy.exp
new file mode 100644
index 000000000..67f8457b6
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/mod-policy.exp
@@ -0,0 +1,703 @@
+source lib.t
+api_exit
+api_start
+
+test "modify-policy 2"
+proc test2 {} {
+ global test
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test2 }
+
+test "modify-policy 4"
+proc test4 {} {
+ global test
+
+ if {! ([policy_exists "$test/a"] ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_REF_COUNT}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test4
+
+test "modify-policy 8"
+proc test8 {} {
+ global test
+# set prms_id 744
+# setup_xfail {*-*-*} $prms_id
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_modify_policy $server_handle [simple_policy ""] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } "BAD_POLICY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test8
+
+test "modify-policy 9"
+proc test9 {} {
+ global test
+ global prompt
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MIN_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+test "modify-policy 10"
+proc test10 {} {
+ global test
+ global prompt
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 32 0 0 0 0 0} \
+ {OVSEC_KADM_PW_MIN_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+
+test "modify-policy 11"
+proc test11 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+test "modify-policy 12"
+proc test12 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 32 0 0 0 0} \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "modify-policy 13"
+proc test13 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MIN_LENGTH}
+ } $test] "BAD_LENGTH"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+test "modify-policy 14"
+proc test14 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 8 0 0 0} \
+ {OVSEC_KADM_PW_MIN_LENGTH}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 3\n"
+ expect {
+ -re "8\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+test "modify-policy 15"
+proc test15 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "modify-policy 16"
+proc test16 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0} \
+ {OVSEC_KADM_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test16
+
+test "modify-policy 17"
+proc test17 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+ {OVSEC_KADM_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "5\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+test "modify-policy 18"
+proc test18 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+ {OVSEC_KADM_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+test "modify-policy 19"
+proc test19 {} {
+ global test
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_HISTORY_NUM}
+ } $test] "BAD_HISTORY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test19
+
+test "modify-policy 20"
+proc test20 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+ {OVSEC_KADM_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test20
+
+test "modify-policy 21"
+proc test21 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+ {OVSEC_KADM_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "10\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21
+
+test "modify-policy 22"
+proc test22 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test22
+
+test "modify-policy 23"
+proc test23 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test23
+
+test "modify-policy 26"
+proc test26 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_modify_policy $server_handle [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test26
+
+test "modify-policy 30"
+proc test30 {} {
+ global test
+
+ one_line_fail_test [format {
+ ovsec_kadm_modify_policy null [simple_policy "%s/a"] \
+ {OVSEC_KADM_PW_MAX_LIFE}
+ } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/mod-principal.exp b/src/lib/kadm5/unit-test/api.0/mod-principal.exp
new file mode 100644
index 000000000..c4bc2bed1
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/mod-principal.exp
@@ -0,0 +1,1942 @@
+source lib.t
+api_exit
+api_start
+
+#test "modify-principal 1"
+#proc test1 {} {
+# global test
+# one_line_fail_test [format {
+# ovsec_kadm_modify_principal $server_handle [simple_principal \
+# "%s/a"] {OVSEC_KADM_PW_EXPIRATION}
+# } $test] "NOT_INIT"
+#}
+#test1
+
+test "modify-principal 2"
+proc test2 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test2 }
+
+test "modify-principal 4"
+proc test4 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINCIPAL}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test4
+
+
+test "modify-principal 5"
+proc test5 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_LAST_PWD_CHANGE}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test5
+
+test "modify-principal 6"
+proc test6 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MOD_TIME}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test6
+
+test "modify-principal 7"
+proc test7 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MOD_NAME}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test7
+
+test "modify-principal 8"
+proc test8 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MKVNO}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test8
+
+test "modify-principal 9"
+proc test9 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_AUX_ATTRIBUTES}
+ } $test] "BAD_MASK"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+test "modify-principal 10"
+proc test10 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test] "UNK_PRINC"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+test "modify-principal 11"
+proc test11 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test11 }
+
+test "modify-principal 12"
+proc test12 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test12 }
+
+test "modify-principal 13"
+proc test13 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test13 }
+
+test "modify-principal 14"
+proc test14 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test14 }
+
+test "modify-principal 15"
+proc test15 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "modify-principal 17"
+proc test17 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ no-policy] {OVSEC_KADM_POLICY}
+ } $test] "UNK_POLICY"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+test "modify-principal 18"
+proc test18 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal "$test/a"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref + 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+test "modify-principal 19"
+proc test19 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal "$test/a"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref + 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test19
+
+test "modify-principal 20"
+proc test20 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_POLICY_CLR}
+ } $test]]} {
+ error "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { fail "$test" }
+ timeout { pass "$test" }
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref - 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test20
+
+test "modify-principal 21"
+proc test21 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol old_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol-nopw old_p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol-nopw] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$old_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ send "lindex \$old_p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set old_p2_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol new_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol-nopw new_p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$new_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ send "lindex \$new_p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set new_p2_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$old_p1_ref - 1"] != $new_p1_ref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { [expr "$old_p2_ref + 1"] != $new_p2_ref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21
+
+test "modify-principal 21.5"
+proc test21.5 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol old_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$old_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol new_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$new_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ if {$old_p1_ref != $new_p1_ref} {
+ fail "$test: policy reference count changed ($old_p1_ref to $new_p1_ref)"
+ return
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21.5
+
+test "modify-principal 22"
+proc test22 {} {
+ global test
+ global prompt
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modifiy failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test22
+
+test "modify-principal 23"
+proc test23 {} {
+ global test
+ global prompt
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" test-pol-nopw])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modifiy failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test23
+
+test "modify-principal 24"
+proc test24 {} {
+ global test
+ global prompt
+# set prms_id 1358
+# setup_xfail {*-*-*} $prms_id
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error_and_restart "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: could not modify principal"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_get_policy $server_handle %s policy
+ } test-pol]]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test24
+
+test "modify-principal 25"
+proc test25 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test25
+
+test "modify-principal 26"
+proc test26 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol-nopw" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test26
+
+test "modify-principal 27"
+proc test27 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test27
+
+test "modify-principal 28"
+proc test28 {} {
+ global test
+ global prompt
+# set prms_id 1358
+# setup_xfail {*-*-*} $prms_id
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 900 0 0 0 0 0 0 0 0} {OVSEC_KADM_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$pw_mod_date + $pw_max_life"] == $pw_expire } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ pass "$test"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "modify-principal 29"
+proc test29 {} {
+ global test
+ global prompt
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { ! ([create_principal_pol "$test/a" test-pol])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_POLICY_CLR}
+ } $test]]} {
+ fail "$test: modifiy failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test29
+
+test "modify-principal 30"
+proc test30 {} {
+ global test
+ global prompt
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal_pol "$test/a" test-pol])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol-nopw] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test30
+
+test "modify-principal 31"
+proc test31 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test31
+
+test "modify-principal 32"
+proc test32 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 1234 0 0 0 0 0 0 0 0 0 0} \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 1\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test32
+
+test "modify-principal 33"
+proc test33 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_ALL_TIX 0 0 0 0} \
+ {OVSEC_KADM_ATTRIBUTES}
+ } $test]]} {
+ fail "$test: modified fail"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 7\n"
+ expect {
+ -re "KRB5_KDB_DISALLOW_ALL_TIX.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test33
+
+test "modify-principal 33.25"
+proc test3325 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 KRB5_KDB_REQUIRES_PWCHANGE 0 0 0 0} \
+ {OVSEC_KADM_ATTRIBUTES}
+ } $test]]} {
+ fail "$test: modified fail"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 7\n"
+ expect {
+ -re "KRB5_KDB_REQUIRES_PWCHANGE.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test3325
+
+test "modify-principal 33.5"
+proc test335 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_TGT_BASED 0 0 0 0} \
+ {OVSEC_KADM_ATTRIBUTES}
+ } $test]]} {
+ fail "$test: modified fail"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 7\n"
+ expect {
+ -re "KRB5_KDB_DISALLOW_TGT_BASED.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test335
+
+
+test "modify-principal 34"
+proc test34 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 0 3456 0 0 0 0 0 0 0} {OVSEC_KADM_MAX_LIFE}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 4\n"
+ expect {
+ -re "3456\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test34
+
+test "modify-principal 35"
+proc test35 {} {
+ global prompt
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 0 7 0 0 0} {OVSEC_KADM_KVNO}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 8\n"
+ expect {
+ -re "7\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test35
+
+test "modify-principal 36"
+proc test36 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol pol}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {OVSEC_KADM_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ send "lindex \$pol 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {ovsec_kadm_get_policy $server_handle test-pol pol2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ send "lindex \$pol2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { $oldref != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test36
+
+test "modify-principal 37"
+proc test37 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal "$test/a"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_POLICY_CLR}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test37
+
+test "modify-principal 38"
+proc test38 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 1\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test38
+
+test "modify-principal 39"
+proc test39 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [simple_principal "%s/a"] \
+ {OVSEC_KADM_MAX_LIFE}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s/a" principal
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 4\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test39
+
+test "modify-principal 40"
+proc test40 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_modify_principal $server_handle null \
+ {OVSEC_KADM_PRINC_EXPIRE_TIME}
+ } "EINVAL"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test40
+
+test "modify-principal 43"
+proc test43 {} {
+ global test
+ one_line_fail_test [format {
+ ovsec_kadm_modify_principal null [simple_principal \
+ "%s/a"] {OVSEC_KADM_PW_EXPIRATION}
+ } $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/randkey-principal.exp b/src/lib/kadm5/unit-test/api.0/randkey-principal.exp
new file mode 100644
index 000000000..259cd8f03
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/randkey-principal.exp
@@ -0,0 +1,319 @@
+source lib.t
+api_exit
+api_start
+
+test "randkey-principal 1"
+proc test1 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd [format {
+ ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test] "PASS_TOOSOON"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test1 }
+
+test "randkey-principal 3"
+proc test3 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd [format {
+ ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test] "PASS_TOOSOON"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if ${RPC} { test3 }
+
+test "randkey-principal 13"
+proc test13 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_modify_principal $server_handle [princ_w_pol "%s/a" \
+ once-a-min] OVSEC_KADM_POLICY
+ } $test]]} {
+ error "$test: failed modify"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+test "randkey-principal 15"
+proc test15 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test] "AUTH_CHANGEPW"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test15 }
+
+test "randkey-principal 28"
+proc test28 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "randkey-principal 28.25"
+proc test2825 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test] "AUTH"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test2825 }
+
+test "randkey-principal 28.5"
+proc test285 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test285
+
+test "randkey-principal 30"
+proc test30 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [create_principal "$test/a"]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+ if {! [cmd [format {
+ ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test30
+
+test "randkey-principal 31"
+proc test31 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal "$test/a"]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd [format {
+ ovsec_kadm_init "%s/a" "%s/a" $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_randkey_principal $server_handle "%s/a" key
+ } $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test31
+
+test "randkey-principal 32"
+proc test32 {} {
+ global test
+
+ if { ! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ ovsec_kadm_randkey_principal $server_handle kadmin/history key
+ } "PROTECT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test32
+
+test "randkey-principal 33"
+proc test33 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if { ! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_randkey_principal null "%s/a" key
+ } $test] "BAD_SERVER_HANDLE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+
+test33
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.0/rename-principal.exp b/src/lib/kadm5/unit-test/api.0/rename-principal.exp
new file mode 100644
index 000000000..56e412955
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.0/rename-principal.exp
@@ -0,0 +1,509 @@
+source lib.t
+api_exit
+api_start
+
+#test "rename-principal 1"
+#proc test1 {} {
+# global test
+# one_line_fail_test [format {
+# ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+# } $test $test] "NOT_INIT"
+#}
+#test1
+
+test "rename-principal 2"
+proc test2 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_CHANGEPW_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "INSUFFICIENT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+
+}
+if {$RPC} { test2 }
+
+test "rename-principal 3"
+proc test3 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/none admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_INSUFFICIENT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test3 }
+
+test "rename-principal 4"
+proc test4 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/modify admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_INSUFFICIENT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test4 }
+
+test "rename-principal 5"
+proc test5 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_INSUFFICIENT"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test5 }
+
+test "rename-principal 6"
+proc test6 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/mod-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test6 }
+
+test "rename-principal 7"
+proc test7 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/mod-delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test7 }
+
+test "rename-principal 8"
+proc test8 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test8 }
+
+test "rename-principal 9"
+proc test9 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/get-delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test9 }
+
+test "rename-principal 10"
+proc test10 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/no-delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_DELETE"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test10 }
+
+test "rename-principal 11"
+proc test11 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/no-add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH_ADD"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test11 }
+
+test "rename-principal 12"
+proc test12 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/add admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test12 }
+
+
+test "rename-principal 13"
+proc test13 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/delete admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "AUTH"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test13 }
+
+test "rename-principal 14"
+proc test14 {} {
+ global test
+
+ if {[principal_exists "$test/a"]} {
+ delete_principal "$test/a"
+ }
+
+ if {[create_principal_with_keysalts "$test/a" "des-cbc-crc:v4"]} {
+ error_and_restart "$test: couldn't create no-salt principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test]
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+test "rename-principal 15"
+proc test15 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( [principal_exists "$test/b"]) ||
+ [create_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "DUP"
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "rename-principal 16"
+proc test16 {} {
+ global test
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal null "%s/a" "%s/b"
+ } $test $test] "BAD_SERVER_HANDLE"
+}
+test16
+
+test "rename-principal 18"
+proc test18 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! (( ! [principal_exists "$test/b"]) ||
+ [delete_principal "$test/b"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ ovsec_kadm_init admin/rename admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ ovsec_kadm_rename_principal $server_handle "%s/a" "%s/b"
+ } $test $test] "NO_RENAME_SALT"
+
+ if { ! [cmd {ovsec_kadm_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.1/lock.exp b/src/lib/kadm5/unit-test/api.1/lock.exp
new file mode 100644
index 000000000..67ab80060
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.1/lock.exp
@@ -0,0 +1,242 @@
+# This is in api.1 so that it happens after all the tests in api.0.
+# If some API function does not unlock the database then the server
+# (whichs runs through all api tests) will still have it locked, and
+# these tests will fail.
+
+source lib.t
+
+if { $RPC } {
+ return
+}
+
+set locktest $LOCKTEST
+set lockfile "/krb5/ovsec_adm.lock"
+
+# The lock tests use the program lock-test in the unit test
+# directory. The basic idea is that lock-test can be told to acquire
+# various kinds of locks and then wait for input before proceeding;
+# this is necessary because otherwise we'd have no way to test locking
+# interactions without a race condition.
+#
+# lock_test_start and lock_test_continue work together to give a crude
+# form of continuations. lock_test_continue expects a list of
+# commands for lock-test (passed on the command line) and responses
+# (read from stdout). When it gets to a command of "wait",
+# lock_test_continue returns, and its return value is a list of the
+# arguments that it should be passed to continue processing that
+# particular list of commands for that particular lock-test after
+# whatever that requried lock-test to wait has been completed.
+#
+# lock_test is simply a wrapper for tests that do not involve wait.
+
+proc lock_test_setup {test cmds} {
+ global locktest spawn_id
+
+ verbose "test $test"
+
+ set cmdline ""
+ foreach cmdpair $cmds {
+ if {[lindex $cmdpair 0] == "eof"} {
+ break
+ }
+ set cmdline "$cmdline [lindex $cmdpair 0]"
+ }
+
+ verbose "spawning $locktest $cmdline"
+ eval "spawn $locktest $cmdline"
+}
+
+proc lock_test {test cmds} {
+ global spawn_id
+
+ lock_test_setup $test $cmds
+ set lockany [lock_test_continue $test $spawn_id 0 "" 0 $cmds]
+ while {$lockany != {}} {
+ set lockany [eval lock_test_continue $lockany]
+ }
+}
+
+proc lock_test_start {test cmds} {
+ global spawn_id
+
+ lock_test_setup $test $cmds
+ return [lock_test_continue $test $spawn_id 0 "" 0 $cmds]
+}
+
+proc lock_test_continue {test my_spawn_id test_failed fail_output cont cmds} {
+ global wait_error_index wait_errno_index wait_status_index
+
+ set spawn_id $my_spawn_id
+
+ if {$cont == 1} {
+ send -i $spawn_id "\n"
+ }
+
+ while {[llength $cmds] > 0} {
+ set cmdpair [lindex $cmds 0]
+ set cmds [lrange $cmds 1 end]
+ set cmd [lindex $cmdpair 0]
+ set output [lindex $cmdpair 1]
+
+ verbose "test $test: command: $cmd"
+
+ if {$cmd == "wait"} {
+ # ah, for continuations...
+ return [list $test $spawn_id $test_failed $fail_output 1 $cmds]
+ }
+ if {$cmd == "eof"} {
+ set status $output
+ set output "doesnotmatchanything"
+ }
+
+ expect {
+ -i $spawn_id
+ -re "$output" { verbose "test $test: read: $output" }
+ timeout {
+ set test_failed 1
+ set fail_output "timeout while waiting for $output"
+ }
+ eof {
+ if {$cmd != "eof"} {
+ set test_failed 1
+ set fail_output "eof while waiting for $output"
+ }
+ }
+ }
+
+ if {$test_failed == 1} { break }
+ }
+
+ set ret [wait -i $spawn_id]
+ verbose "% Exit $ret" 2
+
+ if {$test_failed == 0} {
+ if {[lindex $ret $wait_error_index] == -1} {
+ set test_failed 1
+ set fail_output "wait returned error [lindex $ret $wait_errno_index]"
+ } else {
+ if { [lindex $ret $wait_status_index] == $status ||
+ (($status<0) && ([lindex $ret $wait_status_index] == ($status+256))) } {
+ verbose "test $test: status $status"
+ } else {
+ set test_failed 1
+ set fail_output "unexpected return status [lindex $ret $wait_status_index], should be $status"
+ }
+ }
+ }
+
+ if {$test_failed == 0} {
+ pass $test
+ } else {
+ fail "$test: $fail_output"
+ }
+
+ return {}
+}
+
+lock_test 1 [list \
+ [list shared "shared"] \
+ [list release "released"] \
+ [list eof 0]]
+
+lock_test 2 [list \
+ [list exclusive exclusive] \
+ [list release released] \
+ [list eof 0]]
+
+lock_test 3 [list \
+ [list permanent permanent] \
+ [list release released] \
+ [list eof 0]]
+
+lock_test 4 [list \
+ [list release "Database not locked"] \
+ [list eof 0]]
+
+set lock5 [lock_test_start 5 [list \
+ [list shared shared] \
+ [list wait ""] \
+ [list eof 0]]]
+lock_test 5.1 [list \
+ [list shared shared] \
+ [list eof 0]]
+eval lock_test_continue $lock5
+
+set lock6 [lock_test_start 6 [list \
+ [list exclusive exclusive] \
+ [list wait ""] \
+ [list eof 0]]]
+lock_test 6.1 [list \
+ [list shared "Cannot lock database"] \
+ [list eof 0]]
+eval lock_test_continue $lock6
+
+set lock7 [lock_test_start 7 [list \
+ [list shared shared] \
+ [list wait ""] \
+ [list eof 0]]]
+lock_test 7.1 [list \
+ [list exclusive "Cannot lock database"] \
+ [list eof 0]]
+eval lock_test_continue $lock7
+
+set lock8 [lock_test_start 8 [list \
+ [list permanent permanent] \
+ [list wait ""] \
+ [list release "released" ] \
+ [list eof 0]]]
+lock_test 8.1 [list \
+ [list "" "administration database lock file missing while opening database" ] \
+ [list eof 1]]
+eval lock_test_continue $lock8
+
+set lock9 [lock_test_start 9 [list \
+ [list wait ""] \
+ [list exclusive "database lock file missing while getting exclusive"] \
+ [list eof 0]]]
+set lock9_1 [lock_test_start 9.1 [list \
+ [list permanent permanent] \
+ [list wait ""] \
+ [list release released] \
+ [list eof 0]]]
+eval lock_test_continue $lock9
+eval lock_test_continue $lock9_1
+
+if {! [file exists $lockfile]} {
+ error "lock file missing before test 10"
+}
+set lock10 [lock_test_start 10 [list \
+ [list permanent permanent] \
+ [list wait ""] \
+ [list release released] \
+ [list eof 0]]]
+if {[file exists $lockfile]} {
+ fail "test 10: lock file exists"
+}
+eval lock_test_continue $lock10
+if {[file exists $lockfile]} {
+ pass "test 11: lock file exists"
+} else {
+ fail "test 11: lock file does not exist"
+}
+
+set lock12 [lock_test_start 12 [list \
+ [list shared shared] \
+ [list wait ""] \
+ [list eof 0]]]
+lock_test 12.1 [list \
+ [list "get test-pol" retrieved] \
+ [list eof 0]]
+eval lock_test_continue $lock12
+
+# This test doesn't work yet, somehow I or expect am confused about
+# the spawn_id's between the lock-test and api.
+warning "test 13: doesn't work, bug in unit-test"
+# set lock13 [lock_test_start 13 [list \
+# [list "get lock13" "Principal or policy does not exist"] \
+# [list wait ""] \
+# [list "get lock13" retrieved] \
+# [list eof 0]]]
+# create_policy lock13
+# eval lock_test_continue $lock13
+# delete_policy lock13
diff --git a/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp b/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp
new file mode 100644
index 000000000..88aed8bca
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/chpass-principal-v2.exp
@@ -0,0 +1,68 @@
+source lib.t
+api_exit
+api_start
+
+test "chpass-principal 200"
+proc test200 {} {
+ global test prompt
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal "$test/a"]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ # I'd like to specify a long list of keysalt tuples and make sure
+ # that chpass does the right thing, but we can only use those
+ # enctypes that krbtgt has a key for: des-cbc-crc:normal and
+ # des-cbc-crc:v4, according to the prototype kdc.conf.
+ if {! [cmd [format {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_chpass_principal $server_handle "%s/a" newpassword
+ } $test]]} {
+ error "$test: unexpected failure in chpass_principal"
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" p \
+ {KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+ } $test]]} {
+ error "$test: unexpected failure in get_principal"
+ }
+ send "lindex \$p 16\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting num_keys"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting num_keys"
+ return
+ }
+ }
+
+ # XXX Perhaps I should actually check the key type returned.
+ if {$num_keys == 2} {
+ pass "$test"
+ } else {
+ fail "$test: $num_keys keys, should be 2"
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test200
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/chpass-principal.exp b/src/lib/kadm5/unit-test/api.2/chpass-principal.exp
new file mode 100644
index 000000000..3efdfa9b9
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/chpass-principal.exp
@@ -0,0 +1,176 @@
+source lib.t
+api_exit
+api_start
+
+test "chpass-principal 180"
+proc test180 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_chpass_principal $server_handle "%s/a" FoobarBax
+ } $test]
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test180 }
+
+test "chpass-principal 180.5"
+proc test1805 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_chpass_principal $server_handle "%s/a" FoobarBax
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test1805 }
+
+#
+# admin with changepw service tickets try to change other principals
+# password, failes with AUTH error
+test "chpass-principal 180.625"
+proc test180625 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_chpass_principal $server_handle "%s/a" password
+ } $test] "AUTH"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test180625 }
+
+test "chpass-principal 180.75"
+proc test18075 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_chpass_principal $server_handle "%s/a" Foobar
+ } $test] "AUTH_CHANGEPW"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test18075 }
+
+test "chpass-principal 182"
+proc test182 {} {
+ global test
+
+ if { ! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_chpass_principal $server_handle kadmin/history password
+ } "PROTECT"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test182
+
+test "chpass-principal 183"
+proc test183 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if { ! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_chpass_principal null "%s/a" password
+ } $test] "BAD_SERVER_HANDLE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test183
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/crte-policy.exp b/src/lib/kadm5/unit-test/api.2/crte-policy.exp
new file mode 100644
index 000000000..b0ea04630
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/crte-policy.exp
@@ -0,0 +1,991 @@
+source lib.t
+api_exit
+api_start
+
+# Description: (1) Fails for mask with undefined bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 1"
+proc test1 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ 0xF01000
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test1
+
+# Description: (2) Fails if caller connected with CHANGEPW_SERVICE.
+test "create-policy 2"
+proc test2 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy";
+ return
+ }
+}
+if {$RPC} { test2 }
+
+# Description: (3) Fails for mask without POLICY bit set.
+# 01/24/94: pshuang: untried.
+test "create-policy 3"
+proc test3 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ 0x000000
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test3
+
+# Description: (4) Fails for mask with REF_COUNT bit set.
+test "create-policy 4"
+proc test4 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY KADM5_REF_COUNT}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test4
+
+# Description: (5) Fails for invalid policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 5"
+proc test5 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/"] \
+ {KADM5_POLICY}
+ } $test] "BAD_POLICY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test5
+
+# Description: (6) Fails for existing policy name.
+test "create-policy 6"
+proc test6 {} {
+ global test
+# set prms_id 777
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_create_policy $server_handle [simple_policy test-pol] \
+ {KADM5_POLICY}
+ } "DUP"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test6
+
+# Description: (7) Fails for null policy name.
+# 01/24/94: pshuang: untried.
+test "create-policy 7"
+proc test7 {} {
+ global test
+# set prms_id 1977
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_create_policy $server_handle [simple_policy null] \
+ {KADM5_POLICY}
+ } "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test7
+
+# Description: (8) Fails for empty-string policy name.
+test "create-policy 8"
+proc test8 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_create_policy $server_handle [simple_policy ""] \
+ {KADM5_POLICY}
+ } "BAD_POLICY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test8
+
+# Description: (9) Accepts 0 for pw_min_life.
+test "create-policy 9"
+proc test9 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY KADM5_PW_MIN_LIFE}
+ } $test]]} {
+ fail "$test: create failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+# Description: (10) Accepts non-zero for pw_min_life.
+test "create-policy 10"
+proc test10 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 32 0 0 0 0 0 } \
+ {KADM5_POLICY KADM5_PW_MIN_LIFE}
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+# Description: (11) Accepts 0 for pw_max_life.
+test "create-policy 11"
+proc test11 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY KADM5_PW_MAX_LIFE}
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+# Description: (12) Accepts non-zero for pw_max_life.
+test "create-policy 12"
+proc test12 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 32 0 0 0 0 } \
+ {KADM5_POLICY KADM5_PW_MAX_LIFE}
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+# Description: (13) Rejects 0 for pw_min_length.
+test "create-policy 13"
+proc test13 {} {
+ global test
+ global prompt
+
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY KADM5_PW_MIN_LENGTH}
+ } $test] "BAD_LENGTH"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+# Description: (14) Accepts non-zero for pw_min_length.
+test "create-policy 14"
+proc test14 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 8 0 0 0 } \
+ {KADM5_POLICY KADM5_PW_MIN_LENGTH}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 3\n"
+ expect {
+ -re "8\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+# Description: (15) Rejects 0 for pw_min_classes.
+test "create-policy 15"
+proc test15 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+# Description: (16) Accepts 1 for pw_min_classes.
+test "create-policy 16"
+proc test16 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 0 1 0 0 } \
+ {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test16
+
+# Description: (17) Accepts 4 for pw_min_classes.
+test "create-policy 17"
+proc test17 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+ {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "5\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+# Description: (18) Rejects 5 for pw_min_classes.
+test "create-policy 18"
+proc test18 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+ {KADM5_POLICY KADM5_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+# Description: (19) Rejects 0 for pw_history_num.
+test "create-policy 19"
+proc test19 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+ } $test] "BAD_HISTORY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test19
+
+# Description: (20) Accepts 1 for pw_history_num.
+test "create-policy 20"
+proc test20 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+ {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retreuve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test20
+
+# Description: (21) Accepts 10 for pw_history_num.
+test "create-policy 21"
+proc test21 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+ {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "10\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21
+
+# Description: (21.5) Rejects 11 for pw_history_num.
+# 01/24/94: pshuang: untried.
+
+test "create-policy 21.5"
+proc test215 {} {
+ global test
+ global prompt
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle {"%s/a" 0 0 0 0 11 0} \
+ {KADM5_POLICY KADM5_PW_HISTORY_NUM}
+ } $test] "BAD_HISTORY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test215
+
+
+# Description: (22) Fails for user with no access bits.
+test "create-policy 22"
+proc test22 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test22
+
+# Description: (23) Fails for user with "get" but not "add".
+test "create-policy 23"
+proc test23 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test23
+
+# Description: (24) Fails for user with "modify" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 24"
+proc test24 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test24
+
+# Description: (25) Fails for user with "delete" but not "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 25"
+proc test25 {} {
+ global test
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test25
+
+# Description: Succeeds for user with "add".
+test "create-policy 26"
+proc test26 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test26
+
+# Description: Succeeds for user with "get" and "add".
+# 01/24/94: pshuang: untried.
+test "create-policy 27"
+proc test27 {} {
+ global test
+
+ if {! (( ! [policy_exists "$test/a"]) ||
+ [delete_policy "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/get-add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_create_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test27
+
+# Description: (28) Rejects null policy argument.
+# 01/24/94: pshuang: untried.
+test "create-policy 28"
+proc test28 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_create_policy $server_handle null {KADM5_POLICY}
+ } "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "create-policy 30"
+proc test30 {} {
+ global test
+ one_line_fail_test [format {
+ kadm5_create_policy null [simple_policy "%s/a"] \
+ {KADM5_POLICY}
+ } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/crte-principal.exp b/src/lib/kadm5/unit-test/api.2/crte-principal.exp
new file mode 100644
index 000000000..653d1222a
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/crte-principal.exp
@@ -0,0 +1,1330 @@
+source lib.t
+api_exit
+api_start
+
+#test "create-principal 1"
+#
+#proc test1 {} {
+# global test
+# begin_dump
+# one_line_fail_test [format {
+# kadm5_create_principal $server_handle \
+# [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+# } $test $test] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test1
+
+test "create-principal 2"
+
+proc test2 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_create_principal $server_handle null \
+ {KADM5_PRINCIPAL} testpass
+ } "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test2
+
+test "create-principal 3"
+proc test3 {} {
+ global test
+# set prms_id 777
+# setup_xfail {*-*-*} $prms_id
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} null
+ } $test] "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test3
+
+test "create-principal 4"
+proc test4 {} {
+ global test
+
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} ""
+ } $test] "_Q_TOOSHORT"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test4
+
+test "create-principal 5"
+proc test5 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle \
+ [simple_principal "%s/a"] {0x100001} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test5
+
+test "create-principal 6"
+proc test6 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_LAST_PWD_CHANGE} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test6
+
+test "create-principal 7"
+proc test7 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MOD_TIME} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test7
+
+test "create-principal 8"
+proc test8 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MOD_NAME} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test8
+
+test "create-principal 9"
+proc test9 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MKVNO} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test9
+
+test "create-principal 10"
+proc test10 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_AUX_ATTRIBUTES} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test10
+
+test "create-principal 11"
+proc test11 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_POLICY_CLR} "%s/a"
+ } $test $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test11
+
+test "create-principal 12"
+proc test12 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+
+}
+if {$RPC} { test12 }
+
+test "create-principal 13"
+proc test13 {} {
+ global test
+ begin_dump
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test13 }
+
+test "create-principal 14"
+proc test14 {} {
+ global test
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test14 }
+
+test "create-principal 15"
+proc test15 {} {
+ global test
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test15 }
+
+test "create-principal 16"
+proc test16 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+if {$RPC} { test16 }
+
+test "create-principal 17"
+proc test17 {} {
+ global test
+
+ begin_dump
+ if {! (( [principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "DUP"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test17
+
+test "create-principal 18"
+proc test18 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {KADM5_PRINCIPAL KADM5_POLICY} tP
+ } $test] "_Q_TOOSHORT"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test18
+
+test "create-principal 19"
+proc test19 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {KADM5_PRINCIPAL KADM5_POLICY} testpassword
+ } $test] "_Q_CLASS"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test19
+
+test "create-principal 20"
+proc test20 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {KADM5_PRINCIPAL KADM5_POLICY} Abyssinia
+ } $test] "_Q_DICT"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test20
+
+test "create-principal 21"
+proc test21 {} {
+ global test
+
+ begin_dump
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" non-existant-pol] \
+ {KADM5_PRINCIPAL KADM5_POLICY} NotinTheDictionary
+ } $test] "UNK_POLICY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ end_dump_compare "no-diffs"
+}
+test21
+
+test "create-principal 23"
+proc test23 {} {
+ global test
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ one_line_succeed_test \
+ [format {kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK} $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test23
+
+test "create-principal 24"
+proc test24 {} {
+ global test
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/rename admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ one_line_succeed_test \
+ [format {kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK} $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test24 }
+
+
+test "create-principal 28"
+proc test28 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {KADM5_PRINCIPAL KADM5_POLICY} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "create-principal 29"
+proc test29 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL KADM5_PRINC_EXPIRE_TIME} \
+ inTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 1\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test29
+
+test "create-principal 30"
+proc test30 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test30
+
+test "create-principal 31"
+proc test31 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol-nopw] \
+ {KADM5_PRINCIPAL KADM5_POLICY \
+ KADM5_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test31
+
+test "create-principal 32"
+proc test32 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ [princ_w_pol "%s/a" test-pol] \
+ {KADM5_PRINCIPAL KADM5_POLICY \
+ KADM5_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+
+ send "lindex \$principal 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test32
+
+test "create-principal 33"
+proc test33 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ {"%s/a" 0 0 1234 0 null 0 0 0 0 null 0} \
+ {KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test33
+
+test "create-principal 34"
+proc test34 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ { "%s/a" 0 0 1234 0 null 0 0 0 0 test-pol-nopw 0} \
+ {KADM5_PRINCIPAL KADM5_POLICY \
+ KADM5_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test34
+
+test "create-principal 35"
+proc test35 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ {"%s/a" 0 0 1234 0 null 0 0 0 0 test-pol 0} \
+ {KADM5_PRINCIPAL KADM5_POLICY \
+ KADM5_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test35
+
+test "create-principal 36"
+proc test36 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle \
+ {"%s/a" 0 0 999999999 0 null 0 0 0 0 test-pol 0} \
+ {KADM5_PRINCIPAL KADM5_POLICY \
+ KADM5_PW_EXPIRATION} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol policy} ]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+
+ send "lindex \$principal 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test36
+
+test "create-principal 37"
+proc test37 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test37
+
+test "create-principal 38"
+proc test38 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol-nopw] {KADM5_PRINCIPAL KADM5_POLICY} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test38
+
+test "create-principal 39"
+proc test39 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {KADM5_PRINCIPAL KADM5_POLICY} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if { ! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: cannot not retrieve principal"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$mod_date + $pw_max_life - $pw_expire"] > 5 } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test39
+
+test "create-principal 40"
+proc test40 {} {
+ global test
+ global prompt
+
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL KADM5_PW_EXPIRATION} \
+ NotinTheDictionary
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: can not retreive principal"
+ return;
+ }
+ send "lindex \$principal 4\n"
+ expect {
+ -re "0.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test40
+
+test "create-principal 43"
+proc test43 {} {
+ global test
+ one_line_fail_test [format {
+ kadm5_create_principal null \
+ [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+ } $test $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/destroy.exp b/src/lib/kadm5/unit-test/api.2/destroy.exp
new file mode 100644
index 000000000..808f0b401
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/destroy.exp
@@ -0,0 +1,203 @@
+source lib.t
+api_exit
+api_start
+
+test "destroy 1"
+
+proc test1 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_destroy $server_handle}
+ end_dump_compare "no-diffs"
+}
+test1
+
+#test "destroy 2"
+#
+#proc test2 {} {
+# global test
+# begin_dump
+# if {! [cmd {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure on init"
+# return
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test \
+# {kadm5_get_principal $server_handle admin principal} \
+# "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test2
+
+#test "destroy 3"
+#proc test3 {} {
+# global test
+#
+# begin_dump
+# if {! (( ! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+# error_and_restart "$test couldn't delete principal \"$test/a\""
+# return
+# }
+# if {! [cmd {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure on init"
+# return
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test [format {
+# kadm5_create_principal $server_handle \
+# [simple_principal "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+# } $test $test] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test3
+
+#test "destroy 4"
+#proc test4 {} {
+# global test prompt
+#
+# if {! (([principal_exists "$test/a"]) || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {! ([cmd {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }] &&
+# [cmd [format {
+# kadm5_get_principal $server_handle "%s/a" principal
+# } $test]])} {
+# error_and_restart "$test: error getting principal"
+# return;
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test [format {
+# kadm5_modify_principal $server_handle \
+# {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {KADM5_KVNO}
+# } $test "77"] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test4
+
+#test "destroy 5"
+#
+#proc test5 {} {
+# global test
+#
+# if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {! [cmd {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure on init"
+# return
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# return
+# }
+# one_line_fail_test [format {
+# kadm5_delete_principal $server_handle "%s/a"
+# } $test] "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test5
+
+#test "destroy 6"
+#
+#proc test6 {} {
+# global test
+# begin_dump
+# one_line_fail_test {kadm5_destroy $server_handle} "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test6
+
+
+#test "destroy 7"
+#
+#proc test7 {} {
+# global test
+# begin_dump
+# if {! [cmd {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }]} {
+# error "$test: unexpected failure in init"
+# return
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# }
+# one_line_fail_test {kadm5_destroy $server_handle} "NOT_INIT"
+# end_dump_compare "no-diffs"
+#}
+#test7
+
+test "destroy 8"
+proc test8 {} {
+ global test
+ begin_dump
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+ one_line_succeed_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+ end_dump_compare "no-diffs"
+}
+test8
+
+test "destroy 9"
+proc test9 {} {
+ global test
+ one_line_fail_test {kadm5_destroy null} "BAD_SERVER_HANDLE"
+}
+test9
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/dlte-policy.exp b/src/lib/kadm5/unit-test/api.2/dlte-policy.exp
new file mode 100644
index 000000000..95a57dc20
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/dlte-policy.exp
@@ -0,0 +1,207 @@
+source lib.t
+api_exit
+api_start
+
+test "delete-policy 2"
+proc test2 {} {
+ global test
+# set prms_id 744
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {kadm5_delete_policy $server_handle ""} "BAD_POL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test2
+
+test "delete-policy 5"
+proc test5 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_policy $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if ${RPC} test5
+
+test "delete-policy 6"
+proc test6 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_policy $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if ${RPC} test6
+
+test "delete-policy 7"
+proc test7 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_policy $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test7
+
+test "delete-policy 10"
+proc test10 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_delete_policy $server_handle "%s/a"
+ } $test]]} {
+ fail "$test"
+ return
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if { [policy_exists "$test/a"]} {
+ fail "$test"
+ return
+ }
+}
+test10
+
+test "delete-policy 12"
+proc test12 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test unexecpted failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [princ_w_pol "%s/a" \
+ "%s/a"] {KADM5_PRINCIPAL KADM5_POLICY} \
+ NotinTheDictionary
+ } $test $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {kadm5_delete_policy $server_handle test-pol} "POLICY_REF"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "delete-policy 13"
+proc test13 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_policy null "%s/a"
+ } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/dlte-principal.exp b/src/lib/kadm5/unit-test/api.2/dlte-principal.exp
new file mode 100644
index 000000000..fe157e880
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/dlte-principal.exp
@@ -0,0 +1,329 @@
+source lib.t
+
+api_exit
+api_start
+
+#test "delete-principal 1"
+#proc test1 {} {
+# global test
+# one_line_fail_test [format {
+# kadm5_delete_principal $server_handle "%s/a"
+# } $test] "NOT_INIT"
+#}
+#test1
+
+test "delete-principal 2"
+proc test2 {} {
+ global test
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {kadm5_delete_principal $server_handle null} "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: unexpected failure in destroy"
+ return
+ }
+}
+test2
+
+test "delete-principal 5"
+proc test5 {} {
+ global test
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test] "UNK_PRINC"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test5
+
+test "delete-principal 6"
+proc test6 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" test-pol])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test6 }
+
+
+test "delete-principal 7"
+proc test7 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test7 }
+
+
+test "delete-principal 8"
+proc test8 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test8 }
+
+test "delete-principal 9"
+proc test9 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test9 }
+
+test "delete-principal 10"
+proc test10 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test] "AUTH_DELETE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test10 }
+
+test "delete-principal 11"
+proc test11 {} {
+ global test
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test]]} {
+ fail "$test: delete failed"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if { [principal_exists "$test/a"] } {
+ fail "$test"
+ return
+ }
+}
+test11
+
+test "delete-principal 12"
+proc test12 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" test-pol])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_delete_principal $server_handle "%s/a"
+ } $test]]} {
+ fail "$test: delete failed"
+ return
+ }
+ if { [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ fail "$test: principal still exists"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref - 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ pass "$test"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+
+test12
+
+test "delete-principal 13"
+proc test13 {} {
+ global test
+ one_line_fail_test [format {
+ kadm5_delete_principal null "%s/a"
+ } $test] "BAD_SERVER_HANDLE"
+}
+test13
+
+return ""
+
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.2/get-policy.exp b/src/lib/kadm5/unit-test/api.2/get-policy.exp
new file mode 100644
index 000000000..ff41c17b9
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/get-policy.exp
@@ -0,0 +1,199 @@
+source lib.t
+api_exit
+api_start
+
+test "get-policy 3"
+proc test3 {} {
+ global test
+# set prms_id 744
+# setup_xfail {*-*-*} $prms_id
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {kadm5_get_policy $server_handle "" p} "BAD_POLICY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test3
+
+test "get-policy 6"
+proc test6 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+ "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } test6
+
+test "get-policy 7"
+proc test7 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+ "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } test7
+
+test "get-policy 11"
+proc test11 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/get-pol StupidAdmin $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_get_policy $server_handle test-pol p}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+test "get-policy 12"
+proc test12 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/get-pol StupidAdmin \
+ $KADM5_CHANGEPW_SERVICE null $KADM5_STRUCT_VERSION \
+ $KADM5_API_VERSION_2 server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {kadm5_get_policy $server_handle test-pol-nopw p}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "get-policy 15"
+proc test15 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/pol StupidAdmin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {kadm5_get_policy $server_handle test-pol-nopw p}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "get-policy 16"
+proc test16 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/pol StupidAdmin $KADM5_CHANGEPW_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {kadm5_get_policy $server_handle test-pol-nopw p}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test16
+
+test "get-policy 17"
+proc test17 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_get_policy $server_handle test-pol p}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+test "get-policy 18"
+proc test18 {} {
+ global test
+
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {kadm5_get_policy $server_handle test-pol p} \
+ "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } test18
+
+test "get-policy 21"
+proc test21 {} {
+ global test
+
+ one_line_fail_test {kadm5_get_policy null "pol1" p} "BAD_SERVER_HANDLE"
+}
+test21
diff --git a/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp b/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp
new file mode 100644
index 000000000..486d1a6ab
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/get-principal-v2.exp
@@ -0,0 +1,234 @@
+source lib.t
+api_exit
+api_start
+
+test "get-principal 100"
+proc test100 {} {
+ global test prompt
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd {
+ kadm5_get_principal $server_handle testuser p \
+ {KADM5_PRINCIPAL_NORMAL_MASK}
+ }]} {
+ error "$test: unexpected failure in get_principal"
+ }
+ send "lindex \$p 16\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting num_keys"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting num_keys"
+ return
+ }
+ }
+ send "lindex \$p 17\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" { set num_tl $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting num_tl"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting num_tl"
+ return
+ }
+ }
+ send "lindex \$p 18\n"
+ expect {
+ -re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+ -re "\n$prompt" { set key_data {} }
+ timeout {
+ error_and_restart "$test: timeout getting key_data"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting key_data"
+ return
+ }
+ }
+ send "lindex \$p 19\n"
+ expect {
+ -re "({.*})\n$prompt" {set tl_data $expect_out(1,string) }
+ -re "\n$prompt" { set tl_data {} }
+ timeout {
+ error_and_restart "$test: timeout getting tl_data"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting tl_data"
+ return
+ }
+ }
+
+ set failed 0
+ if {$num_keys != 0} {
+ fail "$test: num_keys $num_keys should be 0"
+ set failed 1
+ }
+ if {$num_tl != 0} {
+ fail "$test: num_tl $num_tl should be 0"
+ set failed 1
+ }
+ if {$key_data != {}} {
+ fail "$test: key_data $key_data should be {}"
+ set failed 1
+ }
+ if {$tl_data != "{}"} {
+ fail "$test: tl_data $tl_data should be {}"
+ set failed 1
+ }
+ if {$failed == 0} {
+ pass "$test"
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test100
+
+proc test101_102 {rpc} {
+ global test prompt
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd {
+ kadm5_get_principal $server_handle testuser p \
+ {KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+ }]} {
+ error "$test: unexpected failure in get_principal"
+ }
+ send "lindex \$p 16\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting num_keys"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting num_keys"
+ return
+ }
+ }
+ send "lindex \$p 18\n"
+ expect {
+ -re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+ -re "\n$prompt" { set key_data {} }
+ timeout {
+ error_and_restart "$test: timeout getting key_data"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting key_data"
+ return
+ }
+ }
+
+ set failed 0
+ if {$num_keys != 2} {
+ fail "$test: num_keys $num_keys should be 2"
+ set failed 1
+ }
+ for {set i 0} {$i < $num_keys} {incr i} {
+ set key "[lindex [lindex $key_data $i] 2]"
+ if {($rpc && [string compare $key ""] != 0) ||
+ ((! $rpc) && [string compare $key ""] == 0)} {
+ fail "$test: key_data $key is wrong"
+ set failed 1
+
+ }
+ }
+ if {$failed == 0} { pass "$test" }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test "get-principal 101"
+if {$RPC} {test101_102 $RPC}
+test "get-principal 102"
+if {! $RPC} {test101_102 $RPC}
+
+test "get-principal 103"
+proc test103 {} {
+ global test prompt
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd {
+ kadm5_get_principal $server_handle testuser p \
+ {KADM5_PRINCIPAL_NORMAL_MASK KADM5_TL_DATA}
+ }]} {
+ error "$test: unexpected failure in get_principal"
+ }
+ send "lindex \$p 17\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" { set num_tl $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting num_tl"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting num_tl"
+ return
+ }
+ }
+ send "lindex \$p 19\n"
+ expect {
+ -re "({.*})\n$prompt" {set tl_data $expect_out(1,string) }
+ -re "\n$prompt" { set tl_data {} }
+ timeout {
+ error_and_restart "$test: timeout getting tl_data"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting tl_data"
+ return
+ }
+ }
+
+ if {$num_tl == 0} {
+ fail "$test: num_tl $num_tl should not be 0"
+ } elseif {$tl_data == {}} {
+ fail "$test: tl_data $tl_data should not be {}"
+ } else {
+ pass "$test"
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test103
+
+return ""
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.2/get-principal.exp b/src/lib/kadm5/unit-test/api.2/get-principal.exp
new file mode 100644
index 000000000..4f91b33bb
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/get-principal.exp
@@ -0,0 +1,346 @@
+source lib.t
+api_exit
+api_start
+
+test "get-principal 1"
+proc test1 {} {
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test \
+ {kadm5_get_principal $server_handle null p KADM5_PRINCIPAL_NORMAL_MASK} "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test1
+
+test "get-principal 2"
+proc test2 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "UNK_PRINC"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test2
+
+test "get-principal 3"
+proc test3 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test3 }
+
+test "get-principal 4"
+proc test4 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test4 }
+
+test "get-principal 5"
+proc test5 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test5 }
+
+test "get-principal 6"
+proc test6 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test6 }
+
+test "get-principal 7"
+proc test7 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test7 }
+
+
+test "get-principal 8"
+proc test8 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_get_principal $server_handle "%s/a" p KADM5_PRINCIPAL_NORMAL_MASK
+ } $test] "AUTH_GET"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test8 }
+
+
+test "get-principal 9"
+proc test9 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {kadm5_get_principal $server_handle admin/none p KADM5_PRINCIPAL_NORMAL_MASK}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+test "get-principal 10"
+proc test10 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test \
+ {kadm5_get_principal $server_handle admin/none p KADM5_PRINCIPAL_NORMAL_MASK}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+test "get-principal 11"
+proc test11 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_get_principal $server_handle admin/get p KADM5_PRINCIPAL_NORMAL_MASK}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+test "get-principal 12"
+proc test12 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_get_principal $server_handle admin/get p KADM5_PRINCIPAL_NORMAL_MASK}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "get-principal 13"
+proc test13 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_get_principal $server_handle admin/add p KADM5_PRINCIPAL_NORMAL_MASK}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+test "get-principal 14"
+proc test14 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin/get-mod admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test {kadm5_get_principal $server_handle admin/add p KADM5_PRINCIPAL_NORMAL_MASK}
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+test "get-principal 15"
+proc test15 {} {
+ one_line_fail_test \
+ {kadm5_get_principal null "admin" p KADM5_PRINCIPAL_NORMAL_MASK} "BAD_SERVER_HANDLE"
+}
+test15
+
+return ""
+
+
+
+
diff --git a/src/lib/kadm5/unit-test/api.2/init-v2.exp b/src/lib/kadm5/unit-test/api.2/init-v2.exp
new file mode 100644
index 000000000..5de25d6fe
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/init-v2.exp
@@ -0,0 +1,545 @@
+source lib.t
+
+api_exit
+api_start
+
+test "init 100"
+proc test100 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_PROFILE} /does-not-exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "ENOENT"
+}
+test100
+
+test "init 101"
+proc test101 {} {
+ global test
+
+ # XXX Fix to work with a remote TEST_SERVER. For now, make sure
+ # it fails in that case.
+ one_line_succeed_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADMIN_SERVER KADM5_CONFIG_KADMIND_PORT} {localhost 1751}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADMIN_SERVER KADM5_CONFIG_KADMIND_PORT} {localhost 1}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "RPC_ERROR"
+}
+if {$RPC} test101
+
+test "init 102"
+proc test102 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADMIN_SERVER} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "CONFIG_BADFORMAT"
+}
+if {$RPC} test102
+
+test "init 103"
+proc test103 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_DBNAME} /does-not-exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "ENOENT"
+}
+if {! $RPC} test103
+
+test "init 104"
+proc test104 {} {
+ global test
+
+ # This is slightly lame, but it works: if CONFIG_ADBNAME is obeyed,
+ # then the lock file will be set based on it, and it won't exist.
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADBNAME} /does-not-exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "NOLOCKFILE"
+}
+if {! $RPC} test104
+
+test "init 105"
+proc test105 {} {
+ global test
+
+ # The lock info is stored in a static structure so that it applies
+ # to all handles in the process (why?). We need to restart the api
+ # in order to ensure we are using the new lockfile.
+ api_exit
+ api_start
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADB_LOCKFILE} /does-not-exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "NOLOCKFILE"
+
+ api_exit
+ api_start
+}
+if {! $RPC} test105
+
+test "init 106"
+proc test106 {} {
+ global test prompt
+
+ send [string trim {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MKEY_FROM_KBD} 1] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]
+ send "\n"
+ expect {
+ -re ":$" { set prompting 1}
+ -re "\nOK .*$prompt$" { fail "$test: premature success" }
+ -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+ timeout { fail "$test: timeout" }
+ eof { fail "$test: eof" }
+ }
+ if {$prompting} {
+ one_line_succeed_test mrroot
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} test106
+
+test "init 107"
+proc test107 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_STASH_FILE} /does-not-exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "KDB_CANTREAD_STORED"
+}
+if {! $RPC} test107
+
+test "init 108"
+proc test108 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MKEY_NAME} does/not/exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "KDB_NOMASTERKEY"
+}
+if {! $RPC} test108
+
+test "init 109-113"
+proc test109 {} {
+ global test prompt
+
+ delete_principal "$test/a"
+
+ # I'd like to specify flags explicitly and check them, as in the
+ # following config_params, but tcl gets mighty confused if I do and
+ # I have no idea why.
+# [config_params {KADM5_CONFIG_MAX_LIFE KADM5_CONFIG_MAX_RLIFE KADM5_CONFIG_EXPIRATION KADM5_CONFIG_FLAGS KADM5_CONFIG_ENCTYPES} {10 20 30 KRB5_KDB_DISALLOW_TGT_BASED {}} ]
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MAX_LIFE KADM5_CONFIG_MAX_RLIFE KADM5_CONFIG_EXPIRATION KADM5_CONFIG_ENCTYPES} {10 20 30 {}} ] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ fail "$test: cannot init with max_life"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_create_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test]]} {
+ fail "$test: can not create principal"
+ return;
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" p \
+ {KADM5_PRINCIPAL_NORMAL_MASK KADM5_KEY_DATA}
+ } $test]]} {
+ fail "$test: can not get principal"
+ return;
+ }
+ send "puts \$p\n"
+ send "lindex \$p 4\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting max_life"
+ return
+ }
+ }
+ send "lindex \$p 12\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set max_rlife $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting max_rlife"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting max_rlife"
+ return
+ }
+ }
+ send "lindex \$p 1\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set expiration $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting expiration"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting expiration"
+ return
+ }
+ }
+ send "lindex \$p 7\n"
+ expect {
+ -re "(\[A-Z_\]*)\n$prompt" {set flags $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting flags"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting flags"
+ return
+ }
+ }
+ # This sorta worries me. Since the test is setting ENCTYPES to
+ # nothing, the principal has no keys. That means that nothing is
+ # printed for the keys in the correct case; but it feels too
+ # likely that nothing will be printed in the case of some problem.
+ send "lindex \$p 18\n"
+ expect {
+ -re "({.*})\n$prompt" {set key_data $expect_out(1,string) }
+ -re "\n$prompt" { set key_data {} }
+ timeout {
+ error_and_restart "$test: timeout getting flags"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting flags"
+ return
+ }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+ if {$max_life == 10} {
+ pass "$test"
+ } else {
+ fail "$test: $max_life is not 10"
+ }
+ if {$max_rlife == 20} {
+ pass "$test"
+ } else {
+ fail "$test: $max_rlife is not 20"
+ }
+ if {$expiration == 30} {
+ pass "$test"
+ } else {
+ fail "$test: $expiration is not 30"
+ }
+ if {$flags == ""} {
+ pass "$test"
+ } else {
+ fail "$test: flags $flags are wrong"
+ }
+ if {$key_data == {}} {
+ pass "$test"
+ } else {
+ fail "$test: key_data $key_data is wrong"
+ }
+}
+if {! $RPC} test109
+
+test "init 114"
+proc test114 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADMIN_SERVER} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_SERVER_PARAMS"
+}
+if {! $RPC} test114
+
+test "init 115"
+proc test115 {} {
+ global test
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_DBNAME} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADBNAME} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ACL_FILE} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_DICT_FILE} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ADMIN_KEYTAB} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MKEY_FROM_KBD} 0] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_STASH_FILE} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MKEY_NAME} does.not.exist] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ENCTYPE} 0] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MAX_LIFE} 0] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_MAX_RLIFE} 0] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_EXPIRATION} 0] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_FLAGS} 0] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_ENCTYPES} {{}}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_CLIENT_PARAMS"
+}
+if {$RPC} test115
+
+test "init 116"
+proc test116 {} {
+ global test
+
+ delete_principal "$test/a"
+
+ if {! [cmd {kadm5_init admin/get-add admin $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ get_add_handle}]} {
+ error_and_restart "$test: couldn't init with admin/get-add"
+ }
+
+ if {! [cmd {kadm5_init admin/mod-delete admin $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ mod_delete_handle}]} {
+ error_and_restart "$test: couldn't init with admin/get-add"
+ }
+
+ one_line_succeed_test {
+ kadm5_get_principal $get_add_handle testuser p \
+ KADM5_PRINCIPAL_NORMAL_MASK
+ }
+ one_line_succeed_test [format {
+ kadm5_create_principal $get_add_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test]
+ one_line_fail_test {
+ kadm5_modify_principal $get_add_handle [simple_principal testuser] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } "AUTH_MODIFY"
+ one_line_fail_test {
+ kadm5_delete_principal $get_add_handle testuser
+ } "AUTH_DELETE"
+
+ one_line_fail_test {
+ kadm5_get_principal $mod_delete_handle testuser p \
+ KADM5_PRINCIPAL_NORMAL_MASK
+ } "AUTH_GET"
+ one_line_fail_test [format {
+ kadm5_create_principal $mod_delete_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL} testpass
+ } $test] "AUTH_ADD"
+ one_line_succeed_test {
+ kadm5_modify_principal $mod_delete_handle [simple_principal testuser] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ }
+ one_line_succeed_test [format {
+ kadm5_delete_principal $mod_delete_handle "%s/a"
+ } $test]
+
+ if {! [cmd {kadm5_destroy $get_add_handle}]} {
+ error_and_restart "$test: couldn't close get_add_handle"
+ }
+ if {! [cmd {kadm5_destroy $mod_delete_handle}]} {
+ error_and_restart "$test: couldn't close mod_delete_handle"
+ }
+}
+if {$RPC} test116
+
+send "puts \$KADM5_ADMIN_SERVICE\n"
+expect {
+ -re "(\[a-zA-Z/@\]+)\n$prompt" {
+ set KADM5_ADMIN_SERVICE $expect_out(1,string)
+ }
+ default {
+ error_and_restart "$test: timeout/eof getting admin_service"
+ return
+ }
+}
+
+send "puts \$KADM5_CHANGEPW_SERVICE\n"
+expect {
+ -re "(\[a-zA-Z/@\]+)\n$prompt" {
+ set KADM5_CHANGEPW_SERVICE $expect_out(1,string)
+ }
+ default {
+ error_and_restart "$test: timeout/eof getting changepw_service"
+ return
+ }
+}
+
+test "init 150"
+proc test150 {} {
+ global test KADM5_ADMIN_SERVICE
+
+ set env(KRB5CCNAME) /tmp/krb5cc_kadm5_init_v2
+ kdestroy
+ kinit testuser notathena "-S $KADM5_ADMIN_SERVICE"
+ one_line_succeed_test {
+ kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ kdestroy
+}
+if {$RPC} test150
+
+test "init 151"
+proc test151 {} {
+ global test KADM5_CHANGEPW_SERVICE
+
+ set env(KRB5CCNAME) /tmp/krb5cc_kadm5_init_v2
+ kdestroy
+ kinit testuser notathena "-S $KADM5_CHANGEPW_SERVICE"
+ one_line_succeed_test {
+ kadm5_init_with_creds testuser null $KADM5_CHANGEPW_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ kdestroy
+}
+if {$RPC} test151
+
+test "init 152"
+proc test152 {} {
+ global test KADM5_ADMIN_SERVICE
+
+ kdestroy
+ one_line_fail_test {
+ kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "GSS_ERROR"
+}
+if {$RPC} test152
+
+test "init 153"
+proc test153 {} {
+ global test KADM5_ADMIN_SERVICE
+
+ set env(KRB5CCNAME) /tmp/krb5cc_kadm5_init_v2
+ kinit testuser notathena
+ one_line_fail_test {
+ kadm5_init_with_creds testuser null $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } "GSS_ERROR"
+}
+if {$RPC} test153
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/init.exp b/src/lib/kadm5/unit-test/api.2/init.exp
new file mode 100644
index 000000000..97a99e0ba
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/init.exp
@@ -0,0 +1,731 @@
+source lib.t
+
+# Assumptions:
+#
+# Principal "admin" exists, with "get", "add", "modify" and "delete"
+# access bits and password "admin".
+# The string "not-the-password" isn't the password of any user in the database.
+# Database master password is "mrroot".
+
+api_exit
+api_start
+test "init 1"
+
+one_line_fail_test_nochk \
+ {kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_REALM} {""}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle}
+
+test "init 2"
+
+one_line_fail_test_nochk \
+ {kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_REALM} {@}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle}
+
+test "init 2.5"
+
+one_line_fail_test_nochk \
+ {kadm5_init admin admin $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_REALM} {BAD.REALM}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 server_handle}
+
+test "init 3"
+
+proc test3 {} {
+ global test
+ if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ one_line_fail_test_nochk [format {
+ kadm5_init admin admin "%s/a" null $KADM5_STRUCT_VERSION \
+ $KADM5_API_VERSION_2 server_handle
+ } $test]
+}
+if {$RPC} { test3 }
+
+test "init 4"
+
+proc test4 {} {
+ global test
+ if {! ((! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+
+ one_line_fail_test_nochk [format {
+ kadm5_init admin admin "%s/a" null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test4 }
+
+test "init 5"
+
+if {$RPC} {
+ one_line_fail_test_nochk {
+ kadm5_init admin admin admin null $KADM5_STRUCT_VERSION \
+ $KADM5_API_VERSION_2 server_handle
+ }
+}
+
+test "init 6"
+
+proc test6 {} {
+ global test
+
+ send "kadm5_init admin null \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_2 server_handle\n"
+
+ expect {
+ {Enter password:} { }
+ eof {
+ fail "$test: eof instead of password prompt"
+ api_exit
+ api_start
+ return
+ }
+ timeout {
+ fail "$test: timeout instead of password prompt"
+ return
+ }
+ }
+ one_line_succeed_test "admin"
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if { $RPC } { test6 }
+
+test "init 7"
+proc test7 {} {
+ global test
+
+ send "kadm5_init admin \"\" \$KADM5_ADMIN_SERVICE null \$KADM5_STRUCT_VERSION \$KADM5_API_VERSION_2 server_handle\n"
+
+ expect {
+ {Enter password:} { }
+ -re "key:$" { }
+ eof {
+ fail "$test: eof instead of password prompt"
+ api_exit
+ api_start
+ return
+ }
+ timeout {
+ fail "$test: timeout instead of password prompt"
+ return
+ }
+ }
+ one_line_succeed_test "admin"
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if { $RPC } { test7 }
+
+test "init 8"
+
+proc test8 {} {
+ global test
+ if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ one_line_fail_test_nochk [format {
+ kadm5_init "%s/a" admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test8 }
+
+test "init 9"
+
+if {$RPC} {
+ global test
+ one_line_fail_test_nochk {
+ kadm5_init admin not-the-password $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+}
+
+test "init 10"
+
+proc test10 {} {
+ global test
+# set prms_id 562
+# setup_xfail {*-*-*} $prms_id
+ one_line_fail_test_nochk {
+ kadm5_init null admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+}
+test10
+
+#test "init 11"
+#
+#proc test11 {} {
+# global test
+# set prms_id 563
+# setup_xfail {*-*-*} $prms_id
+# one_line_fail_test_nochk {
+# kadm5_init "" admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }
+#}
+#test11
+
+test "init 12"
+
+proc test12 {} {
+ global test
+ one_line_fail_test_nochk [format {
+ kadm5_init "%s/a" admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test12 }
+
+test "init 13"
+
+proc test13 {} {
+ global test
+ one_line_fail_test_nochk [format {
+ kadm5_init "%s/a@SECURE-TEST.OV.COM" admin \
+ $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION \
+ $KADM5_API_VERSION_2 server_handle
+ } $test]
+}
+if {$RPC} { test13 }
+
+test "init 14"
+
+proc test14 {} {
+ global test
+ one_line_fail_test_nochk [format {
+ kadm5_init "%s/a@BAD.REALM" admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test]
+}
+if {$RPC} { test14 }
+
+test "init 15"
+
+if {$RPC} {
+ one_line_fail_test_nochk {
+ kadm5_init admin@BAD.REALM admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+}
+
+test "init 16"
+
+proc test16 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test16
+
+test "init 17"
+
+proc test17 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin@SECURE-TEST.OV.COM admin \
+ $KADM5_ADMIN_SERVICE null $KADM5_STRUCT_VERSION \
+ $KADM5_API_VERSION_2 server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test17
+
+test "init 18"
+
+proc test18 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test18
+
+test "init 19"
+
+proc test19 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin@SECURE-TEST.OV.COM admin \
+ $KADM5_ADMIN_SERVICE \
+ [config_params {KADM5_CONFIG_REALM} {SECURE-TEST.OV.COM}] \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test19
+
+test "init 20"
+
+proc test20 {} {
+ global test
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error_and_restart "$test: couldn't init database"
+ return
+ }
+ one_line_succeed_test \
+ {kadm5_get_principal $server_handle admin principal KADM5_PRINCIPAL_NORMAL_MASK}
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test20
+
+#test "init 21"
+#
+#proc test21 {} {
+# global test
+# if {! [cmd {
+# kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }]} {
+# error_and_restart "$test: couldn't init database"
+# return
+# }
+# one_line_fail_test_nochk {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# }
+#}
+#test21
+
+
+# proc test22 {} {
+# global test prompt
+# set prompting 0
+# send [string trim {
+# kadm5_init admin null null null $KADM5_STRUCT_VERSION \
+# $KADM5_API_VERSION_2 server_handle
+# }]
+# send "\n"
+# expect {
+# -re ":$" { set prompting 1}
+# -re "\nOK .*$prompt$" { fail "$test: premature success" }
+# -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+# timeout { fail "$test: timeout" }
+# eof { fail "$test: eof" }
+# }
+# if {$prompting} {
+# one_line_succeed_test mrroot
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# }
+# }
+# if {! $RPC} { test22 }
+#
+# test "init 22.5"
+# proc test225 {} {
+# global test prompt
+# set prompting 0
+# send [string trim {
+# kadm5_init admin null null null $KADM5_STRUCT_VERSION \
+# $KADM5_API_VERSION_2 server_handle
+# }]
+# send "\n"
+# expect {
+# -re ":$" { set prompting 1}
+# -re "\nOK .*$prompt$" { fail "$test: premature success" }
+# -re "\nERROR .*$prompt$" { fail "$test: premature failure" }
+# timeout { fail "$test: timeout" }
+# eof { fail "$test: eof" }
+# }
+# if {$prompting} {
+# one_line_succeed_test mrroot
+# }
+# if {! [cmd {kadm5_destroy $server_handle}]} {
+# error_and_restart "$test: couldn't close database"
+# }
+# }
+# if {! $RPC} { test225 }
+
+test "init 23"
+
+proc test23 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin not-the-password $KADM5_ADMIN_SERVICE \
+ null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test23 }
+
+test "init 24"
+
+proc test24 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin admin null null $KADM5_STRUCT_VERSION \
+ $KADM5_API_VERSION_2 server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test24 }
+
+test "init 25"
+
+proc test25 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin admin foobar null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if {! $RPC} { test25 }
+
+test "init 26"
+
+#proc test26 {} {
+# global test
+#
+# api_exit
+# api_start
+# one_line_fail_test_nochk {
+# kadm5_get_principal $server_handle admin principal
+# }
+#}
+#test26
+
+#test "init 27"
+#
+#proc test27 {} {
+# global test
+#
+# if {! ((! [principal_exists "$test/a"]) || [delete_principal "$test/a"])} {
+# error_and_restart "$test: couldn't delete principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {[cmd [format {
+# kadm5_create_principal $server_handle [simple_principal \
+# "%s/a"] {KADM5_PRINCIPAL} "%s/a"
+# } $test $test]]} {
+# fail "$test: unexpected success in add"
+# return
+# }
+# end_dump_compare "no-diffs"
+#}
+#test27
+
+#test "init 28"
+#
+#proc test28 {} {
+# global test prompt
+#
+# if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {! ([cmd {
+# kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+# $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+# server_handle
+# }] && [cmd [format {
+# kadm5_get_principal $server_handle "%s/a" principal
+# } $test]])} {
+# error_and_restart "$test: error getting principal"
+# return;
+# }
+# send "lindex \$principal 8\n"
+# expect {
+# -re "\n(\[0-9\]+).*$prompt$" {set kvno $expect_out(1,string) }
+# timeout {
+# error_and_restart "$test: timeout getting principal kvno"
+# return
+# }
+# eof {
+# error_and_restart "$test: eof getting principal kvno"
+# return
+# }
+# }
+# api_exit
+# api_start
+# set new_kvno [expr "$kvno + 1"]
+# if {[cmd [format {
+# kadm5_modify_principal $server_handle \
+# {"%s/a" 0 0 0 0 0 0 0 %d 0 0 0} {KADM5_KVNO}
+# } $test $new_kvno]]} {
+# fail "$test: unexpected success in modify"
+# return;
+# }
+# end_dump_compare "no-diffs"
+#}
+#test28
+
+#test "init 29"
+#
+#proc test29 {} {
+# global test
+#
+# if {! ([principal_exists "$test/a"] || [create_principal "$test/a"])} {
+# error_and_restart "$test: couldn't create principal \"$test/a\""
+# return
+# }
+# begin_dump
+# if {[cmd [format {
+# kadm5_delete_principal $server_handle "%s/a"
+# } $test]]} {
+# fail "$test: unexpected success in delete"
+# return
+# }
+# end_dump_compare "no-diffs"
+#}
+#test29
+
+test "init 30"
+proc test30 {} {
+ global test
+ if {[cmd {
+ kadm5_init admin foobar $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error_and_restart "$test: unexpected succsess"
+ return
+ }
+ one_line_succeed_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+if ${RPC} { test30 }
+
+test "init 31"
+proc test31 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $bad_struct_version_mask $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_STRUCT_VERSION"
+}
+test31
+
+test "init 32"
+proc test32 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $no_struct_version_mask $KADM5_API_VERSION_2 \
+ server_handle
+ } "BAD_STRUCT_VERSION"
+}
+test32
+
+test "init 33"
+proc test33 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $old_struct_version $KADM5_API_VERSION_2 \
+ server_handle
+ } "OLD_STRUCT_VERSION"
+}
+test33
+
+test "init 34"
+proc test34 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $new_struct_version $KADM5_API_VERSION_2 \
+ server_handle
+ } "NEW_STRUCT_VERSION"
+}
+test34
+
+test "init 35"
+proc test35 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $bad_api_version_mask \
+ server_handle
+ } "BAD_API_VERSION"
+}
+test35
+
+test "init 36"
+proc test36 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $no_api_version_mask \
+ server_handle
+ } "BAD_API_VERSION"
+}
+test36
+
+test "init 37"
+proc test37 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $old_api_version \
+ server_handle
+ } "OLD_LIB_API_VERSION"
+}
+if { $RPC } test37
+
+test "init 38"
+proc test38 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $old_api_version \
+ server_handle
+ } "OLD_SERVER_API_VERSION"
+}
+if { ! $RPC } test38
+
+test "init 39"
+proc test39 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $new_api_version \
+ server_handle
+ } "NEW_LIB_API_VERSION"
+}
+if { $RPC } test39
+
+test "init 40"
+proc test40 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $new_api_version \
+ server_handle
+ } "NEW_SERVER_API_VERSION"
+}
+if { ! $RPC } test40
+
+test "init 41"
+proc test41 {} {
+ global test
+ one_line_fail_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_API_VERSION_2 $KADM5_STRUCT_VERSION \
+ server_handle
+ } "BAD_"
+}
+test41
+
+test "init 42"
+proc test42 {} {
+ global test
+ one_line_succeed_test {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }
+ if {! [cmd {kadm5_destroy $server_handle}]} {
+ error_and_restart "$test: couldn't close database"
+ }
+}
+test42
+
+
+proc test45_46 {service} {
+ global test kdb5_edit env
+
+ spawn $kdb5_edit -R "del $service"
+ expect {
+ {Type 'yes' to confirm:} {
+ send "yes\n"
+ }
+ default {
+ error "kdb5_edit del failed\n";
+ }
+ }
+ expect eof
+ wait
+
+ one_line_fail_test [concat {kadm5_init admin admin } \
+ $service \
+ { null $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle}] "SECURE_PRINC_MISSING"
+
+ # this leaves the keytab with an incorrect entry
+ exec $kdb5_edit -R "ark $service"
+
+ # restart the api so it gets a new ccache
+ api_exit
+ api_start
+}
+
+if {$RPC} {
+ test "init 45"
+
+ test45_46 ovsec_adm/admin
+
+ test "init 46"
+
+ test45_46 ovsec_adm/changepw
+
+ # re-extract the keytab so it is right
+ exec rm /krb5/ovsec_adm.srvtab
+ exec $env(MAKE_KEYTAB) -princ ovsec_adm/admin -princ ovsec_adm/changepw \
+ -princ kadmin/admin -princ kadmin/changepw /krb5/ovsec_adm.srvtab
+}
+
+return ""
+
diff --git a/src/lib/kadm5/unit-test/api.2/mod-policy.exp b/src/lib/kadm5/unit-test/api.2/mod-policy.exp
new file mode 100644
index 000000000..07e2e62db
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/mod-policy.exp
@@ -0,0 +1,703 @@
+source lib.t
+api_exit
+api_start
+
+test "modify-policy 2"
+proc test2 {} {
+ global test
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MAX_LIFE}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test2 }
+
+test "modify-policy 4"
+proc test4 {} {
+ global test
+
+ if {! ([policy_exists "$test/a"] ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_REF_COUNT}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test4
+
+test "modify-policy 8"
+proc test8 {} {
+ global test
+# set prms_id 744
+# setup_xfail {*-*-*} $prms_id
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_modify_policy $server_handle [simple_policy ""] \
+ {KADM5_PW_MAX_LIFE}
+ } "BAD_POLICY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test8
+
+test "modify-policy 9"
+proc test9 {} {
+ global test
+ global prompt
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MIN_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+test "modify-policy 10"
+proc test10 {} {
+ global test
+ global prompt
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 32 0 0 0 0 0} \
+ {KADM5_PW_MIN_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 1\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+
+test "modify-policy 11"
+proc test11 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MAX_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test11
+
+test "modify-policy 12"
+proc test12 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 32 0 0 0 0} \
+ {KADM5_PW_MAX_LIFE}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "32\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test12
+
+test "modify-policy 13"
+proc test13 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MIN_LENGTH}
+ } $test] "BAD_LENGTH"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+test "modify-policy 14"
+proc test14 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 0 8 0 0 0} \
+ {KADM5_PW_MIN_LENGTH}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 3\n"
+ expect {
+ -re "8\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test14
+
+test "modify-policy 15"
+proc test15 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "modify-policy 16"
+proc test16 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 0 0 1 0 0} \
+ {KADM5_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test16
+
+test "modify-policy 17"
+proc test17 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a"])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 0 0 5 0 0} \
+ {KADM5_PW_MIN_CLASSES}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 4\n"
+ expect {
+ -re "5\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+test "modify-policy 18"
+proc test18 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 0 0 6 0 0} \
+ {KADM5_PW_MIN_CLASSES}
+ } $test] "BAD_CLASS"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+test "modify-policy 19"
+proc test19 {} {
+ global test
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_HISTORY_NUM}
+ } $test] "BAD_HISTORY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test19
+
+test "modify-policy 20"
+proc test20 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 1 0} \
+ {KADM5_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "1\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test20
+
+test "modify-policy 21"
+proc test21 {} {
+ global test
+ global prompt
+
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_policy $server_handle {"%s/a" 0 0 0 0 10 0} \
+ {KADM5_PW_HISTORY_NUM}
+ } $test]]} {
+ fail $test
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_policy $server_handle "%s/a" policy
+ } $test]]} {
+ fail "$test: can not retrieve policy"
+ return
+ }
+ send "lindex \$policy 5\n"
+ expect {
+ -re "10\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21
+
+test "modify-policy 22"
+proc test22 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MAX_LIFE}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test22
+
+test "modify-policy 23"
+proc test23 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MAX_LIFE}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} test23
+
+test "modify-policy 26"
+proc test26 {} {
+ global test
+ if {! (( [policy_exists "$test/a"]) ||
+ [create_policy "$test/a" ])} {
+ error_and_restart "$test: couldn't create policy \"$test/a\""
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_modify_policy $server_handle [simple_policy "%s/a"] \
+ {KADM5_PW_MAX_LIFE}
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test26
+
+test "modify-policy 30"
+proc test30 {} {
+ global test
+
+ one_line_fail_test [format {
+ kadm5_modify_policy null [simple_policy "%s/a"] \
+ {KADM5_PW_MAX_LIFE}
+ } $test] "BAD_SERVER_HANDLE"
+}
+test30
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/mod-principal.exp b/src/lib/kadm5/unit-test/api.2/mod-principal.exp
new file mode 100644
index 000000000..5e24e08b0
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/mod-principal.exp
@@ -0,0 +1,1942 @@
+source lib.t
+api_exit
+api_start
+
+#test "modify-principal 1"
+#proc test1 {} {
+# global test
+# one_line_fail_test [format {
+# kadm5_modify_principal $server_handle [simple_principal \
+# "%s/a"] {KADM5_PW_EXPIRATION}
+# } $test] "NOT_INIT"
+#}
+#test1
+
+test "modify-principal 2"
+proc test2 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MODIFY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test2 }
+
+test "modify-principal 4"
+proc test4 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINCIPAL}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test4
+
+
+test "modify-principal 5"
+proc test5 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_LAST_PWD_CHANGE}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test5
+
+test "modify-principal 6"
+proc test6 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MOD_TIME}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test6
+
+test "modify-principal 7"
+proc test7 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MOD_NAME}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test7
+
+test "modify-principal 8"
+proc test8 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MKVNO}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test8
+
+test "modify-principal 9"
+proc test9 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_AUX_ATTRIBUTES}
+ } $test] "BAD_MASK"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test9
+
+test "modify-principal 10"
+proc test10 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test] "UNK_PRINC"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test10
+
+test "modify-principal 11"
+proc test11 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/none admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test11 }
+
+test "modify-principal 12"
+proc test12 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/get admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test12 }
+
+test "modify-principal 13"
+proc test13 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/add admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test13 }
+
+test "modify-principal 14"
+proc test14 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/delete admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test] "AUTH_MOD"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test14 }
+
+test "modify-principal 15"
+proc test15 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test15
+
+test "modify-principal 17"
+proc test17 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ no-policy] {KADM5_POLICY}
+ } $test] "UNK_POLICY"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test17
+
+test "modify-principal 18"
+proc test18 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal "$test/a"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {KADM5_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref + 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test18
+
+test "modify-principal 19"
+proc test19 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal "$test/a"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {KADM5_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref + 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test19
+
+test "modify-principal 20"
+proc test20 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_POLICY_CLR}
+ } $test]]} {
+ error "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { fail "$test" }
+ timeout { pass "$test" }
+ }
+ send "lindex \$p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$oldref - 1"] != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test20
+
+test "modify-principal 21"
+proc test21 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol old_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol-nopw old_p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol-nopw] {KADM5_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$old_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ send "lindex \$old_p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set old_p2_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol new_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol-nopw new_p2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$new_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ send "lindex \$new_p2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set new_p2_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { [expr "$old_p1_ref - 1"] != $new_p1_ref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { [expr "$old_p2_ref + 1"] != $new_p2_ref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21
+
+test "modify-principal 21.5"
+proc test21.5 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol old_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {KADM5_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$old_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set old_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol new_p1}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+
+ send "lindex \$new_p1 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set new_p1_ref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+
+ if {$old_p1_ref != $new_p1_ref} {
+ fail "$test: policy reference count changed ($old_p1_ref to $new_p1_ref)"
+ return
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test21.5
+
+test "modify-principal 22"
+proc test22 {} {
+ global test
+ global prompt
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modifiy failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test22
+
+test "modify-principal 23"
+proc test23 {} {
+ global test
+ global prompt
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" test-pol-nopw])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modifiy failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test23
+
+test "modify-principal 24"
+proc test24 {} {
+ global test
+ global prompt
+# set prms_id 1358
+# setup_xfail {*-*-*} $prms_id
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error_and_restart "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: could not modify principal"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_get_policy $server_handle %s policy
+ } test-pol]]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test24
+
+test "modify-principal 25"
+proc test25 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test25
+
+test "modify-principal 26"
+proc test26 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol-nopw" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test26
+
+test "modify-principal 27"
+proc test27 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 1234 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test27
+
+test "modify-principal 28"
+proc test28 {} {
+ global test
+ global prompt
+# set prms_id 1358
+# setup_xfail {*-*-*} $prms_id
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal_pol "$test/a" "test-pol" ])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 900 0 0 0 0 0 0 0 0} {KADM5_PW_EXPIRATION}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$pw_mod_date + $pw_max_life"] == $pw_expire } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+ pass "$test"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "modify-principal 29"
+proc test29 {} {
+ global test
+ global prompt
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { ! ([create_principal_pol "$test/a" test-pol])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_POLICY_CLR}
+ } $test]]} {
+ fail "$test: modifiy failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test29
+
+test "modify-principal 30"
+proc test30 {} {
+ global test
+ global prompt
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal_pol "$test/a" test-pol])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol-nopw] {KADM5_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 3\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test30
+
+test "modify-principal 31"
+proc test31 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {KADM5_POLICY}
+ } $test]]} {
+ fail "modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol policy}]} {
+ error_and_restart "$test: cannot retrieve policy"
+ return
+ }
+ send "lindex \$principal 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_mod_date $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_mod_date"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_mod_date"
+ return
+ }
+ }
+
+ send "lindex \$principal 3\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_expire $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_expire"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_expire"
+ return
+ }
+ }
+
+ send "lindex \$policy 2\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" {set pw_max_life $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting pw_max_life"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting pw_max_life"
+ return
+ }
+ }
+ if { [expr "$pw_mod_date + $pw_max_life"] != $pw_expire } {
+ fail "$test: pw_expire is wrong"
+ return
+ }
+
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test31
+
+test "modify-principal 32"
+proc test32 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 1234 0 0 0 0 0 0 0 0 0 0} \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 1\n"
+ expect {
+ -re "1234\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test32
+
+test "modify-principal 33"
+proc test33 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_ALL_TIX 0 0 0 0} \
+ {KADM5_ATTRIBUTES}
+ } $test]]} {
+ fail "$test: modified fail"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 7\n"
+ expect {
+ -re "KRB5_KDB_DISALLOW_ALL_TIX.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test33
+
+test "modify-principal 33.25"
+proc test3325 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 KRB5_KDB_REQUIRES_PWCHANGE 0 0 0 0} \
+ {KADM5_ATTRIBUTES}
+ } $test]]} {
+ fail "$test: modified fail"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 7\n"
+ expect {
+ -re "KRB5_KDB_REQUIRES_PWCHANGE.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test3325
+
+test "modify-principal 33.5"
+proc test335 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 KRB5_KDB_DISALLOW_TGT_BASED 0 0 0 0} \
+ {KADM5_ATTRIBUTES}
+ } $test]]} {
+ fail "$test: modified fail"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 7\n"
+ expect {
+ -re "KRB5_KDB_DISALLOW_TGT_BASED.*$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test335
+
+
+test "modify-principal 34"
+proc test34 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 0 3456 0 0 0 0 0 0 0} {KADM5_MAX_LIFE}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 4\n"
+ expect {
+ -re "3456\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test34
+
+test "modify-principal 35"
+proc test35 {} {
+ global prompt
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd [format {
+ kadm5_modify_principal $server_handle \
+ {"%s/a" 0 0 0 0 0 0 0 7 0 0 0} {KADM5_KVNO}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 8\n"
+ expect {
+ -re "7\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test35
+
+test "modify-principal 36"
+proc test36 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal_pol "$test/a" "test-pol"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol pol}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ test-pol] {KADM5_POLICY}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 10\n"
+ expect {
+ -re "test-pol\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ send "lindex \$pol 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set oldref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { ! [cmd {kadm5_get_policy $server_handle test-pol pol2}]} {
+ error "$test: unexpected failure on get policy"
+ return
+ }
+ send "lindex \$pol2 6\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt$" {set newref $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting principal kvno (second time)"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting principal kvno (second time)"
+ return
+ }
+ }
+ if { $oldref != $newref } {
+ fail "$test: policy reference count is wrong"
+ return;
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test36
+
+test "modify-principal 37"
+proc test37 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if { !( [create_principal "$test/a"])} {
+ error_and_restart "$test: could not create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_POLICY_CLR}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test37
+
+test "modify-principal 38"
+proc test38 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 1\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test38
+
+test "modify-principal 39"
+proc test39 {} {
+ global test
+ global prompt
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! ([create_principal "$test/a"])} {
+ error "$test: unexpected failure in creating principal"
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [simple_principal "%s/a"] \
+ {KADM5_MAX_LIFE}
+ } $test]]} {
+ fail "$test: modify failed"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_get_principal $server_handle "%s/a" principal KADM5_PRINCIPAL_NORMAL_MASK
+ } $test]]} {
+ error_and_restart "$test: could not retrieve principal"
+ return
+ }
+ send "lindex \$principal 4\n"
+ expect {
+ -re "0\n$prompt$" { pass "$test" }
+ timeout { fail "$test" }
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test39
+
+test "modify-principal 40"
+proc test40 {} {
+ global test
+ global prompt
+
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_modify_principal $server_handle null \
+ {KADM5_PRINC_EXPIRE_TIME}
+ } "EINVAL"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test40
+
+test "modify-principal 43"
+proc test43 {} {
+ global test
+ one_line_fail_test [format {
+ kadm5_modify_principal null [simple_principal \
+ "%s/a"] {KADM5_PW_EXPIRATION}
+ } $test] "BAD_SERVER_HANDLE"
+}
+test43
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp b/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp
new file mode 100644
index 000000000..c3dfd18df
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/randkey-principal-v2.exp
@@ -0,0 +1,62 @@
+source lib.t
+api_exit
+api_start
+
+test "randkey-principal 100"
+proc test100 {} {
+ global test prompt
+
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal "$test/a"]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ # I'd like to specify a long list of keysalt tuples and make sure
+ # that randkey does the right thing, but we can only use those
+ # enctypes that krbtgt has a key for: des-cbc-crc:normal and
+ # des-cbc-crc:v4, according to the prototype kdc.conf.
+ if {! [cmd [format {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test]]} {
+ error "$test: unexpected failure in randkey_principal"
+ }
+ send "puts \$num_keys\n"
+ expect {
+ -re "(\[0-9\]+)\n$prompt" { set num_keys $expect_out(1,string) }
+ timeout {
+ error_and_restart "$test: timeout getting num_keys"
+ return
+ }
+ eof {
+ error_and_restart "$test: eof getting num_keys"
+ return
+ }
+ }
+
+ # XXX Perhaps I should actually check the key type returned.
+ if {$num_keys == 1} {
+ pass "$test"
+ } else {
+ fail "$test: $num_keys keys, should be 1"
+ }
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test100
+
+return ""
diff --git a/src/lib/kadm5/unit-test/api.2/randkey-principal.exp b/src/lib/kadm5/unit-test/api.2/randkey-principal.exp
new file mode 100644
index 000000000..d693a2ac1
--- /dev/null
+++ b/src/lib/kadm5/unit-test/api.2/randkey-principal.exp
@@ -0,0 +1,319 @@
+source lib.t
+api_exit
+api_start
+
+test "randkey-principal 1"
+proc test1 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd [format {
+ kadm5_init "%s/a" "%s/a" $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test] "PASS_TOOSOON"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test1 }
+
+test "randkey-principal 3"
+proc test3 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd [format {
+ kadm5_init "%s/a" "%s/a" $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test] "PASS_TOOSOON"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if ${RPC} { test3 }
+
+test "randkey-principal 13"
+proc test13 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_modify_principal $server_handle [princ_w_pol "%s/a" \
+ once-a-min] KADM5_POLICY
+ } $test]]} {
+ error "$test: failed modify"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test13
+
+test "randkey-principal 15"
+proc test15 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal_pol "$test/a" once-a-min]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test] "AUTH_CHANGEPW"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if { $RPC } { test15 }
+
+test "randkey-principal 28"
+proc test28 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test28
+
+test "randkey-principal 28.25"
+proc test2825 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin admin $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test] "AUTH"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+if {$RPC} { test2825 }
+
+test "randkey-principal 28.5"
+proc test285 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [cmd {
+ kadm5_init admin/modify admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test285
+
+test "randkey-principal 30"
+proc test30 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't delete principal \"$test/a\""
+ return
+ }
+ if {! [create_principal "$test/a"]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+ if {! [cmd [format {
+ kadm5_init "%s/a" "%s/a" $KADM5_CHANGEPW_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test30
+
+test "randkey-principal 31"
+proc test31 {} {
+ global test
+ if {! (( ! [principal_exists "$test/a"]) ||
+ [delete_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if {! [create_principal "$test/a"]} {
+ error_and_restart "$test: creating principal"
+ return
+ }
+
+ if {! [cmd [format {
+ kadm5_init "%s/a" "%s/a" $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ } $test $test]]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_succeed_test [format {
+ kadm5_randkey_principal $server_handle "%s/a" keys num_keys
+ } $test]
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test31
+
+test "randkey-principal 32"
+proc test32 {} {
+ global test
+
+ if { ! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test {
+ kadm5_randkey_principal $server_handle kadmin/history keys num_keys
+ } "PROTECT"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+test32
+
+test "randkey-principal 33"
+proc test33 {} {
+ global test
+ if {! (( [principal_exists "$test/a"]) ||
+ [create_principal "$test/a"])} {
+ error_and_restart "$test: couldn't create principal \"$test/a\""
+ return
+ }
+ if { ! [cmd {
+ kadm5_init admin admin $KADM5_ADMIN_SERVICE null \
+ $KADM5_STRUCT_VERSION $KADM5_API_VERSION_2 \
+ server_handle
+ }]} {
+ error "$test: unexpected failure in init"
+ return
+ }
+ one_line_fail_test [format {
+ kadm5_randkey_principal null "%s/a" keys num_keys
+ } $test] "BAD_SERVER_HANDLE"
+ if { ! [cmd {kadm5_destroy $server_handle}]} {
+ error "$test: unexpected failure in destroy"
+ return
+ }
+}
+
+test33
+
+return ""
diff --git a/src/lib/kadm5/unit-test/config/unix.exp b/src/lib/kadm5/unit-test/config/unix.exp
new file mode 100644
index 000000000..e9a681f93
--- /dev/null
+++ b/src/lib/kadm5/unit-test/config/unix.exp
@@ -0,0 +1,113 @@
+set stty_init {-onlcr -opost intr \^C kill \^U}
+set kdb5_edit $KDBFIVE_EDIT
+set kadmin_local $KADMIN_LOCAL
+
+# Backward compatibility until we're using expect 5 everywhere
+if {[info exists exp_version_4]} {
+ global wait_error_index wait_errno_index wait_status_index
+ set wait_error_index 0
+ set wait_errno_index 1
+ set wait_status_index 1
+} else {
+ set wait_error_index 2
+ set wait_errno_index 3
+ set wait_status_index 3
+}
+
+proc api_exit {} {
+ global spawn_id
+
+# puts stdout "Starting api_exit (spawn_id $spawn_id)."
+ catch {close} errMsg
+ catch {wait} errMsg
+# puts stdout "Finishing api_exit."
+}
+
+proc api_version {} {
+}
+
+proc api_start {} {
+ global API
+ global env
+ global spawn_id
+ global prompt
+
+ spawn $API
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF starting API" }
+ timeout { error "Timeout starting API" }
+ }
+ if {! [info exists env(TCLUTIL)]} {
+ error "TCLUTIL environment variable isn't set"
+ }
+ send "source $env(TCLUTIL)\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF starting API" }
+ timeout { error "Timeout starting API" }
+ }
+ send "set current_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION &~ \$OVSEC_KADM_STRUCT_VERSION_MASK\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set current_api_version \[expr \$OVSEC_KADM_API_VERSION_1 &~ \$OVSEC_KADM_API_VERSION_MASK\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set bad_struct_version_mask \[expr 0x65432100 | \$current_struct_version\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set bad_api_version_mask \[expr 0x65432100 | \$current_api_version\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set no_api_version_mask \$current_api_version\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set no_struct_version_mask \$current_struct_version\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set old_api_version \[expr \$OVSEC_KADM_API_VERSION_MASK | 0x00\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set old_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION_MASK | 0x00\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set new_api_version \[expr \$OVSEC_KADM_API_VERSION_MASK | 0xca\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+ send "set new_struct_version \[expr \$OVSEC_KADM_STRUCT_VERSION_MASK | 0xca\]\n"
+ expect {
+ -re "$prompt$" {}
+ eof { error "EOF setting API varibles"}
+ timeout { error "timeout setting API varibles"}
+ }
+# puts stdout "Finishing api_start (spawn_id $spawn_id)."
+}
+api_start
+
diff --git a/src/lib/kadm5/unit-test/destroy-test.c b/src/lib/kadm5/unit-test/destroy-test.c
new file mode 100644
index 000000000..0db69c3a1
--- /dev/null
+++ b/src/lib/kadm5/unit-test/destroy-test.c
@@ -0,0 +1,42 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <kadm5/client_internal.h>
+#include <string.h>
+
+#define TEST_NUM 25
+
+main()
+{
+ ovsec_kadm_ret_t ret;
+ char *cp;
+ int x, i;
+ void *server_handle;
+ kadm5_server_handle_t handle;
+
+ for(x = 0; x < TEST_NUM; x++) {
+ ret = ovsec_kadm_init("admin", "admin", "ovsec_adm/admin", 0,
+ OVSEC_KADM_STRUCT_VERSION,
+ OVSEC_KADM_API_VERSION_1,
+ &server_handle);
+ if(ret != OVSEC_KADM_OK) {
+ com_err("test", ret, "init");
+ exit(2);
+ }
+ handle = (kadm5_server_handle_t) server_handle;
+ cp = (char *) strdup(((char *) (strchr(handle->cache_name, ':')) + 1));
+ ovsec_kadm_destroy(server_handle);
+ if(access(cp, F_OK) == 0) {
+ puts("ticket cache not destroyed");
+ exit(2);
+ }
+ free(cp);
+ }
+ exit(0);
+}
+
diff --git a/src/lib/kadm5/unit-test/diff-files/destroy-1 b/src/lib/kadm5/unit-test/diff-files/destroy-1
new file mode 100644
index 000000000..593d67320
--- /dev/null
+++ b/src/lib/kadm5/unit-test/diff-files/destroy-1
@@ -0,0 +1,2 @@
+##! nochanges
+
diff --git a/src/lib/kadm5/unit-test/diff-files/no-diffs b/src/lib/kadm5/unit-test/diff-files/no-diffs
new file mode 100644
index 000000000..593d67320
--- /dev/null
+++ b/src/lib/kadm5/unit-test/diff-files/no-diffs
@@ -0,0 +1,2 @@
+##! nochanges
+
diff --git a/src/lib/kadm5/unit-test/handle-test.c b/src/lib/kadm5/unit-test/handle-test.c
new file mode 100644
index 000000000..ced1d183d
--- /dev/null
+++ b/src/lib/kadm5/unit-test/handle-test.c
@@ -0,0 +1,131 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <netinet/in.h>
+#include <kadm5/client_internal.h>
+
+
+main(int argc, char *argv[])
+{
+ ovsec_kadm_ret_t ret;
+ void *server_handle;
+ kadm5_server_handle_t handle;
+ kadm5_server_handle_rec orig_handle;
+ ovsec_kadm_policy_ent_t pol;
+ ovsec_kadm_principal_ent_t princ;
+ krb5_keyblock *key;
+ krb5_principal tprinc;
+ krb5_context context;
+ int *p;
+
+
+ krb5_init_context(&context);
+
+ ret = ovsec_kadm_init("admin/none", "admin", "ovsec_adm/admin", 0,
+ OVSEC_KADM_STRUCT_VERSION, OVSEC_KADM_API_VERSION_1,
+ &server_handle);
+ if(ret != OVSEC_KADM_OK) {
+ com_err("test", ret, "init");
+ exit(2);
+ }
+ handle = (kadm5_server_handle_t) server_handle;
+ orig_handle = *handle;
+ handle->magic_number = OVSEC_KADM_STRUCT_VERSION;
+ krb5_parse_name(context, "testuser", &tprinc);
+ ret = ovsec_kadm_get_principal(server_handle, tprinc, &princ);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "get-principal",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_get_policy(server_handle, "pol1", &pol);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "get-policy",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_create_principal(server_handle, princ, OVSEC_KADM_PRINCIPAL, "pass");
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "create-principal",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_create_policy(server_handle, pol, OVSEC_KADM_POLICY);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "create-policy",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_modify_principal(server_handle, princ, OVSEC_KADM_PW_EXPIRATION);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "modify-principal",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_modify_policy(server_handle, pol, OVSEC_KADM_PW_MAX_LIFE);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "modify-policy",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_delete_principal(server_handle, tprinc);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "delete-principal",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_delete_policy(server_handle, "pol1");
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "delete-policy",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_chpass_principal(server_handle, tprinc, "FooBar");
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "chpass",
+ error_message(ret));
+ exit(1);
+ }
+ ret = ovsec_kadm_randkey_principal(server_handle, tprinc, &key);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "randkey",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_rename_principal(server_handle, tprinc, tprinc);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "rename",
+ error_message(ret));
+ exit(1);
+ }
+
+ ret = ovsec_kadm_destroy(server_handle);
+ if(ret != OVSEC_KADM_BAD_SERVER_HANDLE) {
+ fprintf(stderr, "%s -- returned -- %s\n", "destroy",
+ error_message(ret));
+ exit(1);
+ }
+
+ *handle = orig_handle;
+ ret = ovsec_kadm_destroy(server_handle);
+ if (ret != OVSEC_KADM_OK) {
+ fprintf(stderr, "valid %s -- returned -- %s\n", "destroy",
+ error_message(ret));
+ exit(1);
+ }
+
+ exit(0);
+}
diff --git a/src/lib/kadm5/unit-test/init-test.c b/src/lib/kadm5/unit-test/init-test.c
new file mode 100644
index 000000000..823dd222b
--- /dev/null
+++ b/src/lib/kadm5/unit-test/init-test.c
@@ -0,0 +1,26 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+
+main()
+{
+ ovsec_kadm_ret_t ret;
+ void *server_handle;
+
+ ret = ovsec_kadm_init("admin", "admin", OVSEC_KADM_ADMIN_SERVICE, 0,
+ OVSEC_KADM_STRUCT_VERSION,
+ OVSEC_KADM_API_VERSION_1,
+ &server_handle);
+ if (ret == OVSEC_KADM_RPC_ERROR)
+ exit(0);
+ else if (ret != OVSEC_KADM_OK) {
+ com_err("init-test", ret, "while (hacked) initializing");
+ exit(1);
+ }
+ else {
+ fprintf(stderr, "Unexpected success while (hacked) initializing!\n");
+ (void) ovsec_kadm_destroy(server_handle);
+ exit(1);
+ }
+}
diff --git a/src/lib/kadm5/unit-test/iter-test.c b/src/lib/kadm5/unit-test/iter-test.c
new file mode 100644
index 000000000..7ca43d44f
--- /dev/null
+++ b/src/lib/kadm5/unit-test/iter-test.c
@@ -0,0 +1,47 @@
+#include <stdio.h>
+#include <kadm5/admin.h>
+
+main(int argc, char **argv)
+{
+ ovsec_kadm_ret_t ret;
+ void *server_handle;
+ char **names;
+ int count, princ;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s [-princ|-pol] exp\n", argv[0]);
+ exit(1);
+ }
+ princ = (strcmp(argv[1], "-princ") == 0);
+
+ ret = ovsec_kadm_init("admin", "admin", OVSEC_KADM_ADMIN_SERVICE, 0,
+ OVSEC_KADM_STRUCT_VERSION,
+ OVSEC_KADM_API_VERSION_1,
+ &server_handle);
+ if (ret != OVSEC_KADM_OK) {
+ com_err("iter-test", ret, "while initializing");
+ exit(1);
+ }
+
+ if (princ)
+ ret = ovsec_kadm_get_principals(server_handle, argv[2], &names,
+ &count);
+ else
+ ret = ovsec_kadm_get_policies(server_handle, argv[2],
+ &names, &count);
+
+ if (ret != OVSEC_KADM_OK) {
+ com_err("iter-test", ret, "while retrieving list");
+ exit(1);
+ }
+
+ for (ret = 0; ret < count; ret++)
+ printf("%d: %s\n", ret, names[ret]);
+
+ ovsec_kadm_free_name_list(server_handle, names, count);
+
+ (void) ovsec_kadm_destroy(server_handle);
+
+ return 0;
+}
+
diff --git a/src/lib/kadm5/unit-test/lib.t b/src/lib/kadm5/unit-test/lib.t
new file mode 100644
index 000000000..110514de8
--- /dev/null
+++ b/src/lib/kadm5/unit-test/lib.t
@@ -0,0 +1,367 @@
+global timeout
+set timeout 60
+
+proc cmd {command} {
+ global prompt
+ global spawn_id
+ global test
+
+ send "[string trim $command]\n"
+ expect {
+ -re "OK .*$prompt$" { return 1 }
+ -re "ERROR .*$prompt$" { return 0 }
+ "wrong # args" { error "$test: wrong number args"; return 0 }
+ timeout { fail "$test: timeout"; return 0 }
+ eof { fail "$test: eof"; api_exit; api_start; return 0 }
+ }
+}
+
+proc tcl_cmd {command} {
+ global prompt
+ global spawn_id
+
+ send "[string trim $command]\n"
+ expect {
+ -re "$prompt$" { return 1}
+ "wrong # args" { error "$test: wrong number args"; return 0 }
+ timeout { error_and_restart "timeout" }
+ eof { api_exit; api_start; return 0 }
+ }
+}
+
+proc one_line_succeed_test {command} {
+ global prompt
+ global spawn_id
+ global test
+
+ send "[string trim $command]\n"
+ expect {
+ -re "OK .*$prompt$" { pass "$test"; return 1 }
+ -re "ERROR .*$prompt$" {
+ fail "$test: $expect_out(buffer)"; return 0
+ }
+ "wrong # args" { error "$test: wrong number args"; return 0 }
+ timeout { fail "$test: timeout"; return 0 }
+ eof { fail "$test: eof"; api_exit; api_start; return 0 }
+ }
+}
+
+proc one_line_fail_test {command code} {
+ global prompt
+ global spawn_id
+ global test
+
+ send "[string trim $command]\n"
+ expect {
+ -re "ERROR .*$code.*$prompt$" { pass "$test"; return 1 }
+ -re "ERROR .*$prompt$" { fail "$test: bad failure"; return 0 }
+ -re "OK .*$prompt$" { fail "$test: bad success"; return 0 }
+ "wrong # args" { error "$test: wrong number args"; return 0 }
+ timeout { fail "$test: timeout"; return 0 }
+ eof { fail "$test: eof"; api_exit; api_start; return 0 }
+ }
+}
+
+proc one_line_fail_test_nochk {command} {
+ global prompt
+ global spawn_id
+ global test
+
+ send "[string trim $command]\n"
+ expect {
+ -re "ERROR .*$prompt$" { pass "$test:"; return 1 }
+ -re "OK .*$prompt$" { fail "$test: bad success"; return 0 }
+ "wrong # args" { error "$test: wrong number args"; return 0 }
+ timeout { fail "$test: timeout"; return 0 }
+ eof { fail "$test: eof"; api_exit; api_start; return 0 }
+ }
+}
+
+proc resync {} {
+ global prompt
+ global spawn_id
+
+ expect {
+ -re "$prompt$" {}
+ "wrong # args" { error "$test: wrong number args"; return 0 }
+ eof { api_exit; api_start }
+ }
+}
+
+proc create_principal {name} {
+ api_exit
+ api_start
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {
+ ovsec_kadm_create_principal $server_handle [simple_principal \
+ "%s"] {OVSEC_KADM_PRINCIPAL} "%s"
+ } $name $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+ return $ret
+}
+
+proc create_policy {name} {
+ api_exit
+ api_start
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {
+ ovsec_kadm_create_policy $server_handle [simple_policy "%s"] \
+ {OVSEC_KADM_POLICY}
+ } $name $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+ return $ret
+}
+
+proc create_principal_pol {name policy} {
+ api_exit
+ api_start
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {
+ ovsec_kadm_create_principal $server_handle [princ_w_pol "%s" \
+ "%s"] {OVSEC_KADM_PRINCIPAL OVSEC_KADM_POLICY} "%s"
+ } $name $policy $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+ return $ret
+}
+
+proc delete_principal {name} {
+ api_exit
+ api_start
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {
+ ovsec_kadm_delete_principal $server_handle "%s"
+ } $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+ return $ret
+}
+
+proc delete_policy {name} {
+ api_exit
+ api_start
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {ovsec_kadm_delete_policy $server_handle "%s"} $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+ return $ret
+}
+
+proc principal_exists {name} {
+ api_exit
+ api_start
+
+# puts stdout "Starting principal_exists."
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {
+ ovsec_kadm_get_principal $server_handle "%s" principal
+ } $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+# puts stdout "Finishing principal_exists."
+
+ return $ret
+}
+
+proc policy_exists {name} {
+ api_exit
+ api_start
+
+# puts stdout "Starting policy_exists."
+
+ set ret [expr {
+ [cmd {
+ ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null \
+ $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 \
+ server_handle
+ }] &&
+ [cmd [format {
+ ovsec_kadm_get_policy $server_handle "%s" policy
+ } $name]]
+ }]
+
+ cmd {ovsec_kadm_destroy $server_handle}
+
+ api_exit
+ api_start
+
+# puts stdout "Finishing policy_exists."
+
+ return $ret
+}
+
+proc error_and_restart {error} {
+ api_exit
+ api_start
+ error $error
+}
+
+proc test {name} {
+ global test verbose
+
+ set test $name
+ if {$verbose >= 1} {
+ puts stdout "At $test"
+ }
+}
+
+proc begin_dump {} {
+ global TOP
+ global RPC
+
+ if { ! $RPC } {
+# exec $env(SIMPLE_DUMP) > /tmp/dump.before
+ }
+}
+
+proc end_dump_compare {name} {
+ global file
+ global TOP
+ global RPC
+
+ if { ! $RPC } {
+# set file $TOP/admin/lib/unit-test/diff-files/$name
+# exec $env(SIMPLE_DUMP) > /tmp/dump.after
+# exec $env(COMPARE_DUMP) /tmp/dump.before /tmp/dump.after $file
+ }
+}
+
+proc kinit { princ pass {opts ""} } {
+ global env;
+ global KINIT
+
+ eval spawn $KINIT $opts $princ
+ expect {
+ -re {Password for .*: $}
+ {send "$pass\n"}
+ timeout {puts "Timeout waiting for prompt" ; close }
+ }
+
+ # this necessary so close(1) in the child will not sleep waiting for
+ # the parent, which is us, to read pending data.
+
+ expect {
+ eof {}
+ }
+ wait
+}
+
+proc kdestroy {} {
+ global KDESTROY
+ global errorCode errorInfo
+ global env
+
+ if {[info exists errorCode]} {
+ set saveErrorCode $errorCode
+ }
+ if {[info exists errorInfo]} {
+ set saveErrorInfo $errorInfo
+ }
+ catch "system $KDESTROY 2>/dev/null"
+ if {[info exists saveErrorCode]} {
+ set errorCode $saveErrorCode
+ } elseif {[info exists errorCode]} {
+ unset errorCode
+ }
+ if {[info exists saveErrorInfo]} {
+ set errorInfo $saveErrorInfo
+ } elseif {[info exists errorInfo]} {
+ unset errorInfo
+ }
+}
+
+proc create_principal_with_keysalts {name keysalts} {
+ global kadmin_local
+
+ spawn $kadmin_local -e "$keysalts"
+ expect {
+ "kadmin.local:" {}
+ default { error "waiting for kadmin.local prompt"; return 1}
+ }
+ send "ank -pw \"$name\" \"$name\"\n"
+ expect {
+ -re "Principal \"$name.*\" created." {}
+ "kadmin.local:" {
+ error "expecting principal created message";
+ return 1
+ }
+ default { error "waiting for principal created message"; return 1 }
+ }
+ expect {
+ "kadmin.local:" {}
+ default { error "waiting for kadmin.local prompt"; return 1 }
+ }
+ close
+ wait
+ return 0
+}
+
+
diff --git a/src/lib/kadm5/unit-test/lock-test.c b/src/lib/kadm5/unit-test/lock-test.c
new file mode 100644
index 000000000..cff342386
--- /dev/null
+++ b/src/lib/kadm5/unit-test/lock-test.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <kadm5/adb.h>
+
+char *whoami;
+
+void usage()
+{
+ fprintf(stderr,
+ "Usage: %s {shared|exclusive|permanent|release|"
+ "get name|wait} ...\n", whoami);
+ exit(1);
+}
+
+main(int argc, char **argv)
+{
+ osa_adb_ret_t ret;
+ osa_adb_policy_t policy_db;
+ osa_policy_ent_t entry;
+ krb5_context context;
+ kadm5_config_params params;
+
+ whoami = argv[0];
+
+ krb5_init_context(&context);
+
+ initialize_ovk_error_table();
+ initialize_adb_error_table();
+ initialize_ovku_error_table();
+ krb5_init_ets(context);
+
+ params.mask = 0;
+ if (ret = kadm5_get_config_params(context, NULL, NULL, &params,
+ &params)) {
+ com_err(whoami, ret, "while retrieving configuration parameters");
+ exit(1);
+ }
+ if (! (params.mask & KADM5_CONFIG_ADBNAME)) {
+ com_err(whoami, KADM5_BAD_SERVER_PARAMS,
+ "while retrieving configuration parameters");
+ exit(1);
+ }
+
+ ret = osa_adb_open_policy(&policy_db, &params);
+ if (ret != OSA_ADB_OK) {
+ com_err(whoami, ret, "while opening database");
+ exit(1);
+ }
+
+ argc--; argv++;
+ while (argc) {
+ if (strcmp(*argv, "shared") == 0) {
+ ret = osa_adb_get_lock(policy_db, OSA_ADB_SHARED);
+ if (ret != OSA_ADB_OK)
+ com_err(whoami, ret, "while getting shared lock");
+ else
+ printf("shared\n");
+ } else if (strcmp(*argv, "exclusive") == 0) {
+ ret = osa_adb_get_lock(policy_db, OSA_ADB_EXCLUSIVE);
+ if (ret != OSA_ADB_OK)
+ com_err(whoami, ret, "while getting exclusive lock");
+ else
+ printf("exclusive\n");
+ } else if (strcmp(*argv, "permanent") == 0) {
+ ret = osa_adb_get_lock(policy_db, OSA_ADB_PERMANENT);
+ if (ret != OSA_ADB_OK)
+ com_err(whoami, ret, "while getting permanent lock");
+ else
+ printf("permanent\n");
+ } else if (strcmp(*argv, "release") == 0) {
+ ret = osa_adb_release_lock(policy_db);
+ if (ret != OSA_ADB_OK)
+ com_err(whoami, ret, "while releasing lock");
+ else
+ printf("released\n");
+ } else if (strcmp(*argv, "get") == 0) {
+ argc--; argv++;
+ if (!argc) usage();
+ if ((ret = osa_adb_get_policy(policy_db, *argv,
+ &entry)) != OSA_ADB_OK) {
+ com_err(whoami, ret, "while getting policy");
+ } else {
+ printf("retrieved\n");
+ osa_free_policy_ent(entry);
+ }
+ } else if (strcmp(*argv, "wait") == 0) {
+ getchar();
+ } else {
+ fprintf(stderr, "%s: Invalid argument \"%s\"\n",
+ whoami, *argv);
+ usage();
+ }
+
+ argc--; argv++;
+ }
+
+ ret = osa_adb_close_policy(policy_db);
+ if (ret != OSA_ADB_OK) {
+ com_err(whoami, ret, "while closing database");
+ exit(1);
+ }
+
+ return 0;
+}
diff --git a/src/lib/kadm5/unit-test/randkey-test.c b/src/lib/kadm5/unit-test/randkey-test.c
new file mode 100644
index 000000000..8d7e2fece
--- /dev/null
+++ b/src/lib/kadm5/unit-test/randkey-test.c
@@ -0,0 +1,44 @@
+#include <kadm5/admin.h>
+#include <com_err.h>
+#include <stdio.h>
+#include <krb5.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#define TEST_NUM 1000
+
+main()
+{
+ ovsec_kadm_ret_t ret;
+ krb5_keyblock *keys[TEST_NUM];
+ krb5_principal tprinc;
+ krb5_keyblock *newkey;
+ krb5_context context;
+ void *server_handle;
+
+ int x, i;
+
+ krb5_init_context(&context);
+
+ krb5_parse_name(context, "testuser", &tprinc);
+ ret = ovsec_kadm_init("admin", "admin", "ovsec_adm/admin", 0,
+ OVSEC_KADM_STRUCT_VERSION,
+ OVSEC_KADM_API_VERSION_1,
+ &server_handle);
+ if(ret != OVSEC_KADM_OK) {
+ com_err("test", ret, "init");
+ exit(2);
+ }
+ for(x = 0; x < TEST_NUM; x++) {
+ ovsec_kadm_randkey_principal(server_handle, tprinc, &newkey);
+ for(i = 0; i < x; i++) {
+ if (!memcmp(newkey->contents, keys[i]->contents, newkey->length))
+ puts("match found");
+ }
+ krb5_copy_keyblock(context, newkey, &keys[x]);
+ krb5_free_keyblock(context, newkey);
+ }
+ ovsec_kadm_destroy(server_handle);
+ exit(0);
+}
+
diff --git a/src/lib/kadm5/unit-test/site.exp b/src/lib/kadm5/unit-test/site.exp
new file mode 100644
index 000000000..18b435dd1
--- /dev/null
+++ b/src/lib/kadm5/unit-test/site.exp
@@ -0,0 +1,2 @@
+set tool ovsec_kadm_srv_tcl
+set prompt "% "
diff --git a/src/lib/kadm5/unit-test/sizes-test.c b/src/lib/kadm5/unit-test/sizes-test.c
new file mode 100644
index 000000000..5bcbd6252
--- /dev/null
+++ b/src/lib/kadm5/unit-test/sizes-test.c
@@ -0,0 +1,21 @@
+#include <stdio.h>
+#include <rpc/types.h>
+#include <krb5.h>
+
+#define stringify(a) #a
+
+#define test_size(a,b) if (sizeof(a) != sizeof(b)) { \
+ fprintf(stderr, "sizeof(%s) != sizeof(%s)\n", stringify(a), stringify(b)); \
+ exit(1); \
+}
+
+main()
+{
+ test_size(unsigned long, krb5_ui_4);
+ test_size(long, krb5_timestamp);
+ test_size(long, krb5_deltat);
+ test_size(long, krb5_flags);
+
+ exit(0);
+}
+
diff --git a/src/lib/kdb/ChangeLog b/src/lib/kdb/ChangeLog
index fa274c12a..4e5440cc9 100644
--- a/src/lib/kdb/ChangeLog
+++ b/src/lib/kdb/ChangeLog
@@ -1,3 +1,25 @@
+Fri Jul 12 15:32:26 1996 Marc Horowitz <marc@mit.edu>
+
+ * kdb_cpw.c (add_key_pwd): initialize retval = 0, in case the
+ function is called with ks_tuple_count == 0.
+
+Wed Jul 10 16:22:14 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in (USE_KDB5_LIBRARY): removed. the library does not
+ need itself to build, and in fact fails to do so if I try.
+ * Makefile.in (clean-unix): remove the shared/ subdir
+
+Tue Jul 9 17:55:30 1996 Marc Horowitz <marc@mit.edu>
+
+ * configure.in, Makefile.in: added rules and macros to do shared
+ library creation
+
+Mon Jul 8 17:06:00 1996 Barry Jaspan <bjaspan@mit.edu>
+
+ * kdb_dbm.c: Create DB_OPENCLOSE, which opens and closes the
+ databases for each lock. This is slower than the previous method,
+ but unlike the previous method it works.
+
Tue Jun 11 19:27:22 1996 Ezra Peisach <epeisach@kangaroo.mit.edu>
* keytab.c (krb5_ktkdb_close): Free memory allocated by
@@ -12,6 +34,24 @@ Sat May 18 15:07:09 1996 Ezra Peisach (epeisach@paris)
* kdb_dbm.c: Do not provide prototypes for dbm_error or
dbm_clearerr if they are really macros.
+Sun May 12 01:03:07 1996 Marc Horowitz <marc@mit.edu>
+
+ * kdb_xdr.c: reworked all of the krb5_dbe_* tl_data functions.
+ This was necessary so that the admin system could store it's own
+ tl_data, without needing code here. This has the side-effect of
+ eliminating some structures which added no value, therefore
+ changing about a half-dozen files elsewhere in the tree.
+
+ * kdb_cpw.c (add_key_rnd): handle kvno incrementing in the caller,
+ not here.
+ (krb5_dbe_crk): increment the kvno here, not in add_key_rnd
+ (krb5_dbe_ark): increment the kvno here, not in add_key_rnd
+ (add_key_pwd): handle kvno incrementing in the caller, not here.
+ (krb5_dbe_cpw): take an arg to specify the new kvno. if it's
+ <= the old kvno, just increment. Otherwise, pass it to add_key_pwd.
+ This is why all the code in this revision was changed.
+ (krb5_dbe_apw): increment the kvno here, not in add_key_pwd
+
Tue May 7 19:48:57 1996 Ezra Peisach <epeisach@dumpster.rose.brandeis.edu>
* t_kdb.c (do_testing): Compile if using BERK_DB and dbm is not
diff --git a/src/lib/kdb/Makefile.in b/src/lib/kdb/Makefile.in
index 7b1176d89..ba683222a 100644
--- a/src/lib/kdb/Makefile.in
+++ b/src/lib/kdb/Makefile.in
@@ -3,6 +3,10 @@ KRB5_RUN_ENV = @KRB5_RUN_ENV@
all:: $(OBJS)
+.c.o:
+ $(CC) $(CFLAGS) -c $(srcdir)/$*.c
+@SHARED_RULE@
+
SRCS= \
$(srcdir)/keytab.c \
$(srcdir)/encrypt_key.c \
@@ -27,6 +31,21 @@ OBJS= \
setup_mkey.o \
store_mkey.o
+LIB_SUBDIRS= .
+LIBDONE = DONE
+
+all-unix:: shared
+shared::
+ test -d shared || mkdir shared
+
+clean-unix::
+ $(RM) shared/*
+ -rmdir shared
+
+DONE: $(OBJS)
+ $(RM) DONE
+ echo $(OBJS) > DONE
+
libkdb5.a: $(OBJS)
$(RM) $@
$(ARADD) $@ $(OBJS)
@@ -37,7 +56,7 @@ install:: libkdb5.a
$(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libkdb5.a
clean::
- $(RM) libkdb5.a
+ $(RM) libkdb5.a DONE
t_kdb: t_kdb.o $(DEPLIBS)
$(LD) $(LDFLAGS) $(LDARGS) -o t_kdb t_kdb.o $(LIBS)
diff --git a/src/lib/kdb/configure.in b/src/lib/kdb/configure.in
index ec7f93ec1..e480603e4 100644
--- a/src/lib/kdb/configure.in
+++ b/src/lib/kdb/configure.in
@@ -8,8 +8,9 @@ AC_HAVE_HEADERS(unistd.h)
AC_CHECK_FUNCS(srand48 srand srandom umask)
KRB5_RUN_FLAGS
V5_USE_SHARED_LIB
-USE_KDB5_LIBRARY
KRB5_LIBRARIES
+V5_SHARED_LIB_OBJS
+V5_MAKE_SHARED_LIB(libkdb5,0.1,.., ./kdb)
LinkFileDir(../libkdb5.a, libkdb5.a, ./kdb)
AppendRule([all:: libkdb5.a])
AppendRule([all-unix:: ../libkdb5.a])
diff --git a/src/lib/kdb/kdb_cpw.c b/src/lib/kdb/kdb_cpw.c
index 0928eba2a..54316dde0 100644
--- a/src/lib/kdb/kdb_cpw.c
+++ b/src/lib/kdb/kdb_cpw.c
@@ -188,7 +188,7 @@ add_key_rnd(context, master_eblock, ks_tuple, ks_tuple_count, db_entry, kvno)
krb5_finish_key(context, &krbtgt_eblock);
if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock,
- key, NULL, kvno + 1,
+ key, NULL, kvno,
&db_entry->key_data[db_entry->n_key_data-1])) {
krb5_free_keyblock(context, key);
goto add_key_rnd_err;
@@ -233,6 +233,9 @@ krb5_dbe_crk(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
db_entry->key_data = NULL;
db_entry->n_key_data = 0;
+ /* increment the kvno */
+ kvno++;
+
if (retval = add_key_rnd(context, master_eblock, ks_tuple,
ks_tuple_count, db_entry, kvno)) {
cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
@@ -271,15 +274,18 @@ krb5_dbe_ark(context, master_eblock, ks_tuple, ks_tuple_count, db_entry)
db_entry->key_data = NULL;
db_entry->n_key_data = 0;
+ /* increment the kvno */
+ kvno++;
+
if (retval = add_key_rnd(context, master_eblock, ks_tuple,
ks_tuple_count, db_entry, kvno)) {
cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
db_entry->n_key_data = key_data_count;
db_entry->key_data = key_data;
} else {
- /* Copy keys with key_data_kvno = kvno */
+ /* Copy keys with key_data_kvno == kvno - 1 ( = old kvno ) */
for (i = 0; i < key_data_count; i++) {
- if (key_data[i].key_data_kvno = kvno) {
+ if (key_data[i].key_data_kvno == (kvno - 1)) {
if (retval = krb5_dbe_create_key_data(context, db_entry)) {
cleanup_key_data(context, db_entry->n_key_data,
db_entry->key_data);
@@ -318,6 +324,8 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
krb5_boolean found;
int i, j;
+ retval = 0;
+
for (i = 0; i < ks_tuple_count; i++) {
krb5_enctype new_enctype, old_enctype;
@@ -405,7 +413,7 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
if (retval = krb5_dbekd_encrypt_key_data(context, master_eblock, &key,
(const krb5_keysalt *)&key_salt,
- kvno + 1, &db_entry->key_data[db_entry->n_key_data-1])) {
+ kvno, &db_entry->key_data[db_entry->n_key_data-1])) {
krb5_xfree(key.contents);
return(retval);
}
@@ -421,28 +429,36 @@ add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
* As a side effect all old keys are nuked.
*/
krb5_error_code
-krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, db_entry)
+krb5_dbe_cpw(context, master_eblock, ks_tuple, ks_tuple_count, passwd,
+ new_kvno, db_entry)
krb5_context context;
krb5_encrypt_block * master_eblock;
krb5_key_salt_tuple * ks_tuple;
int ks_tuple_count;
char * passwd;
+ int new_kvno;
krb5_db_entry * db_entry;
{
int key_data_count;
krb5_key_data * key_data;
krb5_error_code retval;
- int kvno;
+ int old_kvno;
/* First save the old keydata */
- kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data);
+ old_kvno = get_key_data_kvno(context, db_entry->n_key_data,
+ db_entry->key_data);
key_data_count = db_entry->n_key_data;
key_data = db_entry->key_data;
db_entry->key_data = NULL;
db_entry->n_key_data = 0;
+ /* increment the kvno. if the requested kvno is too small,
+ increment the old kvno */
+ if (new_kvno < old_kvno+1)
+ new_kvno = old_kvno+1;
+
if (retval = add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count,
- passwd, db_entry, kvno)) {
+ passwd, db_entry, new_kvno)) {
cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
db_entry->n_key_data = key_data_count;
db_entry->key_data = key_data;
@@ -470,25 +486,29 @@ krb5_dbe_apw(context, master_eblock, ks_tuple, ks_tuple_count, passwd, db_entry)
int key_data_count;
krb5_key_data * key_data;
krb5_error_code retval;
- int kvno;
+ int old_kvno, new_kvno;
int i;
/* First save the old keydata */
- kvno = get_key_data_kvno(context, db_entry->n_key_data, db_entry->key_data);
+ old_kvno = get_key_data_kvno(context, db_entry->n_key_data,
+ db_entry->key_data);
key_data_count = db_entry->n_key_data;
key_data = db_entry->key_data;
db_entry->key_data = NULL;
db_entry->n_key_data = 0;
+ /* increment the kvno */
+ new_kvno = old_kvno+1;
+
if (retval = add_key_pwd(context, master_eblock, ks_tuple, ks_tuple_count,
- passwd, db_entry, kvno)) {
+ passwd, db_entry, new_kvno)) {
cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
db_entry->n_key_data = key_data_count;
db_entry->key_data = key_data;
} else {
- /* Copy keys with key_data_kvno = kvno */
+ /* Copy keys with key_data_kvno == old_kvno */
for (i = 0; i < key_data_count; i++) {
- if (key_data[i].key_data_kvno = kvno) {
+ if (key_data[i].key_data_kvno == old_kvno) {
if (retval = krb5_dbe_create_key_data(context, db_entry)) {
cleanup_key_data(context, db_entry->n_key_data,
db_entry->key_data);
diff --git a/src/lib/kdb/kdb_dbm.c b/src/lib/kdb/kdb_dbm.c
index e42e31f9d..3931389f4 100644
--- a/src/lib/kdb/kdb_dbm.c
+++ b/src/lib/kdb/kdb_dbm.c
@@ -22,6 +22,8 @@
*
*/
+#define DB_OPENCLOSE
+
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -341,9 +343,13 @@ krb5_dbm_db_init(context)
return(retval);
db_ctx = context->db_context;
+#ifdef DB_OPENCLOSE
+ db_ctx->db_dbm_ctx = NULL;
+#else
if (!(db_ctx->db_dbm_ctx = (DBM *)KDBM_OPEN(db_ctx, db_ctx->db_name,
O_RDWR, 0600)))
return errno;
+#endif
if (!(filename = gen_dbsuffix (db_ctx->db_name, KDBM_LOCK_EXT(db_ctx))))
return ENOMEM;
@@ -367,7 +373,9 @@ krb5_dbm_db_init(context)
return 0;
err_out:
+#ifndef DB_OPENCLOSE
KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx);
+#endif
db_ctx->db_dbm_ctx = (DBM *) NULL;
k5dbm_clear_context(db_ctx);
return (retval);
@@ -387,6 +395,7 @@ krb5_dbm_db_fini(context)
db_ctx = (krb5_db_context *) context->db_context;
if (k5dbm_inited(context)) {
+#ifndef DB_OPENCLOSE
if (db_ctx->db_dbm_ctx) {
/* dbm_close returns void, but it is possible for there to be an
error in close(). Possible changes to this routine: check errno
@@ -395,6 +404,7 @@ krb5_dbm_db_fini(context)
KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx);
db_ctx->db_dbm_ctx = NULL;
}
+#endif
if (close(db_ctx->db_lf_file))
retval = errno;
@@ -471,6 +481,8 @@ krb5_dbm_db_get_mkey(context, db_context, eblock)
*
* Passing a null pointer as "name" will set back to the default.
* If the alternate database doesn't exist, nothing is changed.
+ *
+ * XXX rethink this
*/
krb5_error_code
@@ -621,6 +633,17 @@ krb5_dbm_db_lock(context, mode)
if ((retval = krb5_dbm_db_get_age(context, NULL, &mod_time)))
goto lock_error;
+#ifdef DB_OPENCLOSE
+ if ((db = KDBM_OPEN(db_ctx, db_ctx->db_name,
+ mode == KRB5_LOCKMODE_SHARED ? O_RDONLY : O_RDWR,
+ 0600))) {
+ db_ctx->db_lf_time = mod_time;
+ db_ctx->db_dbm_ctx = db;
+ } else {
+ retval = errno;
+ goto lock_error;
+ }
+#else
if (mod_time != db_ctx->db_lf_time) {
KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx);
if ((db = KDBM_OPEN(db_ctx, db_ctx->db_name, O_RDWR, 0600))) {
@@ -631,12 +654,15 @@ krb5_dbm_db_lock(context, mode)
goto lock_error;
}
}
+#endif
db_ctx->db_lock_mode = mode;
db_ctx->db_locks_held++;
return 0;
lock_error:;
+ db_ctx->db_lock_mode = 0;
+ db_ctx->db_locks_held = 0;
(void) krb5_dbm_db_unlock(context);
return retval;
}
@@ -655,6 +681,10 @@ krb5_dbm_db_unlock(context)
if (!db_ctx->db_locks_held) /* lock already unlocked */
return KRB5_KDB_NOTLOCKED;
+#ifdef DB_OPENCLOSE
+ KDBM_CLOSE(db_ctx, db_ctx->db_dbm_ctx);
+#endif
+
if (--(db_ctx->db_locks_held) == 0) {
retval = krb5_lock_file(context, db_ctx->db_lf_file,
KRB5_LOCKMODE_UNLOCK);
@@ -720,9 +750,8 @@ destroy_file_suffix(dbname, suffix)
if (filename == 0)
return ENOMEM;
if ((fd = open(filename, O_RDWR, 0)) < 0) {
- int retval = errno == ENOENT ? 0 : errno;
free(filename);
- return retval;
+ return errno;
}
/* fstat() will probably not fail unless using a remote filesystem
(which is inappropriate for the kerberos database) so this check
@@ -796,26 +825,40 @@ krb5_dbm_db_destroy(context, dbname)
krb5_context context;
char *dbname;
{
- krb5_error_code retval;
+ krb5_error_code retval1, retval2, retval3;
krb5_boolean tmpcontext;
tmpcontext = 0;
if (!context->db_context) {
tmpcontext = 1;
- if ((retval = k5dbm_init_context(context)))
- return(retval);
+ if ((retval1 = k5dbm_init_context(context)))
+ return(retval1);
}
- if (KDBM_DATA_EXT(context->db_context) &&
- (retval = destroy_file_suffix(dbname,
- KDBM_DATA_EXT(context->db_context))))
- return(retval);
- if (KDBM_INDEX_EXT(context->db_context) &&
- (retval = destroy_file_suffix(dbname,
- KDBM_INDEX_EXT(context->db_context))))
- return(retval);
- if ((retval = destroy_file_suffix(dbname,
- KDBM_LOCK_EXT(context->db_context))))
- return(retval);
+ retval1 = retval2 = retval3 = 0;
+ if (KDBM_DATA_EXT(context->db_context))
+ retval1 = destroy_file_suffix(dbname,
+ KDBM_DATA_EXT(context->db_context));
+ if (KDBM_INDEX_EXT(context->db_context))
+ retval2 = destroy_file_suffix(dbname,
+ KDBM_INDEX_EXT(context->db_context));
+ retval3 = destroy_file_suffix(dbname,
+ KDBM_LOCK_EXT(context->db_context));
+ /*
+ * This kludgery is needed because it is possible to link
+ * against BSD DB but use the ndbm interface. The result is
+ * that the dispatch table thinks the file extensions are
+ * .dir and .pag, but the database layer uses .db.
+ */
+ if (retval1 == ENOENT && retval2 == ENOENT &&
+ KDBM_INDEX_EXT(context->db_context) &&
+ strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 &&
+ KDBM_DATA_EXT(context->db_context) &&
+ strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) {
+ retval1 = retval2 = destroy_file_suffix(dbname, ".db");
+ }
+ if (retval1 || retval2 || retval3)
+ return (retval1 ? retval1 : (retval2 ? retval2 : retval3));
+
if (tmpcontext) {
k5dbm_clear_context((krb5_db_context *) context->db_context);
free(context->db_context);
@@ -841,6 +884,7 @@ krb5_dbm_db_rename(context, from, to)
char *from;
char *to;
{
+ DBM *db;
char *fromdir = 0;
char *todir = 0;
char *frompag = 0;
@@ -853,19 +897,28 @@ krb5_dbm_db_rename(context, from, to)
s_context = context->db_context;
context->db_context = (void *) NULL;
if (!(retval = k5dbm_init_context(context))) {
+ db_ctx = (krb5_db_context *) context->db_context;
+
+ /*
+ * Create the database, failing if it already exists; the
+ * files must exist because krb5_dbm_db_lock, called below,
+ * will fail otherwise.
+ */
+ db = KDBM_OPEN(db_ctx, to, O_RDWR|O_CREAT|O_EXCL, 0600);
+ if (db == NULL) {
+ retval = errno;
+ goto errout;
+ }
+ else
+ KDBM_CLOSE(db_ctx, db);
+
/*
* Set the database to the target, so that other processes sharing
* the target will stop their activity, and notice the new database.
*/
- db_ctx = (krb5_db_context *) context->db_context;
-
retval = krb5_dbm_db_set_name(context, to);
- if (retval) {
- if (retval == ENOENT)
- db_ctx->db_name = strdup(to);
- else
+ if (retval)
goto errout;
- }
db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name,
KDBM_LOCK_EXT(db_ctx));
@@ -931,8 +984,39 @@ krb5_dbm_db_rename(context, from, to)
(void) unlink(fromok);
retval = krb5_dbm_db_end_update(context);
} else {
- (void) krb5_dbm_db_end_update(context);
- retval = errno;
+ /*
+ * This kludgery is needed because it is possible to link
+ * against BSD DB but use the ndbm interface. The result is
+ * that the dispatch table thinks the file extensions are
+ * .dir and .pag, but the database layer uses .db.
+ */
+ if (errno == ENOENT &&
+ KDBM_INDEX_EXT(context->db_context) &&
+ strcmp(KDBM_INDEX_EXT(context->db_context), ".dir") == 0 &&
+ KDBM_DATA_EXT(context->db_context) &&
+ strcmp(KDBM_DATA_EXT(context->db_context), ".pag") == 0) {
+ free(fromdir); free(todir); free(frompag); free(topag);
+
+ fromdir = todir = NULL;
+ frompag = gen_dbsuffix (from, ".db");
+ topag = gen_dbsuffix (to, ".db");
+ if (!frompag || !topag) {
+ retval = ENOMEM;
+ goto errout;
+ }
+ if (rename(frompag, topag) == 0) {
+ /* We only need to unlink the source lock file */
+ if (fromok)
+ (void) unlink(fromok);
+ retval = krb5_dbm_db_end_update(context);
+ } else {
+ (void) krb5_dbm_db_end_update(context);
+ retval = errno;
+ }
+ } else {
+ (void) krb5_dbm_db_end_update(context);
+ retval = errno;
+ }
}
@@ -1082,6 +1166,7 @@ krb5_dbm_db_put_principal(context, entries, nentries)
}
if (KDBM_STORE(db_ctx, db_ctx->db_dbm_ctx, key, contents, DBM_REPLACE))
retval = errno;
+#ifndef DB_OPENCLOSE
else {
DBM *db;
@@ -1093,6 +1178,7 @@ krb5_dbm_db_put_principal(context, entries, nentries)
else
retval = errno;
}
+#endif
krb5_free_princ_contents(context, &contents);
krb5_free_princ_dbmkey(context, &key);
if (retval)
@@ -1166,6 +1252,7 @@ krb5_dbm_db_delete_principal(context, searchfor, nentries)
else {
if (KDBM_DELETE(db_ctx, db, key))
retval = errno;
+#ifndef DB_OPENCLOSE
else {
DBM *db;
@@ -1177,6 +1264,7 @@ krb5_dbm_db_delete_principal(context, searchfor, nentries)
else
retval = errno;
}
+#endif
}
krb5_free_princ_contents(context, &contents2);
cleancontents:
diff --git a/src/lib/kdb/kdb_xdr.c b/src/lib/kdb/kdb_xdr.c
index 5953d6dd2..044ce4c7f 100644
--- a/src/lib/kdb/kdb_xdr.c
+++ b/src/lib/kdb/kdb_xdr.c
@@ -23,200 +23,223 @@
*/
#include "k5-int.h"
+#include <string.h>
#include <stdio.h>
#include <errno.h>
+#define safe_realloc(p,n) ((p)?(realloc(p,n)):(malloc(n)))
+
krb5_error_code
krb5_dbe_create_key_data(context, entry)
krb5_context context;
krb5_db_entry * entry;
{
- if (entry->n_key_data) {
- if ((entry->key_data = (krb5_key_data *)realloc(entry->key_data,
- sizeof(krb5_key_data) * (entry->n_key_data + 1))))
- memset(entry->key_data + entry->n_key_data,0,sizeof(krb5_key_data));
- else
- return ENOMEM;
- } else {
- if ((entry->key_data = (krb5_key_data *)malloc(sizeof(krb5_key_data))))
- memset(entry->key_data, 0, sizeof(krb5_key_data));
- else
- return ENOMEM;
- }
+ if ((entry->key_data =
+ (krb5_key_data *) safe_realloc(entry->key_data,
+ (sizeof(krb5_key_data)*
+ (entry->n_key_data + 1)))) == NULL)
+ return(ENOMEM);
+
+
+ memset(entry->key_data + entry->n_key_data, 0, sizeof(krb5_key_data));
entry->n_key_data++;
+
return 0;
}
krb5_error_code
-krb5_dbe_encode_last_pwd_change(context, stamp, entry)
+krb5_dbe_update_tl_data(context, entry, new_tl_data)
krb5_context context;
- krb5_tl_last_change * stamp;
krb5_db_entry * entry;
+ krb5_tl_data * new_tl_data;
{
- krb5_tl_data ** tl_data;
- krb5_octet * nextloc;
-
- /* Find any old versions and delete them. */
- for (tl_data = &(entry->tl_data); *tl_data;
- tl_data = &((*tl_data)->tl_data_next)) {
- if ((*tl_data)->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) {
- break;
- }
- }
+ krb5_tl_data * tl_data;
+ krb5_octet * tmp;
+
+ /* copy the new data first, so we can fail cleanly if malloc()
+ fails */
- if ((*tl_data) ||
- /* Only zero data if it is freshly allocated */
- ((*tl_data) = (krb5_tl_data *)calloc(1, sizeof(krb5_tl_data)))) {
- if (!(*tl_data)->tl_data_type) {
- if ((nextloc = (*tl_data)->tl_data_contents =
- (krb5_octet *)malloc(sizeof(krb5_timestamp))) == NULL) {
- krb5_xfree(*tl_data);
- (*tl_data) = NULL;
- return ENOMEM;
- }
- (*tl_data)->tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
- (*tl_data)->tl_data_length = sizeof(krb5_timestamp);
- entry->n_tl_data++;
- }
-
- *nextloc++ = (krb5_octet)(stamp->last_pwd_change & 0xff);
- *nextloc++ = (krb5_octet)((stamp->last_pwd_change >> 8) & 0xff);
- *nextloc++ = (krb5_octet)((stamp->last_pwd_change >> 16) & 0xff);
- *nextloc++ = (krb5_octet)((stamp->last_pwd_change >> 24) & 0xff);
-
- return 0;
+ if ((tmp = (krb5_octet *) malloc(new_tl_data->tl_data_length)) == NULL)
+ return(ENOMEM);
+
+ /* Find an existing entry of the specified type and point at
+ it, or NULL if not found */
+
+ for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next)
+ if (tl_data->tl_data_type == new_tl_data->tl_data_type)
+ break;
+
+ /* if necessary, chain a new record in the beginning and point at it */
+
+ if (!tl_data) {
+ if ((tl_data = (krb5_tl_data *) calloc(1, sizeof(krb5_tl_data)))
+ == NULL) {
+ free(tmp);
+ return(ENOMEM);
+ }
+ tl_data->tl_data_next = entry->tl_data;
+ entry->tl_data = tl_data;
+ entry->n_tl_data++;
}
- return ENOMEM;
+
+ /* fill in the record */
+
+ if (tl_data->tl_data_contents)
+ free(tl_data->tl_data_contents);
+
+ tl_data->tl_data_type = new_tl_data->tl_data_type;
+ tl_data->tl_data_length = new_tl_data->tl_data_length;
+ tl_data->tl_data_contents = tmp;
+ memcpy(tmp, new_tl_data->tl_data_contents, tl_data->tl_data_length);
+
+ return(0);
}
krb5_error_code
-krb5_dbe_decode_last_pwd_change(context, entry, stamp)
+krb5_dbe_lookup_tl_data(context, entry, ret_tl_data)
krb5_context context;
krb5_db_entry * entry;
- krb5_tl_last_change * stamp;
+ krb5_tl_data * ret_tl_data;
{
- krb5_tl_data * tl_data;
+ krb5_tl_data *tl_data;
for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
- if (tl_data->tl_data_type == KRB5_TL_LAST_PWD_CHANGE) {
- krb5_octet * nextloc = tl_data->tl_data_contents;
-
- stamp->last_pwd_change = *nextloc++;
- stamp->last_pwd_change += (*nextloc++ << 8);
- stamp->last_pwd_change += (*nextloc++ << 16);
- stamp->last_pwd_change += (*nextloc++ << 24);
- return 0;
- }
+ if (tl_data->tl_data_type == ret_tl_data->tl_data_type) {
+ *ret_tl_data = *tl_data;
+ return(0);
+ }
}
- stamp->last_pwd_change = 0;
- return 0;
+
+ /* if the requested record isn't found, return zero bytes.
+ if it ever means something to have a zero-length tl_data,
+ this code and its callers will have to be changed */
+
+ ret_tl_data->tl_data_length = 0;
+ ret_tl_data->tl_data_contents = NULL;
+ return(0);
+}
+
+krb5_error_code
+krb5_dbe_update_last_pwd_change(context, entry, stamp)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_timestamp stamp;
+{
+ krb5_tl_data tl_data;
+ krb5_octet buf[4]; /* this is the encoded size of an int32 */
+
+ tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+ tl_data.tl_data_length = sizeof(buf);
+ krb5_kdb_encode_int32((krb5_int32) stamp, buf);
+ tl_data.tl_data_contents = buf;
+
+ return(krb5_dbe_update_tl_data(context, entry, &tl_data));
}
krb5_error_code
-krb5_dbe_encode_mod_princ_data(context, mod_princ, entry)
+krb5_dbe_lookup_last_pwd_change(context, entry, stamp)
+ krb5_context context;
+ krb5_db_entry * entry;
+ krb5_timestamp * stamp;
+{
+ krb5_tl_data tl_data;
+ krb5_error_code code;
+ krb5_int32 tmp;
+
+ tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE;
+
+ if (code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))
+ return(code);
+
+ if (tl_data.tl_data_length != 4) {
+ *stamp = 0;
+ return(0);
+ }
+
+ krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp);
+
+ *stamp = (krb5_timestamp) tmp;
+
+ return(0);
+}
+
+/* it seems odd that there's no function to remove a tl_data, but if
+ I need one, I'll add one */
+
+krb5_error_code
+krb5_dbe_update_mod_princ_data(context, entry, mod_date, mod_princ)
krb5_context context;
- krb5_tl_mod_princ * mod_princ;
krb5_db_entry * entry;
+ krb5_timestamp mod_date;
+ krb5_principal mod_princ;
{
+ krb5_tl_data tl_data;
+
krb5_error_code retval = 0;
- krb5_tl_data ** tl_data;
krb5_octet * nextloc = 0;
char * unparse_mod_princ = 0;
int unparse_mod_princ_size;
- /*
- * Allocate *tl_data if necessary otherwise reuse it
- * Need 04 bytes for date
- * Need XX bytes for string
- */
- if ((retval = krb5_unparse_name(context, mod_princ->mod_princ,
- &unparse_mod_princ)))
+ if ((retval = krb5_unparse_name(context, mod_princ,
+ &unparse_mod_princ)))
return(retval);
unparse_mod_princ_size = (int) strlen(unparse_mod_princ) + 1;
- if ((nextloc = malloc(unparse_mod_princ_size + 4)) == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
-
- /* Find any old versions and delete them. */
- for (tl_data = &(entry->tl_data); *tl_data;
- tl_data = &((*tl_data)->tl_data_next)) {
- if ((*tl_data)->tl_data_type == KRB5_TL_MOD_PRINC) {
- free((*tl_data)->tl_data_contents);
- entry->n_tl_data--;
- break;
- }
+ if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
+ == NULL) {
+ free(unparse_mod_princ);
+ return(ENOMEM);
}
- /* Allocate a new TL_MOD_PRINC structure if necessary */
- if (*tl_data == 0) {
- (*tl_data) = (krb5_tl_data *)calloc(1, sizeof(krb5_tl_data));
- if (*tl_data == 0) {
- retval = ENOMEM;
- goto cleanup;
- }
- }
-
- entry->n_tl_data++;
- (*tl_data)->tl_data_type = KRB5_TL_MOD_PRINC;
- (*tl_data)->tl_data_length = unparse_mod_princ_size + 4;
- (*tl_data)->tl_data_contents = nextloc;
+ tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
+ tl_data.tl_data_length = unparse_mod_princ_size + 4;
+ tl_data.tl_data_contents = nextloc;
/* Mod Date */
- krb5_kdb_encode_int32(mod_princ->mod_date, nextloc);
- nextloc += 4;
+ krb5_kdb_encode_int32(mod_date, nextloc);
/* Mod Princ */
- memcpy(nextloc, unparse_mod_princ, unparse_mod_princ_size);
- nextloc = 0;
+ memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);
-cleanup:
- if (nextloc)
- free(nextloc);
- if (unparse_mod_princ)
- free(unparse_mod_princ);
- return retval;
+ retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
+
+ free(unparse_mod_princ);
+ free(nextloc);
+
+ return(retval);
}
krb5_error_code
-krb5_dbe_decode_mod_princ_data(context, entry, mod_princ)
+krb5_dbe_lookup_mod_princ_data(context, entry, mod_time, mod_princ)
krb5_context context;
krb5_db_entry * entry;
- krb5_tl_mod_princ ** mod_princ;
+ krb5_timestamp * mod_time;
+ krb5_principal * mod_princ;
{
- krb5_error_code retval;
- krb5_tl_data * tl_data;
- krb5_octet * nextloc;
+ krb5_tl_data tl_data;
+ krb5_error_code code;
+ krb5_int32 tmp;
- retval = 0;
- for (tl_data = entry->tl_data; tl_data; tl_data = tl_data->tl_data_next) {
- if (tl_data->tl_data_type == KRB5_TL_MOD_PRINC) {
- if ((*mod_princ = malloc(sizeof(krb5_tl_mod_princ))) == NULL)
- return ENOMEM;
-
- nextloc = tl_data->tl_data_contents;
-
- /* Mod Date */
- krb5_kdb_decode_int32(nextloc, (*mod_princ)->mod_date);
- nextloc += 4;
-
- /* Mod Princ */
- if ((retval = krb5_parse_name(context, (const char *) nextloc,
- &((*mod_princ)->mod_princ))))
- break;
- if ((strlen((char *) nextloc) + 1 + 4) !=
- (size_t) tl_data->tl_data_length) {
- retval = KRB5_KDB_TRUNCATED_RECORD;
- break;
- }
- }
- }
+ tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
- if (retval && (*mod_princ))
- free(*mod_princ);
- return retval;
+ if (code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))
+ return(code);
+
+ if ((tl_data.tl_data_length < 5) ||
+ (tl_data.tl_data_contents[tl_data.tl_data_length-1] != '\0'))
+ return(KRB5_KDB_TRUNCATED_RECORD);
+
+ /* Mod Date */
+ krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time);
+
+ /* Mod Princ */
+ if ((code = krb5_parse_name(context,
+ (const char *) (tl_data.tl_data_contents+4),
+ mod_princ)))
+ return(code);
+
+ return(0);
}
krb5_error_code
diff --git a/src/lib/krb5/keytab/file/ChangeLog b/src/lib/krb5/keytab/file/ChangeLog
index 58112dccc..39c397434 100644
--- a/src/lib/krb5/keytab/file/ChangeLog
+++ b/src/lib/krb5/keytab/file/ChangeLog
@@ -1,3 +1,8 @@
+Fri Jul 12 21:16:50 1996 Marc Horowitz <marc@mit.edu>
+
+ * ktf_g_name.c (krb5_ktfile_get_name): include the prefix in the
+ returned name.
+
Wed Jun 12 01:09:01 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* ser_ktf.c: Add #ifdef _WIN32 in places where we had #ifdef _MSDOS
diff --git a/src/lib/krb5/keytab/file/ktf_g_name.c b/src/lib/krb5/keytab/file/ktf_g_name.c
index a8f27c474..dd8aadc74 100644
--- a/src/lib/krb5/keytab/file/ktf_g_name.c
+++ b/src/lib/krb5/keytab/file/ktf_g_name.c
@@ -36,10 +36,24 @@ krb5_ktfile_get_name(context, id, name, len)
/*
* This routine returns the name of the name of the file associated with
* this file-based keytab. name is zeroed and the filename is truncated
- * to fit in name if necessary.
+ * to fit in name if necessary. The name is prefixed with PREFIX:, so that
+ * trt will happen if the name is passed back to resolve.
*/
{
memset(name, 0, len);
- strncpy(name, KTFILENAME(id), len);
+
+ if (len < strlen(id->ops->prefix)+2)
+ return(ENAMETOOLONG);
+ strcpy(name, id->ops->prefix);
+ name += strlen(id->ops->prefix);
+ name[0] = ':';
+ name++;
+ len -= strlen(id->ops->prefix)+1;
+
+ if (len < strlen(KTFILENAME(id)+1))
+ return(ENAMETOOLONG);
+ strcpy(name, KTFILENAME(id));
+ /* strcpy will NUL-terminate the destination */
+
return(0);
}
diff --git a/src/lib/krb5/os/ChangeLog b/src/lib/krb5/os/ChangeLog
index 75d2f0d3e..721ce1e5e 100644
--- a/src/lib/krb5/os/ChangeLog
+++ b/src/lib/krb5/os/ChangeLog
@@ -1,3 +1,8 @@
+Fri Jul 12 21:38:15 1996 Marc Horowitz <marc@mit.edu>
+
+ * ktdefname.c (krb5_kt_default_name): allow the default keytab name
+ to be specified in the config file.
+
Wed Jun 12 01:12:32 1996 Theodore Ts'o <tytso@rsts-11.mit.edu>
* net_read.c (krb5_net_read):
diff --git a/src/lib/krb5/os/ktdefname.c b/src/lib/krb5/os/ktdefname.c
index 433c1c9da..29eb54fe2 100644
--- a/src/lib/krb5/os/ktdefname.c
+++ b/src/lib/krb5/os/ktdefname.c
@@ -37,12 +37,22 @@ krb5_kt_default_name(context, name, namesize)
int namesize;
{
char *cp = 0;
+ krb5_error_code code;
+ char *retval;
- if (context->profile_secure == FALSE) cp = getenv("KRB5_KTNAME");
- if (cp) {
+ if ((context->profile_secure == FALSE) &&
+ (cp = getenv("KRB5_KTNAME"))) {
strncpy(name, cp, namesize);
if (strlen(cp) >= (size_t) namesize)
return KRB5_CONFIG_NOTENUFSPACE;
+ } else if (((code = profile_get_string(context->profile,
+ "libdefaults",
+ "default_keytab_name", NULL,
+ NULL, &retval)) == 0) &&
+ retval) {
+ strncpy(name, retval, namesize);
+ if ((size_t) namesize < strlen(retval))
+ return KRB5_CONFIG_NOTENUFSPACE;
} else {
#if defined (_MSDOS) || defined(_WIN32)
{
diff --git a/src/lib/rpc/ChangeLog b/src/lib/rpc/ChangeLog
new file mode 100644
index 000000000..a78d05c37
--- /dev/null
+++ b/src/lib/rpc/ChangeLog
@@ -0,0 +1,20 @@
+Fri Jul 12 15:33:50 1996 Marc Horowitz <marc@mit.edu>
+
+ * rpc_dtablesize.c (_rpc_dtablesize): put in a few checks to make
+ sure that the return value is never larger than FD_SETSIZE, since
+ this function's purpose is to be used as the first arg to
+ select().
+
+Tue Jul 9 17:56:54 1996 Marc Horowitz <marc@mit.edu>
+
+ * rpc.h, netdb.h, getrpcent.c: Our build can (and will) require
+ that the rpc header files shipped with kerberos be used if the
+ library shipped with kerberos is used. Thus, some simplifying
+ assumptions can be made, mostly having to do with the declaration
+ of struct rpcent and the related functions.
+ * clnt_perror.c: made usage of sys_errlist conditional on
+ NEED_SYS_ERRLIST
+ * configure.in (DECLARE_SYS_ERRLIST): added
+ * Makefile.in (DONE): added a few rules and variable so shared
+ library creation would work
+
diff --git a/src/lib/rpc/Makefile.in b/src/lib/rpc/Makefile.in
new file mode 100644
index 000000000..9426bb94c
--- /dev/null
+++ b/src/lib/rpc/Makefile.in
@@ -0,0 +1,148 @@
+CFLAGS = $(CCOPTS) $(DEFS) -DDEBUG_GSSAPI -I$(srcdir)/..
+
+##DOSBUILDTOP = ..\..
+##DOSLIBNAME=libgssrpc.lib
+
+.c.o:
+ $(CC) $(CFLAGS) -c $(srcdir)/$*.c
+@SHARED_RULE@
+
+SRCS = $(srcdir)/auth_none.c \
+ $(srcdir)/auth_unix.c \
+ $(srcdir)/auth_any.c \
+ $(srcdir)/authunix_prot.c \
+ $(srcdir)/auth_gssapi.c \
+ $(srcdir)/auth_gssapi_misc.c \
+ $(srcdir)/bindresvport.c \
+ $(srcdir)/clnt_generic.c \
+ $(srcdir)/clnt_perror.c \
+ $(srcdir)/clnt_raw.c \
+ $(srcdir)/clnt_simple.c \
+ $(srcdir)/clnt_tcp.c \
+ $(srcdir)/clnt_udp.c \
+ $(srcdir)/rpc_dtablesize.c \
+ $(srcdir)/get_myaddress.c \
+ $(srcdir)/getrpcent.c \
+ $(srcdir)/getrpcport.c \
+ $(srcdir)/pmap_clnt.c \
+ $(srcdir)/pmap_getmaps.c \
+ $(srcdir)/pmap_getport.c \
+ $(srcdir)/pmap_prot.c \
+ $(srcdir)/pmap_prot2.c \
+ $(srcdir)/pmap_rmt.c \
+ $(srcdir)/rpc_prot.c \
+ $(srcdir)/rpc_commondata.c \
+ $(srcdir)/rpc_callmsg.c \
+ $(srcdir)/svc.c \
+ $(srcdir)/svc_auth.c \
+ $(srcdir)/svc_auth_unix.c \
+ $(srcdir)/svc_auth_any.c \
+ $(srcdir)/svc_auth_gssapi.c \
+ $(srcdir)/svc_raw.c \
+ $(srcdir)/svc_run.c \
+ $(srcdir)/svc_simple.c \
+ $(srcdir)/svc_tcp.c \
+ $(srcdir)/svc_udp.c \
+ $(srcdir)/xdr.c \
+ $(srcdir)/xdr_array.c \
+ $(srcdir)/xdr_float.c \
+ $(srcdir)/xdr_mem.c \
+ $(srcdir)/xdr_rec.c \
+ $(srcdir)/xdr_reference.c \
+ $(srcdir)/xdr_stdio.c \
+ $(srcdir)/xdr_alloc.c
+
+OBJS = auth_none.$(OBJEXT) \
+ auth_unix.$(OBJEXT) \
+ auth_any.$(OBJEXT) \
+ authunix_prot.$(OBJEXT) \
+ auth_gssapi.$(OBJEXT) \
+ auth_gssapi_misc.$(OBJEXT) \
+ bindresvport.$(OBJEXT) \
+ clnt_generic.$(OBJEXT) \
+ clnt_perror.$(OBJEXT) \
+ clnt_raw.$(OBJEXT) \
+ clnt_simple.$(OBJEXT) \
+ clnt_tcp.$(OBJEXT) \
+ clnt_udp.$(OBJEXT) \
+ rpc_dtablesize.$(OBJEXT) \
+ get_myaddress.$(OBJEXT) \
+ getrpcent.$(OBJEXT) \
+ getrpcport.$(OBJEXT) \
+ pmap_clnt.$(OBJEXT) \
+ pmap_getmaps.$(OBJEXT) \
+ pmap_getport.$(OBJEXT) \
+ pmap_prot.$(OBJEXT) \
+ pmap_prot2.$(OBJEXT) \
+ pmap_rmt.$(OBJEXT) \
+ rpc_prot.$(OBJEXT) \
+ rpc_commondata.$(OBJEXT) \
+ rpc_callmsg.$(OBJEXT) \
+ svc.$(OBJEXT) \
+ svc_auth.$(OBJEXT) \
+ svc_auth_unix.$(OBJEXT) \
+ svc_auth_any.$(OBJEXT) \
+ svc_auth_gssapi.$(OBJEXT) \
+ svc_raw.$(OBJEXT) \
+ svc_run.$(OBJEXT) \
+ svc_simple.$(OBJEXT) \
+ svc_tcp.$(OBJEXT) \
+ svc_udp.$(OBJEXT) \
+ xdr.$(OBJEXT) \
+ xdr_array.$(OBJEXT) \
+ xdr_float.$(OBJEXT) \
+ xdr_mem.$(OBJEXT) \
+ xdr_rec.$(OBJEXT) \
+ xdr_reference.$(OBJEXT) \
+ xdr_stdio.$(OBJEXT) \
+ xdr_alloc.$(OBJEXT)
+
+LIB_SUBDIRS= .
+LIBDONE= DONE
+#
+# Depends on libgssapi_krb5, libkrb5, libcrypto, libcom_err
+#
+GSSAPI_KRB5_VER=@GSSAPI_KRB5_SH_VERS@
+KRB5_VER=@KRB5_SH_VERS@
+CRYPTO_VER=@CRYPTO_SH_VERS@
+COMERR_VER=@COMERR_SH_VERS@
+DEPLIBS=$(TOPLIBD)/libgssapi_krb5.$(SHEXT).$(COMERR_VER) \
+ $(TOPLIBD)/libkrb5.$(SHEXT).$(KRB5_VER) \
+ $(TOPLIBD)/libcrypto.$(SHEXT).$(CRYPTO_VER) \
+ $(TOPLIBD)/libcom_err.$(SHEXT).$(COMERR_VER)
+
+SHLIB_LIBS=-lkrb5 -lcrypto -lcom_err -ldyn
+SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@
+SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
+
+all-unix:: shared includes $(OBJS)
+all-mac:: $(OBJS)
+all-windows:: $(OBJS)
+
+shared:
+ mkdir shared
+
+check-windows::
+
+clean-unix::
+ $(RM) shared/*
+
+clean-mac::
+clean-windows::
+
+DONE: $(OBJS)
+ $(RM) DONE
+ echo $(OBJS) > DONE
+
+libgssrpc.$(STEXT): $(OBJS)
+ $(RM) $@
+ $(ARADD) $@ $(OBJS)
+ $(RANLIB) $@
+
+install:: libgssrpc.a
+ $(INSTALL_DATA) libgssrpc.a $(DESTDIR)$(KRB5_LIBDIR)/libgssrpc.a
+ $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libgssrpc.a
+
+clean::
+ $(RM) libgssrpc.$(LIBEXT) libgssrpc.bak DONE
+
diff --git a/src/lib/rpc/Makefile.ov b/src/lib/rpc/Makefile.ov
new file mode 100644
index 000000000..d64c77e22
--- /dev/null
+++ b/src/lib/rpc/Makefile.ov
@@ -0,0 +1,52 @@
+#
+# Makefile for librpclib.a.
+#
+# $Id$
+# $Source$
+#
+TOP = ..
+include $(TOP)/config.mk/template
+
+SUBDIRS = unit-test
+
+SRCS = auth_none.c auth_unix.c auth_any.c authunix_prot.c \
+ auth_gssapi.c auth_gssapi_misc.c bindresvport.c \
+ clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
+ clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \
+ pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
+ pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
+ svc.c svc_auth.c svc_auth_unix.c svc_auth_any.c svc_auth_gssapi.c \
+ svc_raw.c svc_run.c svc_simple.c \
+ svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+ xdr_rec.c xdr_reference.c xdr_stdio.c xdr_alloc.c
+
+OBJS = auth_none.o auth_unix.o auth_any.o authunix_prot.o \
+ auth_gssapi.o auth_gssapi_misc.o bindresvport.o \
+ clnt_generic.o clnt_perror.o clnt_raw.o clnt_simple.o clnt_tcp.o \
+ clnt_udp.o rpc_dtablesize.o get_myaddress.o getrpcent.o getrpcport.o \
+ pmap_clnt.o pmap_getmaps.o pmap_getport.o pmap_prot.o \
+ pmap_prot2.o pmap_rmt.o rpc_prot.o rpc_commondata.o rpc_callmsg.o \
+ svc.o svc_auth.o svc_auth_unix.o svc_auth_any.o svc_auth_gssapi.o \
+ svc_raw.o svc_run.o svc_simple.o \
+ svc_tcp.o svc_udp.o xdr.o xdr_array.o xdr_float.o xdr_mem.o \
+ xdr_rec.o xdr_reference.o xdr_stdio.o xdr_alloc.o
+
+HDRS = auth.h auth_unix.h auth_gssapi.h clnt.h pmap_clnt.h \
+ pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h
+
+HDRS_DIR = rpc
+
+LIB = librpclib.a
+
+CFLAGS := -I.. $(CFLAGS) -DDEBUG_GSSAPI=0 $(D_NEEDS_RPCENT)
+
+expand StageLibrary
+
+expand StageIncludes
+
+expand Depend
+
+expand SubdirTarget
+
+expand Saber
+
diff --git a/src/lib/rpc/auth.h b/src/lib/rpc/auth.h
new file mode 100644
index 000000000..4b0a40ccc
--- /dev/null
+++ b/src/lib/rpc/auth.h
@@ -0,0 +1,197 @@
+/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client. The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+
+
+#define MAX_AUTH_BYTES 400
+#define MAXNETNAMELEN 255 /* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+ AUTH_OK=0,
+ /*
+ * failed at remote end
+ */
+ AUTH_BADCRED=1, /* bogus credentials (seal broken) */
+ AUTH_REJECTEDCRED=2, /* client should begin new session */
+ AUTH_BADVERF=3, /* bogus verifier (seal broken) */
+ AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */
+ AUTH_TOOWEAK=5, /* rejected due to security reasons */
+ /*
+ * failed locally
+ */
+ AUTH_INVALIDRESP=6, /* bogus response verifier */
+ AUTH_FAILED=7 /* some unknown reason */
+};
+
+union des_block {
+#if 0 /* XXX nothing uses this, anyway */
+ struct {
+ rpc_u_int32 high;
+ rpc_u_int32 low;
+ } key;
+#endif
+ char c[8];
+};
+typedef union des_block des_block;
+extern bool_t xdr_des_block();
+
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ unsigned int oa_length; /* not to exceed MAX_AUTH_BYTES */
+};
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct {
+ struct opaque_auth ah_cred;
+ struct opaque_auth ah_verf;
+ union des_block ah_key;
+ struct auth_ops {
+ void (*ah_nextverf)();
+ int (*ah_marshal)(); /* nextverf & serialize */
+ int (*ah_validate)(); /* validate varifier */
+ int (*ah_refresh)(); /* refresh credentials */
+ void (*ah_destroy)(); /* destroy this structure */
+ int (*ah_wrap)(); /* encode data for wire */
+ int (*ah_unwrap)(); /* decode data from wire */
+ } *ah_ops;
+ caddr_t ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH *auth;
+ * XDR *xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+#define auth_refresh(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+
+#define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+ xfunc, xwhere))
+
+#define AUTH_DESTROY(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+extern struct opaque_auth _null_auth;
+
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Any style authentication. These routines can be used by any
+ * authentication style that does not use the wrap/unwrap functions.
+ */
+int authany_wrap(), authany_unwrap();
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ * char *machname;
+ * int uid;
+ * int gid;
+ * int len;
+ * int *aup_gids;
+ */
+extern AUTH *authunix_create();
+extern AUTH *authunix_create_default(); /* takes no parameters */
+extern AUTH *authnone_create(); /* takes no parameters */
+extern AUTH *authdes_create();
+
+/*
+ * GSS-API style authentication:
+ * see <rpc/auth_gssapi.h>
+ */
+
+#define AUTH_NONE 0 /* no authentication */
+#define AUTH_NULL 0 /* backward compatibility */
+#define AUTH_UNIX 1 /* unix style (uid, gids) */
+#define AUTH_SHORT 2 /* short hand unix style */
+#define AUTH_DES 3 /* des style (encrypted timestamps) */
+#define AUTH_GSSAPI 300001 /* GSS-API style */
+
+/*
+ * BACKWARDS COMPATIBILIY! OpenV*Secure 1.0 had AUTH_GSSAPI == 4. We
+ * need to accept this value until 1.0 is dead.
+ */
+#define AUTH_GSSAPI_COMPAT 4
diff --git a/src/lib/rpc/auth_any.c b/src/lib/rpc/auth_any.c
new file mode 100644
index 000000000..5e2a8633a
--- /dev/null
+++ b/src/lib/rpc/auth_any.c
@@ -0,0 +1,19 @@
+/*
+ * auth_any.c
+ * Provides default functions for authentication flavors that do not
+ * use all the fields in structauth_ops.
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+
+int authany_wrap(auth, xdrs, xfunc, xwhere)
+ AUTH *auth;
+ XDR *xdrs;
+ xdrproc_t xfunc;
+ caddr_t xwhere;
+{
+ return (*xfunc)(xdrs, xwhere);
+}
diff --git a/src/lib/rpc/auth_gssapi.c b/src/lib/rpc/auth_gssapi.c
new file mode 100644
index 000000000..0ffe96d18
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.23 1996/07/22 20:39:39 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.22.4.1 1996/07/18 04:18:29 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.22.2.1 1996/06/20 23:35:31 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.22 1996/06/05 20:56:16 bjaspan
+ * memset bindings to zero before use
+ *
+ * Revision 1.21 1996/05/12 06:11:38 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.20 1995/12/13 14:02:45 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.19 1995/10/31 16:36:00 bjaspan
+ * GS reported this bug. When talking to a 1.1 server, the server will
+ * not fail indicating the version is wrong because it never checks the
+ * version; it just responds with call_res.version 1. So we have to
+ * deal. Oops.
+ *
+ * It's amazing what can fall through the cracks when most of the
+ * development team is fired..
+ *
+ * Revision 1.18 1995/10/31 16:07:06 bjaspan
+ * fix from grier
+ *
+ * Revision 1.17 1995/08/24 21:06:26 bjaspan
+ * set acceptor channel bindings
+ *
+ * Revision 1.16 1995/08/23 20:27:37 bjaspan
+ * [secure-rpc/3392] add channel bindinds to the rpc
+ *
+ * Revision 1.15 1995/05/08 22:32:01 marc
+ * change call_arg.version from 1 to 2 to indicate the new client is in use.
+ *
+ * Revision 1.14 1995/03/22 22:05:20 jik
+ * Reorder the auth_ops structure, to agree with the order of the version of
+ * this library in the GK source tree. I chose to reorder this one rather
+ * than reorder the GK tree because Barry says that the order in the GK tree
+ * makes more sense.
+ *
+ * Revision 1.13 1994/10/27 12:39:02 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * change to use GSS_ERROR &c macros; I don't think this is correct
+ * =============================================================================
+ *
+ * Revision 1.14 1994/10/26 20:03:46 bjaspan
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.13 1994/04/07 16:12:06 jik
+ * The second argument to xdr_opaque_auth is struct auth *, not struct
+ * auth.
+ *
+ * Revision 1.12 1993/12/08 21:42:43 bjaspan
+ * use AUTH_GSSAPI_DISPLAY_STATUS macro, reindent
+ *
+ * Revision 1.11 1993/12/06 21:21:03 bjaspan
+ * debugging levels
+ *
+ * Revision 1.10 1993/11/18 23:13:07 bjaspan
+ * add some function comments
+ *
+ * Revision 1.9 1993/11/15 19:50:03 bjaspan
+ * redefine AUTH_REFRESH to take the error message as an argument, and
+ * change auth_gssapi_refresh to increment the seq_num on REJECTEDVERF
+ *
+ * Revision 1.8 1993/11/12 02:31:59 bjaspan
+ * set rpc_createerr as appropriate
+ *
+ * Revision 1.7 1993/11/03 21:21:02 bjaspan
+ * fix seq_num handling in cases of errors and retransmission
+ *
+ * Revision 1.6 1993/11/01 19:55:20 bjaspan
+ * display gss_major and gss_minor, and unstatic auth_gssapi_debug
+ *
+ * Revision 1.5 1993/10/28 22:07:33 bjaspan
+ * create_default takes char *, use seq_num in args/results
+ *
+ * Revision 1.4 1993/10/26 21:11:53 bjaspan
+ * working
+ *
+ * Revision 1.3 1993/10/21 19:01:09 bjaspan
+ * added auth_gssapi_destroy, cleaned up a few things
+ *
+ * Revision 1.2 1993/10/19 03:10:58 bjaspan
+ * snapshot: GSS-API working in hacked up state, not seal/unseal
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+
+#include <rpc/rpc.h>
+#include <rpc/auth_gssapi.h>
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int auth_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (auth_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (auth_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+static void auth_gssapi_nextverf();
+static bool_t auth_gssapi_marshall();
+static bool_t auth_gssapi_validate();
+static bool_t auth_gssapi_refresh();
+static bool_t auth_gssapi_wrap();
+static bool_t auth_gssapi_unwrap();
+static void auth_gssapi_destroy();
+
+static bool_t marshall_new_creds();
+
+static struct auth_ops auth_gssapi_ops = {
+ auth_gssapi_nextverf,
+ auth_gssapi_marshall,
+ auth_gssapi_validate,
+ auth_gssapi_refresh,
+ auth_gssapi_destroy,
+ auth_gssapi_wrap,
+ auth_gssapi_unwrap,
+};
+
+/*
+ * the ah_private data structure for an auth_handle
+ */
+struct auth_gssapi_data {
+ bool_t established;
+ CLIENT *clnt;
+ gss_ctx_id_t context;
+ gss_buffer_desc client_handle;
+ rpc_u_int32 seq_num;
+ int def_cred;
+
+ /* pre-serialized ah_cred */
+ unsigned char cred_buf[MAX_AUTH_BYTES];
+ rpc_u_int32 cred_len;
+};
+#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
+
+extern struct rpc_createerr rpc_createerr;
+
+/*
+ * Function: auth_gssapi_create_default
+ *
+ * Purpose: Create a GSS-API style authenticator, with default
+ * options, and return the handle.
+ *
+ * Effects: See design document, section XXX.
+ */
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name)
+{
+ AUTH *auth;
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc input_name;
+ gss_name_t target_name;
+
+ input_name.value = service_name;
+ input_name.length = strlen(service_name) + 1;
+
+ gssstat = gss_import_name(&minor_stat, &input_name,
+ gss_nt_service_name, &target_name);
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("parsing name", gssstat,
+ minor_stat));
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = ENOMEM;
+ return NULL;
+ }
+
+ auth = auth_gssapi_create(clnt,
+ &gssstat,
+ &minor_stat,
+ GSS_C_NO_CREDENTIAL,
+ target_name,
+ GSS_C_NULL_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+
+ gss_release_name(&minor_stat, &target_name);
+ return auth;
+}
+
+/*
+ * Function: auth_gssapi_create
+ *
+ * Purpose: Create a GSS-API style authenticator, with all the
+ * options, and return the handle.
+ *
+ * Effects: See design document, section XXX.
+ */
+AUTH *auth_gssapi_create(CLIENT *clnt,
+ OM_uint32 *gssstat,
+ OM_uint32 *minor_stat,
+ gss_cred_id_t claimant_cred_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ int req_flags,
+ OM_uint32 time_req,
+ gss_OID *actual_mech_type,
+ int *ret_flags,
+ OM_uint32 *time_rec)
+{
+ AUTH *auth, *save_auth;
+ struct auth_gssapi_data *pdata;
+ struct gss_channel_bindings_struct bindings, *bindp;
+ struct sockaddr_in laddr, raddr;
+ enum clnt_stat callstat;
+ struct timeval timeout;
+ int init_func;
+
+ auth_gssapi_init_arg call_arg;
+ auth_gssapi_init_res call_res;
+ gss_buffer_desc *input_token, isn_buf;
+
+ memset(&rpc_createerr, 0, sizeof(rpc_createerr));
+
+ /* this timeout is only used if clnt_control(clnt, CLSET_TIMEOUT) */
+ /* has not already been called.. therefore, we can just pick */
+ /* something reasonable-sounding.. */
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ auth = NULL;
+ pdata = NULL;
+
+ auth = (AUTH *) malloc(sizeof(*auth));
+ pdata = (struct auth_gssapi_data *) malloc(sizeof(*pdata));
+ if (auth == NULL || pdata == NULL) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = ENOMEM;
+ goto cleanup;
+ }
+ memset((char *) auth, 0, sizeof(*auth));
+ memset((char *) pdata, 0, sizeof(*pdata));
+
+ auth->ah_ops = &auth_gssapi_ops;
+ auth->ah_private = (caddr_t) pdata;
+
+ /* initial creds are auth_msg TRUE and no handle */
+ marshall_new_creds(auth, TRUE, NULL);
+
+ /* initial verifier is empty */
+ auth->ah_verf.oa_flavor = AUTH_GSSAPI;
+ auth->ah_verf.oa_base = NULL;
+ auth->ah_verf.oa_length = 0;
+
+ AUTH_PRIVATE(auth)->established = FALSE;
+ AUTH_PRIVATE(auth)->clnt = clnt;
+ AUTH_PRIVATE(auth)->def_cred = (claimant_cred_handle ==
+ GSS_C_NO_CREDENTIAL);
+
+ /* don't assume the caller will want to change clnt->cl_auth */
+ save_auth = clnt->cl_auth;
+ clnt->cl_auth = auth;
+
+ /* start by trying latest version */
+ call_arg.version = 3;
+
+try_new_version:
+ /* set state for initial call to init_sec_context */
+ input_token = GSS_C_NO_BUFFER;
+ AUTH_PRIVATE(auth)->context = GSS_C_NO_CONTEXT;
+ init_func = AUTH_GSSAPI_INIT;
+
+ if (call_arg.version == 3) {
+ if (clnt_control(clnt, CLGET_LOCAL_ADDR, &laddr) == FALSE) {
+ PRINTF(("gssapi_create: CLGET_LOCAL_ADDR failed"));
+ goto cleanup;
+ }
+ if (clnt_control(clnt, CLGET_SERVER_ADDR, &raddr) == FALSE) {
+ PRINTF(("gssapi_create: CLGET_SERVER_ADDR failed"));
+ goto cleanup;
+ }
+
+ memset(&bindings, 0, sizeof(bindings));
+ bindings.application_data.length = 0;
+ bindings.initiator_addrtype = GSS_C_AF_INET;
+ bindings.initiator_address.length = 4;
+ bindings.initiator_address.value = &laddr.sin_addr.s_addr;
+
+ bindings.acceptor_addrtype = GSS_C_AF_INET;
+ bindings.acceptor_address.length = 4;
+ bindings.acceptor_address.value = &raddr.sin_addr.s_addr;
+ bindp = &bindings;
+ } else {
+ bindp = NULL;
+ }
+
+ memset((char *) &call_res, 0, sizeof(call_res));
+
+next_token:
+ *gssstat = gss_init_sec_context(minor_stat,
+ claimant_cred_handle,
+ &AUTH_PRIVATE(auth)->context,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ bindp,
+ input_token,
+ actual_mech_type,
+ &call_arg.token,
+ ret_flags,
+ time_rec);
+
+ if (*gssstat != GSS_S_COMPLETE && *gssstat != GSS_S_CONTINUE_NEEDED) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("initializing context", *gssstat,
+ *minor_stat));
+ goto cleanup;
+ }
+
+ /* if we got a token, pass it on */
+ if (call_arg.token.length != 0) {
+
+ /*
+ * sanity check: if we received a signed isn in the last
+ * response then there *cannot* be another token to send
+ */
+ if (call_res.signed_isn.length != 0) {
+ PRINTF(("gssapi_create: unexpected token from init_sec\n"));
+ goto cleanup;
+ }
+
+ PRINTF(("gssapi_create: calling GSSAPI_INIT (%d)\n", init_func));
+
+ memset((char *) &call_res, 0, sizeof(call_res));
+ callstat = clnt_call(clnt, init_func,
+ xdr_authgssapi_init_arg, &call_arg,
+ xdr_authgssapi_init_res, &call_res,
+ timeout);
+ gss_release_buffer(minor_stat, &call_arg.token);
+
+ if (callstat != RPC_SUCCESS) {
+ struct rpc_err err;
+
+ clnt_geterr(clnt, &err);
+ if (callstat == RPC_AUTHERROR &&
+ (err.re_why == AUTH_BADCRED || err.re_why == AUTH_FAILED)
+ && call_arg.version >= 1) {
+ L_PRINTF(1, ("call_arg protocol "
+ "version %d rejected, trying %d.\n",
+ call_arg.version, call_arg.version-1));
+ call_arg.version--;
+ goto try_new_version;
+ } else {
+ PRINTF(("gssapi_create: GSSAPI_INIT (%d) failed, stat %d\n",
+ init_func, callstat));
+ }
+
+ goto cleanup;
+ } else if (call_res.version != call_arg.version &&
+ !(call_arg.version == 2 && call_res.version == 1)) {
+ /*
+ * The Secure 1.1 servers always respond with version
+ * 1. Thus, if we just tried a version >=3, fall all
+ * the way back to version 1 since that is all they
+ * understand
+ */
+ if (call_arg.version > 2 && call_res.version == 1) {
+ L_PRINTF(1, ("Talking to Secure 1.1 server, "
+ "using version 1.\n"));
+ call_arg.version = 1;
+ goto try_new_version;
+ }
+
+ PRINTF(("gssapi_create: invalid call_res vers %d\n",
+ call_res.version));
+ goto cleanup;
+ } else if (call_res.gss_major != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("in response from server",
+ call_res.gss_major,
+ call_res.gss_minor));
+ goto cleanup;
+ }
+
+ PRINTF(("gssapi_create: GSSAPI_INIT (%d) succeeded\n", init_func));
+ init_func = AUTH_GSSAPI_CONTINUE_INIT;
+
+ /* check for client_handle */
+ if (AUTH_PRIVATE(auth)->client_handle.length == 0) {
+ if (call_res.client_handle.length == 0) {
+ PRINTF(("gssapi_create: expected client_handle\n"));
+ goto cleanup;
+ } else {
+ PRINTF(("gssapi_create: got client_handle %d\n",
+ *((rpc_u_int32 *)call_res.client_handle.value)));
+
+ GSS_DUP_BUFFER(AUTH_PRIVATE(auth)->client_handle,
+ call_res.client_handle);
+
+ /* auth_msg is TRUE; there may be more tokens */
+ marshall_new_creds(auth, TRUE,
+ &AUTH_PRIVATE(auth)->client_handle);
+ }
+ } else if (!GSS_BUFFERS_EQUAL(AUTH_PRIVATE(auth)->client_handle,
+ call_res.client_handle)) {
+ PRINTF(("gssapi_create: got different client_handle\n"));
+ goto cleanup;
+ }
+
+ /* check for token */
+ if (call_res.token.length==0 && *gssstat==GSS_S_CONTINUE_NEEDED) {
+ PRINTF(("gssapi_create: expected token\n"));
+ goto cleanup;
+ } else if (call_res.token.length != 0) {
+ if (*gssstat == GSS_S_COMPLETE) {
+ PRINTF(("gssapi_create: got unexpected token\n"));
+ goto cleanup;
+ } else {
+ /* assumes call_res is safe until init_sec_context */
+ input_token = &call_res.token;
+ PRINTF(("gssapi_create: got new token\n"));
+ }
+ }
+ }
+
+ /* check for isn */
+ if (*gssstat == GSS_S_COMPLETE) {
+ if (call_res.signed_isn.length == 0) {
+ PRINTF(("gssapi_created: expected signed isn\n"));
+ goto cleanup;
+ } else {
+ PRINTF(("gssapi_create: processing signed isn\n"));
+
+ /* don't check conf (integ only) or qop (accpet default) */
+ *gssstat = gss_unseal(minor_stat,
+ AUTH_PRIVATE(auth)->context,
+ &call_res.signed_isn,
+ &isn_buf, NULL, NULL);
+
+ if (*gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("unsealing isn",
+ *gssstat, *minor_stat));
+ goto cleanup;
+ } else if (isn_buf.length != sizeof(rpc_u_int32)) {
+ PRINTF(("gssapi_create: gss_unseal gave %d bytes\n",
+ isn_buf.length));
+ goto cleanup;
+ }
+
+ AUTH_PRIVATE(auth)->seq_num = (rpc_u_int32)
+ ntohl(*((rpc_u_int32*)isn_buf.value));
+ *gssstat = gss_release_buffer(minor_stat, &isn_buf);
+ if (*gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("releasing unsealed isn",
+ *gssstat, *minor_stat));
+ goto cleanup;
+ }
+
+ PRINTF(("gssapi_create: isn is %d\n",
+ AUTH_PRIVATE(auth)->seq_num));
+
+ /* we no longer need these results.. */
+ xdr_free(xdr_authgssapi_init_res, &call_res);
+ }
+ } else if (call_res.signed_isn.length != 0) {
+ PRINTF(("gssapi_create: got signed isn, can't check yet\n"));
+ }
+
+ /* results were okay.. continue if necessary */
+ if (*gssstat == GSS_S_CONTINUE_NEEDED) {
+ PRINTF(("gssapi_create: not done, continuing\n"));
+ goto next_token;
+ }
+
+ /*
+ * Done! Context is established, we have client_handle and isn.
+ */
+ AUTH_PRIVATE(auth)->established = TRUE;
+
+ marshall_new_creds(auth, FALSE,
+ &AUTH_PRIVATE(auth)->client_handle);
+
+ PRINTF(("gssapi_create: done. client_handle %#x, isn %d\n\n",
+ *((rpc_u_int32 *)AUTH_PRIVATE(auth)->client_handle.value),
+ AUTH_PRIVATE(auth)->seq_num));
+
+ /* don't assume the caller will want to change clnt->cl_auth */
+ clnt->cl_auth = save_auth;
+
+ return auth;
+
+ /******************************************************************/
+
+cleanup:
+ PRINTF(("gssapi_create: bailing\n\n"));
+
+ if (AUTH_PRIVATE(auth))
+ auth_gssapi_destroy(auth);
+ else if (auth)
+ free(auth);
+ auth = NULL;
+
+ /* don't assume the caller will want to change clnt->cl_auth */
+ clnt->cl_auth = save_auth;
+
+ if (rpc_createerr.cf_stat == 0)
+ rpc_createerr.cf_stat = RPC_AUTHERROR;
+
+ return auth;
+}
+
+/*
+ * Function: marshall_new_creds
+ *
+ * Purpose: (pre-)serialize auth_msg and client_handle fields of
+ * auth_gssapi_creds into auth->cred_buf
+ *
+ * Arguments:
+ *
+ * auth (r/w) the AUTH structure to modify
+ * auth_msg (r) the auth_msg field to serialize
+ * client_handle (r) the client_handle field to serialize, or
+ * NULL
+ *
+ * Returns: TRUE if successful, FALSE if not
+ *
+ * Requires: auth must point to a valid GSS-API auth structure, auth_msg
+ * must be TRUE or FALSE, client_handle must be a gss_buffer_t with a valid
+ * value and length field or NULL.
+ *
+ * Effects: auth->ah_cred is set to the serialized auth_gssapi_creds
+ * version 2 structure (stored in the cred_buf field of private data)
+ * containing version, auth_msg and client_handle.
+ * auth->ah_cred.oa_flavor is set to AUTH_GSSAPI. If cliend_handle is
+ * NULL, it is treated as if it had a length of 0 and a value of NULL.
+ *
+ * Modifies: auth
+ */
+static bool_t marshall_new_creds(auth, auth_msg, client_handle)
+ AUTH *auth;
+ bool_t auth_msg;
+ gss_buffer_t client_handle;
+{
+ auth_gssapi_creds creds;
+ XDR xdrs;
+
+ PRINTF(("marshall_new_creds: starting\n"));
+
+ creds.version = 2;
+
+ creds.auth_msg = auth_msg;
+ if (client_handle)
+ GSS_COPY_BUFFER(creds.client_handle, *client_handle)
+ else {
+ creds.client_handle.length = 0;
+ creds.client_handle.value = NULL;
+ }
+
+ xdrmem_create(&xdrs, AUTH_PRIVATE(auth)->cred_buf,
+ MAX_AUTH_BYTES, XDR_ENCODE);
+ if (! xdr_authgssapi_creds(&xdrs, &creds)) {
+ PRINTF(("marshall_new_creds: failed encoding auth_gssapi_creds\n"));
+ XDR_DESTROY(&xdrs);
+ return FALSE;
+ }
+ AUTH_PRIVATE(auth)->cred_len = xdr_getpos(&xdrs);
+ XDR_DESTROY(&xdrs);
+
+ PRINTF(("marshall_new_creds: auth_gssapi_creds is %d bytes\n",
+ AUTH_PRIVATE(auth)->cred_len));
+
+ auth->ah_cred.oa_flavor = AUTH_GSSAPI;
+ auth->ah_cred.oa_base = (char *) AUTH_PRIVATE(auth)->cred_buf;
+ auth->ah_cred.oa_length = AUTH_PRIVATE(auth)->cred_len;
+
+ PRINTF(("marshall_new_creds: succeeding\n"));
+
+ return TRUE;
+}
+
+
+/*
+ * Function: auth_gssapi_nextverf
+ *
+ * Purpose: None.
+ *
+ * Effects: None. Never called.
+ */
+static void auth_gssapi_nextverf(/*auth*/)
+ /*AUTH *auth;*/
+{
+}
+
+/*
+ * Function: auth_gssapi_marhsall
+ *
+ * Purpose: Marshall RPC credentials and verifier onto xdr stream.
+ *
+ * Arguments:
+ *
+ * auth (r/w) AUTH structure for client
+ * xdrs (r/w) XDR stream to marshall to
+ *
+ * Returns: boolean indicating success/failure
+ *
+ * Effects:
+ *
+ * The pre-serialized credentials in cred_buf are serialized. If the
+ * context is established, the sealed sequence number is serialized as
+ * the verifier. If the context is not established, an empty verifier
+ * is serialized. The sequence number is *not* incremented, because
+ * this function is called multiple times if retransmission is required.
+ *
+ * If this took all the header fields as arguments, it could sign
+ * them.
+ */
+static bool_t auth_gssapi_marshall(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ OM_uint32 minor_stat;
+ gss_buffer_desc out_buf;
+ rpc_u_int32 seq_num;
+
+ if (AUTH_PRIVATE(auth)->established == TRUE) {
+ PRINTF(("gssapi_marshall: starting\n"));
+
+ seq_num = AUTH_PRIVATE(auth)->seq_num + 1;
+
+ PRINTF(("gssapi_marshall: sending seq_num %d\n", seq_num));
+
+ if (auth_gssapi_seal_seq(AUTH_PRIVATE(auth)->context, seq_num,
+ &out_buf) == FALSE) {
+ PRINTF(("gssapi_marhshall: seal failed\n"));
+ }
+
+ auth->ah_verf.oa_base = out_buf.value;
+ auth->ah_verf.oa_length = out_buf.length;
+
+ if (! xdr_opaque_auth(xdrs, &auth->ah_cred) ||
+ ! xdr_opaque_auth(xdrs, &auth->ah_verf)) {
+ (void) gss_release_buffer(&minor_stat, &out_buf);
+ return FALSE;
+ }
+ (void) gss_release_buffer(&minor_stat, &out_buf);
+ } else {
+ PRINTF(("gssapi_marshall: not established, sending null verf\n"));
+
+ auth->ah_verf.oa_base = NULL;
+ auth->ah_verf.oa_length = 0;
+
+ if (! xdr_opaque_auth(xdrs, &auth->ah_cred) ||
+ ! xdr_opaque_auth(xdrs, &auth->ah_verf)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_validate
+ *
+ * Purpose: Validate RPC response verifier from server.
+ *
+ * Effects: See design document, section XXX.
+ */
+static bool_t auth_gssapi_validate(auth, verf)
+ AUTH *auth;
+ struct opaque_auth *verf;
+{
+ gss_buffer_desc in_buf;
+ rpc_u_int32 seq_num;
+
+ if (AUTH_PRIVATE(auth)->established == FALSE) {
+ PRINTF(("gssapi_validate: not established, noop\n"));
+ return TRUE;
+ }
+
+ PRINTF(("gssapi_validate: starting\n"));
+
+ in_buf.length = verf->oa_length;
+ in_buf.value = verf->oa_base;
+ if (auth_gssapi_unseal_seq(AUTH_PRIVATE(auth)->context, &in_buf,
+ &seq_num) == FALSE) {
+ PRINTF(("gssapi_validate: failed unsealing verifier\n"));
+ return FALSE;
+ }
+
+ /* we sent seq_num+1, so we should get back seq_num+2 */
+ if (AUTH_PRIVATE(auth)->seq_num+2 != seq_num) {
+ PRINTF(("gssapi_validate: expecting seq_num %d, got %d (%#x)\n",
+ AUTH_PRIVATE(auth)->seq_num + 2, seq_num, seq_num));
+ return FALSE;
+ }
+ PRINTF(("gssapi_validate: seq_num %d okay\n", seq_num));
+
+ /* +1 for successful transmission, +1 for successful validation */
+ AUTH_PRIVATE(auth)->seq_num += 2;
+
+ PRINTF(("gssapi_validate: succeeding\n"));
+
+ return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_refresh
+ *
+ * Purpose: Attempts to resyncrhonize the sequence number.
+ *
+ * Effects:
+ *
+ * When the server receives a properly authenticated RPC call, it
+ * increments the sequence number it is expecting from the client.
+ * But if the server's response is lost for any reason, the client
+ * can't know whether the server ever received it, assumes it didn't,
+ * and does *not* increment its sequence number. Thus, the client's
+ * next call will fail with AUTH_REJECTEDCRED because the server will
+ * think it is a replay attack.
+ *
+ * When an AUTH_REJECTEDCRED error arrives, this function attempts to
+ * resyncrhonize by incrementing the client's sequence number and
+ * returning TRUE. If any other error arrives, it returns FALSE.
+ */
+static bool_t auth_gssapi_refresh(auth, msg)
+ AUTH *auth;
+ struct rpc_msg *msg;
+{
+ if (msg->rm_reply.rp_rjct.rj_stat == AUTH_ERROR &&
+ msg->rm_reply.rp_rjct.rj_why == AUTH_REJECTEDVERF) {
+ PRINTF(("gssapi_refresh: rejected verifier, incrementing\n"));
+ AUTH_PRIVATE(auth)->seq_num++;
+ return TRUE;
+ } else {
+ PRINTF(("gssapi_refresh: failing\n"));
+ return FALSE;
+ }
+}
+
+/*
+ * Function: auth_gssapi_destroy
+ *
+ * Purpose: Destroy a GSS-API authentication structure.
+ *
+ * Effects: This function destroys the GSS-API authentication
+ * context, and sends a message to the server instructing it to
+ * invokte gss_process_token() and thereby destroy its corresponding
+ * context. Since the client doesn't really care whether the server
+ * gets this message, no failures are reported.
+ */
+static void auth_gssapi_destroy(auth)
+ AUTH *auth;
+{
+ struct timeval timeout;
+ OM_uint32 gssstat, minor_stat;
+ gss_cred_id_t cred;
+ int callstat;
+
+ if (AUTH_PRIVATE(auth)->client_handle.length == 0) {
+ PRINTF(("gssapi_destroy: no client_handle, not calling destroy\n"));
+ goto skip_call;
+ }
+
+ PRINTF(("gssapi_destroy: marshalling new creds\n"));
+ if (!marshall_new_creds(auth, TRUE, &AUTH_PRIVATE(auth)->client_handle)) {
+ PRINTF(("gssapi_destroy: marshall_new_creds failed\n"));
+ goto skip_call;
+ }
+
+ PRINTF(("gssapi_destroy: calling GSSAPI_DESTROY\n"));
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_DESTROY,
+ xdr_void, NULL, xdr_void, NULL, timeout);
+ if (callstat != RPC_SUCCESS)
+ clnt_sperror(AUTH_PRIVATE(auth)->clnt,
+ "gssapi_destroy: GSSAPI_DESTROY failed");
+
+skip_call:
+ PRINTF(("gssapi_destroy: deleting context\n"));
+ gssstat = gss_delete_sec_context(&minor_stat,
+ &AUTH_PRIVATE(auth)->context,
+ NULL);
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
+ minor_stat));
+ if (AUTH_PRIVATE(auth)->def_cred) {
+ cred = GSS_C_NO_CREDENTIAL;
+ gssstat = gss_release_cred(&minor_stat, &cred);
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("deleting default credential",
+ gssstat, minor_stat));
+ }
+
+ if (AUTH_PRIVATE(auth)->client_handle.length != 0)
+ gss_release_buffer(&minor_stat,
+ &AUTH_PRIVATE(auth)->client_handle);
+
+#if 0
+ PRINTF(("gssapi_destroy: calling GSSAPI_EXIT\n"));
+ AUTH_PRIVATE(auth)->established = FALSE;
+ callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_EXIT,
+ xdr_void, NULL, xdr_void, NULL, timeout);
+#endif
+
+ free(auth->ah_private);
+ free(auth);
+ PRINTF(("gssapi_destroy: done\n"));
+}
+
+/*
+ * Function: auth_gssapi_wrap
+ *
+ * Purpose: encrypt the serialized arguments from xdr_func applied to
+ * xdr_ptr and write the result to xdrs.
+ *
+ * Effects: See design doc, section XXX.
+ */
+static bool_t auth_gssapi_wrap(auth, out_xdrs, xdr_func, xdr_ptr)
+ AUTH *auth;
+ XDR *out_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ OM_uint32 gssstat, minor_stat;
+
+ if (! AUTH_PRIVATE(auth)->established) {
+ PRINTF(("gssapi_wrap: context not established, noop\n"));
+ return (*xdr_func)(out_xdrs, xdr_ptr);
+ } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
+ AUTH_PRIVATE(auth)->context,
+ AUTH_PRIVATE(auth)->seq_num+1,
+ out_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_unwrap
+ *
+ * Purpose: read encrypted arguments from xdrs, decrypt, and
+ * deserialize with xdr_func into xdr_ptr.
+ *
+ * Effects: See design doc, section XXX.
+ */
+static bool_t auth_gssapi_unwrap(auth, in_xdrs, xdr_func, xdr_ptr)
+ AUTH *auth;
+ XDR *in_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ OM_uint32 gssstat, minor_stat;
+
+ if (! AUTH_PRIVATE(auth)->established) {
+ PRINTF(("gssapi_unwrap: context not established, noop\n"));
+ return (*xdr_func)(in_xdrs, xdr_ptr);
+ } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
+ AUTH_PRIVATE(auth)->context,
+ AUTH_PRIVATE(auth)->seq_num,
+ in_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
diff --git a/src/lib/rpc/auth_gssapi.h b/src/lib/rpc/auth_gssapi.h
new file mode 100644
index 000000000..9092149a5
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi.h
@@ -0,0 +1,161 @@
+/*
+ * auth_gssapi.h, Protocol for GSS-API style authentication parameters for RPC
+ *
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.18 1996/07/22 20:39:41 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.17.4.1 1996/07/18 04:18:31 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.17.2.1 1996/06/20 23:35:44 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.17 1996/05/12 06:11:38 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.16 1996/01/31 19:16:16 grier
+ * [secure/3570]
+ * Remove (void *) casts to memcpy() args
+ *
+ * Revision 1.15 1995/12/28 17:54:34 jik
+ * Don't define DEBUG_GSSAPI here.
+ *
+ * Revision 1.14 1995/12/13 14:03:01 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.13 1995/11/07 23:15:26 grier
+ * memcpy() casts
+ *
+ * Revision 1.12 1995/05/25 18:35:59 bjaspan
+ * [secure-rpc/3103] log misc errors from RPC
+ *
+ * Revision 1.11 1994/10/27 12:39:14 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.11 1994/10/26 20:04:00 bjaspan
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.10 1993/11/12 02:32:50 bjaspan
+ * add badauth, don't use const_gss_OID
+ *
+ * Revision 1.9 1993/11/03 23:46:15 bjaspan
+ * new log_badverf format
+ *
+ * Revision 1.8 1993/11/03 21:21:38 bjaspan
+ * added log_badverf
+ *
+ * Revision 1.7 1993/11/03 01:29:56 bjaspan
+ * add const to gss_nt_*
+ *
+ */
+
+#define AUTH_GSSAPI_EXIT 0
+#define AUTH_GSSAPI_INIT 1
+#define AUTH_GSSAPI_CONTINUE_INIT 2
+#define AUTH_GSSAPI_MSG 3
+#define AUTH_GSSAPI_DESTROY 4
+
+typedef struct _auth_gssapi_name {
+ char *name;
+ gss_OID type;
+} auth_gssapi_name;
+
+typedef struct _auth_gssapi_creds {
+ rpc_u_int32 version;
+ bool_t auth_msg;
+ gss_buffer_desc client_handle;
+} auth_gssapi_creds;
+
+typedef struct _auth_gssapi_init_arg {
+ rpc_u_int32 version;
+ gss_buffer_desc token;
+} auth_gssapi_init_arg;
+
+typedef struct _auth_gssapi_init_res {
+ rpc_u_int32 version;
+ gss_buffer_desc client_handle;
+ OM_uint32 gss_major, gss_minor;
+ gss_buffer_desc token;
+ gss_buffer_desc signed_isn;
+} auth_gssapi_init_res;
+
+typedef void (*auth_gssapi_log_badauth_func)(OM_uint32 major,
+ OM_uint32 minor,
+ struct sockaddr_in *raddr,
+ caddr_t data);
+
+typedef void (*auth_gssapi_log_badverf_func)(gss_name_t client,
+ gss_name_t server,
+ struct svc_req *rqst,
+ struct rpc_msg *msg,
+ caddr_t data);
+
+typedef void (*auth_gssapi_log_miscerr_func)(struct svc_req *rqst,
+ struct rpc_msg *msg,
+ char *error,
+ caddr_t data);
+
+bool_t xdr_authgssapi_creds();
+bool_t xdr_authgssapi_init_arg();
+bool_t xdr_authgssapi_init_res();
+
+bool_t auth_gssapi_wrap_data(OM_uint32 *major, OM_uint32 *minor,
+ gss_ctx_id_t context, rpc_u_int32 seq_num, XDR
+ *out_xdrs, bool_t (*xdr_func)(), caddr_t
+ xdr_ptr);
+bool_t auth_gssapi_unwrap_data(OM_uint32 *major, OM_uint32 *minor,
+ gss_ctx_id_t context, rpc_u_int32 seq_num, XDR
+ *in_xdrs, bool_t (*xdr_func)(), caddr_t
+ xdr_ptr);
+
+AUTH *auth_gssapi_create(CLIENT *clnt,
+ OM_uint32 *major_status,
+ OM_uint32 *minor_status,
+ gss_cred_id_t claimant_cred_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ int req_flags,
+ OM_uint32 time_req,
+ gss_OID *actual_mech_type,
+ int *ret_flags,
+ OM_uint32 *time_rec);
+
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name);
+
+void auth_gssapi_display_status(char *msg, OM_uint32 major,
+ OM_uint32 minor);
+bool_t _svcauth_gssapi_set_name(char *name, gss_OID name_type);
+
+void _svcauth_set_log_badauth_func(auth_gssapi_log_badauth_func func,
+ caddr_t data);
+void _svcauth_set_log_badverf_func(auth_gssapi_log_badverf_func func,
+ caddr_t data);
+void _svcauth_set_log_miscerr_func(auth_gssapi_log_miscerr_func func,
+ caddr_t data);
+
+#define GSS_COPY_BUFFER(dest, src) { \
+ (dest).length = (src).length; \
+ (dest).value = (src).value; }
+
+#define GSS_DUP_BUFFER(dest, src) { \
+ (dest).length = (src).length; \
+ (dest).value = (void *) malloc((dest).length); \
+ memcpy((dest).value, (src).value, (dest).length); }
+
+#define GSS_BUFFERS_EQUAL(b1, b2) (((b1).length == (b2).length) && \
+ !memcmp((b1).value,(b2).value,(b1.length)))
+
diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c
new file mode 100644
index 000000000..bd7b6e5a3
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi_misc.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.14 1996/07/22 20:39:44 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.13.4.1 1996/07/18 04:18:32 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.13.2.1 1996/06/20 23:35:49 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.13 1996/05/12 06:11:38 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.12 1996/02/25 15:53:57 grier
+ * [secure/3570]
+ * OSF1 long changes
+ *
+ * Revision 1.11 1995/12/13 14:03:30 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.10 1994/10/27 12:39:23 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] back out the backwards compat hack (I only put it
+ * there in case we ever decide we want it, which we won't) and just
+ * handle the version field as if it were always there
+ *
+ * [secure-rpc/2808] add a backwards-compatible version field encoder
+ *
+ * change to use GSS_ERROR &c macros; I don't think this is correct
+ * =============================================================================
+ *
+ * Revision 1.12 1994/10/26 19:48:45 bjaspan
+ * [secure-rpc/2808] back out the backwards compat hack (I only put it
+ * there in case we ever decide we want it, which we won't) and just
+ * handle the version field as if it were always there
+ *
+ * Revision 1.11 1994/10/26 19:47:42 bjaspan
+ * [secure-rpc/2808] add a backwards-compatible version field encoder
+ *
+ * Revision 1.10 1993/12/19 22:19:40 bjaspan
+ * [secure-rpc/1077] use free instead of xdr_free(xdr_bytes,...) because
+ * xdr_bytes takes non-standard arguments
+ *
+ * Revision 1.9 1993/12/08 21:43:37 bjaspan
+ * use AUTH_GSSAPI_DISPLAY_STATUS macro, reindent
+ *
+ * Revision 1.8 1993/12/06 21:21:21 bjaspan
+ * debugging levels
+ *
+ * Revision 1.7 1993/11/03 23:46:34 bjaspan
+ * add debugging printfs showing amount of data wrapped/unwrapped
+ *
+ * Revision 1.6 1993/11/03 21:21:53 bjaspan
+ * unstatic misc_debug_gssapi
+ *
+ * Revision 1.5 1993/11/01 19:55:54 bjaspan
+ * improve display_status messages, and include gss_{major,minor}
+ *
+ * Revision 1.4 1993/10/28 22:08:21 bjaspan
+ * wrap/unwrap_data include sequence number in arg/result block
+ *
+ * Revision 1.3 1993/10/27 18:26:16 bjaspan
+ * use xdr_free instead of free(in_buf.value); doesn't actually make a
+ * difference, though
+ *
+ * Revision 1.2 1993/10/26 21:12:38 bjaspan
+ * cleaning
+ *
+ * Revision 1.1 1993/10/19 03:12:28 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/rpc.h>
+#include <stdio.h>
+
+#include <gssapi/gssapi.h>
+#include <rpc/auth_gssapi.h>
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int misc_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (misc_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (misc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+static void auth_gssapi_display_status_1(char *, OM_uint32, int, int);
+
+bool_t xdr_gss_buf(xdrs, buf)
+ XDR *xdrs;
+ gss_buffer_t buf;
+{
+ /*
+ * On decode, xdr_bytes will only allocate buf->value if the
+ * length read in is < maxsize (last arg). This is dumb, because
+ * the whole point of allocating memory is so that I don't *have*
+ * to know the maximum length. -1 effectively disables this
+ * braindamage.
+ */
+ return xdr_bytes(xdrs, (char **) &buf->value, (unsigned int *) &buf->length,
+ (xdrs->x_op == XDR_DECODE && buf->value == NULL)
+ ? (unsigned int) -1 : (unsigned int) buf->length);
+}
+
+bool_t xdr_authgssapi_creds(xdrs, creds)
+ XDR *xdrs;
+ auth_gssapi_creds *creds;
+{
+ if (! xdr_u_int32(xdrs, &creds->version) ||
+ ! xdr_bool(xdrs, &creds->auth_msg) ||
+ ! xdr_gss_buf(xdrs, &creds->client_handle))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t xdr_authgssapi_init_arg(xdrs, init_arg)
+ XDR *xdrs;
+ auth_gssapi_init_arg *init_arg;
+{
+ if (! xdr_u_int32(xdrs, &init_arg->version) ||
+ ! xdr_gss_buf(xdrs, &init_arg->token))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t xdr_authgssapi_init_res(xdrs, init_res)
+ XDR *xdrs;
+ auth_gssapi_init_res *init_res;
+{
+ if (! xdr_u_int32(xdrs, &init_res->version) ||
+ ! xdr_gss_buf(xdrs, &init_res->client_handle) ||
+ ! xdr_u_int32(xdrs, &init_res->gss_major) ||
+ ! xdr_u_int32(xdrs, &init_res->gss_minor) ||
+ ! xdr_gss_buf(xdrs, &init_res->token) ||
+ ! xdr_gss_buf(xdrs, &init_res->signed_isn))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t auth_gssapi_seal_seq(context, seq_num, out_buf)
+ gss_ctx_id_t context;
+ rpc_u_int32 seq_num;
+ gss_buffer_t out_buf;
+{
+ gss_buffer_desc in_buf;
+ OM_uint32 gssstat, minor_stat;
+ rpc_u_int32 nl_seq_num;
+
+ nl_seq_num = htonl(seq_num);
+
+ in_buf.length = sizeof(rpc_u_int32);
+ in_buf.value = (char *) &nl_seq_num;
+ gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
+ &in_buf, NULL, out_buf);
+ if (gssstat != GSS_S_COMPLETE) {
+ PRINTF(("gssapi_seal_seq: failed\n"));
+ AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
+ gssstat, minor_stat));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool_t auth_gssapi_unseal_seq(context, in_buf, seq_num)
+ gss_ctx_id_t context;
+ gss_buffer_t in_buf;
+ rpc_u_int32 *seq_num;
+{
+ gss_buffer_desc out_buf;
+ OM_uint32 gssstat, minor_stat;
+ rpc_u_int32 nl_seq_num;
+
+ gssstat = gss_unseal(&minor_stat, context, in_buf, &out_buf,
+ NULL, NULL);
+ if (gssstat != GSS_S_COMPLETE) {
+ PRINTF(("gssapi_unseal_seq: failed\n"));
+ AUTH_GSSAPI_DISPLAY_STATUS(("unsealing sequence number",
+ gssstat, minor_stat));
+ return FALSE;
+ } else if (out_buf.length != sizeof(rpc_u_int32)) {
+ PRINTF(("gssapi_unseal_seq: unseal gave %d bytes\n",
+ out_buf.length));
+ gss_release_buffer(&minor_stat, &out_buf);
+ return FALSE;
+ }
+
+ nl_seq_num = *((rpc_u_int32 *) out_buf.value);
+ *seq_num = (rpc_u_int32) ntohl(nl_seq_num);
+ gss_release_buffer(&minor_stat, &out_buf);
+
+ return TRUE;
+}
+
+void auth_gssapi_display_status(char *msg, OM_uint32 major, OM_uint32 minor)
+{
+ auth_gssapi_display_status_1(msg, major, GSS_C_GSS_CODE, 0);
+ auth_gssapi_display_status_1(msg, minor, GSS_C_MECH_CODE, 0);
+}
+
+static void auth_gssapi_display_status_1(char *m, OM_uint32 code, int type,
+ int rec)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc msg;
+ int msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ gssstat = gss_display_status(&minor_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg);
+ if (gssstat != GSS_S_COMPLETE) {
+ if (!rec) {
+ auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1);
+ auth_gssapi_display_status_1(m, minor_stat,
+ GSS_C_MECH_CODE, 1);
+ } else
+ fprintf(stderr,"GSS-API authentication error %s: "
+ "recursive failure!\n", msg);
+ return;
+ }
+
+ fprintf(stderr, "GSS-API authentication error %s: %s\n", m,
+ (char *)msg.value);
+ (void) gss_release_buffer(&minor_stat, &msg);
+
+ if (!msg_ctx)
+ break;
+ }
+}
+
+bool_t auth_gssapi_wrap_data(major, minor, context, seq_num, out_xdrs,
+ xdr_func, xdr_ptr)
+ OM_uint32 *major, *minor;
+ gss_ctx_id_t context;
+ rpc_u_int32 seq_num;
+ XDR *out_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ gss_buffer_desc in_buf, out_buf;
+ XDR temp_xdrs;
+ int conf_state;
+
+ PRINTF(("gssapi_wrap_data: starting\n"));
+
+ *major = GSS_S_COMPLETE;
+ *minor = 0; /* assumption */
+
+ xdralloc_create(&temp_xdrs, XDR_ENCODE);
+
+ /* serialize the sequence number into local memory */
+ PRINTF(("gssapi_wrap_data: encoding seq_num %d\n", seq_num));
+ if (! xdr_u_int32(&temp_xdrs, &seq_num)) {
+ PRINTF(("gssapi_wrap_data: serializing seq_num failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ /* serialize the arguments into local memory */
+ if (!(*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ PRINTF(("gssapi_wrap_data: serializing arguments failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ in_buf.length = xdr_getpos(&temp_xdrs);
+ in_buf.value = xdralloc_getdata(&temp_xdrs);
+
+ *major = gss_seal(minor, context, 1,
+ GSS_C_QOP_DEFAULT, &in_buf, &conf_state,
+ &out_buf);
+ if (*major != GSS_S_COMPLETE) {
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ PRINTF(("gssapi_wrap_data: %d bytes data, %d bytes sealed\n",
+ in_buf.length, out_buf.length));
+
+ /* write the token */
+ if (! xdr_bytes(out_xdrs, (char **) &out_buf.value,
+ (unsigned int *) &out_buf.length,
+ out_buf.length)) {
+ PRINTF(("gssapi_wrap_data: serializing encrypted data failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ *major = gss_release_buffer(minor, &out_buf);
+
+ PRINTF(("gssapi_wrap_data: succeeding\n\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return TRUE;
+}
+
+bool_t auth_gssapi_unwrap_data(major, minor, context, seq_num,
+ in_xdrs, xdr_func, xdr_ptr)
+ OM_uint32 *major, *minor;
+ gss_ctx_id_t context;
+ rpc_u_int32 seq_num;
+ XDR *in_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ gss_buffer_desc in_buf, out_buf;
+ XDR temp_xdrs;
+ rpc_u_int32 verf_seq_num;
+ int conf, qop;
+
+ PRINTF(("gssapi_unwrap_data: starting\n"));
+
+ *major = GSS_S_COMPLETE;
+ *minor = 0; /* assumption */
+
+ in_buf.value = NULL;
+ out_buf.value = NULL;
+
+ if (! xdr_bytes(in_xdrs, (char **) &in_buf.value,
+ (unsigned int *) &in_buf.length, (unsigned int) -1)) {
+ PRINTF(("gssapi_unwrap_data: deserializing encrypted data failed\n"));
+ return FALSE;
+ }
+
+ *major = gss_unseal(minor, context, &in_buf, &out_buf, &conf,
+ &qop);
+ free(in_buf.value);
+ if (*major != GSS_S_COMPLETE)
+ return FALSE;
+
+ PRINTF(("gssapi_unwrap_data: %d bytes data, %d bytes sealed\n",
+ out_buf.length, in_buf.length));
+
+ xdrmem_create(&temp_xdrs, out_buf.value, out_buf.length, XDR_DECODE);
+
+ /* deserialize the sequence number */
+ if (! xdr_u_int32(&temp_xdrs, &verf_seq_num)) {
+ PRINTF(("gssapi_unwrap_data: deserializing verf_seq_num failed\n"));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+ if (verf_seq_num != seq_num) {
+ PRINTF(("gssapi_unwrap_data: seq %d specified, read %d\n",
+ seq_num, verf_seq_num));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+ PRINTF(("gssapi_unwrap_data: unwrap seq_num %d okay\n", verf_seq_num));
+
+ /* deserialize the arguments into xdr_ptr */
+ if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ PRINTF(("gssapi_unwrap_data: succeeding\n\n"));
+
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return TRUE;
+}
diff --git a/src/lib/rpc/auth_none.c b/src/lib/rpc/auth_none.c
new file mode 100644
index 000000000..90f3bb8be
--- /dev/null
+++ b/src/lib/rpc/auth_none.c
@@ -0,0 +1,136 @@
+/* @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <stdlib.h>
+#define MAX_MARSHEL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+static void authnone_verf();
+static void authnone_destroy();
+static bool_t authnone_marshal();
+static bool_t authnone_validate();
+static bool_t authnone_refresh();
+
+static struct auth_ops ops = {
+ authnone_verf,
+ authnone_marshal,
+ authnone_validate,
+ authnone_refresh,
+ authnone_destroy,
+ authany_wrap,
+ authany_wrap,
+};
+
+static struct authnone_private {
+ AUTH no_client;
+ char marshalled_client[MAX_MARSHEL_SIZE];
+ unsigned int mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create()
+{
+ register struct authnone_private *ap = authnone_private;
+ XDR xdr_stream;
+ register XDR *xdrs;
+
+ if (ap == 0) {
+ ap = (struct authnone_private *)calloc(1, sizeof (*ap));
+ if (ap == 0)
+ return (0);
+ authnone_private = ap;
+ }
+ if (!ap->mcnt) {
+ ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
+ ap->no_client.ah_ops = &ops;
+ xdrs = &xdr_stream;
+ xdrmem_create(xdrs, ap->marshalled_client, (unsigned int)MAX_MARSHEL_SIZE,
+ XDR_ENCODE);
+ (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
+ (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
+ ap->mcnt = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+ }
+ return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(client, xdrs)
+ AUTH *client;
+ XDR *xdrs;
+{
+ register struct authnone_private *ap = authnone_private;
+
+ if (ap == 0)
+ return (0);
+ return ((*xdrs->x_ops->x_putbytes)(xdrs,
+ ap->marshalled_client, ap->mcnt));
+}
+
+static void
+authnone_verf()
+{
+}
+
+static bool_t
+authnone_validate()
+{
+
+ return (TRUE);
+}
+
+static bool_t
+authnone_refresh()
+{
+
+ return (FALSE);
+}
+
+static void
+authnone_destroy()
+{
+}
diff --git a/src/lib/rpc/auth_unix.c b/src/lib/rpc/auth_unix.c
new file mode 100644
index 000000000..b41e442fc
--- /dev/null
+++ b/src/lib/rpc/auth_unix.c
@@ -0,0 +1,322 @@
+/* @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The system is very weak. The client uses no encryption for it's
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ *
+ */
+
+#include <stdio.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+
+
+/*
+ * Unix authenticator operations vector
+ */
+static void authunix_nextverf();
+static bool_t authunix_marshal();
+static bool_t authunix_validate();
+static bool_t authunix_refresh();
+static void authunix_destroy();
+
+static struct auth_ops auth_unix_ops = {
+ authunix_nextverf,
+ authunix_marshal,
+ authunix_validate,
+ authunix_refresh,
+ authunix_destroy,
+ authany_wrap,
+ authany_wrap,
+};
+
+/*
+ * This struct is pointed to by the ah_private field of an auth_handle.
+ */
+struct audata {
+ struct opaque_auth au_origcred; /* original credentials */
+ struct opaque_auth au_shcred; /* short hand cred */
+ rpc_u_int32 au_shfaults; /* short hand cache faults */
+ char au_marshed[MAX_AUTH_BYTES];
+ unsigned int au_mpos; /* xdr pos at end of marshed */
+};
+#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
+
+static bool_t marshal_new_auth();
+
+
+/*
+ * Create a unix style authenticator.
+ * Returns an auth handle with the given stuff in it.
+ */
+AUTH *
+authunix_create(machname, uid, gid, len, aup_gids)
+ char *machname;
+ int uid;
+ int gid;
+ register int len;
+ int *aup_gids;
+{
+ struct authunix_parms aup;
+ char mymem[MAX_AUTH_BYTES];
+ struct timeval now;
+ XDR xdrs;
+ register AUTH *auth;
+ register struct audata *au;
+
+ /*
+ * Allocate and set up auth handle
+ */
+ auth = (AUTH *)mem_alloc(sizeof(*auth));
+#ifndef KERNEL
+ if (auth == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ au = (struct audata *)mem_alloc(sizeof(*au));
+#ifndef KERNEL
+ if (au == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ auth->ah_ops = &auth_unix_ops;
+ auth->ah_private = (caddr_t)au;
+ auth->ah_verf = au->au_shcred = _null_auth;
+ au->au_shfaults = 0;
+
+ /*
+ * fill in param struct from the given params
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ aup.aup_time = now.tv_sec;
+ aup.aup_machname = machname;
+ aup.aup_uid = uid;
+ aup.aup_gid = gid;
+ aup.aup_len = (unsigned int)len;
+ aup.aup_gids = aup_gids;
+
+ /*
+ * Serialize the parameters into origcred
+ */
+ xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+ if (! xdr_authunix_parms(&xdrs, &aup))
+ abort();
+ au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
+ au->au_origcred.oa_flavor = AUTH_UNIX;
+#ifdef KERNEL
+ au->au_origcred.oa_base = mem_alloc((unsigned int) len);
+#else
+ if ((au->au_origcred.oa_base = mem_alloc((unsigned int) len)) == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ memmove(au->au_origcred.oa_base, mymem, (unsigned int)len);
+
+ /*
+ * set auth handle to reflect new cred.
+ */
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+ return (auth);
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default()
+{
+ register int len;
+ char machname[MAX_MACHINE_NAME + 1];
+ register int uid;
+ register int gid;
+ int gids[NGRPS];
+
+ if (gethostname(machname, MAX_MACHINE_NAME) == -1)
+ abort();
+ machname[MAX_MACHINE_NAME] = 0;
+ uid = geteuid();
+ gid = getegid();
+ if ((len = getgroups(NGRPS, gids)) < 0)
+ abort();
+ return (authunix_create(machname, uid, gid, len, gids));
+}
+
+/*
+ * authunix operations
+ */
+
+static void
+authunix_nextverf(auth)
+ AUTH *auth;
+{
+ /* no action necessary */
+}
+
+static bool_t
+authunix_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(auth, verf)
+ register AUTH *auth;
+ struct opaque_auth verf;
+{
+ register struct audata *au;
+ XDR xdrs;
+
+ if (verf.oa_flavor == AUTH_SHORT) {
+ au = AUTH_PRIVATE(auth);
+ xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
+
+ if (au->au_shcred.oa_base != NULL) {
+ mem_free(au->au_shcred.oa_base,
+ au->au_shcred.oa_length);
+ au->au_shcred.oa_base = NULL;
+ }
+ if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
+ auth->ah_cred = au->au_shcred;
+ } else {
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
+ au->au_shcred.oa_base = NULL;
+ auth->ah_cred = au->au_origcred;
+ }
+ marshal_new_auth(auth);
+ }
+ return (TRUE);
+}
+
+static bool_t
+authunix_refresh(auth)
+ register AUTH *auth;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+ struct authunix_parms aup;
+ struct timeval now;
+ XDR xdrs;
+ register int stat;
+
+ if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
+ /* there is no hope. Punt */
+ return (FALSE);
+ }
+ au->au_shfaults ++;
+
+ /* first deserialize the creds back into a struct authunix_parms */
+ aup.aup_machname = NULL;
+ aup.aup_gids = (int *)NULL;
+ xdrmem_create(&xdrs, au->au_origcred.oa_base,
+ au->au_origcred.oa_length, XDR_DECODE);
+ stat = xdr_authunix_parms(&xdrs, &aup);
+ if (! stat)
+ goto done;
+
+ /* update the time and serialize in place */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ aup.aup_time = now.tv_sec;
+ xdrs.x_op = XDR_ENCODE;
+ XDR_SETPOS(&xdrs, 0);
+ stat = xdr_authunix_parms(&xdrs, &aup);
+ if (! stat)
+ goto done;
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+done:
+ /* free the struct authunix_parms created by deserializing */
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_authunix_parms(&xdrs, &aup);
+ XDR_DESTROY(&xdrs);
+ return (stat);
+}
+
+static void
+authunix_destroy(auth)
+ register AUTH *auth;
+{
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+
+ if (au->au_shcred.oa_base != NULL)
+ mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+
+ mem_free(auth->ah_private, sizeof(struct audata));
+
+ if (auth->ah_verf.oa_base != NULL)
+ mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+
+ mem_free((caddr_t)auth, sizeof(*auth));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static bool_t
+marshal_new_auth(auth)
+ register AUTH *auth;
+{
+ XDR xdr_stream;
+ register XDR *xdrs = &xdr_stream;
+ register struct audata *au = AUTH_PRIVATE(auth);
+
+ xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+ if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
+ (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
+ perror("auth_none.c - Fatal marshalling problem");
+ } else {
+ au->au_mpos = XDR_GETPOS(xdrs);
+ }
+ XDR_DESTROY(xdrs);
+}
diff --git a/src/lib/rpc/auth_unix.h b/src/lib/rpc/auth_unix.h
new file mode 100644
index 000000000..4b54f1db6
--- /dev/null
+++ b/src/lib/rpc/auth_unix.h
@@ -0,0 +1,72 @@
+/* @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)auth_unix.h 1.5 86/07/16 SMI */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * The system is very weak. The client uses no encryption for it
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ */
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+ rpc_u_int32 aup_time;
+ char *aup_machname;
+ int aup_uid;
+ int aup_gid;
+ unsigned int aup_len;
+ int *aup_gids;
+};
+
+extern bool_t xdr_authunix_parms();
+
+/*
+ * If a response verifier has flavor AUTH_SHORT,
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+ struct opaque_auth new_cred;
+};
diff --git a/src/lib/rpc/authunix_prot.c b/src/lib/rpc/authunix_prot.c
new file mode 100644
index 000000000..36770f298
--- /dev/null
+++ b/src/lib/rpc/authunix_prot.c
@@ -0,0 +1,66 @@
+/* @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(xdrs, p)
+ register XDR *xdrs;
+ register struct authunix_parms *p;
+{
+
+ if (xdr_u_int32(xdrs, &(p->aup_time))
+ && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
+ && xdr_int(xdrs, &(p->aup_uid))
+ && xdr_int(xdrs, &(p->aup_gid))
+ && xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
+ &(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
diff --git a/src/lib/rpc/bindresvport.c b/src/lib/rpc/bindresvport.c
new file mode 100644
index 000000000..875aeefb6
--- /dev/null
+++ b/src/lib/rpc/bindresvport.c
@@ -0,0 +1,79 @@
+static char sccsid[] = "@(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC 1.8 88/02/08 SMI";
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+bindresvport(sd, sin)
+ int sd;
+ struct sockaddr_in *sin;
+{
+ int res;
+ static short port;
+ struct sockaddr_in myaddr;
+ extern int errno;
+ int i;
+
+#define STARTPORT 600
+#define ENDPORT (IPPORT_RESERVED - 1)
+#define NPORTS (ENDPORT - STARTPORT + 1)
+
+ if (sin == (struct sockaddr_in *)0) {
+ sin = &myaddr;
+ memset(sin, 0, sizeof (*sin));
+ sin->sin_family = AF_INET;
+ } else if (sin->sin_family != AF_INET) {
+ errno = EPFNOSUPPORT;
+ return (-1);
+ }
+ if (port == 0) {
+ port = (getpid() % NPORTS) + STARTPORT;
+ }
+ res = -1;
+ errno = EADDRINUSE;
+ for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
+ sin->sin_port = htons(port++);
+ if (port > ENDPORT) {
+ port = STARTPORT;
+ }
+ res = bind(sd, (struct sockaddr *) sin,
+ sizeof(struct sockaddr_in));
+ }
+ return (res);
+}
diff --git a/src/lib/rpc/clnt.h b/src/lib/rpc/clnt.h
new file mode 100644
index 000000000..442a96d44
--- /dev/null
+++ b/src/lib/rpc/clnt.h
@@ -0,0 +1,335 @@
+/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _CLNT_
+#define _CLNT_
+
+/*
+ * Rpc calls return an enum clnt_stat. This should be looked at more,
+ * since each implementation is required to live with this (implementation
+ * independent) list of errors.
+ */
+enum clnt_stat {
+ RPC_SUCCESS=0, /* call succeeded */
+ /*
+ * local errors
+ */
+ RPC_CANTENCODEARGS=1, /* can't encode arguments */
+ RPC_CANTDECODERES=2, /* can't decode results */
+ RPC_CANTSEND=3, /* failure in sending call */
+ RPC_CANTRECV=4, /* failure in receiving result */
+ RPC_TIMEDOUT=5, /* call timed out */
+ /*
+ * remote errors
+ */
+ RPC_VERSMISMATCH=6, /* rpc versions not compatible */
+ RPC_AUTHERROR=7, /* authentication error */
+ RPC_PROGUNAVAIL=8, /* program not available */
+ RPC_PROGVERSMISMATCH=9, /* program version mismatched */
+ RPC_PROCUNAVAIL=10, /* procedure unavailable */
+ RPC_CANTDECODEARGS=11, /* decode arguments error */
+ RPC_SYSTEMERROR=12, /* generic "other problem" */
+
+ /*
+ * callrpc & clnt_create errors
+ */
+ RPC_UNKNOWNHOST=13, /* unknown host name */
+ RPC_UNKNOWNPROTO=17, /* unkown protocol */
+
+ /*
+ * _ create errors
+ */
+ RPC_PMAPFAILURE=14, /* the pmapper failed in its call */
+ RPC_PROGNOTREGISTERED=15, /* remote program is not registered */
+ /*
+ * unspecified error
+ */
+ RPC_FAILED=16
+};
+
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+ enum clnt_stat re_status;
+ union {
+ int RE_errno; /* realated system error */
+ enum auth_stat RE_why; /* why the auth error occurred */
+ struct {
+ rpc_u_int32 low; /* lowest verion supported */
+ rpc_u_int32 high; /* highest verion supported */
+ } RE_vers;
+ struct { /* maybe meaningful if RPC_FAILED */
+ rpc_int32 s1;
+ rpc_int32 s2;
+ } RE_lb; /* life boot & debugging only */
+ } ru;
+#define re_errno ru.RE_errno
+#define re_why ru.RE_why
+#define re_vers ru.RE_vers
+#define re_lb ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations, see e.g. rpc_udp.c.
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct {
+ AUTH *cl_auth; /* authenticator */
+ struct clnt_ops {
+ enum clnt_stat (*cl_call)(); /* call remote procedure */
+ void (*cl_abort)(); /* abort a call */
+ void (*cl_geterr)(); /* get specific error code */
+ bool_t (*cl_freeres)(); /* frees results */
+ void (*cl_destroy)();/* destroy this structure */
+ bool_t (*cl_control)();/* the ioctl() of rpc */
+ } *cl_ops;
+ caddr_t cl_private; /* private stuff */
+} CLIENT;
+
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * CLIENT *rh;
+ * rpc_u_int32 proc;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ * struct timeval timeout;
+ */
+#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * CLIENT *rh;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ */
+#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ * CLIENT *cl;
+ * unsigned int request;
+ * char *info;
+ */
+#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to both udp and tcp transports
+ */
+#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
+#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
+/*
+ * udp only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
+/*
+ * new control operations
+ */
+#define CLGET_LOCAL_ADDR 6 /* get local address (sockaddr, getsockname)*/
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+
+
+/*
+ * RPCTEST is a test program which is accessable on every rpc
+ * transport/port. It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM ((rpc_u_int32)1)
+#define RPCTEST_VERSION ((rpc_u_int32)1)
+#define RPCTEST_NULL_PROC ((rpc_u_int32)2)
+#define RPCTEST_NULL_BATCH_PROC ((rpc_u_int32)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((rpc_u_int32)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc. They can return NULL if a
+ * creation failure occurs.
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clntraw_create(prog, vers)
+ * rpc_u_int32 prog;
+ * rpc_u_int32 vers;
+ */
+extern CLIENT *clntraw_create();
+
+
+/*
+ * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ */
+extern CLIENT *
+clnt_create(/*host, prog, vers, prot*/); /*
+ char *host; -- hostname
+ rpc_u_int32 prog; -- program number
+ rpc_u_int32 vers; -- version number
+ char *prot; -- protocol
+*/
+
+
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * rpc_u_int32 prog;
+ * rpc_u_int32 version;
+ * register int *sockp;
+ * unsigned int sendsz;
+ * unsigned int recvsz;
+ */
+extern CLIENT *clnttcp_create();
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * rpc_u_int32 program;
+ * rpc_u_int32 version;
+ * struct timeval wait;
+ * int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * rpc_u_int32 program;
+ * rpc_u_int32 version;
+ * struct timeval wait;
+ * int *sockp;
+ * unsigned int sendsz;
+ * unsigned int recvsz;
+ */
+extern CLIENT *clntudp_create();
+extern CLIENT *clntudp_bufcreate();
+
+/*
+ * Print why creation failed
+ */
+void clnt_pcreateerror(/* char *msg */); /* stderr */
+char *clnt_spcreateerror(/* char *msg */); /* string */
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */
+void clnt_perrno(/* enum clnt_stat num */); /* stderr */
+
+/*
+ * Print an English error message, given the client error code
+ */
+void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */
+char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */
+
+/*
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+ enum clnt_stat cf_stat;
+ struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+extern struct rpc_createerr rpc_createerr;
+
+
+
+/*
+ * Copy error message to buffer.
+ */
+char *clnt_sperrno(/* enum clnt_stat num */); /* string */
+
+
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+#endif /*!_CLNT_*/
diff --git a/src/lib/rpc/clnt_generic.c b/src/lib/rpc/clnt_generic.c
new file mode 100644
index 000000000..f111c2e14
--- /dev/null
+++ b/src/lib/rpc/clnt_generic.c
@@ -0,0 +1,110 @@
+/* @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
+#endif
+/*
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ */
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <netdb.h>
+
+/*
+ * Generic client creation: takes (hostname, program-number, protocol) and
+ * returns client handle. Default options are set, which the user can
+ * change using the rpc equivalent of ioctl()'s.
+ */
+CLIENT *
+clnt_create(hostname, prog, vers, proto)
+ char *hostname;
+ unsigned prog;
+ unsigned vers;
+ char *proto;
+{
+ struct hostent *h;
+ struct protoent *p;
+ struct sockaddr_in sin;
+ int sock;
+ struct timeval tv;
+ CLIENT *client;
+
+ h = gethostbyname(hostname);
+ if (h == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+ return (NULL);
+ }
+ if (h->h_addrtype != AF_INET) {
+ /*
+ * Only support INET for now
+ */
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ sin.sin_family = h->h_addrtype;
+ sin.sin_port = 0;
+ memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
+ memmove((char*)&sin.sin_addr, h->h_addr, h->h_length);
+ p = getprotobyname(proto);
+ if (p == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ return (NULL);
+ }
+ sock = RPC_ANYSOCK;
+ switch (p->p_proto) {
+ case IPPROTO_UDP:
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ client = clntudp_create(&sin, prog, vers, tv, &sock);
+ if (client == NULL) {
+ return (NULL);
+ }
+ tv.tv_sec = 25;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+ break;
+ case IPPROTO_TCP:
+ client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);
+ if (client == NULL) {
+ return (NULL);
+ }
+ tv.tv_sec = 25;
+ tv.tv_usec = 0;
+ clnt_control(client, CLSET_TIMEOUT, &tv);
+ break;
+ default:
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
+ return (NULL);
+ }
+ return (client);
+}
diff --git a/src/lib/rpc/clnt_perror.c b/src/lib/rpc/clnt_perror.c
new file mode 100644
index 000000000..63eef49f0
--- /dev/null
+++ b/src/lib/rpc/clnt_perror.c
@@ -0,0 +1,306 @@
+/* @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+static char *auth_errmsg();
+
+extern char *strcpy();
+
+static char *buf;
+
+static char *
+_buf()
+{
+
+ if (buf == 0)
+ buf = (char *)malloc(256);
+ return (buf);
+}
+
+/*
+ * Print reply error info
+ */
+char *
+clnt_sperror(rpch, s)
+ CLIENT *rpch;
+ char *s;
+{
+ struct rpc_err e;
+ void clnt_perrno();
+ char *err;
+ char *str = _buf();
+ char *strstart = str;
+
+ if (str == 0)
+ return (0);
+ CLNT_GETERR(rpch, &e);
+
+ (void) sprintf(str, "%s: ", s);
+ str += strlen(str);
+
+ (void) strcpy(str, clnt_sperrno(e.re_status));
+ str += strlen(str);
+
+ switch (e.re_status) {
+ case RPC_SUCCESS:
+ case RPC_CANTENCODEARGS:
+ case RPC_CANTDECODERES:
+ case RPC_TIMEDOUT:
+ case RPC_PROGUNAVAIL:
+ case RPC_PROCUNAVAIL:
+ case RPC_CANTDECODEARGS:
+ case RPC_SYSTEMERROR:
+ case RPC_UNKNOWNHOST:
+ case RPC_UNKNOWNPROTO:
+ case RPC_PMAPFAILURE:
+ case RPC_PROGNOTREGISTERED:
+ case RPC_FAILED:
+ break;
+
+ case RPC_CANTSEND:
+ case RPC_CANTRECV:
+ (void) sprintf(str, "; errno = %s",
+ sys_errlist[e.re_errno]);
+ str += strlen(str);
+ break;
+
+ case RPC_VERSMISMATCH:
+ (void) sprintf(str,
+ "; low version = %lu, high version = %lu",
+ e.re_vers.low, e.re_vers.high);
+ str += strlen(str);
+ break;
+
+ case RPC_AUTHERROR:
+ err = auth_errmsg(e.re_why);
+ (void) sprintf(str,"; why = ");
+ str += strlen(str);
+ if (err != NULL) {
+ (void) sprintf(str, "%s",err);
+ } else {
+ (void) sprintf(str,
+ "(unknown authentication error - %d)",
+ (int) e.re_why);
+ }
+ str += strlen(str);
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ (void) sprintf(str,
+ "; low version = %lu, high version = %lu",
+ e.re_vers.low, e.re_vers.high);
+ str += strlen(str);
+ break;
+
+ default: /* unknown */
+ (void) sprintf(str,
+ "; s1 = %lu, s2 = %lu",
+ e.re_lb.s1, e.re_lb.s2);
+ str += strlen(str);
+ break;
+ }
+ (void) sprintf(str, "\n");
+ return(strstart) ;
+}
+
+void
+clnt_perror(rpch, s)
+ CLIENT *rpch;
+ char *s;
+{
+ (void) fprintf(stderr,"%s",clnt_sperror(rpch,s));
+}
+
+
+struct rpc_errtab {
+ enum clnt_stat status;
+ char *message;
+};
+
+static struct rpc_errtab rpc_errlist[] = {
+ { RPC_SUCCESS,
+ "RPC: Success" },
+ { RPC_CANTENCODEARGS,
+ "RPC: Can't encode arguments" },
+ { RPC_CANTDECODERES,
+ "RPC: Can't decode result" },
+ { RPC_CANTSEND,
+ "RPC: Unable to send" },
+ { RPC_CANTRECV,
+ "RPC: Unable to receive" },
+ { RPC_TIMEDOUT,
+ "RPC: Timed out" },
+ { RPC_VERSMISMATCH,
+ "RPC: Incompatible versions of RPC" },
+ { RPC_AUTHERROR,
+ "RPC: Authentication error" },
+ { RPC_PROGUNAVAIL,
+ "RPC: Program unavailable" },
+ { RPC_PROGVERSMISMATCH,
+ "RPC: Program/version mismatch" },
+ { RPC_PROCUNAVAIL,
+ "RPC: Procedure unavailable" },
+ { RPC_CANTDECODEARGS,
+ "RPC: Server can't decode arguments" },
+ { RPC_SYSTEMERROR,
+ "RPC: Remote system error" },
+ { RPC_UNKNOWNHOST,
+ "RPC: Unknown host" },
+ { RPC_UNKNOWNPROTO,
+ "RPC: Unknown protocol" },
+ { RPC_PMAPFAILURE,
+ "RPC: Port mapper failure" },
+ { RPC_PROGNOTREGISTERED,
+ "RPC: Program not registered"},
+ { RPC_FAILED,
+ "RPC: Failed (unspecified error)"}
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(stat)
+ enum clnt_stat stat;
+{
+ int i;
+
+ for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
+ if (rpc_errlist[i].status == stat) {
+ return (rpc_errlist[i].message);
+ }
+ }
+ return ("RPC: (unknown error code)");
+}
+
+void
+clnt_perrno(num)
+ enum clnt_stat num;
+{
+ (void) fprintf(stderr,"%s",clnt_sperrno(num));
+}
+
+
+char *
+clnt_spcreateerror(s)
+ char *s;
+{
+ extern int sys_nerr;
+ char *str = _buf();
+
+ if (str == 0)
+ return(0);
+ (void) sprintf(str, "%s: ", s);
+ (void) strcat(str, clnt_sperrno(rpc_createerr.cf_stat));
+ switch (rpc_createerr.cf_stat) {
+ case RPC_PMAPFAILURE:
+ (void) strcat(str, " - ");
+ (void) strcat(str,
+ clnt_sperrno(rpc_createerr.cf_error.re_status));
+ break;
+
+ case RPC_SYSTEMERROR:
+ (void) strcat(str, " - ");
+ if (rpc_createerr.cf_error.re_errno > 0
+ && rpc_createerr.cf_error.re_errno < sys_nerr)
+ (void) strcat(str,
+ sys_errlist[rpc_createerr.cf_error.re_errno]);
+ else
+ (void) sprintf(&str[strlen(str)], "Error %d",
+ rpc_createerr.cf_error.re_errno);
+ break;
+ }
+ (void) strcat(str, "\n");
+ return (str);
+}
+
+void
+clnt_pcreateerror(s)
+ char *s;
+{
+ (void) fprintf(stderr,"%s",clnt_spcreateerror(s));
+}
+
+struct auth_errtab {
+ enum auth_stat status;
+ char *message;
+};
+
+static struct auth_errtab auth_errlist[] = {
+ { AUTH_OK,
+ "Authentication OK" },
+ { AUTH_BADCRED,
+ "Invalid client credential" },
+ { AUTH_REJECTEDCRED,
+ "Server rejected credential" },
+ { AUTH_BADVERF,
+ "Invalid client verifier" },
+ { AUTH_REJECTEDVERF,
+ "Server rejected verifier" },
+ { AUTH_TOOWEAK,
+ "Client credential too weak" },
+ { AUTH_INVALIDRESP,
+ "Invalid server verifier" },
+ { AUTH_FAILED,
+ "Failed (unspecified error)" },
+};
+
+static char *
+auth_errmsg(stat)
+ enum auth_stat stat;
+{
+ int i;
+
+ for (i = 0; i < sizeof(auth_errlist)/sizeof(struct auth_errtab); i++) {
+ if (auth_errlist[i].status == stat) {
+ return(auth_errlist[i].message);
+ }
+ }
+ return(NULL);
+}
diff --git a/src/lib/rpc/clnt_raw.c b/src/lib/rpc/clnt_raw.c
new file mode 100644
index 000000000..d05dbaa7e
--- /dev/null
+++ b/src/lib/rpc/clnt_raw.c
@@ -0,0 +1,239 @@
+/* @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_raw.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Memory based rpc for simple testing and timing.
+ * Interface to create an rpc client and server in the same process.
+ * This lets us similate rpc and get round trip overhead, without
+ * any interference from the kernal.
+ */
+
+#include <rpc/rpc.h>
+
+#define MCALL_MSG_SIZE 24
+
+/*
+ * This is the "network" we will be moving stuff over.
+ */
+static struct clntraw_private {
+ CLIENT client_object;
+ XDR xdr_stream;
+ char _raw_buf[UDPMSGSIZE];
+ char mashl_callmsg[MCALL_MSG_SIZE];
+ unsigned int mcnt;
+} *clntraw_private;
+
+static enum clnt_stat clntraw_call();
+static void clntraw_abort();
+static void clntraw_geterr();
+static bool_t clntraw_freeres();
+static bool_t clntraw_control();
+static void clntraw_destroy();
+
+static struct clnt_ops client_ops = {
+ clntraw_call,
+ clntraw_abort,
+ clntraw_geterr,
+ clntraw_freeres,
+ clntraw_destroy,
+ clntraw_control
+};
+
+void svc_getreq();
+
+/*
+ * Create a client handle for memory based rpc.
+ */
+CLIENT *
+clntraw_create(prog, vers)
+ rpc_u_int32 prog;
+ rpc_u_int32 vers;
+{
+ register struct clntraw_private *clp = clntraw_private;
+ struct rpc_msg call_msg;
+ XDR *xdrs = &clp->xdr_stream;
+ CLIENT *client = &clp->client_object;
+
+ if (clp == 0) {
+ clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
+ if (clp == 0)
+ return (0);
+ clntraw_private = clp;
+ }
+ /*
+ * pre-serialize the staic part of the call msg and stash it away
+ */
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+ xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
+ if (! xdr_callhdr(xdrs, &call_msg)) {
+ perror("clnt_raw.c - Fatal header serialization error.");
+ }
+ clp->mcnt = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+
+ /*
+ * Set xdrmem for client/server shared buffer
+ */
+ xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+
+ /*
+ * create client handle
+ */
+ client->cl_ops = &client_ops;
+ client->cl_auth = authnone_create();
+ return (client);
+}
+
+static enum clnt_stat
+clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+ CLIENT *h;
+ rpc_u_int32 proc;
+ xdrproc_t xargs;
+ caddr_t argsp;
+ xdrproc_t xresults;
+ caddr_t resultsp;
+ struct timeval timeout;
+{
+ register struct clntraw_private *clp = clntraw_private;
+ register XDR *xdrs = &clp->xdr_stream;
+ struct rpc_msg msg;
+ enum clnt_stat status;
+ struct rpc_err error;
+ long procl = proc;
+
+ if (clp == 0)
+ return (RPC_FAILED);
+call_again:
+ /*
+ * send request
+ */
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ ((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ;
+ if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
+ (! XDR_PUTLONG(xdrs, &procl)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ return (RPC_CANTENCODEARGS);
+ }
+ (void)XDR_GETPOS(xdrs); /* called just to cause overhead */
+
+ /*
+ * We have to call server input routine here because this is
+ * all going on in one process. Yuk.
+ */
+ svc_getreq(1);
+
+ /*
+ * get results
+ */
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where = resultsp;
+ msg.acpted_rply.ar_results.proc = xresults;
+ if (! xdr_replymsg(xdrs, &msg))
+ return (RPC_CANTDECODERES);
+ sunrpc_seterr_reply(&msg, &error);
+ status = error.re_status;
+
+ if (status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+ status = RPC_AUTHERROR;
+ }
+ } /* end successful completion */
+ else {
+ if (AUTH_REFRESH(h->cl_auth, &msg))
+ goto call_again;
+ } /* end of unsuccessful completion */
+
+ if (status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+ status = RPC_AUTHERROR;
+ }
+ if (msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
+ }
+ }
+
+ return (status);
+}
+
+static void
+clntraw_geterr()
+{
+}
+
+
+static bool_t
+clntraw_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct clntraw_private *clp = clntraw_private;
+ register XDR *xdrs = &clp->xdr_stream;
+ bool_t rval;
+
+ if (clp == 0)
+ {
+ rval = (bool_t) RPC_FAILED;
+ return (rval);
+ }
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntraw_abort()
+{
+}
+
+static bool_t
+clntraw_control()
+{
+ return (FALSE);
+}
+
+static void
+clntraw_destroy()
+{
+}
diff --git a/src/lib/rpc/clnt_simple.c b/src/lib/rpc/clnt_simple.c
new file mode 100644
index 000000000..0d8f7a4df
--- /dev/null
+++ b/src/lib/rpc/clnt_simple.c
@@ -0,0 +1,112 @@
+/* @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+
+static struct callrpc_private {
+ CLIENT *client;
+ int socket;
+ int oldprognum, oldversnum, valid;
+ char *oldhost;
+} *callrpc_private;
+
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+ char *host;
+ xdrproc_t inproc, outproc;
+ char *in, *out;
+{
+ register struct callrpc_private *crp = callrpc_private;
+ struct sockaddr_in server_addr;
+ enum clnt_stat clnt_stat;
+ struct hostent *hp;
+ struct timeval timeout, tottimeout;
+
+ if (crp == 0) {
+ crp = (struct callrpc_private *)calloc(1, sizeof (*crp));
+ if (crp == 0)
+ return (0);
+ callrpc_private = crp;
+ }
+ if (crp->oldhost == NULL) {
+ crp->oldhost = mem_alloc(256);
+ crp->oldhost[0] = 0;
+ crp->socket = RPC_ANYSOCK;
+ }
+ if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
+ && strcmp(crp->oldhost, host) == 0) {
+ /* reuse old client */
+ } else {
+ crp->valid = 0;
+ (void)close(crp->socket);
+ crp->socket = RPC_ANYSOCK;
+ if (crp->client) {
+ clnt_destroy(crp->client);
+ crp->client = NULL;
+ }
+ if ((hp = gethostbyname(host)) == NULL)
+ return ((int) RPC_UNKNOWNHOST);
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 5;
+ memmove((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((crp->client = clntudp_create(&server_addr, (rpc_u_int32)prognum,
+ (rpc_u_int32)versnum, timeout, &crp->socket)) == NULL)
+ return ((int) rpc_createerr.cf_stat);
+ crp->valid = 1;
+ crp->oldprognum = prognum;
+ crp->oldversnum = versnum;
+ (void) strcpy(crp->oldhost, host);
+ }
+ tottimeout.tv_sec = 25;
+ tottimeout.tv_usec = 0;
+ clnt_stat = clnt_call(crp->client, procnum, inproc, in,
+ outproc, out, tottimeout);
+ /*
+ * if call failed, empty cache
+ */
+ if (clnt_stat != RPC_SUCCESS)
+ crp->valid = 0;
+ return ((int) clnt_stat);
+}
diff --git a/src/lib/rpc/clnt_tcp.c b/src/lib/rpc/clnt_tcp.c
new file mode 100644
index 000000000..c573897f7
--- /dev/null
+++ b/src/lib/rpc/clnt_tcp.c
@@ -0,0 +1,476 @@
+/* @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer. The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent. The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message. Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+
+#define MCALL_MSG_SIZE 24
+
+extern int errno;
+
+static int readtcp();
+static int writetcp();
+
+static enum clnt_stat clnttcp_call();
+static void clnttcp_abort();
+static void clnttcp_geterr();
+static bool_t clnttcp_freeres();
+static bool_t clnttcp_control();
+static void clnttcp_destroy();
+
+static struct clnt_ops tcp_ops = {
+ clnttcp_call,
+ clnttcp_abort,
+ clnttcp_geterr,
+ clnttcp_freeres,
+ clnttcp_destroy,
+ clnttcp_control
+};
+
+struct ct_data {
+ int ct_sock;
+ bool_t ct_closeit;
+ struct timeval ct_wait;
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct sockaddr_in ct_addr;
+ struct rpc_err ct_error;
+ char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ unsigned int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs;
+};
+
+/*
+ * Create a client handle for a tcp/ip connection.
+ * If *sockp<0, *sockp is set to a newly created TCP socket and it is
+ * connected to raddr. If *sockp non-negative then
+ * raddr is ignored. The rpc/tcp package does buffering
+ * similar to stdio, so the client must pick send and receive buffer sizes,];
+ * 0 => use the default.
+ * If raddr->sin_port is 0, then a binder on the remote machine is
+ * consulted for the right port number.
+ * NB: *sockp is copied into a private area.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
+ * something more useful.
+ */
+CLIENT *
+clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ rpc_u_int32 prog;
+ rpc_u_int32 vers;
+ register int *sockp;
+ unsigned int sendsz;
+ unsigned int recvsz;
+{
+ CLIENT *h;
+ register struct ct_data *ct;
+ struct timeval now;
+ struct rpc_msg call_msg;
+
+ h = (CLIENT *)mem_alloc(sizeof(*h));
+ if (h == NULL) {
+ (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ ct = (struct ct_data *)mem_alloc(sizeof(*ct));
+ if (ct == NULL) {
+ (void)fprintf(stderr, "clnttcp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+
+ /*
+ * If no port number given ask the pmap for one
+ */
+ if (raddr->sin_port == 0) {
+ unsigned short port;
+ if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+ }
+ raddr->sin_port = htons(port);
+ }
+
+ /*
+ * If no socket given, open one
+ */
+ if (*sockp < 0) {
+ *sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ (void)bindresvport(*sockp, (struct sockaddr_in *)0);
+ if ((*sockp < 0)
+ || (connect(*sockp, (struct sockaddr *)raddr,
+ sizeof(*raddr)) < 0)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ (void)close(*sockp);
+ goto fooy;
+ }
+ ct->ct_closeit = TRUE;
+ } else {
+ ct->ct_closeit = FALSE;
+ }
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_sock = *sockp;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr = *raddr;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, (struct timezone *)0);
+ call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = prog;
+ call_msg.rm_call.cb_vers = vers;
+
+ /*
+ * pre-serialize the staic part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)close(*sockp);
+ }
+ goto fooy;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ (caddr_t)ct, readtcp, writetcp);
+ h->cl_ops = &tcp_ops;
+ h->cl_private = (caddr_t) ct;
+ h->cl_auth = authnone_create();
+ return (h);
+
+fooy:
+ /*
+ * Something goofed, free stuff and barf
+ */
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ register CLIENT *h;
+ rpc_u_int32 proc;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+ xdrproc_t xdr_results;
+ caddr_t results_ptr;
+ struct timeval timeout;
+{
+ register struct ct_data *ct = (struct ct_data *) h->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ rpc_u_int32 x_id;
+ rpc_u_int32 *msg_x_id = (rpc_u_int32 *)(ct->ct_mcall); /* yuk */
+ register bool_t shipnow;
+ int refreshes = 2;
+ long procl = proc;
+
+ if (!ct->ct_waitset) {
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
+ && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+ xdrs->x_op = XDR_ENCODE;
+ ct->ct_error.re_status = RPC_SUCCESS;
+ x_id = ntohl(--(*msg_x_id));
+ if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
+ (! XDR_PUTLONG(xdrs, &procl)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! AUTH_WRAP(h->cl_auth, xdrs, xdr_args, args_ptr))) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTENCODEARGS;
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (ct->ct_error.re_status);
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow))
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ if (! shipnow)
+ return (RPC_SUCCESS);
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ return(ct->ct_error.re_status = RPC_TIMEDOUT);
+ }
+
+
+ /*
+ * Keep receiving until we get a valid transaction id
+ */
+ xdrs->x_op = XDR_DECODE;
+ while (TRUE) {
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = xdr_void;
+ if (! xdrrec_skiprecord(xdrs))
+ return (ct->ct_error.re_status);
+ /* now decode and validate the response header */
+ if (! xdr_replymsg(xdrs, &reply_msg)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ continue;
+ return (ct->ct_error.re_status);
+ }
+ if (reply_msg.rm_xid == x_id)
+ break;
+ }
+
+ /*
+ * process header
+ */
+ sunrpc_seterr_reply(&reply_msg, &(ct->ct_error));
+ if (ct->ct_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else if (! AUTH_UNWRAP(h->cl_auth, xdrs,
+ xdr_results, results_ptr)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTDECODERES;
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ /* free verifier ... */
+ if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
+ }
+ return (ct->ct_error.re_status);
+}
+
+static void
+clnttcp_geterr(h, errp)
+ CLIENT *h;
+ struct rpc_err *errp;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clnttcp_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ register XDR *xdrs = &(ct->ct_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clnttcp_abort()
+{
+}
+
+static bool_t
+clnttcp_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct ct_data *ct = (struct ct_data *)cl->cl_private;
+ int len;
+
+ switch (request) {
+ case CLSET_TIMEOUT:
+ ct->ct_wait = *(struct timeval *)info;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ *(struct timeval *)info = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ *(struct sockaddr_in *)info = ct->ct_addr;
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(ct->ct_sock, (struct sockaddr*)info, &len) < 0)
+ return FALSE;
+ else
+ return TRUE;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+
+static void
+clnttcp_destroy(h)
+ CLIENT *h;
+{
+ register struct ct_data *ct =
+ (struct ct_data *) h->cl_private;
+
+ if (ct->ct_closeit) {
+ (void)close(ct->ct_sock);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ mem_free((caddr_t)ct, sizeof(struct ct_data));
+ mem_free((caddr_t)h, sizeof(CLIENT));
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+readtcp(ct, buf, len)
+ register struct ct_data *ct;
+ caddr_t buf;
+ register int len;
+{
+#ifdef FD_SETSIZE
+ fd_set mask;
+ fd_set readfds;
+
+ if (len == 0)
+ return (0);
+ FD_ZERO(&mask);
+ FD_SET(ct->ct_sock, &mask);
+#else
+ register int mask = 1 << (ct->ct_sock);
+ int readfds;
+
+ if (len == 0)
+ return (0);
+
+#endif /* def FD_SETSIZE */
+ while (TRUE) {
+ readfds = mask;
+ switch (select(_rpc_dtablesize(), &readfds, (fd_set*)NULL, (fd_set*)NULL,
+ &(ct->ct_wait))) {
+ case 0:
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = errno;
+ return (-1);
+ }
+ break;
+ }
+ switch (len = read(ct->ct_sock, buf, len)) {
+
+ case 0:
+ /* premature eof */
+ ct->ct_error.re_errno = ECONNRESET;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ len = -1; /* it's really an error */
+ break;
+
+ case -1:
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ break;
+ }
+ return (len);
+}
+
+static int
+writetcp(ct, buf, len)
+ struct ct_data *ct;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ return (len);
+}
diff --git a/src/lib/rpc/clnt_udp.c b/src/lib/rpc/clnt_udp.c
new file mode 100644
index 000000000..000b9683d
--- /dev/null
+++ b/src/lib/rpc/clnt_udp.c
@@ -0,0 +1,460 @@
+/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_udp.c, Implements a UDP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#if defined(sparc)
+#include <sys/filio.h>
+#endif
+#include <netdb.h>
+#include <errno.h>
+#include <rpc/pmap_clnt.h>
+
+extern int errno;
+
+/*
+ * UDP bases client side rpc operations
+ */
+static enum clnt_stat clntudp_call();
+static void clntudp_abort();
+static void clntudp_geterr();
+static bool_t clntudp_freeres();
+static bool_t clntudp_control();
+static void clntudp_destroy();
+
+static struct clnt_ops udp_ops = {
+ clntudp_call,
+ clntudp_abort,
+ clntudp_geterr,
+ clntudp_freeres,
+ clntudp_destroy,
+ clntudp_control
+};
+
+/*
+ * Private data kept per client handle
+ */
+struct cu_data {
+ int cu_sock;
+ bool_t cu_closeit;
+ struct sockaddr_in cu_raddr;
+ int cu_rlen;
+ struct timeval cu_wait;
+ struct timeval cu_total;
+ struct rpc_err cu_error;
+ XDR cu_outxdrs;
+ unsigned int cu_xdrpos;
+ unsigned int cu_sendsz;
+ char *cu_outbuf;
+ unsigned int cu_recvsz;
+ char cu_inbuf[1];
+};
+
+/*
+ * Create a UDP based client handle.
+ * If *sockp<0, *sockp is set to a newly created UPD socket.
+ * If raddr->sin_port is 0 a binder on the remote machine
+ * is consulted for the correct port number.
+ * NB: It is the clients responsibility to close *sockp.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ * Caller may wish to set this something more useful.
+ *
+ * wait is the amount of time used between retransmitting a call if
+ * no response has been heard; retransmition occurs until the actual
+ * rpc call times out.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received.
+ */
+CLIENT *
+clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ struct timeval wait;
+ register int *sockp;
+ unsigned int sendsz;
+ unsigned int recvsz;
+{
+ CLIENT *cl;
+ register struct cu_data *cu;
+ struct timeval now;
+ struct rpc_msg call_msg;
+
+ cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
+ if (cl == NULL) {
+ (void) fprintf(stderr, "clntudp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ sendsz = ((sendsz + 3) / 4) * 4;
+ recvsz = ((recvsz + 3) / 4) * 4;
+ cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
+ if (cu == NULL) {
+ (void) fprintf(stderr, "clntudp_create: out of memory\n");
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+
+ (void)gettimeofday(&now, (struct timezone *)0);
+ if (raddr->sin_port == 0) {
+ unsigned short port;
+ if ((port =
+ pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
+ goto fooy;
+ }
+ raddr->sin_port = htons(port);
+ }
+ cl->cl_ops = &udp_ops;
+ cl->cl_private = (caddr_t)cu;
+ cu->cu_raddr = *raddr;
+ cu->cu_rlen = sizeof (cu->cu_raddr);
+ cu->cu_wait = wait;
+ cu->cu_total.tv_sec = -1;
+ cu->cu_total.tv_usec = -1;
+ cu->cu_sendsz = sendsz;
+ cu->cu_recvsz = recvsz;
+ call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = program;
+ call_msg.rm_call.cb_vers = version;
+ xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
+ sendsz, XDR_ENCODE);
+ if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
+ goto fooy;
+ }
+ cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+ if (*sockp < 0) {
+ int dontblock = 1;
+
+ *sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (*sockp < 0) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto fooy;
+ }
+ /* attempt to bind to prov port */
+ (void)bindresvport(*sockp, (struct sockaddr_in *)0);
+ /* the sockets rpc controls are non-blocking */
+ (void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
+ cu->cu_closeit = TRUE;
+ } else {
+ cu->cu_closeit = FALSE;
+ }
+ cu->cu_sock = *sockp;
+ cl->cl_auth = authnone_create();
+ return (cl);
+fooy:
+ if (cu)
+ mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
+ if (cl)
+ mem_free((caddr_t)cl, sizeof(CLIENT));
+ return ((CLIENT *)NULL);
+}
+
+CLIENT *
+clntudp_create(raddr, program, version, wait, sockp)
+ struct sockaddr_in *raddr;
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ struct timeval wait;
+ register int *sockp;
+{
+
+ return(clntudp_bufcreate(raddr, program, version, wait, sockp,
+ UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum clnt_stat
+clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
+ register CLIENT *cl; /* client handle */
+ rpc_u_int32 proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t resultsp; /* pointer to results */
+ struct timeval utimeout; /* seconds to wait before giving up */
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register XDR *xdrs;
+ register int outlen;
+ register int inlen;
+ int fromlen;
+#ifdef FD_SETSIZE
+ fd_set readfds;
+ fd_set mask;
+#else
+ int readfds;
+ register int mask;
+#endif /* def FD_SETSIZE */
+ struct sockaddr_in from;
+ struct rpc_msg reply_msg;
+ XDR reply_xdrs;
+ struct timeval time_waited;
+ bool_t ok;
+ int nrefreshes = 2; /* number of times to refresh cred */
+ struct timeval timeout;
+ long procl = proc;
+
+ if (cu->cu_total.tv_usec == -1) {
+ timeout = utimeout; /* use supplied timeout */
+ } else {
+ timeout = cu->cu_total; /* use default timeout */
+ }
+
+ time_waited.tv_sec = 0;
+ time_waited.tv_usec = 0;
+call_again:
+ xdrs = &(cu->cu_outxdrs);
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, cu->cu_xdrpos);
+ /*
+ * the transaction is the first thing in the out buffer
+ */
+ (*(unsigned short *)(cu->cu_outbuf))++;
+ if ((! XDR_PUTLONG(xdrs, &procl)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, argsp)))
+ return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
+ outlen = (int)XDR_GETPOS(xdrs);
+
+send_again:
+ if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
+ (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
+ != outlen) {
+ cu->cu_error.re_errno = errno;
+ return (cu->cu_error.re_status = RPC_CANTSEND);
+ }
+
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+ }
+ /*
+ * sub-optimal code appears here because we have
+ * some clock time to spare while the packets are in flight.
+ * (We assume that this is actually only executed once.)
+ */
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = xdr_void;
+#ifdef FD_SETSIZE
+ FD_ZERO(&mask);
+ FD_SET(cu->cu_sock, &mask);
+#else
+ mask = 1 << cu->cu_sock;
+#endif /* def FD_SETSIZE */
+ for (;;) {
+ readfds = mask;
+ switch (select(_rpc_dtablesize(), &readfds, (fd_set *)NULL,
+ (fd_set *)NULL, &(cu->cu_wait))) {
+
+ case 0:
+ time_waited.tv_sec += cu->cu_wait.tv_sec;
+ time_waited.tv_usec += cu->cu_wait.tv_usec;
+ while (time_waited.tv_usec >= 1000000) {
+ time_waited.tv_sec++;
+ time_waited.tv_usec -= 1000000;
+ }
+ if ((time_waited.tv_sec < timeout.tv_sec) ||
+ ((time_waited.tv_sec == timeout.tv_sec) &&
+ (time_waited.tv_usec < timeout.tv_usec)))
+ goto send_again;
+ return (cu->cu_error.re_status = RPC_TIMEDOUT);
+
+ /*
+ * buggy in other cases because time_waited is not being
+ * updated.
+ */
+ case -1:
+ if (errno == EINTR)
+ continue;
+ cu->cu_error.re_errno = errno;
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+ do {
+ fromlen = sizeof(struct sockaddr);
+ inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
+ (int) cu->cu_recvsz, 0,
+ (struct sockaddr *)&from, &fromlen);
+ } while (inlen < 0 && errno == EINTR);
+ if (inlen < 0) {
+ if (errno == EWOULDBLOCK)
+ continue;
+ cu->cu_error.re_errno = errno;
+ return (cu->cu_error.re_status = RPC_CANTRECV);
+ }
+ if (inlen < sizeof(rpc_u_int32))
+ continue;
+ /* see if reply transaction id matches sent id */
+ if (*((rpc_u_int32 *)(cu->cu_inbuf)) != *((rpc_u_int32 *)(cu->cu_outbuf)))
+ continue;
+ /* we now assume we have the proper reply */
+ break;
+ }
+
+ /*
+ * now decode and validate the response
+ */
+ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (unsigned int)inlen, XDR_DECODE);
+ ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+ /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
+ if (ok) {
+ sunrpc_seterr_reply(&reply_msg, &(cu->cu_error));
+ if (cu->cu_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(cl->cl_auth,
+ &reply_msg.acpted_rply.ar_verf)) {
+ cu->cu_error.re_status = RPC_AUTHERROR;
+ cu->cu_error.re_why = AUTH_INVALIDRESP;
+ } else if (! AUTH_UNWRAP(cl->cl_auth, &reply_xdrs,
+ xresults, resultsp)) {
+ if (cu->cu_error.re_status == RPC_SUCCESS)
+ cu->cu_error.re_status = RPC_CANTDECODERES;
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (nrefreshes > 0 &&
+ AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
+ nrefreshes--;
+ goto call_again;
+ }
+ } /* end of unsuccessful completion */
+ /* free verifier */
+ if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (reply_msg.acpted_rply.ar_verf.oa_base != NULL)) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs,
+ &(reply_msg.acpted_rply.ar_verf));
+ }
+ } /* end of valid reply message */
+ else {
+ cu->cu_error.re_status = RPC_CANTDECODERES;
+ }
+ return (cu->cu_error.re_status);
+}
+
+static void
+clntudp_geterr(cl, errp)
+ CLIENT *cl;
+ struct rpc_err *errp;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ *errp = cu->cu_error;
+}
+
+
+static bool_t
+clntudp_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ caddr_t res_ptr;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ register XDR *xdrs = &(cu->cu_outxdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+static void
+clntudp_abort(/*h*/)
+ /*CLIENT *h;*/
+{
+}
+
+static bool_t
+clntudp_control(cl, request, info)
+ CLIENT *cl;
+ int request;
+ char *info;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ int len;
+
+ switch (request) {
+ case CLSET_TIMEOUT:
+ cu->cu_total = *(struct timeval *)info;
+ break;
+ case CLGET_TIMEOUT:
+ *(struct timeval *)info = cu->cu_total;
+ break;
+ case CLSET_RETRY_TIMEOUT:
+ cu->cu_wait = *(struct timeval *)info;
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ *(struct timeval *)info = cu->cu_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ *(struct sockaddr_in *)info = cu->cu_raddr;
+ break;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(cu->cu_sock, (struct sockaddr*)info, &len) < 0)
+ return FALSE;
+ else
+ return TRUE;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+static void
+clntudp_destroy(cl)
+ CLIENT *cl;
+{
+ register struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ if (cu->cu_closeit) {
+ (void)close(cu->cu_sock);
+ }
+ XDR_DESTROY(&(cu->cu_outxdrs));
+ mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
+ mem_free((caddr_t)cl, sizeof(CLIENT));
+}
diff --git a/src/lib/rpc/configure.in b/src/lib/rpc/configure.in
new file mode 100644
index 000000000..6084638d3
--- /dev/null
+++ b/src/lib/rpc/configure.in
@@ -0,0 +1,41 @@
+AC_INIT(auth_gssapi.c)
+CONFIG_RULES
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+
+AC_CHECK_SIZEOF(int)
+SIZEOF_INT=$ac_cv_sizeof_int
+AC_SUBST(SIZEOF_INT)
+AC_CHECK_SIZEOF(long)
+SIZEOF_LONG=$ac_cv_sizeof_long
+AC_SUBST(SIZEOF_LONG)
+
+DECLARE_SYS_ERRLIST
+
+V5_SHARED_LIB_OBJS
+V5_MAKE_SHARED_LIB(libgssrpc,1.0,.., ./rpc)
+GSSAPI_KRB5_SH_VERS=$krb5_cv_shlib_version_libgssapi_krb5
+AC_SUBST(GSSAPI_KRB5_SH_VERS)
+KRB5_SH_VERS=$krb5_cv_shlib_version_libkrb5
+AC_SUBST(KRB5_SH_VERS)
+CRYPTO_SH_VERS=$krb5_cv_shlib_version_libcrypto
+AC_SUBST(CRYPTO_SH_VERS)
+COMERR_SH_VERS=$krb5_cv_shlib_version_libcom_err
+AC_SUBST(COMERR_SH_VERS)
+CopySrcHeader(auth.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(auth_gssapi.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(auth_unix.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(clnt.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(netdb.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(pmap_clnt.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(pmap_prot.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(pmap_rmt.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(rpc.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(rpc_msg.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(svc.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(svc_auth.h,[$](BUILDTOP)/include/rpc)
+CopyHeader(types.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(xdr.h,[$](BUILDTOP)/include/rpc)
+V5_AC_OUTPUT_MAKEFILE( ,types.h:types.hin)
diff --git a/src/lib/rpc/get_myaddress.c b/src/lib/rpc/get_myaddress.c
new file mode 100644
index 000000000..fa4c54e78
--- /dev/null
+++ b/src/lib/rpc/get_myaddress.c
@@ -0,0 +1,95 @@
+/* @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * get_myaddress.c
+ *
+ * Get client's IP address via ioctl. This avoids using the yellowpages.
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/pmap_prot.h>
+#include <sys/socket.h>
+#if defined(sun)
+#include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+/*
+ * don't use gethostbyname, which would invoke yellow pages
+ */
+get_myaddress(addr)
+ struct sockaddr_in *addr;
+{
+ int s;
+ char buf[BUFSIZ];
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr;
+ int len;
+
+ if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ perror("get_myaddress: socket");
+ exit(1);
+ }
+ ifc.ifc_len = sizeof (buf);
+ ifc.ifc_buf = buf;
+ if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
+ perror("get_myaddress: ioctl (get interface configuration)");
+ exit(1);
+ }
+ ifr = ifc.ifc_req;
+ for (len = ifc.ifc_len; len; len -= sizeof ifreq) {
+ ifreq = *ifr;
+ if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ perror("get_myaddress: ioctl");
+ exit(1);
+ }
+ if ((ifreq.ifr_flags & IFF_UP) &&
+ ifr->ifr_addr.sa_family == AF_INET) {
+ *addr = *((struct sockaddr_in *)&ifr->ifr_addr);
+ addr->sin_port = htons(PMAPPORT);
+ break;
+ }
+ ifr++;
+ }
+ (void) close(s);
+}
diff --git a/src/lib/rpc/getrpcent.c b/src/lib/rpc/getrpcent.c
new file mode 100644
index 000000000..e48d5b1e9
--- /dev/null
+++ b/src/lib/rpc/getrpcent.c
@@ -0,0 +1,256 @@
+/* @(#)getrpcent.c 2.2 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)getrpcent.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/netdb.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+
+/* setrpcent is declared as int-returning in netdb.h on hpux */
+/* setrpcent is declared as int-returning in rpc/rpcent.h on Solaris */
+#if !defined(hpux) && !(defined(sun) && defined(__svr4__))
+#define SETRPCENT_TYPE void
+#else
+#define SETRPCENT_TYPE int
+#endif
+
+/* endrpcent is declared as int-returning in netdb.h on hpux */
+#ifndef hpux
+#define ENDRPCENT_TYPE void
+#else
+#define ENDRPCENT_TYPE int
+#endif
+
+SETRPCENT_TYPE setrpcent(int);
+ENDRPCENT_TYPE endrpcent(void);
+
+/*
+ * Internet version.
+ */
+struct rpcdata {
+ FILE *rpcf;
+ char *current;
+ int currentlen;
+ int stayopen;
+#define MAXALIASES 35
+ char *rpc_aliases[MAXALIASES];
+ struct rpcent rpc;
+ char line[BUFSIZ+1];
+ char *domain;
+} *rpcdata;
+static struct rpcdata *_rpcdata();
+
+static struct rpcent *interpret();
+struct hostent *gethostent();
+char *inet_ntoa();
+
+static char RPCDB[] = "/etc/rpc";
+
+static struct rpcdata *
+_rpcdata()
+{
+ register struct rpcdata *d = rpcdata;
+
+ if (d == 0) {
+ d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
+ rpcdata = d;
+ }
+ return (d);
+}
+
+struct rpcent *
+getrpcbynumber(number)
+ register int number;
+{
+ register struct rpcdata *d = _rpcdata();
+ register struct rpcent *p;
+ int reason;
+ char adrstr[16], *val = NULL;
+ int vallen;
+
+ if (d == 0)
+ return (0);
+ setrpcent(0);
+ while (p = getrpcent()) {
+ if (p->r_number == number)
+ break;
+ }
+ endrpcent();
+ return (p);
+}
+
+struct rpcent *
+getrpcbyname(name)
+ const char *name;
+{
+ struct rpcent *rpc;
+ char **rp;
+
+ setrpcent(0);
+ while(rpc = getrpcent()) {
+ if (strcmp(rpc->r_name, name) == 0)
+ return (rpc);
+ for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+ if (strcmp(*rp, name) == 0)
+ return (rpc);
+ }
+ }
+ endrpcent();
+ return (NULL);
+}
+
+SETRPCENT_TYPE setrpcent(f)
+ int f;
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+ if (d->rpcf == NULL)
+ d->rpcf = fopen(RPCDB, "r");
+ else
+ rewind(d->rpcf);
+ if (d->current)
+ free(d->current);
+ d->current = NULL;
+ d->stayopen |= f;
+}
+
+ENDRPCENT_TYPE endrpcent()
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+ if (d->current && !d->stayopen) {
+ free(d->current);
+ d->current = NULL;
+ }
+ if (d->rpcf && !d->stayopen) {
+ fclose(d->rpcf);
+ d->rpcf = NULL;
+ }
+}
+
+struct rpcent *
+getrpcent()
+{
+ struct rpcent *hp;
+ int reason;
+ char *key = NULL, *val = NULL;
+ int keylen, vallen;
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return(NULL);
+ if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
+ return (NULL);
+ if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
+ return (NULL);
+ return interpret(d->line, strlen(d->line));
+}
+
+static struct rpcent *
+interpret(val, len)
+char *val;
+{
+ register struct rpcdata *d = _rpcdata();
+ char *p;
+ register char *cp, **q;
+
+ if (d == 0)
+ return;
+ strncpy(d->line, val, len);
+ p = d->line;
+ d->line[len] = '\n';
+ if (*p == '#')
+ return (getrpcent());
+ cp = strchr(p, '#');
+ if (cp == NULL)
+ {
+ cp = strchr(p, '\n');
+ if (cp == NULL)
+ return (getrpcent());
+ }
+ *cp = '\0';
+ cp = strchr(p, ' ');
+ if (cp == NULL)
+ {
+ cp = strchr(p, '\t');
+ if (cp == NULL)
+ return (getrpcent());
+ }
+ *cp++ = '\0';
+ /* THIS STUFF IS INTERNET SPECIFIC */
+ d->rpc.r_name = d->line;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ d->rpc.r_number = atoi(cp);
+ q = d->rpc.r_aliases = d->rpc_aliases;
+ cp = strchr(p, ' ');
+ if (cp != NULL)
+ *cp++ = '\0';
+ else
+ {
+ cp = strchr(p, '\t');
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &(d->rpc_aliases[MAXALIASES - 1]))
+ *q++ = cp;
+ cp = strchr(p, ' ');
+ if (cp != NULL)
+ *cp++ = '\0';
+ else
+ {
+ cp = strchr(p, '\t');
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (&d->rpc);
+}
diff --git a/src/lib/rpc/getrpcport.c b/src/lib/rpc/getrpcport.c
new file mode 100644
index 000000000..d209a1527
--- /dev/null
+++ b/src/lib/rpc/getrpcport.c
@@ -0,0 +1,55 @@
+/* @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <netdb.h>
+#include <sys/socket.h>
+
+getrpcport(host, prognum, versnum, proto)
+ char *host;
+{
+ struct sockaddr_in addr;
+ struct hostent *hp;
+
+ if ((hp = gethostbyname(host)) == NULL)
+ return (0);
+ memmove((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ return (pmap_getport(&addr, prognum, versnum, proto));
+}
diff --git a/src/lib/rpc/netdb.h b/src/lib/rpc/netdb.h
new file mode 100644
index 000000000..f6b6374b5
--- /dev/null
+++ b/src/lib/rpc/netdb.h
@@ -0,0 +1,50 @@
+#ifndef RPC_NETDB_H
+#define RPC_NETDB_H
+
+/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)rpc.h 1.8 87/07/24 SMI */
+
+/* since the gssrpc library requires that any application using it be
+built with these header files, I am making the decision that any app
+which uses the rpcent routines must use this header file, or something
+compatible (which most <netdb.h> are) --marc */
+
+/* Really belongs in <netdb.h> */
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent();
+
+#endif
diff --git a/src/lib/rpc/pmap_clnt.c b/src/lib/rpc/pmap_clnt.c
new file mode 100644
index 000000000..7218777cc
--- /dev/null
+++ b/src/lib/rpc/pmap_clnt.c
@@ -0,0 +1,115 @@
+/* @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+void clnt_perror();
+
+
+/*
+ * Set a mapping between program,version and port.
+ * Calls the pmap service remotely to do the mapping.
+ */
+bool_t
+pmap_set(program, version, protocol, port)
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ int protocol;
+ unsigned short port;
+{
+ struct sockaddr_in myaddress;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+ bool_t rslt;
+
+ get_myaddress(&myaddress);
+ client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+ timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client == (CLIENT *)NULL)
+ return (FALSE);
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = port;
+ if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
+ tottimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "Cannot register service");
+ return (FALSE);
+ }
+ CLNT_DESTROY(client);
+ (void)close(socket);
+ return (rslt);
+}
+
+/*
+ * Remove the mapping between program,version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(program, version)
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+{
+ struct sockaddr_in myaddress;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+ bool_t rslt;
+
+ get_myaddress(&myaddress);
+ client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
+ timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client == (CLIENT *)NULL)
+ return (FALSE);
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_port = parms.pm_prot = 0;
+ CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
+ tottimeout);
+ CLNT_DESTROY(client);
+ (void)close(socket);
+ return (rslt);
+}
diff --git a/src/lib/rpc/pmap_clnt.h b/src/lib/rpc/pmap_clnt.h
new file mode 100644
index 000000000..dfb00dcc5
--- /dev/null
+++ b/src/lib/rpc/pmap_clnt.h
@@ -0,0 +1,65 @@
+/* @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Usage:
+ * success = pmap_set(program, version, protocol, port);
+ * success = pmap_unset(program, version);
+ * port = pmap_getport(address, program, version, protocol);
+ * head = pmap_getmaps(address);
+ * clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ * (works for udp only.)
+ * clnt_stat = clnt_broadcast(program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, eachresult)
+ * (like pmap_rmtcall, except the call is broadcasted to all
+ * locally connected nets. For each valid response received,
+ * the procedure eachresult is called. Its form is:
+ * done = eachresult(resp, raddr)
+ * bool_t done;
+ * caddr_t resp;
+ * struct sockaddr_in raddr;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast.
+ */
+
+extern bool_t pmap_set();
+extern bool_t pmap_unset();
+extern struct pmaplist *pmap_getmaps();
+enum clnt_stat pmap_rmtcall();
+enum clnt_stat clnt_broadcast();
+extern unsigned short pmap_getport();
diff --git a/src/lib/rpc/pmap_getmaps.c b/src/lib/rpc/pmap_getmaps.c
new file mode 100644
index 000000000..472b2a46d
--- /dev/null
+++ b/src/lib/rpc/pmap_getmaps.c
@@ -0,0 +1,88 @@
+/* @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_getmap.c
+ * Client interface to pmap rpc service.
+ * contains pmap_getmaps, which is only tcp service involved
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#define NAMELEN 255
+#define MAX_BROADCAST_SIZE 1400
+
+extern int errno;
+
+/*
+ * Get a copy of the current port maps.
+ * Calls the pmap service remotely to do get the maps.
+ */
+struct pmaplist *
+pmap_getmaps(address)
+ struct sockaddr_in *address;
+{
+ struct pmaplist *head = (struct pmaplist *)NULL;
+ int socket = -1;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ address->sin_port = htons(PMAPPORT);
+ client = clnttcp_create(address, PMAPPROG,
+ PMAPVERS, &socket, 50, 500);
+ if (client != (CLIENT *)NULL) {
+ if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
+ &head, minutetimeout) != RPC_SUCCESS) {
+ clnt_perror(client, "pmap_getmaps rpc problem");
+ }
+ CLNT_DESTROY(client);
+ }
+ (void)close(socket);
+ address->sin_port = 0;
+ return (head);
+}
diff --git a/src/lib/rpc/pmap_getport.c b/src/lib/rpc/pmap_getport.c
new file mode 100644
index 000000000..40b764880
--- /dev/null
+++ b/src/lib/rpc/pmap_getport.c
@@ -0,0 +1,91 @@
+/* @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <sys/socket.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+
+static struct timeval timeout = { 5, 0 };
+static struct timeval tottimeout = { 60, 0 };
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+unsigned short
+pmap_getport(address, program, version, protocol)
+ struct sockaddr_in *address;
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ unsigned int protocol;
+{
+ unsigned short port = 0;
+ int socket = -1;
+ register CLIENT *client;
+ struct pmap parms;
+
+ address->sin_port = htons(PMAPPORT);
+ client = clntudp_bufcreate(address, PMAPPROG,
+ PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client != (CLIENT *)NULL) {
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = 0; /* not needed or used */
+ if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms,
+ xdr_u_short, &port, tottimeout) != RPC_SUCCESS){
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ } else if (port == 0) {
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ }
+ CLNT_DESTROY(client);
+ }
+ (void)close(socket);
+ address->sin_port = 0;
+ return (port);
+}
diff --git a/src/lib/rpc/pmap_prot.c b/src/lib/rpc/pmap_prot.c
new file mode 100644
index 000000000..1dffffe17
--- /dev/null
+++ b/src/lib/rpc/pmap_prot.c
@@ -0,0 +1,57 @@
+/* @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+
+
+bool_t
+xdr_pmap(xdrs, regs)
+ XDR *xdrs;
+ struct pmap *regs;
+{
+
+ if (xdr_u_int32(xdrs, &regs->pm_prog) &&
+ xdr_u_int32(xdrs, &regs->pm_vers) &&
+ xdr_u_int32(xdrs, &regs->pm_prot))
+ return (xdr_u_int32(xdrs, &regs->pm_port));
+ return (FALSE);
+}
diff --git a/src/lib/rpc/pmap_prot.h b/src/lib/rpc/pmap_prot.h
new file mode 100644
index 000000000..4f76580f4
--- /dev/null
+++ b/src/lib/rpc/pmap_prot.h
@@ -0,0 +1,94 @@
+/* @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Registers the tuple
+ * [prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Un-registers pair
+ * [prog, vers]. prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (rpc_int32 unsigned).
+ * 0 is failure. Otherwise returns the port number where the pair
+ * [prog, vers] is registered. It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+ * RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * Calls the procedure on the local machine. If it is not registered,
+ * this procedure is quite; ie it does not return error information!!!
+ * This procedure only is supported on rpc/udp and calls via
+ * rpc/udp. This routine only passes null authentication parameters.
+ * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#define PMAPPORT ((unsigned short)111)
+#define PMAPPROG ((rpc_u_int32)100000)
+#define PMAPVERS ((rpc_u_int32)2)
+#define PMAPVERS_PROTO ((rpc_u_int32)2)
+#define PMAPVERS_ORIG ((rpc_u_int32)1)
+#define PMAPPROC_NULL ((rpc_u_int32)0)
+#define PMAPPROC_SET ((rpc_u_int32)1)
+#define PMAPPROC_UNSET ((rpc_u_int32)2)
+#define PMAPPROC_GETPORT ((rpc_u_int32)3)
+#define PMAPPROC_DUMP ((rpc_u_int32)4)
+#define PMAPPROC_CALLIT ((rpc_u_int32)5)
+
+struct pmap {
+ rpc_u_int32 pm_prog;
+ rpc_u_int32 pm_vers;
+ rpc_u_int32 pm_prot;
+ rpc_u_int32 pm_port;
+};
+
+extern bool_t xdr_pmap();
+
+struct pmaplist {
+ struct pmap pml_map;
+ struct pmaplist *pml_next;
+};
+
+extern bool_t xdr_pmaplist();
diff --git a/src/lib/rpc/pmap_prot2.c b/src/lib/rpc/pmap_prot2.c
new file mode 100644
index 000000000..5f48f2a28
--- /dev/null
+++ b/src/lib/rpc/pmap_prot2.c
@@ -0,0 +1,116 @@
+/* @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+
+
+/*
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ * struct pmap pml_map;
+ * struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ *
+ * case TRUE: struct {
+ * struct pmap;
+ * pmaplist_t foo;
+ * };
+ *
+ * case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable. The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the
+ * xdr union, pamplist_t.
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list. Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(xdrs, rp)
+ register XDR *xdrs;
+ register struct pmaplist **rp;
+{
+ /*
+ * more_elements is pre-computed in case the direction is
+ * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
+ * xdr_bool when the direction is XDR_DECODE.
+ */
+ bool_t more_elements;
+ register int freeing = (xdrs->x_op == XDR_FREE);
+ register struct pmaplist **next;
+
+ while (TRUE) {
+ more_elements = (bool_t)(*rp != NULL);
+ if (! xdr_bool(xdrs, &more_elements))
+ return (FALSE);
+ if (! more_elements)
+ return (TRUE); /* we are done */
+ /*
+ * the unfortunate side effect of non-recursion is that in
+ * the case of freeing we must remember the next object
+ * before we free the current object ...
+ */
+ if (freeing)
+ next = &((*rp)->pml_next);
+ if (! xdr_reference(xdrs, (caddr_t *)rp,
+ (unsigned int)sizeof(struct pmaplist), xdr_pmap))
+ return (FALSE);
+ rp = (freeing) ? next : &((*rp)->pml_next);
+ }
+}
diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c
new file mode 100644
index 000000000..6a2376763
--- /dev/null
+++ b/src/lib/rpc/pmap_rmt.c
@@ -0,0 +1,403 @@
+/* @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#include <sys/socket.h>
+#ifdef sparc
+#include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#define MAX_BROADCAST_SIZE 1400
+
+extern int errno;
+static struct timeval timeout = { 3, 0 };
+
+
+/*
+ * pmapper remote-call-service interface.
+ * This routine is used to call the pmapper remote call service
+ * which will look up a service program in the port maps, and then
+ * remotely call that routine with the given parameters. This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ struct sockaddr_in *addr;
+ rpc_u_int32 prog, vers, proc;
+ xdrproc_t xdrargs, xdrres;
+ caddr_t argsp, resp;
+ struct timeval tout;
+ rpc_u_int32 *port_ptr;
+{
+ int socket = -1;
+ register CLIENT *client;
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ enum clnt_stat stat;
+
+ addr->sin_port = htons(PMAPPORT);
+ client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket);
+ if (client != (CLIENT *)NULL) {
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.args_ptr = argsp;
+ a.xdr_args = xdrargs;
+ r.port_ptr = port_ptr;
+ r.results_ptr = resp;
+ r.xdr_results = xdrres;
+ stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a,
+ xdr_rmtcallres, &r, tout);
+ CLNT_DESTROY(client);
+ } else {
+ stat = RPC_FAILED;
+ }
+ (void)close(socket);
+ addr->sin_port = 0;
+ return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(xdrs, cap)
+ register XDR *xdrs;
+ register struct rmtcallargs *cap;
+{
+ unsigned int lenposition, argposition, position;
+
+ if (xdr_u_int32(xdrs, &(cap->prog)) &&
+ xdr_u_int32(xdrs, &(cap->vers)) &&
+ xdr_u_int32(xdrs, &(cap->proc))) {
+ lenposition = XDR_GETPOS(xdrs);
+ if (! xdr_u_int32(xdrs, &(cap->arglen)))
+ return (FALSE);
+ argposition = XDR_GETPOS(xdrs);
+ if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
+ return (FALSE);
+ position = XDR_GETPOS(xdrs);
+ cap->arglen = (rpc_u_int32)position - (rpc_u_int32)argposition;
+ XDR_SETPOS(xdrs, lenposition);
+ if (! xdr_u_int32(xdrs, &(cap->arglen)))
+ return (FALSE);
+ XDR_SETPOS(xdrs, position);
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rmtcallres(xdrs, crp)
+ register XDR *xdrs;
+ register struct rmtcallres *crp;
+{
+ caddr_t port_ptr;
+
+ port_ptr = (caddr_t)crp->port_ptr;
+ if (xdr_reference(xdrs, &port_ptr, sizeof (rpc_u_int32),
+ xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) {
+ crp->port_ptr = (rpc_u_int32 *)port_ptr;
+ return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+ }
+ return (FALSE);
+}
+
+
+/*
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these trivial
+ * routines which only support udp/ip .
+ */
+
+static int
+getbroadcastnets(addrs, sock, buf)
+ struct in_addr *addrs;
+ int sock; /* any valid socket will do */
+ char *buf; /* why allocxate more when we can use existing... */
+{
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr;
+ struct sockaddr_in *sin;
+ int n, i;
+
+ ifc.ifc_len = UDPMSGSIZE;
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ perror("broadcast: ioctl (get interface configuration)");
+ return (0);
+ }
+ ifr = ifc.ifc_req;
+ for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
+ ifreq = *ifr;
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ perror("broadcast: ioctl (get interface flags)");
+ continue;
+ }
+ if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+ (ifreq.ifr_flags & IFF_UP) &&
+ ifr->ifr_addr.sa_family == AF_INET) {
+ sin = (struct sockaddr_in *)&ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR /* 4.3BSD */
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+ addrs[i++].s_addr = INADDR_ANY;
+#if 0 /* this is uuuuugly */
+ addrs[i++] = inet_makeaddr(inet_netof
+#if defined(hpux) || (defined(sparc) && defined(__svr4__)) || defined(linux) || (defined(__osf__) && defined(__alpha__))
+ (sin->sin_addr), INADDR_ANY);
+#else /* hpux or solaris */
+ (sin->sin_addr.s_addr), INADDR_ANY);
+#endif
+#endif
+ } else {
+ addrs[i++] = ((struct sockaddr_in*)
+ &ifreq.ifr_addr)->sin_addr;
+ }
+#else /* 4.2 BSD */
+ addrs[i++] = inet_makeaddr(inet_netof
+ (sin->sin_addr.s_addr), INADDR_ANY);
+#endif
+ }
+ }
+ return (i);
+}
+
+typedef bool_t (*resultproc_t)();
+
+enum clnt_stat
+clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
+ rpc_u_int32 prog; /* program number */
+ rpc_u_int32 vers; /* version number */
+ rpc_u_int32 proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t resultsp; /* pointer to results */
+ resultproc_t eachresult; /* call with each result obtained */
+{
+ enum clnt_stat stat;
+ AUTH *unix_auth = authunix_create_default();
+ XDR xdr_stream;
+ register XDR *xdrs = &xdr_stream;
+ int outlen, inlen, fromlen, nets;
+ register int sock;
+ int on = 1;
+#ifdef FD_SETSIZE
+ fd_set mask;
+ fd_set readfds;
+#else
+ int readfds;
+ register int mask;
+#endif /* def FD_SETSIZE */
+ register int i;
+ bool_t done = FALSE;
+ register rpc_u_int32 xid;
+ rpc_u_int32 port;
+ struct in_addr addrs[20];
+ struct sockaddr_in baddr, raddr; /* broadcast and response addresses */
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ struct rpc_msg msg;
+ struct timeval t;
+ char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];
+
+ /*
+ * initialization: create a socket, a broadcast address, and
+ * preserialize the arguments into a send buffer.
+ */
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("Cannot create socket for broadcast rpc");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+#ifdef SO_BROADCAST
+ if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *) &on,
+ sizeof (on)) < 0) {
+ perror("Cannot set socket option SO_BROADCAST");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+#endif /* def SO_BROADCAST */
+#ifdef FD_SETSIZE
+ FD_ZERO(&mask);
+ FD_SET(sock, &mask);
+#else
+ mask = (1 << sock);
+#endif /* def FD_SETSIZE */
+ nets = getbroadcastnets(addrs, sock, inbuf);
+ bzero((char *)&baddr, sizeof (baddr));
+ baddr.sin_family = AF_INET;
+ baddr.sin_port = htons(PMAPPORT);
+ baddr.sin_addr.s_addr = htonl(INADDR_ANY);
+/* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
+ (void)gettimeofday(&t, (struct timezone *)0);
+ msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec;
+ t.tv_usec = 0;
+ msg.rm_direction = CALL;
+ msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ msg.rm_call.cb_prog = PMAPPROG;
+ msg.rm_call.cb_vers = PMAPVERS;
+ msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+ msg.rm_call.cb_cred = unix_auth->ah_cred;
+ msg.rm_call.cb_verf = unix_auth->ah_verf;
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.xdr_args = xargs;
+ a.args_ptr = argsp;
+ r.port_ptr = &port;
+ r.xdr_results = xresults;
+ r.results_ptr = resultsp;
+ xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
+ if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) {
+ stat = RPC_CANTENCODEARGS;
+ goto done_broad;
+ }
+ outlen = (int)xdr_getpos(xdrs);
+ xdr_destroy(xdrs);
+ /*
+ * Basic loop: broadcast a packet and wait a while for response(s).
+ * The response timeout grows larger per iteration.
+ */
+ for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {
+ for (i = 0; i < nets; i++) {
+ baddr.sin_addr = addrs[i];
+ if (sendto(sock, outbuf, outlen, 0,
+ (struct sockaddr *)&baddr,
+ sizeof (struct sockaddr)) != outlen) {
+ perror("Cannot send broadcast packet");
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+ }
+ if (eachresult == NULL) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ }
+ recv_again:
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where = (caddr_t)&r;
+ msg.acpted_rply.ar_results.proc = xdr_rmtcallres;
+ readfds = mask;
+ switch (select(_rpc_dtablesize(), &readfds, (fd_set *)NULL,
+ (fd_set *)NULL, &t)) {
+
+ case 0: /* timed out */
+ stat = RPC_TIMEDOUT;
+ continue;
+
+ case -1: /* some kind of error */
+ if (errno == EINTR)
+ goto recv_again;
+ perror("Broadcast select problem");
+ stat = RPC_CANTRECV;
+ goto done_broad;
+
+ } /* end of select results switch */
+ try_again:
+ fromlen = sizeof(struct sockaddr);
+ inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0,
+ (struct sockaddr *)&raddr, &fromlen);
+ if (inlen < 0) {
+ if (errno == EINTR)
+ goto try_again;
+ perror("Cannot receive reply to broadcast");
+ stat = RPC_CANTRECV;
+ goto done_broad;
+ }
+ if (inlen < sizeof(rpc_u_int32))
+ goto recv_again;
+ /*
+ * see if reply transaction id matches sent id.
+ * If so, decode the results.
+ */
+ xdrmem_create(xdrs, inbuf, (unsigned int)inlen, XDR_DECODE);
+ if (xdr_replymsg(xdrs, &msg)) {
+ if ((msg.rm_xid == xid) &&
+ (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (msg.acpted_rply.ar_stat == SUCCESS)) {
+ raddr.sin_port = htons((unsigned short)port);
+ done = (*eachresult)(resultsp, &raddr);
+ }
+ /* otherwise, we just ignore the errors ... */
+ } else {
+#ifdef notdef
+ /* some kind of deserialization problem ... */
+ if (msg.rm_xid == xid)
+ fprintf(stderr, "Broadcast deserialization problem");
+ /* otherwise, just random garbage */
+#endif
+ }
+ xdrs->x_op = XDR_FREE;
+ msg.acpted_rply.ar_results.proc = xdr_void;
+ (void)xdr_replymsg(xdrs, &msg);
+ (void)(*xresults)(xdrs, resultsp);
+ xdr_destroy(xdrs);
+ if (done) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ } else {
+ goto recv_again;
+ }
+ }
+done_broad:
+ (void)close(sock);
+ AUTH_DESTROY(unix_auth);
+ return (stat);
+}
+
diff --git a/src/lib/rpc/pmap_rmt.h b/src/lib/rpc/pmap_rmt.h
new file mode 100644
index 000000000..2ea22120e
--- /dev/null
+++ b/src/lib/rpc/pmap_rmt.h
@@ -0,0 +1,53 @@
+/* @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+struct rmtcallargs {
+ rpc_u_int32 prog, vers, proc, arglen;
+ caddr_t args_ptr;
+ xdrproc_t xdr_args;
+};
+
+bool_t xdr_rmtcall_args();
+
+struct rmtcallres {
+ rpc_u_int32 *port_ptr;
+ rpc_u_int32 resultslen;
+ caddr_t results_ptr;
+ xdrproc_t xdr_results;
+};
+
+bool_t xdr_rmtcallres();
diff --git a/src/lib/rpc/rpc.h b/src/lib/rpc/rpc.h
new file mode 100644
index 000000000..d0280aaa0
--- /dev/null
+++ b/src/lib/rpc/rpc.h
@@ -0,0 +1,74 @@
+/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef __RPC_HEADER__
+#define __RPC_HEADER__
+
+#include <rpc/types.h> /* some typedefs */
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <rpc/xdr.h> /* generic (de)serializer */
+
+/* Client side only authentication */
+#include <rpc/auth.h> /* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <rpc/clnt.h> /* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <rpc/rpc_msg.h> /* protocol for rpc messages */
+#include <rpc/auth_unix.h> /* protocol for unix style cred */
+/*
+ * Uncomment-out the next line if you are building the rpc library with
+ * DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+/*#include <rpc/auth_des.h> protocol for des style cred */
+
+/* Server side only remote procedure callee */
+#include <rpc/svc_auth.h> /* service side authenticator */
+#include <rpc/svc.h> /* service manager and multiplexer */
+
+/*
+ * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION
+ * OF UNIX BASED ON NFSSRC. These systems will already have the structures
+ * defined by <rpc/netdb.h> included in <netdb.h>.
+ */
+/* routines for parsing /etc/rpc */
+#include <netdb.h>
+#include <rpc/netdb.h> /* structures and routines to parse /etc/rpc */
+
+#endif /* ndef __RPC_HEADER__ */
diff --git a/src/lib/rpc/rpc_callmsg.c b/src/lib/rpc/rpc_callmsg.c
new file mode 100644
index 000000000..370e79ff9
--- /dev/null
+++ b/src/lib/rpc/rpc_callmsg.c
@@ -0,0 +1,195 @@
+/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include <sys/param.h>
+
+#include <rpc/rpc.h>
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(xdrs, cmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+ register rpc_int32 *buf;
+ register struct opaque_auth *oa;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ buf = (rpc_int32 *) XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
+ + RNDUP(cmsg->rm_call.cb_cred.oa_length)
+ + 2 * BYTES_PER_XDR_UNIT
+ + RNDUP(cmsg->rm_call.cb_verf.oa_length));
+ if (buf != NULL) {
+ IXDR_PUT_LONG(buf, cmsg->rm_xid);
+ IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog);
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers);
+ IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc);
+ oa = &cmsg->rm_call.cb_cred;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memmove((caddr_t)buf, oa->oa_base,
+ oa->oa_length);
+ buf += RNDUP(oa->oa_length) / sizeof (rpc_int32);
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memmove((caddr_t)buf, oa->oa_base,
+ oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) / sizeof (rpc_int32);
+ */
+ }
+ return (TRUE);
+ }
+ }
+ if (xdrs->x_op == XDR_DECODE) {
+ buf = (rpc_int32 *) XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
+ if (buf != NULL) {
+ cmsg->rm_xid = IXDR_GET_LONG(buf);
+ cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf);
+ cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf);
+ cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf);
+ oa = &cmsg->rm_call.cb_cred;
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = IXDR_GET_LONG(buf);
+ if (oa->oa_length) {
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ }
+ buf = (rpc_int32 *)
+ XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, (caddr_t)buf,
+ oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) /
+ sizeof (rpc_int32);
+ */
+ }
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ buf = (rpc_int32 *)
+ XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
+ xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = IXDR_GET_LONG(buf);
+ }
+ if (oa->oa_length) {
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ }
+ buf = (rpc_int32 *)
+ XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, (caddr_t) buf,
+ oa->oa_length);
+ /* no real need...
+ buf += RNDUP(oa->oa_length) /
+ sizeof (rpc_int32);
+ */
+ }
+ }
+ return (TRUE);
+ }
+ }
+ if (
+ xdr_u_int32(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+ (cmsg->rm_direction == CALL) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_prog)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_vers)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_proc)) &&
+ xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
+ return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
+ return (FALSE);
+}
+
diff --git a/src/lib/rpc/rpc_commondata.c b/src/lib/rpc/rpc_commondata.c
new file mode 100644
index 000000000..75cead087
--- /dev/null
+++ b/src/lib/rpc/rpc_commondata.c
@@ -0,0 +1,41 @@
+/* @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#include <rpc/rpc.h>
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces
+ */
+struct opaque_auth _null_auth;
+#ifdef FD_SETSIZE
+fd_set svc_fdset;
+#else
+int svc_fds;
+#endif /* def FD_SETSIZE */
+struct rpc_createerr rpc_createerr;
diff --git a/src/lib/rpc/rpc_dtablesize.c b/src/lib/rpc/rpc_dtablesize.c
new file mode 100644
index 000000000..d252d6acd
--- /dev/null
+++ b/src/lib/rpc/rpc_dtablesize.c
@@ -0,0 +1,60 @@
+/* @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+#endif
+
+#include <unistd.h>
+
+/*
+ * Cache the result of getdtablesize(), so we don't have to do an
+ * expensive system call every time.
+ */
+_rpc_dtablesize()
+{
+ static int size;
+
+ if (size == 0) {
+#ifdef _SC_OPEN_MAX
+ size = (int) sysconf(_SC_OPEN_MAX);
+#else
+ size = getdtablesize();
+#endif
+
+/* sysconf() can return a number larger than what will fit in an
+ fd_set. we can't use fd's larger than this, anyway. */
+
+#ifdef FD_SETSIZE
+ if (size >= FD_SETSIZE)
+ size = FD_SETSIZE-1;
+#endif
+ }
+ return (size);
+}
diff --git a/src/lib/rpc/rpc_msg.h b/src/lib/rpc/rpc_msg.h
new file mode 100644
index 000000000..66b10c5fb
--- /dev/null
+++ b/src/lib/rpc/rpc_msg.h
@@ -0,0 +1,187 @@
+/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)rpc_msg.h 1.7 86/07/16 SMI */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#define RPC_MSG_VERSION ((rpc_u_int32) 2)
+#define RPC_SERVICE_PORT ((unsigned short) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+ CALL=0,
+ REPLY=1
+};
+
+enum reply_stat {
+ MSG_ACCEPTED=0,
+ MSG_DENIED=1
+};
+
+enum accept_stat {
+ SUCCESS=0,
+ PROG_UNAVAIL=1,
+ PROG_MISMATCH=2,
+ PROC_UNAVAIL=3,
+ GARBAGE_ARGS=4,
+ SYSTEM_ERR=5
+};
+
+enum reject_stat {
+ RPC_MISMATCH=0,
+ AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+ struct opaque_auth ar_verf;
+ enum accept_stat ar_stat;
+ union {
+ struct {
+ rpc_u_int32 low;
+ rpc_u_int32 high;
+ } AR_versions;
+ struct {
+ caddr_t where;
+ xdrproc_t proc;
+ } AR_results;
+ /* and many other null cases */
+ } ru;
+#define ar_results ru.AR_results
+#define ar_vers ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+ enum reject_stat rj_stat;
+ union {
+ struct {
+ rpc_u_int32 low;
+ rpc_u_int32 high;
+ } RJ_versions;
+ enum auth_stat RJ_why; /* why authentication did not work */
+ } ru;
+#define rj_vers ru.RJ_versions
+#define rj_why ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+ enum reply_stat rp_stat;
+ union {
+ struct accepted_reply RP_ar;
+ struct rejected_reply RP_dr;
+ } ru;
+#define rp_acpt ru.RP_ar
+#define rp_rjct ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+ rpc_u_int32 cb_rpcvers; /* must be equal to two */
+ rpc_u_int32 cb_prog;
+ rpc_u_int32 cb_vers;
+ rpc_u_int32 cb_proc;
+ struct opaque_auth cb_cred;
+ struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+ rpc_u_int32 rm_xid;
+ enum msg_type rm_direction;
+ union {
+ struct call_body RM_cmb;
+ struct reply_body RM_rmb;
+ } ru;
+#define rm_call ru.RM_cmb
+#define rm_reply ru.RM_rmb
+};
+#define acpted_rply ru.RM_rmb.ru.RP_ar
+#define rjcted_rply ru.RM_rmb.ru.RP_dr
+
+
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callmsg();
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callhdr();
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *rmsg;
+ */
+extern bool_t xdr_replymsg();
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * struct rpc_msg *msg;
+ * struct rpc_err *error;
+ */
+extern void _seterr_reply();
diff --git a/src/lib/rpc/rpc_prot.c b/src/lib/rpc/rpc_prot.c
new file mode 100644
index 000000000..6fea605e6
--- /dev/null
+++ b/src/lib/rpc/rpc_prot.c
@@ -0,0 +1,287 @@
+/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include <sys/param.h>
+
+#include <rpc/rpc.h>
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(xdrs, ap)
+ register XDR *xdrs;
+ register struct opaque_auth *ap;
+{
+
+ if (xdr_enum(xdrs, &(ap->oa_flavor)))
+ return (xdr_bytes(xdrs, &ap->oa_base,
+ &ap->oa_length, MAX_AUTH_BYTES));
+ return (FALSE);
+}
+
+/*
+ * XDR a DES block
+ */
+bool_t
+xdr_des_block(xdrs, blkp)
+ register XDR *xdrs;
+ register des_block *blkp;
+{
+ return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t
+xdr_accepted_reply(xdrs, ar)
+ register XDR *xdrs;
+ register struct accepted_reply *ar;
+{
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+ return (FALSE);
+ if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
+ return (FALSE);
+ switch (ar->ar_stat) {
+
+ case SUCCESS:
+ return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
+
+ case PROG_MISMATCH:
+ if (! xdr_u_int32(xdrs, &(ar->ar_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32(xdrs, &(ar->ar_vers.high)));
+ }
+ return (TRUE); /* TRUE => open ended set of problems */
+}
+
+/*
+ * XDR the MSG_DENIED part of a reply message union
+ */
+bool_t
+xdr_rejected_reply(xdrs, rr)
+ register XDR *xdrs;
+ register struct rejected_reply *rr;
+{
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
+ return (FALSE);
+ switch (rr->rj_stat) {
+
+ case RPC_MISMATCH:
+ if (! xdr_u_int32(xdrs, &(rr->rj_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32(xdrs, &(rr->rj_vers.high)));
+
+ case AUTH_ERROR:
+ return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
+ }
+ return (FALSE);
+}
+
+static struct xdr_discrim reply_dscrm[3] = {
+ { (int)MSG_ACCEPTED, xdr_accepted_reply },
+ { (int)MSG_DENIED, xdr_rejected_reply },
+ { __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(xdrs, rmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *rmsg;
+{
+ if (
+ xdr_u_int32(xdrs, &(rmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
+ (rmsg->rm_direction == REPLY) )
+ return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
+ (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t));
+ return (FALSE);
+}
+
+
+/*
+ * Serializes the "static part" of a call message header.
+ * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
+ * The rm_xid is not really static, but the user can easily munge on the fly.
+ */
+bool_t
+xdr_callhdr(xdrs, cmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+
+ cmsg->rm_direction = CALL;
+ cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ if (
+ (xdrs->x_op == XDR_ENCODE) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_prog)) )
+ return (xdr_u_int32(xdrs, &(cmsg->rm_call.cb_vers)));
+ return (FALSE);
+}
+
+/* ************************** Client utility routine ************* */
+
+static void
+accepted(acpt_stat, error)
+ register enum accept_stat acpt_stat;
+ register struct rpc_err *error;
+{
+
+ switch (acpt_stat) {
+
+ case PROG_UNAVAIL:
+ error->re_status = RPC_PROGUNAVAIL;
+ return;
+
+ case PROG_MISMATCH:
+ error->re_status = RPC_PROGVERSMISMATCH;
+ return;
+
+ case PROC_UNAVAIL:
+ error->re_status = RPC_PROCUNAVAIL;
+ return;
+
+ case GARBAGE_ARGS:
+ error->re_status = RPC_CANTDECODEARGS;
+ return;
+
+ case SYSTEM_ERR:
+ error->re_status = RPC_SYSTEMERROR;
+ return;
+
+ case SUCCESS:
+ error->re_status = RPC_SUCCESS;
+ return;
+ }
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (rpc_int32)MSG_ACCEPTED;
+ error->re_lb.s2 = (rpc_int32)acpt_stat;
+}
+
+static void
+rejected(rjct_stat, error)
+ register enum reject_stat rjct_stat;
+ register struct rpc_err *error;
+{
+
+ switch (rjct_stat) {
+
+ case RPC_VERSMISMATCH:
+ error->re_status = RPC_VERSMISMATCH;
+ return;
+
+ case AUTH_ERROR:
+ error->re_status = RPC_AUTHERROR;
+ return;
+ }
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (rpc_int32)MSG_DENIED;
+ error->re_lb.s2 = (rpc_int32)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+sunrpc_seterr_reply(msg, error)
+ register struct rpc_msg *msg;
+ register struct rpc_err *error;
+{
+
+ /* optimized for normal, SUCCESSful case */
+ switch (msg->rm_reply.rp_stat) {
+
+ case MSG_ACCEPTED:
+ if (msg->acpted_rply.ar_stat == SUCCESS) {
+ error->re_status = RPC_SUCCESS;
+ return;
+ };
+ accepted(msg->acpted_rply.ar_stat, error);
+ break;
+
+ case MSG_DENIED:
+ rejected(msg->rjcted_rply.rj_stat, error);
+ break;
+
+ default:
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (rpc_int32)(msg->rm_reply.rp_stat);
+ break;
+ }
+ switch (error->re_status) {
+
+ case RPC_VERSMISMATCH:
+ error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+ error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+ break;
+
+ case RPC_AUTHERROR:
+ error->re_why = msg->rjcted_rply.rj_why;
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ error->re_vers.low = msg->acpted_rply.ar_vers.low;
+ error->re_vers.high = msg->acpted_rply.ar_vers.high;
+ break;
+ }
+}
diff --git a/src/lib/rpc/svc.c b/src/lib/rpc/svc.c
new file mode 100644
index 000000000..cb4d877a7
--- /dev/null
+++ b/src/lib/rpc/svc.c
@@ -0,0 +1,492 @@
+/* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here. The xprt routines are
+ * for handling transport handles. The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <sys/errno.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <stdio.h>
+
+extern int errno;
+
+#ifdef FD_SETSIZE
+static SVCXPRT **xports;
+#else
+#define NOFILE 32
+
+static SVCXPRT *xports[NOFILE];
+#endif /* def FD_SETSIZE */
+
+#define NULL_SVC ((struct svc_callout *)0)
+#define RQCRED_SIZE 400 /* this size is excessive */
+
+/*
+ * The services list
+ * Each entry represents a set of procedures (an rpc program).
+ * The dispatch routine takes request structs and runs the
+ * apropriate procedure.
+ */
+static struct svc_callout {
+ struct svc_callout *sc_next;
+ rpc_u_int32 sc_prog;
+ rpc_u_int32 sc_vers;
+ void (*sc_dispatch)();
+} *svc_head;
+
+static struct svc_callout *svc_find();
+
+/* *************** SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(xprt)
+ SVCXPRT *xprt;
+{
+ register int sock = xprt->xp_sock;
+
+#ifdef FD_SETSIZE
+ if (xports == NULL) {
+ xports = (SVCXPRT **)
+ mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
+ }
+ if (sock < _rpc_dtablesize()) {
+ xports[sock] = xprt;
+ FD_SET(sock, &svc_fdset);
+ }
+#else
+ if (sock < NOFILE) {
+ xports[sock] = xprt;
+ svc_fds |= (1 << sock);
+ }
+#endif /* def FD_SETSIZE */
+
+}
+
+/*
+ * De-activate a transport handle.
+ */
+void
+xprt_unregister(xprt)
+ SVCXPRT *xprt;
+{
+ register int sock = xprt->xp_sock;
+
+#ifdef FD_SETSIZE
+ if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) {
+ xports[sock] = (SVCXPRT *)0;
+ FD_CLR(sock, &svc_fdset);
+ }
+#else
+ if ((sock < NOFILE) && (xports[sock] == xprt)) {
+ xports[sock] = (SVCXPRT *)0;
+ svc_fds &= ~(1 << sock);
+ }
+#endif /* def FD_SETSIZE */
+}
+
+
+/* ********************** CALLOUT list related stuff ************* */
+
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_register(xprt, prog, vers, dispatch, protocol)
+ SVCXPRT *xprt;
+ rpc_u_int32 prog;
+ rpc_u_int32 vers;
+ void (*dispatch)();
+ int protocol;
+{
+ struct svc_callout *prev;
+ register struct svc_callout *s;
+
+ if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
+ if (s->sc_dispatch == dispatch)
+ goto pmap_it; /* he is registering another xptr */
+ return (FALSE);
+ }
+ s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
+ if (s == (struct svc_callout *)0) {
+ return (FALSE);
+ }
+ s->sc_prog = prog;
+ s->sc_vers = vers;
+ s->sc_dispatch = dispatch;
+ s->sc_next = svc_head;
+ svc_head = s;
+pmap_it:
+ /* now register the information with the local binder service */
+ if (protocol) {
+ return (pmap_set(prog, vers, protocol, xprt->xp_port));
+ }
+ return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unregister(prog, vers)
+ rpc_u_int32 prog;
+ rpc_u_int32 vers;
+{
+ struct svc_callout *prev;
+ register struct svc_callout *s;
+
+ if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
+ return;
+ if (prev == NULL_SVC) {
+ svc_head = s->sc_next;
+ } else {
+ prev->sc_next = s->sc_next;
+ }
+ s->sc_next = NULL_SVC;
+ mem_free((char *) s, (unsigned int) sizeof(struct svc_callout));
+ /* now unregister the information with the local binder service */
+ (void)pmap_unset(prog, vers);
+}
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(prog, vers, prev)
+ rpc_u_int32 prog;
+ rpc_u_int32 vers;
+ struct svc_callout **prev;
+{
+ register struct svc_callout *s, *p;
+
+ p = NULL_SVC;
+ for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+ if ((s->sc_prog == prog) && (s->sc_vers == vers))
+ goto done;
+ p = s;
+ }
+done:
+ *prev = p;
+ return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(xprt, xdr_results, xdr_location)
+ register SVCXPRT *xprt;
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = SUCCESS;
+ rply.acpted_rply.ar_results.where = xdr_location;
+ rply.acpted_rply.ar_results.proc = xdr_results;
+ return (SVC_REPLY(xprt, &rply));
+}
+
+/*
+ * No procedure error reply
+ */
+void
+svcerr_noproc(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Can't decode args error reply
+ */
+void
+svcerr_decode(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Some system error
+ */
+void
+svcerr_systemerr(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = SYSTEM_ERR;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(xprt, why)
+ SVCXPRT *xprt;
+ enum auth_stat why;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_DENIED;
+ rply.rjcted_rply.rj_stat = AUTH_ERROR;
+ rply.rjcted_rply.rj_why = why;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Auth too weak error reply
+ */
+void
+svcerr_weakauth(xprt)
+ SVCXPRT *xprt;
+{
+
+ svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void
+svcerr_noprog(xprt)
+ register SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Program version mismatch error reply
+ */
+void
+svcerr_progvers(xprt, low_vers, high_vers)
+ register SVCXPRT *xprt;
+ rpc_u_int32 low_vers;
+ rpc_u_int32 high_vers;
+{
+ struct rpc_msg rply;
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROG_MISMATCH;
+ rply.acpted_rply.ar_vers.low = low_vers;
+ rply.acpted_rply.ar_vers.high = high_vers;
+ SVC_REPLY(xprt, &rply);
+}
+
+/* ******************* SERVER INPUT STUFF ******************* */
+
+/*
+ * Get server side input from some transport.
+ *
+ * Statement of authentication parameters management:
+ * This function owns and manages all authentication parameters, specifically
+ * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
+ * the "cooked" credentials (rqst->rq_clntcred).
+ * However, this function does not know the structure of the cooked
+ * credentials, so it make the following assumptions:
+ * a) the structure is contiguous (no pointers), and
+ * b) the cred structure size does not exceed RQCRED_SIZE bytes.
+ * In all events, all three parameters are freed upon exit from this routine.
+ * The storage is trivially management on the call stack in user land, but
+ * is mallocated in kernel land.
+ */
+
+void
+svc_getreq(rdfds)
+ int rdfds;
+{
+#ifdef FD_SETSIZE
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ readfds.fds_bits[0] = rdfds;
+ svc_getreqset(&readfds);
+#else
+ int readfds = rdfds & svc_fds;
+
+ svc_getreqset(&readfds);
+#endif /* def FD_SETSIZE */
+}
+
+void
+svc_getreqset(readfds)
+#ifdef FD_SETSIZE
+ fd_set *readfds;
+{
+#else
+ int *readfds;
+{
+ int readfds_local = *readfds;
+#endif /* def FD_SETSIZE */
+ enum xprt_stat stat;
+ struct rpc_msg msg;
+ int prog_found;
+ rpc_u_int32 low_vers;
+ rpc_u_int32 high_vers;
+ struct svc_req r;
+ register SVCXPRT *xprt;
+ rpc_u_int32 mask;
+ int bit;
+ rpc_u_int32 *maskp;
+ register int setsize;
+ register int sock;
+ bool_t no_dispatch;
+
+ char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
+ msg.rm_call.cb_cred.oa_base = cred_area;
+ msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
+ r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
+
+#ifdef FD_SETSIZE
+ setsize = _rpc_dtablesize();
+
+ maskp = (rpc_u_int32 *)readfds->fds_bits;
+ for (sock = 0; sock < setsize; sock += NFDBITS) {
+ for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) {
+ /* sock has input waiting */
+ xprt = xports[sock + bit - 1];
+#else
+ for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
+ if ((readfds_local & 1) != 0) {
+ /* sock has input waiting */
+ xprt = xports[sock];
+#endif /* def FD_SETSIZE */
+ /* now receive msgs from xprtprt (support batch calls) */
+ do {
+ if (SVC_RECV(xprt, &msg)) {
+
+ /* now find the exported program and call it */
+ register struct svc_callout *s;
+ enum auth_stat why;
+
+ r.rq_xprt = xprt;
+ r.rq_prog = msg.rm_call.cb_prog;
+ r.rq_vers = msg.rm_call.cb_vers;
+ r.rq_proc = msg.rm_call.cb_proc;
+ r.rq_cred = msg.rm_call.cb_cred;
+
+ /* in case _authenticate has been replaced
+ with an old-style version */
+ r.rq_xprt->xp_auth = &svc_auth_any;
+ no_dispatch = FALSE;
+
+ /* first authenticate the message */
+ why=_authenticate(&r, &msg, &no_dispatch);
+ if (why != AUTH_OK) {
+ svcerr_auth(xprt, why);
+ goto call_done;
+ } else if (no_dispatch) {
+ goto call_done;
+ }
+
+ /* now match message with a registered service*/
+ prog_found = FALSE;
+ low_vers = 0 - 1;
+ high_vers = 0;
+ for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
+ if (s->sc_prog == r.rq_prog) {
+ if (s->sc_vers == r.rq_vers) {
+ (*s->sc_dispatch)(&r, xprt);
+ goto call_done;
+ } /* found correct version */
+ prog_found = TRUE;
+ if (s->sc_vers < low_vers)
+ low_vers = s->sc_vers;
+ if (s->sc_vers > high_vers)
+ high_vers = s->sc_vers;
+ } /* found correct program */
+ }
+ /*
+ * if we got here, the program or version
+ * is not served ...
+ */
+ if (prog_found)
+ svcerr_progvers(xprt,
+ low_vers, high_vers);
+ else
+ svcerr_noprog(xprt);
+ /* Fall through to ... */
+ }
+ call_done:
+ if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+ SVC_DESTROY(xprt);
+ break;
+ }
+ } while (stat == XPRT_MOREREQS);
+ }
+ }
+}
diff --git a/src/lib/rpc/svc.h b/src/lib/rpc/svc.h
new file mode 100644
index 000000000..2114d6249
--- /dev/null
+++ b/src/lib/rpc/svc.h
@@ -0,0 +1,298 @@
+/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __SVC_HEADER__
+#define __SVC_HEADER__
+
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received. The two most notable transports are TCP and UDP; they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services. Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service; if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport. The request's program and version numbers must match
+ * those of the registered service. The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+enum xprt_stat {
+ XPRT_DIED,
+ XPRT_MOREREQS,
+ XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct {
+ int xp_sock;
+ unsigned short xp_port; /* associated port number */
+ struct xp_ops {
+ bool_t (*xp_recv)(); /* receive incomming requests */
+ enum xprt_stat (*xp_stat)(); /* get transport status */
+ bool_t (*xp_getargs)(); /* get arguments */
+ bool_t (*xp_reply)(); /* send reply */
+ bool_t (*xp_freeargs)();/* free mem allocated for args */
+ void (*xp_destroy)(); /* destroy this struct */
+ } *xp_ops;
+ int xp_addrlen; /* length of remote address */
+ struct sockaddr_in xp_raddr; /* remote address */
+ struct opaque_auth xp_verf; /* raw response verifier */
+ SVCAUTH *xp_auth; /* auth flavor of current req */
+ caddr_t xp_p1; /* private */
+ caddr_t xp_p2; /* private */
+} SVCXPRT;
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT *xprt;
+ * struct rpc_msg *msg;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ */
+#define SVC_RECV(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_GETARGS_REQ(xprt, req, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+#define svc_getargs_req(xprt, req, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_REPLY_REQ(xprt, req, msg) \
+ (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+#define svc_reply_req(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+
+
+/*
+ * Service request
+ */
+struct svc_req {
+ rpc_u_int32 rq_prog; /* service program number */
+ rpc_u_int32 rq_vers; /* service protocol version */
+ rpc_u_int32 rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ caddr_t rq_clntcred; /* read only cooked client cred */
+ caddr_t rq_svccred; /* read only cooked svc cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+
+ /* The request's auth flavor *should* be here, but the svc_req */
+ /* isn't passed around everywhere it is necessary. The */
+ /* transport *is* passed around, so the auth flavor it stored */
+ /* there. This means that the transport must be single */
+ /* threaded, but other parts of SunRPC already require that. */
+ /*SVCAUTH *rq_auth; associated auth flavor */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * rpc_u_int32 prog;
+ * rpc_u_int32 vers;
+ * void (*dispatch)();
+ * int protocol; like TCP or UDP, zero means do not register
+ */
+extern bool_t svc_register();
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * rpc_u_int32 prog;
+ * rpc_u_int32 vers;
+ */
+extern void svc_unregister();
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ * SVCXPRT *xprt;
+ */
+extern void xprt_register();
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ * SVCXPRT *xprt;
+ */
+extern void xprt_unregister();
+
+
+
+
+/*
+ * When the service routine is called, it must first check to see if
+ * it knows about the procedure; if not, it should call svcerr_noproc
+ * and return. If so, it should deserialize its arguments via
+ * SVC_GETARGS or the new SVC_GETARGS_REQ (both defined above). If
+ * the deserialization does not work, svcerr_decode should be called
+ * followed by a return. Successful decoding of the arguments should
+ * be followed the execution of the procedure's code and a call to
+ * svc_sendreply or the new svc_sendreply_req.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg. This message is sent when svc_sendreply is called.
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void; use
+ * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining. In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not. Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+extern bool_t svc_sendreply();
+extern void svcerr_decode();
+extern void svcerr_weakauth();
+extern void svcerr_noproc();
+extern void svcerr_progvers();
+extern void svcerr_auth();
+extern void svcerr_noprog();
+extern void svcerr_systemerr();
+
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine. The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided. It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select
+ */
+#ifdef FD_SETSIZE
+extern fd_set svc_fdset;
+#define svc_fds svc_fdset.fds_bits[0] /* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
+
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+extern void rpctest_service();
+
+extern void svc_getreq();
+extern void svc_getreqset(); /* takes fdset instead of int */
+extern void svc_run(); /* never returns */
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define RPC_ANYSOCK -1
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+extern SVCXPRT *svcraw_create();
+
+/*
+ * Udp based rpc.
+ */
+extern SVCXPRT *svcudp_create();
+extern SVCXPRT *svcudp_bufcreate();
+
+/*
+ * Tcp based rpc.
+ */
+extern SVCXPRT *svctcp_create();
+
+#endif /* !__SVC_HEADER__ */
diff --git a/src/lib/rpc/svc_auth.c b/src/lib/rpc/svc_auth.c
new file mode 100644
index 000000000..281d7cba4
--- /dev/null
+++ b/src/lib/rpc/svc_auth.c
@@ -0,0 +1,119 @@
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c 2.1 88/08/07 4.0 RPCSRC; from 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * svc_auth_nodes.c, Server-side rpc authenticator interface,
+ * *WITHOUT* DES authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+
+/*
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks
+ * like:
+ *
+ * enum auth_stat
+ * flavorx_auth(rqst, msg)
+ * register struct svc_req *rqst;
+ * register struct rpc_msg *msg;
+ *
+ */
+
+enum auth_stat _svcauth_null(); /* no authentication */
+enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */
+enum auth_stat _svcauth_short(); /* short hand unix style */
+enum auth_stat _svcauth_gssapi(); /* GSS-API style */
+
+static struct svcauthsw_type {
+ unsigned int flavor;
+ enum auth_stat (*authenticator)();
+} svcauthsw[] = {
+ AUTH_GSSAPI, _svcauth_gssapi, /* AUTH_GSSAPI */
+ AUTH_NONE, _svcauth_null, /* AUTH_NULL */
+ AUTH_GSSAPI_COMPAT, _svcauth_gssapi, /* AUTH_GSSAPI_COMPAT */
+ AUTH_UNIX, _svcauth_unix, /* AUTH_UNIX */
+ AUTH_SHORT, _svcauth_short, /* AUTH_SHORT */
+};
+static int svcauthnum = sizeof(svcauthsw) / sizeof(struct svcauthsw_type);
+
+/*
+ * The call rpc message, msg has been obtained from the wire. The msg contains
+ * the raw form of credentials and verifiers. authenticate returns AUTH_OK
+ * if the msg is successfully authenticated. If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf. The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ */
+enum auth_stat
+_authenticate(rqst, msg, no_dispatch)
+ register struct svc_req *rqst;
+ struct rpc_msg *msg;
+ bool_t *no_dispatch;
+{
+ register int cred_flavor, i;
+
+ rqst->rq_cred = msg->rm_call.cb_cred;
+ rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ cred_flavor = rqst->rq_cred.oa_flavor;
+ *no_dispatch = FALSE;
+ for (i = 0; i < svcauthnum; i++) {
+ if (cred_flavor == svcauthsw[i].flavor &&
+ svcauthsw[i].authenticator != NULL) {
+ return ((*(svcauthsw[i].authenticator))(rqst,
+ msg,
+ no_dispatch));
+ }
+ }
+
+ return (AUTH_REJECTEDCRED);
+}
+
+enum auth_stat
+_svcauth_null(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+ return (AUTH_OK);
+}
diff --git a/src/lib/rpc/svc_auth.h b/src/lib/rpc/svc_auth.h
new file mode 100644
index 000000000..4d5963144
--- /dev/null
+++ b/src/lib/rpc/svc_auth.h
@@ -0,0 +1,61 @@
+/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)svc_auth.h 1.6 86/07/16 SMI */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Interface to server-side authentication flavors.
+ */
+typedef struct {
+ struct svc_auth_ops {
+ int (*svc_ah_wrap)();
+ int (*svc_ah_unwrap)();
+ } *svc_ah_ops;
+ caddr_t svc_ah_private;
+} SVCAUTH;
+
+extern SVCAUTH svc_auth_any;
+
+/*
+ * Server side authenticator
+ */
+extern enum auth_stat _authenticate();
+
+#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, xdrs, xfunc, xwhere))
+
+
diff --git a/src/lib/rpc/svc_auth_any.c b/src/lib/rpc/svc_auth_any.c
new file mode 100644
index 000000000..2f0a66dc8
--- /dev/null
+++ b/src/lib/rpc/svc_auth_any.c
@@ -0,0 +1,22 @@
+/*
+ * svc_auth_any.c
+ * Provides default service-side functions for authentication flavors
+ * that do not use all the fields in struct svc_auth_ops.
+ *
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+extern int authany_wrap();
+
+struct svc_auth_ops svc_auth_any_ops = {
+ authany_wrap,
+ authany_wrap,
+};
+
+SVCAUTH svc_auth_any = {
+ &svc_auth_any_ops,
+ NULL,
+};
diff --git a/src/lib/rpc/svc_auth_gssapi.c b/src/lib/rpc/svc_auth_gssapi.c
new file mode 100644
index 000000000..07cf59ab8
--- /dev/null
+++ b/src/lib/rpc/svc_auth_gssapi.c
@@ -0,0 +1,1181 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.37 1996/07/22 20:41:00 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.36.4.1 1996/07/18 04:19:34 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.36.2.1 1996/06/20 23:39:22 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.36 1996/05/30 19:25:02 bjaspan
+ * zero bindings structure before using it
+ *
+ * Revision 1.35 1996/05/12 06:17:25 marc
+ * changed around the file includes, since krb5 has changed some.
+ *
+ * added conditionalization GSS_BACKWARD_HACK until and if this hack is
+ * reimplemented in the newly merged gssapi.
+ *
+ * conditionalize out the host-specific cruft for setting the local
+ * address to INADDR_ANY, since you can just assign it that way on all
+ * platforms I know of.
+ *
+ * Revision 1.34 1996/02/12 15:14:00 grier
+ * [secure/3570]
+ * restore (struct sockaddr *) cast that got mangled
+ *
+ * Revision 1.33 1996/02/07 13:09:52 jik
+ * Actually, I should have used krb5_error_code, not krb5_int32.
+ *
+ * Revision 1.32 1996/02/07 13:08:31 jik
+ * Include <krb5/krb5.h> to get the krb5_int32 typedef, which we then use
+ * in a cast when checking if the GSS-API minor status value is equal to
+ * a krb5 error code.
+ *
+ * Revision 1.31 1996/02/01 18:29:29 grier
+ * Restore use of error code definition.
+ * Return original code structure.
+ *
+ * Revision 1.30 1996/01/31 19:15:49 grier
+ * [secure/3570]
+ * Remove (void *) casts to memcpy() args
+ *
+ * Revision 1.29 1996/01/25 03:58:04 grier
+ * Remove debug code
+ *
+ * Revision 1.28 1996/01/25 03:56:50 grier
+ * secure/3570 - missed Alpha checkin
+ *
+ * Revision 1.26 1995/11/07 23:17:23 grier
+ * memcpy() cast
+ *
+ * Revision 1.25 1995/08/24 21:05:48 bjaspan
+ * set acceptor channel bindings
+ *
+ * Revision 1.24 1995/08/23 20:28:02 bjaspan
+ * [secure-rpc/3392] add channel bindinds to the rpc
+ *
+ * Revision 1.23 1995/07/10 18:49:22 bjaspan
+ * [secure-build/3377] remove use of BSD db
+ *
+ * Revision 1.22 1995/05/25 18:35:53 bjaspan
+ * [secure-rpc/3103] log misc errors from RPC
+ *
+ * Revision 1.21 1995/05/24 17:34:03 bjaspan
+ * [secure-rpc/3302] don't allow client to make server exit unless
+ * debugging is enabled
+ *
+ * Revision 1.20 1995/05/08 22:32:44 marc
+ * if a new client is in use, set the krb5 gssapi mech into
+ * backward-compatibility mode.
+ *
+ * Revision 1.19 1994/10/27 12:38:51 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.22 1994/10/26 20:03:27 bjaspan
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.21 1994/05/23 01:26:01 bjaspan
+ * [secure-rpc/1911] set rq_svccred to the context instead of the service
+ * gss name
+ *
+ * Revision 1.20 1994/05/09 17:48:39 shanzer
+ * change sys/fcntl.h to fcntl.h
+ *
+ * Revision 1.19 1994/04/08 17:21:32 bjaspan
+ * remove KRB5KTNAME hack
+ *
+ * Revision 1.18 1994/03/18 15:48:13 shanzer
+ * include sys/fcntl.h
+ *
+ * Revision 1.17 1994/03/08 00:05:56 shanzer
+ * call rand() instead random()
+ *
+ * Revision 1.16 1993/12/08 21:43:54 bjaspan
+ * gss_delete_sec_context failure is not fatal (in fact, the context
+ * will often be expired); use AUTH_GSSAPI_DISPLAY_STATUS macro
+ *
+ * Revision 1.15 1993/12/08 20:20:08 bjaspan
+ * add debugging info to expire_client, correct comment above btree->put
+ *
+ * Revision 1.14 1993/12/08 06:52:49 bjaspan
+ * *many* debugging improvements to help find secure-rpc/586, and (I hope)
+ * the fix: don't change client_data->expiration without deleting it
+ * and reinserting it into the btree
+ *
+ * Revision 1.13 1993/12/06 21:22:26 bjaspan
+ * debugging levels, #ifdef PURIFY, call abort() on impossible failures
+ *
+ * Revision 1.12 1993/11/12 02:33:14 bjaspan
+ * add badauth
+ * /
+ *
+ * Revision 1.11 1993/11/03 23:46:15 bjaspan
+ * new log_badverf format
+ *
+ * Revision 1.10 1993/11/03 21:23:30 bjaspan
+ * handle GSS_C_INDEFINITE expiration, add log_badverf, set rq_svccred
+ *
+ * Revision 1.9 1993/11/03 01:30:36 bjaspan
+ * don't include gssapi_krb5.h, it isn't needed
+ *
+ * Revision 1.8 1993/11/02 22:09:02 bjaspan
+ * support multiple service-side names via _svcauth_gssapi_set_names
+ *
+ * Revision 1.7 1993/11/01 19:56:22 bjaspan
+ * unstatic svc_debug_gssapi, and send gss_{major,minor} back if
+ * accept_sec_context fails
+ *
+ * Revision 1.6 1993/10/28 22:09:58 bjaspan
+ * fix verifier mem leak, clean_clients() first to avoid dangling ref,
+ * only include hacked kt_default_name if DEBUG_GSSAPI defined
+ *
+ * Revision 1.5 1993/10/27 18:26:51 bjaspan
+ * use xdr_free instead of gss_release_buffer; this fixes memory leaks
+ * that were probably caused by zero-length seal/unseal tokens
+ *
+ * Revision 1.4 1993/10/26 21:12:51 bjaspan
+ * fully working
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+/*
+ * svc_auth_gssapi.c
+ * Handles the GSS-API flavor authentication parameters on the service
+ * side of RPC.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+
+#include <gssapi/gssapi_generic.h>
+#include <rpc/auth_gssapi.h>
+
+#ifdef GSS_BACKWARD_HACK
+#include <gssapi/gssapi_krb5.h>
+#endif
+
+/* This is here for the krb5_error_code typedef and the
+ KRB5KRB_AP_WRONG_PRINC #define.*/
+#include <krb5.h>
+
+#include <sys/file.h>
+#include <fcntl.h>
+
+#define INITIATION_TIMEOUT 60*15 /* seconds until partially created */
+ /* context is destroed */
+#define INDEF_EXPIRE 60*60*24 /* seconds until an context with no */
+ /* expiration time is expired */
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int svc_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (svc_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (svc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+typedef struct _svc_auth_gssapi_data {
+ bool_t established;
+
+ gss_ctx_id_t context;
+ gss_name_t client_name, server_name;
+ gss_cred_id_t server_creds;
+
+ rpc_u_int32 expiration;
+ rpc_u_int32 seq_num;
+ rpc_u_int32 key;
+
+ SVCAUTH svcauth;
+
+ /* kludge to free verifiers on next call */
+ gss_buffer_desc prev_verf;
+} svc_auth_gssapi_data;
+
+#define SVCAUTH_PRIVATE(auth) \
+ ((svc_auth_gssapi_data *)(auth)->svc_ah_private)
+
+static bool_t svc_auth_gssapi_wrap();
+static bool_t svc_auth_gssapi_unwrap();
+static svc_auth_gssapi_data *create_client();
+static svc_auth_gssapi_data *get_client(gss_buffer_t client_handle);
+static void destroy_client(svc_auth_gssapi_data *client_data);
+static void clean_client(), cleanup();
+static void client_expire(svc_auth_gssapi_data *client_data, rpc_u_int32 exp);
+static void dump_db(char *msg);
+
+struct svc_auth_ops svc_auth_gssapi_ops = {
+ svc_auth_gssapi_wrap,
+ svc_auth_gssapi_unwrap,
+};
+
+/*
+ * Globals! Eeek! Run for the hills!
+ */
+static gss_cred_id_t *server_creds_list = NULL;
+static gss_name_t *server_name_list = NULL;
+static int server_creds_count = 0;
+
+static auth_gssapi_log_badauth_func log_badauth = NULL;
+static caddr_t log_badauth_data = NULL;
+static auth_gssapi_log_badverf_func log_badverf = NULL;
+static caddr_t log_badverf_data = NULL;
+static auth_gssapi_log_miscerr_func log_miscerr = NULL;
+static caddr_t log_miscerr_data = NULL;
+
+#define LOG_MISCERR(arg) if (log_miscerr) \
+ (*log_miscerr)(rqst, msg, arg, log_miscerr_data)
+
+typedef struct _client_list {
+ svc_auth_gssapi_data *client;
+ struct _client_list *next;
+} client_list;
+
+static client_list *clients = NULL;
+
+extern int errno;
+
+enum auth_stat _svcauth_gssapi(rqst, msg, no_dispatch)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+ bool_t *no_dispatch;
+{
+ XDR xdrs;
+ auth_gssapi_creds creds;
+ auth_gssapi_init_arg call_arg;
+ auth_gssapi_init_res call_res;
+ gss_buffer_desc output_token, in_buf, out_buf;
+ gss_cred_id_t server_creds;
+ struct gss_channel_bindings_struct bindings, *bindp;
+ struct sockaddr_in sockname;
+ OM_uint32 gssstat, minor_stat, time_rec;
+ struct opaque_auth *cred, *verf;
+ svc_auth_gssapi_data *client_data;
+ int ret_flags, ret, i;
+ rpc_u_int32 seq_num;
+ int flag;
+
+ PRINTF(("svcauth_gssapi: starting\n"));
+
+ /* clean up expired entries */
+ clean_client();
+
+ /* use AUTH_NONE until there is a client_handle */
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+
+ memset((char *) &call_res, 0, sizeof(call_res));
+
+ cred = &msg->rm_call.cb_cred;
+ verf = &msg->rm_call.cb_verf;
+
+ if (cred->oa_length == 0) {
+ PRINTF(("svcauth_gssapi: empty creds, failing\n"));
+ LOG_MISCERR("empty client credentials");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: decoding credentials\n"));
+ xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE);
+ memset((char *) &creds, 0, sizeof(creds));
+ if (! xdr_authgssapi_creds(&xdrs, &creds)) {
+ PRINTF(("svcauth_gssapi: failed decoding creds\n"));
+ LOG_MISCERR("protocol error in client credentials");
+ XDR_DESTROY(&xdrs);
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+ XDR_DESTROY(&xdrs);
+
+ PRINTF(("svcauth_gssapi: got credentials, version %d, "
+ "client_handle len %d\n", creds.version,
+ creds.client_handle.length));
+
+ if (creds.version != 2) {
+ PRINTF(("svcauth_gssapi: bad credential version\n"));
+ LOG_MISCERR("unsupported client credentials version");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+#ifdef DEBUG_GSSAPI
+ if (svc_debug_gssapi) {
+ if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) {
+ PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n"));
+ svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+ xdr_free(xdr_authgssapi_creds, &creds);
+ cleanup();
+ exit(0);
+ }
+ }
+#endif
+
+ /*
+ * If this is an auth_msg and proc is GSSAPI_INIT, then create a
+ * client handle for this client. Otherwise, look up the
+ * existing handle.
+ */
+ if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_INIT) {
+ if (creds.client_handle.length != 0) {
+ PRINTF(("svcauth_gssapi: non-empty handle on GSSAPI_INIT\n"));
+ LOG_MISCERR("protocol error in client handle");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: GSSAPI_INIT, creating client.\n"));
+
+ client_data = create_client();
+ if (client_data == NULL) {
+ PRINTF(("svcauth_gssapi: create_client failed\n"));
+ LOG_MISCERR("internal error creating client record");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+ } else {
+ if (creds.client_handle.length == 0) {
+ PRINTF(("svcauth_gssapi: expected non-empty creds\n"));
+ LOG_MISCERR("protocol error in client credentials");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: incoming client_handle %d, len %d\n",
+ *((rpc_u_int32 *) creds.client_handle.value),
+ creds.client_handle.length));
+
+ client_data = get_client(&creds.client_handle);
+ if (client_data == NULL) {
+ PRINTF(("svcauth_gssapi: client_handle lookup failed\n"));
+ LOG_MISCERR("invalid client handle received");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+ PRINTF(("svcauth_gssapi: client_handle lookup succeeded\n"));
+ }
+
+ /* any response we send will use client_handle, so set it now */
+ call_res.client_handle.length = sizeof(client_data->key);
+ call_res.client_handle.value = (char *) &client_data->key;
+
+ /* mark this call as using AUTH_GSSAPI via client_data's SVCAUTH */
+ rqst->rq_xprt->xp_auth = &client_data->svcauth;
+
+ if (client_data->established == FALSE) {
+ PRINTF(("svcauth_gssapi: context is not established\n"));
+
+ if (creds.auth_msg == FALSE) {
+ PRINTF(("svcauth_gssapi: expected auth_msg TRUE\n"));
+ LOG_MISCERR("protocol error on incomplete connection");
+ ret = AUTH_REJECTEDCRED;
+ goto error;
+ }
+
+ /*
+ * If the context is not established, then only GSSAPI_INIT
+ * and _CONTINUE requests are valid.
+ */
+ if (rqst->rq_proc != AUTH_GSSAPI_INIT && rqst->rq_proc !=
+ AUTH_GSSAPI_CONTINUE_INIT) {
+ PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
+ rqst->rq_proc));
+ LOG_MISCERR("protocol error on incomplete connection");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ /* call is for us, deserialize arguments */
+ memset(&call_arg, 0, sizeof(call_arg));
+ if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
+ &call_arg)) {
+ PRINTF(("svcauth_gssapi: cannot decode args\n"));
+ LOG_MISCERR("protocol error in procedure arguments");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+ /*
+ * Process the call arg version number.
+ *
+ * Set the krb5_gss backwards-compatibility mode based on client
+ * version. This controls whether the AP_REP message is
+ * encrypted with the session key (version 2+, correct) or the
+ * session subkey (version 1, incorrect). This function can
+ * never fail, so we don't bother checking its return value.
+ */
+ switch (call_arg.version) {
+ case 1:
+ case 2:
+ LOG_MISCERR("Warning: Accepted old RPC protocol request");
+ call_res.version = 1;
+ break;
+ case 3:
+ call_res.version = call_arg.version;
+ break;
+ default:
+ PRINTF(("svcauth_gssapi: bad GSSAPI_INIT version\n"));
+ LOG_MISCERR("unsupported GSSAPI_INIT version");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+#ifdef GSS_BACKWARD_HACK
+ krb5_gss_set_backward_mode(&minor_stat, call_arg.version == 1);
+#endif
+
+ if (call_arg.version == 3) {
+ int len;
+
+ memset(&bindings, 0, sizeof(bindings));
+ bindings.application_data.length = 0;
+ bindings.initiator_addrtype = GSS_C_AF_INET;
+ bindings.initiator_address.length = 4;
+ bindings.initiator_address.value =
+ &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr;
+
+ len = sizeof(sockname);
+ if (getsockname(rqst->rq_xprt->xp_sock,
+ (struct sockaddr *) &sockname, &len) < 0) {
+ LOG_MISCERR("cannot get local address");
+ PRINTF(("svcauth_gssapi: errno %d while getting address",
+ errno));
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ bindings.acceptor_addrtype = GSS_C_AF_INET;
+ bindings.acceptor_address.length = 4;
+ bindings.acceptor_address.value = &sockname.sin_addr.s_addr;
+
+ bindp = &bindings;
+ } else {
+ bindp = GSS_C_NO_CHANNEL_BINDINGS;
+ }
+
+ /*
+ * If the client's server_creds is already set, use it.
+ * Otherwise, try each credential in server_creds_list until
+ * one of them succeedes, then set the client server_creds
+ * to that. If all fail, the client's server_creds isn't
+ * set (which is fine, because the client will be gc'ed
+ * anyway).
+ *
+ * If accept_sec_context returns something other than
+ * success and GSS_S_FAILURE, then assume different
+ * credentials won't help and stop looping.
+ *
+ * Note that there are really two cases here: (1) the client
+ * has a server_creds already, and (2) it does not. They
+ * are both written in the same loop so that there is only
+ * one textual call to gss_accept_sec_context; in fact, in
+ * case (1), the loop is executed exactly once.
+ */
+ for (i = 0; i < server_creds_count; i++) {
+ if (client_data->server_creds != NULL) {
+ PRINTF(("svcauth_gssapi: using's clients server_creds\n"));
+ server_creds = client_data->server_creds;
+ } else {
+ PRINTF(("svcauth_gssapi: trying creds %d\n", i));
+ server_creds = server_creds_list[i];
+ }
+
+ call_res.gss_major =
+ gss_accept_sec_context(&call_res.gss_minor,
+ &client_data->context,
+ server_creds,
+ &call_arg.token,
+ bindp,
+ &client_data->client_name,
+ NULL,
+ &output_token,
+ &ret_flags,
+ &time_rec,
+ NULL);
+
+ if (server_creds == client_data->server_creds)
+ break;
+
+ if (call_res.gss_major == GSS_S_COMPLETE ||
+ call_res.gss_major == GSS_S_CONTINUE_NEEDED) {
+ /* server_creds was right, set it! */
+ PRINTF(("svcauth_gssapi: creds are correct, storing\n"));
+ client_data->server_creds = server_creds;
+ client_data->server_name = server_name_list[i];
+ break;
+ } else if (call_res.gss_major != GSS_S_FAILURE ||
+ /*
+ * XXX hard-coded because there is no other
+ * way to prevent all GSS_S_FAILURES from
+ * returning a "wrong principal in request"
+ * error
+ */
+ ((krb5_error_code) call_res.gss_minor !=
+ (krb5_error_code) KRB5KRB_AP_WRONG_PRINC)) {
+ break;
+ }
+ }
+
+ gssstat = call_res.gss_major;
+ minor_stat = call_res.gss_minor;
+
+ /* done with call args */
+ xdr_free(xdr_authgssapi_init_arg, &call_arg);
+
+ PRINTF(("svcauth_gssapi: accept_sec_context returned %#x\n",
+ call_res.gss_major));
+ if (call_res.gss_major != GSS_S_COMPLETE &&
+ call_res.gss_major != GSS_S_CONTINUE_NEEDED) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("accepting context",
+ call_res.gss_major,
+ call_res.gss_minor));
+
+ if (log_badauth != NULL)
+ (*log_badauth)(call_res.gss_major,
+ call_res.gss_minor,
+ &rqst->rq_xprt->xp_raddr,
+ log_badauth_data);
+
+ svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
+ (caddr_t) &call_res);
+ *no_dispatch = TRUE;
+ ret = AUTH_OK;
+ goto error;
+ }
+
+ if (output_token.length != 0) {
+ PRINTF(("svcauth_gssapi: got new output token\n"));
+ GSS_COPY_BUFFER(call_res.token, output_token);
+ }
+
+ if (gssstat == GSS_S_COMPLETE) {
+ client_data->seq_num = rand();
+ client_expire(client_data,
+ (time_rec == GSS_C_INDEFINITE ?
+ INDEF_EXPIRE : time_rec) + time(0));
+
+ PRINTF(("svcauth_gssapi: context established, isn %d\n",
+ client_data->seq_num));
+
+ if (auth_gssapi_seal_seq(client_data->context,
+ client_data->seq_num,
+ &call_res.signed_isn) ==
+ FALSE) {
+ ret = AUTH_FAILED;
+ LOG_MISCERR("internal error sealing sequence number");
+ goto error;
+ }
+ }
+
+ PRINTF(("svcauth_gssapi: sending reply\n"));
+ svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
+ (caddr_t) &call_res);
+ *no_dispatch = TRUE;
+
+ /*
+ * If appropriate, set established to TRUE *after* sending
+ * response (otherwise, the client will receive the final
+ * token encrypted)
+ */
+ if (gssstat == GSS_S_COMPLETE) {
+ gss_release_buffer(&minor_stat, &call_res.signed_isn);
+ client_data->established = TRUE;
+ }
+ gss_release_buffer(&minor_stat, &output_token);
+ } else {
+ PRINTF(("svcauth_gssapi: context is established\n"));
+
+ /* check the verifier */
+ PRINTF(("svcauth_gssapi: checking verifier, len %d\n",
+ verf->oa_length));
+
+ in_buf.length = verf->oa_length;
+ in_buf.value = verf->oa_base;
+
+ if (auth_gssapi_unseal_seq(client_data->context, &in_buf,
+ &seq_num) == FALSE) {
+ ret = AUTH_BADVERF;
+ LOG_MISCERR("internal error unsealing sequence number");
+ goto error;
+ }
+
+ if (seq_num != client_data->seq_num + 1) {
+ PRINTF(("svcauth_gssapi: expected isn %d, got %d\n",
+ client_data->seq_num + 1, seq_num));
+ if (log_badverf != NULL)
+ (*log_badverf)(client_data->client_name,
+ client_data->server_name,
+ rqst, msg, log_badverf_data);
+
+ ret = AUTH_REJECTEDVERF;
+ goto error;
+ }
+ client_data->seq_num++;
+
+ PRINTF(("svcauth_gssapi: seq_num %d okay\n", seq_num));
+
+ /* free previous response verifier, if any */
+ if (client_data->prev_verf.length != 0) {
+ gss_release_buffer(&minor_stat, &client_data->prev_verf);
+ client_data->prev_verf.length = 0;
+ }
+
+ /* prepare response verifier */
+ seq_num = client_data->seq_num + 1;
+ if (auth_gssapi_seal_seq(client_data->context, seq_num,
+ &out_buf) == FALSE) {
+ ret = AUTH_FAILED;
+ LOG_MISCERR("internal error sealing sequence number");
+ goto error;
+ }
+
+ client_data->seq_num++;
+
+ PRINTF(("svcauth_gssapi; response seq_num %d\n", seq_num));
+
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_GSSAPI;
+ rqst->rq_xprt->xp_verf.oa_base = out_buf.value;
+ rqst->rq_xprt->xp_verf.oa_length = out_buf.length;
+
+ /* save verifier so it can be freed next time */
+ client_data->prev_verf.value = out_buf.value;
+ client_data->prev_verf.length = out_buf.length;
+
+ /*
+ * Message is authentic. If auth_msg if true, process the
+ * call; otherwise, return AUTH_OK so it will be dispatched
+ * to the application server.
+ */
+
+ if (creds.auth_msg == TRUE) {
+ /*
+ * If process_token fails, then the token probably came
+ * from an attacker. No response (error or otherwise)
+ * should be returned to the client, since it won't be
+ * accepting one.
+ */
+
+ switch (rqst->rq_proc) {
+ case AUTH_GSSAPI_MSG:
+ PRINTF(("svcauth_gssapi: GSSAPI_MSG, getting args\n"));
+ memset(&call_arg, 0, sizeof(call_arg));
+ if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
+ &call_arg)) {
+ PRINTF(("svcauth_gssapi: cannot decode args\n"));
+ LOG_MISCERR("protocol error in call arguments");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: processing token\n"));
+ gssstat = gss_process_context_token(&minor_stat,
+ client_data->context,
+ &call_arg.token);
+
+ /* done with call args */
+ xdr_free(xdr_authgssapi_init_arg, &call_arg);
+
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("processing token",
+ gssstat, minor_stat));
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+ *no_dispatch = TRUE;
+ break;
+
+ case AUTH_GSSAPI_DESTROY:
+ PRINTF(("svcauth_gssapi: GSSAPI_DESTROY\n"));
+
+ PRINTF(("svcauth_gssapi: sending reply\n"));
+ svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+ *no_dispatch = TRUE;
+
+ destroy_client(client_data);
+ break;
+
+ default:
+ PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
+ rqst->rq_proc));
+ LOG_MISCERR("invalid call procedure number");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+ } else {
+ /* set credentials for app server; comment in svc.c */
+ /* seems to imply this is incorrect, but I don't see */
+ /* any problem with it... */
+ rqst->rq_clntcred = (char *)client_data->client_name;
+ rqst->rq_svccred = (char *)client_data->context;
+ }
+ }
+
+ if (creds.client_handle.length != 0) {
+ PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
+ creds.client_handle.length));
+ xdr_free(xdr_authgssapi_creds, &creds);
+ }
+
+ PRINTF(("\n"));
+ return AUTH_OK;
+
+error:
+ if (creds.client_handle.length != 0) {
+ PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
+ creds.client_handle.length));
+ xdr_free(xdr_authgssapi_creds, &creds);
+ }
+
+ PRINTF(("\n"));
+ return ret;
+}
+
+static void cleanup()
+{
+ client_list *c, *c2;
+
+ PRINTF(("cleanup_and_exit: starting\n"));
+
+ c = clients;
+ while (c) {
+ c2 = c;
+ c = c->next;
+ destroy_client(c2->client);
+ free(c2);
+ }
+
+ exit(0);
+}
+
+/*
+ * Function: create_client
+ *
+ * Purpose: Creates an new client_data structure and stores it in the
+ * database.
+ *
+ * Returns: the new client_data structure, or NULL on failure.
+ *
+ * Effects:
+ *
+ * A new client_data is created and stored in the hash table and
+ * b-tree. A new key that is unique in the current database is
+ * chosen; this key should be used as the client's client_handle.
+ */
+static svc_auth_gssapi_data *create_client()
+{
+ client_list *c;
+ svc_auth_gssapi_data *client_data;
+ static int client_key = 1;
+ int ret;
+
+ PRINTF(("svcauth_gssapi: empty creds, creating\n"));
+
+ client_data = (svc_auth_gssapi_data *) malloc(sizeof(*client_data));
+ if (client_data == NULL)
+ return NULL;
+ memset((char *) client_data, 0, sizeof(*client_data));
+ L_PRINTF(2, ("create_client: new client_data = %#x\n", client_data));
+
+ /* set up client data structure */
+ client_data->established = 0;
+ client_data->context = GSS_C_NO_CONTEXT;
+ client_data->expiration = time(0) + INITIATION_TIMEOUT;
+
+ /* set up psycho-recursive SVCAUTH hack */
+ client_data->svcauth.svc_ah_ops = &svc_auth_gssapi_ops;
+ client_data->svcauth.svc_ah_private = (caddr_t) client_data;
+
+ client_data->key = client_key++;
+
+ c = (client_list *) malloc(sizeof(client_list));
+ if (c == NULL)
+ return NULL;
+ c->client = client_data;
+ c->next = NULL;
+
+
+ if (clients == NULL)
+ clients = c;
+ else {
+ c->next = clients;
+ clients = c;
+ }
+
+ PRINTF(("svcauth_gssapi: new handle %d\n", client_data->key));
+ L_PRINTF(2, ("create_client: done\n"));
+
+ return client_data;
+}
+
+/*
+ * Function: client_expire
+ *
+ * Purpose: change the expiration time of a client in the database
+ *
+ * Arguments:
+ *
+ * client_data (r) the client_data to expire
+ * exp (r) the new expiration time
+ *
+ * Effects:
+ *
+ * client_data->expiration = exp
+ *
+ * This function used to remove client_data from the database, change
+ * its expiration time, and re-add it, which was necessary because the
+ * database was sorted by expiration time so a simple modification
+ * would break the rep invariant. Now the database is an unsorted
+ * linked list, so it doesn't matter.
+ */
+static void client_expire(svc_auth_gssapi_data *client_data, rpc_u_int32 exp)
+{
+ client_data->expiration = exp;
+}
+
+/*
+ * Function get_client
+ *
+ * Purpose: retrieve a client_data structure from the database based
+ * on its client handle (key)
+ *
+ * Arguments:
+ *
+ * client_handle (r) the handle (key) to retrieve
+ *
+ * Effects:
+ *
+ * Searches the list and returns the client_data whose key field
+ * matches the contents of client_handle, or returns NULL if none was
+ * found.
+ */
+static svc_auth_gssapi_data *get_client(gss_buffer_t client_handle)
+{
+ client_list *c;
+ rpc_u_int32 handle;
+
+ memcpy(&handle, client_handle->value, 4);
+
+ L_PRINTF(2, ("get_client: looking for client %d\n", handle));
+
+ c = clients;
+ while (c) {
+ if (c->client->key == handle)
+ return c->client;
+ c = c->next;
+ }
+
+ L_PRINTF(2, ("get_client: client_handle lookup failed\n"));
+ return NULL;
+}
+
+/*
+ * Function: destroy_client
+ *
+ * Purpose: destroys a client entry and removes it from the database
+ *
+ * Arguments:
+ *
+ * client_data (r) the client to be destroyed
+ *
+ * Effects:
+ *
+ * client_data->context is deleted with gss_delete_sec_context.
+ * client_data's entry in the database is destroyed. client_data is
+ * freed.
+ */
+static void destroy_client(svc_auth_gssapi_data *client_data)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc out_buf;
+ client_list *c, *c2;
+ int ret;
+
+ PRINTF(("destroy_client: destroying client_data\n"));
+ L_PRINTF(2, ("destroy_client: client_data = %#x\n", client_data));
+
+#ifdef DEBUG_GSSAPI
+ if (svc_debug_gssapi >= 3)
+ dump_db("before frees");
+#endif
+
+ /* destroy client struct even if error occurs */
+
+ gssstat = gss_delete_sec_context(&minor_stat, &client_data->context,
+ &out_buf);
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
+ minor_stat));
+
+ gss_release_buffer(&minor_stat, &out_buf);
+ gss_release_name(&minor_stat, &client_data->client_name);
+ if (client_data->prev_verf.length != 0)
+ gss_release_buffer(&minor_stat, &client_data->prev_verf);
+
+ if (clients == NULL) {
+ PRINTF(("destroy_client: called on empty database\n"));
+ abort();
+ } else if (clients->client == client_data) {
+ c = clients;
+ clients = clients->next;
+ free(c);
+ } else {
+ c2 = clients;
+ c = clients->next;
+ while (c) {
+ if (c->client == client_data) {
+ c2->next = c->next;
+ free(c);
+ goto done;
+ } else
+ c = c->next;
+ }
+ PRINTF(("destroy_client: client_handle delete failed\n"));
+ abort();
+ }
+
+done:
+
+ L_PRINTF(2, ("destroy_client: client %d destroyed\n", client_data->key));
+
+ free(client_data);
+
+#ifdef PURIFY
+ purify_watch_n(client_data, sizeof(*client_data), "rw");
+#endif
+}
+
+static void dump_db(char *msg)
+{
+ svc_auth_gssapi_data *client_data;
+ client_list *c;
+
+ L_PRINTF(3, ("dump_db: %s:\n", msg));
+
+ c = clients;
+ while (c) {
+ client_data = c->client;
+ L_PRINTF(3, ("\tclient_data = %#x, exp = %d\n",
+ client_data, client_data->expiration));
+ c = c->next;
+ }
+
+ L_PRINTF(3, ("\n"));
+}
+
+static void clean_client()
+{
+ svc_auth_gssapi_data *client_data;
+ client_list *c;
+
+ PRINTF(("clean_client: starting\n"));
+
+ c = clients;
+ while (c) {
+ client_data = c->client;
+
+ L_PRINTF(2, ("clean_client: client_data = %#x\n",
+ client_data));
+
+ if (client_data->expiration < time(0)) {
+ PRINTF(("clean_client: client %d expired\n",
+ client_data->key));
+ destroy_client(client_data);
+ c = clients; /* start over, just to be safe */
+ } else {
+ c = c->next;
+ }
+ }
+
+done:
+ PRINTF(("clean_client: done\n"));
+}
+
+/*
+ * Function: _svcauth_gssapi_set_name
+ *
+ * Purpose: Sets the list of service names for which incoming
+ * authentication requests should be honored.
+ *
+ * See functional specifications.
+ */
+bool_t _svcauth_gssapi_set_names(auth_gssapi_name *names, int num)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc in_buf;
+ int i;
+
+ if (num == 0)
+ for (; names[num].name != NULL; num++)
+ ;
+
+ server_creds_list = NULL;
+ server_name_list = NULL;
+
+ server_creds_list = (gss_cred_id_t *) malloc(num*sizeof(gss_cred_id_t));
+ if (server_creds_list == NULL)
+ goto fail;
+ server_name_list = (gss_name_t *) malloc(num*sizeof(gss_name_t));
+ if (server_name_list == NULL)
+ goto fail;
+
+ for (i = 0; i < num; i++) {
+ in_buf.value = names[i].name;
+ in_buf.length = strlen(in_buf.value) + 1;
+
+ gssstat = gss_import_name(&minor_stat, &in_buf, names[i].type,
+ &server_name_list[i]);
+
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("importing name", gssstat,
+ minor_stat));
+ goto fail;
+ }
+
+ gssstat = gss_acquire_cred(&minor_stat, server_name_list[i], 0,
+ GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+ &server_creds_list[i], NULL, NULL);
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("acquiring credentials",
+ gssstat, minor_stat));
+ goto fail;
+ }
+ }
+
+ server_creds_count = num;
+
+ return TRUE;
+
+fail:
+ /* memory leak: not releasing names/creds already acquired */
+ if (server_creds_list)
+ free(server_creds_list);
+ if (server_name_list)
+ free(server_name_list);
+ return FALSE;
+}
+
+/*
+ * Function: _svcauth_gssapi_set_log_badauth_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void _svcauth_gssapi_set_log_badauth_func
+ (auth_gssapi_log_badauth_func func, caddr_t data)
+{
+ log_badauth = func;
+ log_badauth_data = data;
+}
+
+/*
+ * Function: _svcauth_gssapi_set_log_badverf_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void _svcauth_gssapi_set_log_badverf_func
+ (auth_gssapi_log_badverf_func func, caddr_t data)
+{
+ log_badverf = func;
+ log_badverf_data = data;
+}
+
+/*
+ * Function: _svcauth_gssapi_set_log_miscerr_func
+ *
+ * Purpose: sets the logging function called when a miscellaneous
+ * AUTH_GSSAPI error occurs
+ *
+ * See functional specifications.
+ */
+void _svcauth_gssapi_set_log_miscerr_func
+ (auth_gssapi_log_miscerr_func func, caddr_t data)
+{
+ log_miscerr = func;
+ log_miscerr_data = data;
+}
+
+/*
+ * Encrypt the serialized arguments from xdr_func applied to xdr_ptr
+ * and write the result to xdrs.
+ */
+static bool_t svc_auth_gssapi_wrap(auth, out_xdrs, xdr_func, xdr_ptr)
+ SVCAUTH *auth;
+ XDR *out_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ OM_uint32 gssstat, minor_stat;
+
+ if (! SVCAUTH_PRIVATE(auth)->established) {
+ PRINTF(("svc_gssapi_wrap: not established, noop\n"));
+ return (*xdr_func)(out_xdrs, xdr_ptr);
+ } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
+ SVCAUTH_PRIVATE(auth)->context,
+ SVCAUTH_PRIVATE(auth)->seq_num,
+ out_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
+
+static bool_t svc_auth_gssapi_unwrap(auth, in_xdrs, xdr_func, xdr_ptr)
+ SVCAUTH *auth;
+ XDR *in_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth);
+ OM_uint32 gssstat, minor_stat;
+
+ if (! client_data->established) {
+ PRINTF(("svc_gssapi_unwrap: not established, noop\n"));
+ return (*xdr_func)(in_xdrs, (auth_gssapi_init_arg *) xdr_ptr);
+ } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
+ client_data->context,
+ client_data->seq_num-1,
+ in_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
diff --git a/src/lib/rpc/svc_auth_unix.c b/src/lib/rpc/svc_auth_unix.c
new file mode 100644
index 000000000..1ff21588c
--- /dev/null
+++ b/src/lib/rpc/svc_auth_unix.c
@@ -0,0 +1,137 @@
+/* @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC; from 1.28 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_auth_unix.c
+ * Handles UNIX flavor authentication parameters on the service side of rpc.
+ * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
+ * _svcauth_unix does full blown unix style uid,gid+gids auth,
+ * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
+ * Note: the shorthand has been gutted for efficiency.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+_svcauth_unix(rqst, msg)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+{
+ register enum auth_stat stat;
+ XDR xdrs;
+ register struct authunix_parms *aup;
+ register rpc_int32 *buf;
+ struct area {
+ struct authunix_parms area_aup;
+ char area_machname[MAX_MACHINE_NAME+1];
+ int area_gids[NGRPS];
+ } *area;
+ unsigned int auth_len;
+ int str_len, gid_len;
+ register int i;
+
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+
+ area = (struct area *) rqst->rq_clntcred;
+ aup = &area->area_aup;
+ aup->aup_machname = area->area_machname;
+ aup->aup_gids = area->area_gids;
+ auth_len = (unsigned int)msg->rm_call.cb_cred.oa_length;
+ xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+ buf = (rpc_int32 *) XDR_INLINE(&xdrs, auth_len);
+ if (buf != NULL) {
+ aup->aup_time = IXDR_GET_LONG(buf);
+ str_len = IXDR_GET_U_LONG(buf);
+ if (str_len > MAX_MACHINE_NAME) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ memmove(aup->aup_machname, (caddr_t)buf, (unsigned int)str_len);
+ aup->aup_machname[str_len] = 0;
+ str_len = RNDUP(str_len);
+ buf += str_len / sizeof (rpc_int32);
+ aup->aup_uid = IXDR_GET_LONG(buf);
+ aup->aup_gid = IXDR_GET_LONG(buf);
+ gid_len = IXDR_GET_U_LONG(buf);
+ if (gid_len > NGRPS) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ aup->aup_len = gid_len;
+ for (i = 0; i < gid_len; i++) {
+ aup->aup_gids[i] = IXDR_GET_LONG(buf);
+ }
+ /*
+ * five is the smallest unix credentials structure -
+ * timestamp, hostname len (0), uid, gid, and gids len (0).
+ */
+ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
+ (void) printf("bad auth_len gid %d str %d auth %d\n",
+ gid_len, str_len, auth_len);
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ } else if (! xdr_authunix_parms(&xdrs, aup)) {
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_authunix_parms(&xdrs, aup);
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ stat = AUTH_OK;
+done:
+ XDR_DESTROY(&xdrs);
+ return (stat);
+}
+
+
+/*
+ * Shorthand unix authenticator
+ * Looks up longhand in a cache.
+ */
+/*ARGSUSED*/
+enum auth_stat
+_svcauth_short(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+ return (AUTH_REJECTEDCRED);
+}
diff --git a/src/lib/rpc/svc_raw.c b/src/lib/rpc/svc_raw.c
new file mode 100644
index 000000000..1170ecec8
--- /dev/null
+++ b/src/lib/rpc/svc_raw.c
@@ -0,0 +1,166 @@
+/* @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_raw.c, This a toy for simple testing and timing.
+ * Interface to create an rpc client and server in the same UNIX process.
+ * This lets us similate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernal.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+static struct svcraw_private {
+ char _raw_buf[UDPMSGSIZE];
+ SVCXPRT server;
+ XDR xdr_stream;
+ char verf_body[MAX_AUTH_BYTES];
+} *svcraw_private;
+
+static bool_t svcraw_recv();
+static enum xprt_stat svcraw_stat();
+static bool_t svcraw_getargs();
+static bool_t svcraw_reply();
+static bool_t svcraw_freeargs();
+static void svcraw_destroy();
+
+static struct xp_ops server_ops = {
+ svcraw_recv,
+ svcraw_stat,
+ svcraw_getargs,
+ svcraw_reply,
+ svcraw_freeargs,
+ svcraw_destroy
+};
+
+SVCXPRT *
+svcraw_create()
+{
+ register struct svcraw_private *srp = svcraw_private;
+
+ if (srp == 0) {
+ srp = (struct svcraw_private *)calloc(1, sizeof (*srp));
+ if (srp == 0)
+ return (0);
+ }
+ srp->server.xp_sock = 0;
+ srp->server.xp_port = 0;
+ srp->server.xp_ops = &server_ops;
+ srp->server.xp_verf.oa_base = srp->verf_body;
+ xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+ return (&srp->server);
+}
+
+static enum xprt_stat
+svcraw_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcraw_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcraw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (0);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+svcraw_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcraw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (FALSE);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_replymsg(xdrs, msg))
+ return (FALSE);
+ (void)XDR_GETPOS(xdrs); /* called just for overhead */
+ return (TRUE);
+}
+
+static bool_t
+svcraw_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register struct svcraw_private *srp = svcraw_private;
+
+ if (srp == 0)
+ return (FALSE);
+ return ((*xdr_args)(&srp->xdr_stream, args_ptr));
+}
+
+static bool_t
+svcraw_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register struct svcraw_private *srp = svcraw_private;
+ register XDR *xdrs;
+
+ if (srp == 0)
+ return (FALSE);
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcraw_destroy()
+{
+}
diff --git a/src/lib/rpc/svc_run.c b/src/lib/rpc/svc_run.c
new file mode 100644
index 000000000..d43aa2425
--- /dev/null
+++ b/src/lib/rpc/svc_run.c
@@ -0,0 +1,72 @@
+/* @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include <rpc/rpc.h>
+#include <sys/errno.h>
+
+void
+svc_run()
+{
+#ifdef FD_SETSIZE
+ fd_set readfds;
+#else
+ int readfds;
+#endif /* def FD_SETSIZE */
+ extern int errno;
+
+ for (;;) {
+#ifdef FD_SETSIZE
+ readfds = svc_fdset;
+#else
+ readfds = svc_fds;
+#endif /* def FD_SETSIZE */
+ switch (select(_rpc_dtablesize(), &readfds, (fd_set *)0,
+ (fd_set *)0, (struct timeval *)0)) {
+ case -1:
+ if (errno == EINTR) {
+ continue;
+ }
+ perror("svc_run: - select failed");
+ return;
+ case 0:
+ continue;
+ default:
+ svc_getreqset(&readfds);
+ }
+ }
+}
diff --git a/src/lib/rpc/svc_simple.c b/src/lib/rpc/svc_simple.c
new file mode 100644
index 000000000..2a22e5722
--- /dev/null
+++ b/src/lib/rpc/svc_simple.c
@@ -0,0 +1,143 @@
+/* @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_simple.c
+ * Simplified front end to rpc.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+static struct proglst {
+ char *(*p_progname)();
+ int p_prognum;
+ int p_procnum;
+ xdrproc_t p_inproc, p_outproc;
+ struct proglst *p_nxt;
+} *proglst;
+static void universal();
+static SVCXPRT *transp;
+struct proglst *pl;
+
+registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
+ char *(*progname)();
+ xdrproc_t inproc, outproc;
+{
+
+ if (procnum == NULLPROC) {
+ (void) fprintf(stderr,
+ "can't reassign procedure number %d\n", NULLPROC);
+ return (-1);
+ }
+ if (transp == 0) {
+ transp = svcudp_create(RPC_ANYSOCK);
+ if (transp == NULL) {
+ (void) fprintf(stderr, "couldn't create an rpc server\n");
+ return (-1);
+ }
+ }
+ (void) pmap_unset((rpc_u_int32)prognum, (rpc_u_int32)versnum);
+ if (!svc_register(transp, (rpc_u_int32)prognum, (rpc_u_int32)versnum,
+ universal, IPPROTO_UDP)) {
+ (void) fprintf(stderr, "couldn't register prog %d vers %d\n",
+ prognum, versnum);
+ return (-1);
+ }
+ pl = (struct proglst *)malloc(sizeof(struct proglst));
+ if (pl == NULL) {
+ (void) fprintf(stderr, "registerrpc: out of memory\n");
+ return (-1);
+ }
+ pl->p_progname = progname;
+ pl->p_prognum = prognum;
+ pl->p_procnum = procnum;
+ pl->p_inproc = inproc;
+ pl->p_outproc = outproc;
+ pl->p_nxt = proglst;
+ proglst = pl;
+ return (0);
+}
+
+static void
+universal(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ int prog, proc;
+ char *outdata;
+ char xdrbuf[UDPMSGSIZE];
+ struct proglst *pl;
+
+ /*
+ * enforce "procnum 0 is echo" convention
+ */
+ if (rqstp->rq_proc == NULLPROC) {
+ if (svc_sendreply(transp, xdr_void, (char *)NULL) == FALSE) {
+ (void) fprintf(stderr, "xxx\n");
+ exit(1);
+ }
+ return;
+ }
+ prog = rqstp->rq_prog;
+ proc = rqstp->rq_proc;
+ for (pl = proglst; pl != NULL; pl = pl->p_nxt)
+ if (pl->p_prognum == prog && pl->p_procnum == proc) {
+ /* decode arguments into a CLEAN buffer */
+ memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */
+ if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
+ svcerr_decode(transp);
+ return;
+ }
+ outdata = (*(pl->p_progname))(xdrbuf);
+ if (outdata == NULL && pl->p_outproc != xdr_void)
+ /* there was an error */
+ return;
+ if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
+ (void) fprintf(stderr,
+ "trouble replying to prog %d\n",
+ pl->p_prognum);
+ exit(1);
+ }
+ /* free the decoded arguments */
+ (void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
+ return;
+ }
+ (void) fprintf(stderr, "never registered prog %d\n", prog);
+ exit(1);
+}
+
diff --git a/src/lib/rpc/svc_tcp.c b/src/lib/rpc/svc_tcp.c
new file mode 100644
index 000000000..e20a29b19
--- /dev/null
+++ b/src/lib/rpc/svc_tcp.c
@@ -0,0 +1,453 @@
+/* @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_tcp.c, Server side for TCP/IP based RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdlib.h>
+/*extern bool_t abort();*.
+extern errno;
+
+/*
+ * Ops vector for TCP/IP based rpc service handle
+ */
+static bool_t svctcp_recv();
+static enum xprt_stat svctcp_stat();
+static bool_t svctcp_getargs();
+static bool_t svctcp_reply();
+static bool_t svctcp_freeargs();
+static void svctcp_destroy();
+
+static struct xp_ops svctcp_op = {
+ svctcp_recv,
+ svctcp_stat,
+ svctcp_getargs,
+ svctcp_reply,
+ svctcp_freeargs,
+ svctcp_destroy
+};
+
+/*
+ * Ops vector for TCP/IP rendezvous handler
+ */
+static bool_t rendezvous_request();
+static bool_t abortx();
+static enum xprt_stat rendezvous_stat();
+
+static struct xp_ops svctcp_rendezvous_op = {
+ rendezvous_request,
+ rendezvous_stat,
+ abortx,
+ abortx,
+ abortx,
+ svctcp_destroy
+};
+
+static int readtcp(), writetcp();
+static SVCXPRT *makefd_xprt();
+
+struct tcp_rendezvous { /* kept in xprt->xp_p1 */
+ unsigned int sendsize;
+ unsigned int recvsize;
+};
+
+struct tcp_conn { /* kept in xprt->xp_p1 */
+ enum xprt_stat strm_stat;
+ rpc_u_int32 x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+};
+
+/*
+ * Usage:
+ * xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register). This routine returns
+ * a NULL if a problem occurred.
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svctcp_create
+ * binds it to an arbitrary port. The routine then starts a tcp
+ * listener on the socket's associated port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ *
+ * Since tcp streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svctcp_create(sock, sendsize, recvsize)
+ register int sock;
+ unsigned int sendsize;
+ unsigned int recvsize;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct tcp_rendezvous *r;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ perror("svctcp_.c - udp socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset((char *)&addr, 0, sizeof (addr));
+ addr.sin_family = AF_INET;
+ if (bindresvport(sock, &addr)) {
+ addr.sin_port = 0;
+ (void)bind(sock, (struct sockaddr *)&addr, len);
+ }
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+ perror("svc_tcp.c - cannot getsockname");
+ if (madesock)
+ (void) close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ if (listen(sock, 2) != 0) {
+ perror("svctcp_.c - cannot listen");
+ if (madesock)
+ (void)close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ (void) fprintf(stderr, "svctcp_create: out of memory\n");
+ return (NULL);
+ }
+ r->sendsize = sendsize;
+ r->recvsize = recvsize;
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void) fprintf(stderr, "svctcp_create: out of memory\n");
+ return (NULL);
+ }
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)r;
+ xprt->xp_verf = _null_auth;
+ xprt->xp_ops = &svctcp_rendezvous_op;
+ xprt->xp_port = ntohs(addr.sin_port);
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svcfd_create(fd, sendsize, recvsize)
+ int fd;
+ unsigned int sendsize;
+ unsigned int recvsize;
+{
+
+ return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ unsigned int sendsize;
+ unsigned int recvsize;
+{
+ register SVCXPRT *xprt;
+ register struct tcp_conn *cd;
+
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == (SVCXPRT *)NULL) {
+ (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+ goto done;
+ }
+ cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
+ if (cd == (struct tcp_conn *)NULL) {
+ (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
+ mem_free((char *) xprt, sizeof(SVCXPRT));
+ xprt = (SVCXPRT *)NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ (caddr_t)xprt, readtcp, writetcp);
+ xprt->xp_p2 = NULL;
+ xprt->xp_p1 = (caddr_t)cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ xprt->xp_addrlen = 0;
+ xprt->xp_ops = &svctcp_op; /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_sock = fd;
+ xprt_register(xprt);
+ done:
+ return (xprt);
+}
+
+static bool_t
+rendezvous_request(xprt)
+ register SVCXPRT *xprt;
+{
+ int sock;
+ struct tcp_rendezvous *r;
+ struct sockaddr_in addr;
+ int len;
+
+ r = (struct tcp_rendezvous *)xprt->xp_p1;
+ again:
+ len = sizeof(struct sockaddr_in);
+ if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ return (FALSE);
+ }
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ xprt->xp_raddr = addr;
+ xprt->xp_addrlen = len;
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+static enum xprt_stat
+rendezvous_stat()
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svctcp_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
+
+ xprt_unregister(xprt);
+ (void)close(xprt->xp_sock);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ }
+ mem_free((caddr_t)cd, sizeof(struct tcp_conn));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+/*
+ * All read operations timeout after 35 seconds.
+ * A timeout is fatal for the connection.
+ */
+static struct timeval wait_per_try = { 35, 0 };
+
+/*
+ * reads data from the tcp conection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ */
+static int
+readtcp(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ register int len;
+{
+ register int sock = xprt->xp_sock;
+#ifdef FD_SETSIZE
+ fd_set mask;
+ fd_set readfds;
+
+ FD_ZERO(&mask);
+ FD_SET(sock, &mask);
+#else
+ register int mask = 1 << sock;
+ int readfds;
+#endif /* def FD_SETSIZE */
+ do {
+ readfds = mask;
+ if (select(_rpc_dtablesize(), &readfds, (fd_set*)NULL,
+ (fd_set*)NULL, &wait_per_try) <= 0) {
+ if (errno == EINTR) {
+ continue;
+ }
+ goto fatal_err;
+ }
+#ifdef FD_SETSIZE
+ } while (!FD_ISSET(sock, &readfds));
+#else
+ } while (readfds != mask);
+#endif /* def FD_SETSIZE */
+ if ((len = read(sock, buf, len)) > 0) {
+ return (len);
+ }
+fatal_err:
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+writetcp(xprt, buf, len)
+ register SVCXPRT *xprt;
+ caddr_t buf;
+ int len;
+{
+ register int i, cnt;
+
+ for (cnt = len; cnt > 0; cnt -= i, buf += i) {
+ if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
+ ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
+ XPRT_DIED;
+ return (-1);
+ }
+ }
+ return (len);
+}
+
+static enum xprt_stat
+svctcp_stat(xprt)
+ SVCXPRT *xprt;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+
+ if (cd->strm_stat == XPRT_DIED)
+ return (XPRT_DIED);
+ if (! xdrrec_eof(&(cd->xdrs)))
+ return (XPRT_MOREREQS);
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svctcp_recv(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_DECODE;
+ (void)xdrrec_skiprecord(xdrs);
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+static bool_t
+svctcp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ return (SVCAUTH_UNWRAP(xprt->xp_auth,
+ &(((struct tcp_conn *)(xprt->xp_p1))->xdrs),
+ xdr_args, args_ptr));
+}
+
+static bool_t
+svctcp_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs =
+ &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t svctcp_reply(xprt, msg)
+ SVCXPRT *xprt;
+ register struct rpc_msg *msg;
+{
+ register struct tcp_conn *cd =
+ (struct tcp_conn *)(xprt->xp_p1);
+ register XDR *xdrs = &(cd->xdrs);
+ register bool_t stat;
+
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+ bool_t has_args;
+
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ has_args = TRUE;
+ xdr_results = msg->acpted_rply.ar_results.proc;
+ xdr_location = msg->acpted_rply.ar_results.where;
+
+ msg->acpted_rply.ar_results.proc = xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+ } else
+ has_args = FALSE;
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = FALSE;
+ if (xdr_replymsg(xdrs, msg) &&
+ (!has_args ||
+ (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
+ stat = TRUE;
+ }
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
+
+static bool_t abortx()
+{
+ abort();
+ return 1;
+}
+
diff --git a/src/lib/rpc/svc_udp.c b/src/lib/rpc/svc_udp.c
new file mode 100644
index 000000000..d44c7f5d8
--- /dev/null
+++ b/src/lib/rpc/svc_udp.c
@@ -0,0 +1,496 @@
+/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc_udp.c,
+ * Server side for UDP/IP based RPC. (Does some caching in the hopes of
+ * achieving execute-at-most-once semantics.)
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+#ifndef MAX
+#define MAX(a, b) ((a > b) ? a : b)
+#endif
+
+static bool_t svcudp_recv();
+static bool_t svcudp_reply();
+static enum xprt_stat svcudp_stat();
+static bool_t svcudp_getargs();
+static bool_t svcudp_freeargs();
+static void svcudp_destroy();
+
+static void cache_set();
+static int cache_get();
+
+static struct xp_ops svcudp_op = {
+ svcudp_recv,
+ svcudp_stat,
+ svcudp_getargs,
+ svcudp_reply,
+ svcudp_freeargs,
+ svcudp_destroy
+};
+
+extern int errno;
+
+/*
+ * kept in xprt->xp_p2
+ */
+struct svcudp_data {
+ unsigned int su_iosz; /* byte size of send.recv buffer */
+ rpc_u_int32 su_xid; /* transaction id */
+ XDR su_xdrs; /* XDR handle */
+ char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
+ char * su_cache; /* cached data, NULL if no cache */
+};
+#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
+
+/*
+ * Usage:
+ * xprt = svcudp_create(sock);
+ *
+ * If sock<0 then a socket is created, else sock is used.
+ * If the socket, sock is not bound to a port then svcudp_create
+ * binds it to an arbitrary port. In any (successful) case,
+ * xprt->xp_sock is the registered socket number and xprt->xp_port is the
+ * associated port number.
+ * Once *xprt is initialized, it is registered as a transporter;
+ * see (svc.h, xprt_register).
+ * The routines returns NULL if a problem occurred.
+ */
+SVCXPRT *
+svcudp_bufcreate(sock, sendsz, recvsz)
+ register int sock;
+ unsigned int sendsz, recvsz;
+{
+ bool_t madesock = FALSE;
+ register SVCXPRT *xprt;
+ register struct svcudp_data *su;
+ struct sockaddr_in addr;
+ int len = sizeof(struct sockaddr_in);
+
+ if (sock == RPC_ANYSOCK) {
+ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+ perror("svcudp_create: socket creation problem");
+ return ((SVCXPRT *)NULL);
+ }
+ madesock = TRUE;
+ }
+ memset((char *)&addr, 0, sizeof (addr));
+ addr.sin_family = AF_INET;
+ if (bindresvport(sock, &addr)) {
+ addr.sin_port = 0;
+ (void)bind(sock, (struct sockaddr *)&addr, len);
+ }
+ if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
+ perror("svcudp_create - cannot getsockname");
+ if (madesock)
+ (void)close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
+ if (xprt == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ su = (struct svcudp_data *)mem_alloc(sizeof(*su));
+ if (su == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
+ if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
+ (void)fprintf(stderr, "svcudp_create: out of memory\n");
+ return (NULL);
+ }
+ xdrmem_create(
+ &(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
+ su->su_cache = NULL;
+ xprt->xp_p2 = (caddr_t)su;
+ xprt->xp_verf.oa_base = su->su_verfbody;
+ xprt->xp_ops = &svcudp_op;
+ xprt->xp_port = ntohs(addr.sin_port);
+ xprt->xp_sock = sock;
+ xprt_register(xprt);
+ return (xprt);
+}
+
+SVCXPRT *
+svcudp_create(sock)
+ int sock;
+{
+
+ return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
+}
+
+static enum xprt_stat
+svcudp_stat(xprt)
+ SVCXPRT *xprt;
+{
+
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svcudp_recv(xprt, msg)
+ register SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcudp_data *su = su_data(xprt);
+ register XDR *xdrs = &(su->su_xdrs);
+ register int rlen;
+ char *reply;
+ rpc_u_int32 replylen;
+
+ again:
+ xprt->xp_addrlen = sizeof(struct sockaddr_in);
+ rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
+ 0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
+ if (rlen == -1 && errno == EINTR)
+ goto again;
+ if (rlen < (int) 4*sizeof(rpc_u_int32))
+ return (FALSE);
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg))
+ return (FALSE);
+ su->su_xid = msg->rm_xid;
+ if (su->su_cache != NULL) {
+ if (cache_get(xprt, msg, &reply, &replylen)) {
+ (void) sendto(xprt->xp_sock, reply, (int) replylen, 0,
+ (struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
+ return (TRUE);
+ }
+ }
+ return (TRUE);
+}
+
+static bool_t svcudp_reply(xprt, msg)
+ register SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ register struct svcudp_data *su = su_data(xprt);
+ register XDR *xdrs = &(su->su_xdrs);
+ register int slen;
+ register bool_t stat = FALSE;
+
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+ bool_t has_args;
+
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ has_args = TRUE;
+ xdr_results = msg->acpted_rply.ar_results.proc;
+ xdr_location = msg->acpted_rply.ar_results.where;
+
+ msg->acpted_rply.ar_results.proc = xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+ } else
+ has_args = FALSE;
+
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ msg->rm_xid = su->su_xid;
+ if (xdr_replymsg(xdrs, msg) &&
+ (!has_args ||
+ (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
+ slen = (int)XDR_GETPOS(xdrs);
+ if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
+ (struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
+ == slen) {
+ stat = TRUE;
+ if (su->su_cache && slen >= 0) {
+ cache_set(xprt, (rpc_u_int32) slen);
+ }
+ }
+ }
+ return (stat);
+}
+
+static bool_t
+svcudp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ return (SVCAUTH_UNWRAP(xprt->xp_auth, &(su_data(xprt)->su_xdrs),
+ xdr_args, args_ptr));
+}
+
+static bool_t
+svcudp_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ register XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static void
+svcudp_destroy(xprt)
+ register SVCXPRT *xprt;
+{
+ register struct svcudp_data *su = su_data(xprt);
+
+ xprt_unregister(xprt);
+ (void)close(xprt->xp_sock);
+ XDR_DESTROY(&(su->su_xdrs));
+ mem_free(rpc_buffer(xprt), su->su_iosz);
+ mem_free((caddr_t)su, sizeof(struct svcudp_data));
+ mem_free((caddr_t)xprt, sizeof(SVCXPRT));
+}
+
+
+/***********this could be a separate file*********************/
+
+/*
+ * Fifo cache for udp server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4 /* 75% sparse */
+
+#define CACHE_PERROR(msg) \
+ (void) fprintf(stderr,"%s\n", msg)
+
+#define ALLOC(type, size) \
+ (type *) mem_alloc((unsigned) (sizeof(type) * (size)))
+
+#define BZERO(addr, type, size) \
+ memset((char *) addr, 0, sizeof(type) * (int) (size))
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+ /*
+ * Index into cache is xid, proc, vers, prog and address
+ */
+ rpc_u_int32 cache_xid;
+ rpc_u_int32 cache_proc;
+ rpc_u_int32 cache_vers;
+ rpc_u_int32 cache_prog;
+ struct sockaddr_in cache_addr;
+ /*
+ * The cached reply and length
+ */
+ char * cache_reply;
+ rpc_u_int32 cache_replylen;
+ /*
+ * Next node on the list, if there is a collision
+ */
+ cache_ptr cache_next;
+};
+
+
+
+/*
+ * The entire cache
+ */
+struct udp_cache {
+ rpc_u_int32 uc_size; /* size of cache */
+ cache_ptr *uc_entries; /* hash table of entries in cache */
+ cache_ptr *uc_fifo; /* fifo list of entries in cache */
+ rpc_u_int32 uc_nextvictim; /* points to next victim in fifo list */
+ rpc_u_int32 uc_prog; /* saved program number */
+ rpc_u_int32 uc_vers; /* saved version number */
+ rpc_u_int32 uc_proc; /* saved procedure number */
+ struct sockaddr_in uc_addr; /* saved caller's address */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid) \
+ (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
+
+
+/*
+ * Enable use of the cache.
+ * Note: there is no disable.
+ */
+svcudp_enablecache(transp, size)
+ SVCXPRT *transp;
+ rpc_u_int32 size;
+{
+ struct svcudp_data *su = su_data(transp);
+ struct udp_cache *uc;
+
+ if (su->su_cache != NULL) {
+ CACHE_PERROR("enablecache: cache already enabled");
+ return(0);
+ }
+ uc = ALLOC(struct udp_cache, 1);
+ if (uc == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache");
+ return(0);
+ }
+ uc->uc_size = size;
+ uc->uc_nextvictim = 0;
+ uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+ if (uc->uc_entries == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache data");
+ return(0);
+ }
+ BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ uc->uc_fifo = ALLOC(cache_ptr, size);
+ if (uc->uc_fifo == NULL) {
+ CACHE_PERROR("enablecache: could not allocate cache fifo");
+ return(0);
+ }
+ BZERO(uc->uc_fifo, cache_ptr, size);
+ su->su_cache = (char *) uc;
+ return(1);
+}
+
+
+/*
+ * Set an entry in the cache
+ */
+static void
+cache_set(xprt, replylen)
+ SVCXPRT *xprt;
+ rpc_u_int32 replylen;
+{
+ register cache_ptr victim;
+ register cache_ptr *vicp;
+ register struct svcudp_data *su = su_data(xprt);
+ struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+ unsigned int loc;
+ char *newbuf;
+
+ /*
+ * Find space for the new entry, either by
+ * reusing an old entry, or by mallocing a new one
+ */
+ victim = uc->uc_fifo[uc->uc_nextvictim];
+ if (victim != NULL) {
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ for (vicp = &uc->uc_entries[loc];
+ *vicp != NULL && *vicp != victim;
+ vicp = &(*vicp)->cache_next)
+ ;
+ if (*vicp == NULL) {
+ CACHE_PERROR("cache_set: victim not found");
+ return;
+ }
+ *vicp = victim->cache_next; /* remote from cache */
+ newbuf = victim->cache_reply;
+ } else {
+ victim = ALLOC(struct cache_node, 1);
+ if (victim == NULL) {
+ CACHE_PERROR("cache_set: victim alloc failed");
+ return;
+ }
+ newbuf = mem_alloc(su->su_iosz);
+ if (newbuf == NULL) {
+ CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
+ return;
+ }
+ }
+
+ /*
+ * Store it away
+ */
+ victim->cache_replylen = replylen;
+ victim->cache_reply = rpc_buffer(xprt);
+ rpc_buffer(xprt) = newbuf;
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE);
+ victim->cache_xid = su->su_xid;
+ victim->cache_proc = uc->uc_proc;
+ victim->cache_vers = uc->uc_vers;
+ victim->cache_prog = uc->uc_prog;
+ victim->cache_addr = uc->uc_addr;
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ victim->cache_next = uc->uc_entries[loc];
+ uc->uc_entries[loc] = victim;
+ uc->uc_fifo[uc->uc_nextvictim++] = victim;
+ uc->uc_nextvictim %= uc->uc_size;
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found
+ */
+static int
+cache_get(xprt, msg, replyp, replylenp)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+ char **replyp;
+ rpc_u_int32 *replylenp;
+{
+ unsigned int loc;
+ register cache_ptr ent;
+ register struct svcudp_data *su = su_data(xprt);
+ register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
+
+# define EQADDR(a1, a2) (memcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
+
+ loc = CACHE_LOC(xprt, su->su_xid);
+ for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+ if (ent->cache_xid == su->su_xid &&
+ ent->cache_proc == uc->uc_proc &&
+ ent->cache_vers == uc->uc_vers &&
+ ent->cache_prog == uc->uc_prog &&
+ EQADDR(ent->cache_addr, uc->uc_addr)) {
+ *replyp = ent->cache_reply;
+ *replylenp = ent->cache_replylen;
+ return(1);
+ }
+ }
+ /*
+ * Failed to find entry
+ * Remember a few things so we can do a set later
+ */
+ uc->uc_proc = msg->rm_call.cb_proc;
+ uc->uc_vers = msg->rm_call.cb_vers;
+ uc->uc_prog = msg->rm_call.cb_prog;
+ uc->uc_addr = xprt->xp_raddr;
+ return(0);
+}
+
diff --git a/src/lib/rpc/types.hin b/src/lib/rpc/types.hin
new file mode 100644
index 000000000..619a9ce20
--- /dev/null
+++ b/src/lib/rpc/types.hin
@@ -0,0 +1,90 @@
+/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)types.h 1.18 87/07/24 SMI */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef __TYPES_RPC_HEADER__
+#define __TYPES_RPC_HEADER__
+
+#include <sys/types.h>
+
+/* this is a 32-bit int type */
+
+#if @SIZEOF_INT@ == 4
+typedef int rpc_int32;
+typedef unsigned int rpc_u_int32;
+#elif @SIZEOF_LONG@ == 4
+typedef long rpc_int32;
+typedef unsigned long rpc_u_int32;
+#endif
+
+#define bool_t int
+#define enum_t int
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (1)
+#endif
+#define __dontcare__ -1
+#ifndef NULL
+# define NULL 0
+#endif
+
+#if defined(__osf__)
+#include <stdlib.h>
+#endif
+#define mem_alloc(bsize) (char *) malloc(bsize)
+#define mem_free(ptr, bsize) free(ptr)
+
+#ifndef makedev /* ie, we haven't already included it */
+#include <sys/types.h>
+#endif
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <sys/param.h>
+#include <netdb.h> /* XXX This should not have to be here.
+ * I got sick of seeing the warnings for MAXHOSTNAMELEN
+ * and the two values were different. -- shanzer
+ */
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (rpc_u_int32)0x7F000001
+#endif
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#endif /* ndef __TYPES_RPC_HEADER__ */
diff --git a/src/lib/rpc/unit-test/Makefile b/src/lib/rpc/unit-test/Makefile
new file mode 100644
index 000000000..31853cb35
--- /dev/null
+++ b/src/lib/rpc/unit-test/Makefile
@@ -0,0 +1,97 @@
+# Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+#
+# $Id$
+# $Source$
+#
+# $Log$
+# Revision 1.9 1996/07/22 20:41:38 marc
+# this commit includes all the changes on the OV_9510_INTEGRATION and
+# OV_MERGE branches. This includes, but is not limited to, the new openvision
+# admin system, and major changes to gssapi to add functionality, and bring
+# the implementation in line with rfc1964. before committing, the
+# code was built and tested for netbsd and solaris.
+#
+# Revision 1.8.4.1 1996/07/18 04:20:01 marc
+# merged in changes from OV_9510_BP to OV_9510_FINAL1
+#
+# Revision 1.8.2.1 1996/06/20 23:41:48 marc
+# File added to the repository on a branch
+#
+# Revision 1.8 1995/12/07 17:36:54 jik
+# Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on
+# some systems. See PR 3553.
+#
+# Revision 1.7 1995/10/02 08:02:49 jik
+# Delete rpc-tset_clnt.c, rpc-test_svc.c and rpc-test.h before creating
+# them, because rpcgen on some platforms won't output to a file that
+# already exists.
+#
+# Revision 1.6 1994/10/24 19:35:57 bjaspan
+# [secure-build/2649: cannot use -L when compiling]
+#
+# Sandbox:
+#
+# [secure-build/2649] don't use -L
+#
+# Revision 1.7 1994/10/11 20:06:14 bjaspan
+# [secure-build/2649] don't use -L
+#
+# Revision 1.6 1994/09/30 22:25:29 jik
+# Don't need to set MDFLAGS to -a anymore, because it's done
+# automatically by the rules now.
+#
+# Revision 1.5 1994/03/22 19:55:34 shanzer
+# change NETLIBS to NETLIB
+#
+# Revision 1.4 1994/03/18 17:47:00 shanzer
+# added NETLIBS and BSDLIB
+#
+# Revision 1.3 1993/12/13 02:00:39 bjaspan
+# recurse to testsuite subdir.
+#
+# Revision 1.2 1993/12/08 21:45:47 bjaspan
+# misc
+#
+# Revision 1.1 1993/11/03 23:53:58 bjaspan
+# Initial revision
+#
+
+TOP = ../..
+include $(TOP)/config.mk/template
+
+SUBDIRS = testsuite
+
+expand SubdirTarget
+
+SRCS = client.c server.c
+
+CFLAGS := -I../.. -I. $(CFLAGS)
+
+#LIBS = ../librpclib.a $(LIBGSSAPI_TRUST) $(LIBDB) $(LIBCOM_ERR) $(LIBDYN)
+LIBS = ../librpclib.a $(LIBGSSAPI_KRB5) $(LIBDB) $(LIBKRB5) \
+ $(LIBCRYPTO) $(LIBISODE) $(LIBCOM_ERR) $(LIBDYN) $(BSDLIB) $(NETLIB)
+DEPS = ../librpclib.a rpc_test.h
+DEPENDS = rpc_test.h
+
+PROG = client
+SRCS = client.c
+OBJS = client.o rpc_test_clnt.o
+
+expand Program
+expand Depend
+
+PROG = server
+SRCS = server.c
+OBJS = server.o rpc_test_svc.o
+
+expand Program
+expand Depend
+
+rpc_test.h rpc_test_clnt.c rpc_test_svc.c: rpc_test.x
+ -rm -f rpc_test_clnt.c rpc_test_svc.c rpc_test.h
+ rpcgen -l rpc_test.x -o rpc_test_clnt.c
+ rpcgen -m rpc_test.x -o rpc_test_svc.c
+ rpcgen -h rpc_test.x -o rpc_test.h
+
+clean::
+ rm -f rpc_test.h rpc_test_clnt.c rpc_test_svc.c
diff --git a/src/lib/rpc/unit-test/client.c b/src/lib/rpc/unit-test/client.c
new file mode 100644
index 000000000..bcf2700e5
--- /dev/null
+++ b/src/lib/rpc/unit-test/client.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.13 1996/07/22 20:41:40 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.12.4.1 1996/07/18 04:20:03 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.12.2.1 1996/06/20 23:41:56 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.12 1996/05/12 06:58:10 marc
+ * type renamings for compatibility with beta6
+ *
+ * Revision 1.11 1996/02/12 15:58:42 grier
+ * [secure/3570]
+ * long conversion
+ *
+ * Revision 1.10 1995/12/07 17:37:03 jik
+ * Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on
+ * some systems. See PR 3553.
+ *
+ * Revision 1.9 1994/09/21 18:38:56 bjaspan
+ * [secure-rpc/2536: unit test client.c: memory initialization and out-of-bounds reference bugs]
+ * [secure-releng/2537: audit secure-rpc/2536: minor memory problems in unit-test client]
+ *
+ * Sandbox:
+ *
+ * 1. Don't allow the count specifie on the command line to be bigger
+ * than the size of the buffer use for testing.
+ * 2. When initializing the buffer for the lengths test, initialize it to
+ * count bytes.
+ *
+ * Revision 1.9 1994/09/19 01:28:04 root
+ * 1. Don't allow the count specifie on the command line to be bigger
+ * than the size of the buffer use for testing.
+ * 2. When initializing the buffer for the lengths test, initialize it to
+ * count bytes.
+ *
+ * Revision 1.8 1994/04/06 22:13:01 jik
+ * Change -auth_once to -o, add -a, -m and -s arguments to set
+ * auth_debug_gssapi, svc_debug_gssapi and misc_debug_gssapi variables.
+ *
+ * Revision 1.7 1994/04/05 20:50:09 bjaspan
+ * fix typo that causes coredump when server blocks/fails
+ *
+ * Revision 1.6 1993/12/08 21:44:45 bjaspan
+ * test fix for secure-rpc/586, improve arg handlng
+ *
+ * Revision 1.5 1993/12/06 21:23:30 bjaspan
+ * accept count arg for RPC_TEST_LENGTHS
+ *
+ * Revision 1.4 1993/12/01 23:41:45 bjaspan
+ * don't free echo_resp if call fails
+ *
+ * Revision 1.3 1993/11/15 19:53:09 bjaspan
+ * test auto-syncrhonization
+ *
+ * Revision 1.2 1993/11/12 02:33:43 bjaspan
+ * use clnt_pcreateerror for auth failures
+ *
+ * Revision 1.1 1993/11/03 23:53:58 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <gssapi/gssapi.h>
+#include <rpc/rpc.h>
+#include <rpc/auth_gssapi.h>
+#include "rpc_test.h"
+
+#define BIG_BUF 4096
+/* copied from auth_gssapi.c for hackery */
+struct auth_gssapi_data {
+ bool_t established;
+ CLIENT *clnt;
+ gss_ctx_id_t context;
+ gss_buffer_desc client_handle;
+ OM_uint32 seq_num;
+ int def_cred;
+
+ /* pre-serialized ah_cred */
+ u_char cred_buf[MAX_AUTH_BYTES];
+ rpc_int32 cred_len;
+};
+#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
+
+extern int auth_debug_gssapi;
+char *whoami;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *host, *target, *echo_arg, **echo_resp, buf[BIG_BUF];
+ CLIENT *clnt;
+ AUTH *tmp_auth;
+ struct rpc_err e;
+ int i, count, auth_once;
+ extern int optind;
+ extern char *optarg;
+ extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi;
+ int c;
+
+ whoami = argv[0];
+ count = 1026;
+ auth_once = 0;
+
+ while ((c = getopt(argc, argv, "a:m:os:")) != -1) {
+ switch (c) {
+ case 'a':
+ auth_debug_gssapi = atoi(optarg);
+ break;
+ case 'm':
+ misc_debug_gssapi = atoi(optarg);
+ break;
+ case 'o':
+ auth_once++;
+ break;
+ case 's':
+ svc_debug_gssapi = atoi(optarg);
+ break;
+ case '?':
+ usage();
+ break;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ switch (argc) {
+ case 3:
+ count = atoi(argv[2]);
+ if (count > BIG_BUF) {
+ fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF);
+ usage();
+ }
+ case 2:
+ host = argv[0];
+ target = argv[1];
+ break;
+ default:
+ usage();
+ }
+
+ /* client handle to rstat */
+ clnt = clnt_create(host, RPC_TEST_PROG, RPC_TEST_VERS_1, "tcp");
+ if (clnt == NULL) {
+ clnt_pcreateerror(whoami);
+ exit(1);
+ }
+
+ clnt->cl_auth = auth_gssapi_create_default(clnt, target);
+ if (clnt->cl_auth == NULL) {
+ clnt_pcreateerror(whoami);
+ exit(2);
+ }
+
+ /*
+ * Call the echo service multiple times.
+ */
+ echo_arg = buf;
+ for (i = 0; i < 3; i++) {
+ sprintf(buf, "testing %d\n", i);
+
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL) {
+ fprintf(stderr, "RPC_TEST_ECHO call %d%s", i,
+ clnt_sperror(clnt, ""));
+ }
+ if (strncmp(*echo_resp, "Echo: ", 6) &&
+ strcmp(echo_arg, (*echo_resp) + 6) != 0)
+ fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: "
+ "arg = %s, resp = %s\n", echo_arg, *echo_resp);
+ xdr_free(xdr_wrapstring, echo_resp);
+ }
+
+ /*
+ * Make a call with an invalid verifier and check for error;
+ * server should log error message. It is important to
+ *increment* seq_num here, since a decrement would be fixed (see
+ * below). Note that seq_num will be incremented (by
+ * authg_gssapi_refresh) twice, so we need to decrement by three
+ * to reset.
+ */
+ AUTH_PRIVATE(clnt->cl_auth)->seq_num++;
+
+ echo_arg = "testing with bad verf";
+
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL) {
+ CLNT_GETERR(clnt, &e);
+ if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF)
+ clnt_perror(clnt, whoami);
+ } else {
+ fprintf(stderr, "bad seq didn't cause failure\n");
+ }
+
+ AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3;
+
+ /*
+ * Make sure we're resyncronized.
+ */
+ echo_arg = "testing for reset";
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL)
+ clnt_perror(clnt, "Sequence number improperly reset");
+
+ /*
+ * Now simulate a lost server response, and see if
+ * auth_gssapi_refresh recovers.
+ */
+ AUTH_PRIVATE(clnt->cl_auth)->seq_num--;
+ echo_arg = "forcing auto-resynchronization";
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL)
+ clnt_perror(clnt, "Auto-resynchronization failed");
+
+ /*
+ * Now make sure auto-resyncrhonization actually worked
+ */
+ echo_arg = "testing for resynchronization";
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL)
+ clnt_perror(clnt, "Auto-resynchronization did not work");
+
+ /*
+ * Test fix for secure-rpc/586, part 1: btree keys must be
+ * unique. Create another context from the same credentials; it
+ * should have the same expiration time and will cause the server
+ * to abort if the clients are not differentiated.
+ *
+ * Test fix for secure-rpc/586, part 2: btree keys cannot be
+ * mutated in place. To test this: a second client, *with a
+ * later expiration time*, must be run. The second client should
+ * destroy itself *after* the first one; if the key-mutating bug
+ * is not fixed, the second client_data will be in the btree
+ * before the first, but its key will be larger; thus, when the
+ * first client calls AUTH_DESTROY, the server won't find it in
+ * the btree and call abort.
+ *
+ * For unknown reasons, running just a second client didn't
+ * tickle the bug; the btree code seemed to guess which node to
+ * look at first. Running a total of three clients does ticket
+ * the bug. Thus, the full test sequence looks like this:
+ *
+ * kinit -l 20m user && client server test@ddn 200
+ * sleep 1
+ * kini -l 30m user && client server test@ddn 300
+ * sleep 1
+ * kinit -l 40m user && client server test@ddn 400
+ */
+ if (! auth_once) {
+ tmp_auth = clnt->cl_auth;
+ clnt->cl_auth = auth_gssapi_create_default(clnt, target);
+ if (clnt->cl_auth == NULL) {
+ clnt_pcreateerror(whoami);
+ exit(2);
+ }
+ AUTH_DESTROY(clnt->cl_auth);
+ clnt->cl_auth = tmp_auth;
+ }
+
+ /*
+ * Try RPC calls with argument/result lengths [0, 1025]. Do
+ * this last, since it takes a while..
+ */
+ echo_arg = buf;
+ memset(buf, 0, count);
+ for (i = 0; i < count; i++) {
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL) {
+ fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i,
+ clnt_sperror(clnt, ""));
+ break;
+ } else {
+ if (strncmp(*echo_resp, "Echo: ", 6) &&
+ strcmp(echo_arg, (*echo_resp) + 6) != 0)
+ fprintf(stderr,
+ "RPC_TEST_LENGTHS call %d response wrong\n");
+ xdr_free(xdr_wrapstring, echo_resp);
+ }
+
+ /* cycle from 1 to 255 */
+ buf[i] = (i % 255) + 1;
+
+ if (i % 100 == 0) {
+ fputc('.', stdout);
+ fflush(stdout);
+ }
+ }
+ fputc('\n', stdout);
+
+ AUTH_DESTROY(clnt->cl_auth);
+ CLNT_DESTROY(clnt);
+ exit(0);
+}
+
+usage()
+{
+ fprintf(stderr, "usage: %s [-a] [-s num] [-m num] host service [count]\n",
+ whoami);
+ exit(1);
+}
diff --git a/src/lib/rpc/unit-test/rpc_test.x b/src/lib/rpc/unit-test/rpc_test.x
new file mode 100644
index 000000000..e9ae27c97
--- /dev/null
+++ b/src/lib/rpc/unit-test/rpc_test.x
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.2 1996/07/22 20:41:42 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.1.4.1 1996/07/18 04:20:04 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+# Revision 1.1.2.1 1996/06/20 23:42:06 marc
+# File added to the repository on a branch
+#
+# Revision 1.1 1993/11/03 23:53:58 bjaspan
+# Initial revision
+#
+ */
+
+program RPC_TEST_PROG {
+ version RPC_TEST_VERS_1 {
+ string RPC_TEST_ECHO(string) = 1;
+ } = 1;
+} = 1000001;
diff --git a/src/lib/rpc/unit-test/server.c b/src/lib/rpc/unit-test/server.c
new file mode 100644
index 000000000..d98b2df0b
--- /dev/null
+++ b/src/lib/rpc/unit-test/server.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.15 1996/07/22 20:41:44 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.14.4.1 1996/07/18 04:20:06 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.14.2.1 1996/06/20 23:42:16 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.14 1996/05/12 06:59:06 marc
+ * change SERVICE_NAME to "host" instead of "server"
+ *
+ * remove KRB5KTNAME support, since the library supports it internally now.
+ *
+ * Revision 1.13 1995/12/07 17:36:58 jik
+ * Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on
+ * some systems. See PR 3553.
+ *
+ * Revision 1.12 1995/11/07 23:20:44 grier
+ * Add stdlib.h
+ * Add string.h
+ *
+ * Revision 1.11 1995/03/24 19:55:28 jik
+ * Cast a const gss_OID to (gss_OID) to prevent a compiler warning.
+ *
+ * Revision 1.10 1995/02/22 15:54:17 jik
+ * I was a moron in revision 1.8. This is the server function, not the
+ * client function, so it gets a struct svc_req *, not a CLIENT *.
+ *
+ * Revision 1.9 1995/02/22 15:21:51 jik
+ * Linux's rpcgen names the server function differently from the client
+ * function ("_svc" is appended to the end of it).
+ *
+ * Revision 1.8 1995/02/22 14:35:05 jik
+ * RPC server functions have CLIENT * passed into them, so I added it as
+ * an argument to rpc_test_echo_1.
+ *
+ * Revision 1.7 1994/09/21 18:35:57 bjaspan
+ * [gssapi/438: gss_nt_service_name should default to local host]
+ * [secure-releng/2513: audit gssapi/438: gss_nt_service_name should default to local host]
+ *
+ * Sandbox:
+ *
+ * Don't need to get local host name and put it in the service name,
+ * since the gssapi library does that now. See PR 438.
+ *
+ * Revision 1.8 1994/09/01 17:21:59 jik
+ * Don't need to get local host name and put it in the service name,
+ * since the gssapi library does that now. See PR 438.
+ *
+ * Revision 1.7 1994/04/08 17:22:11 bjaspan
+ * add KRB5KTNAME hack so unit tests continue to work
+ *
+ * Revision 1.6 1994/04/05 20:50:26 bjaspan
+ * print "running" when ready to tests can proceed
+ *
+ * Revision 1.5 1994/04/05 19:49:54 jik
+ * Use host name instead of localhost.
+ *
+ * Revision 1.4 1994/03/08 00:14:58 shanzer
+ * changed call to inet_ntoa
+ *
+ * Revision 1.3 1993/12/13 01:37:54 bjaspan
+ * update for new test system
+ * ,.
+ *
+ * Revision 1.2 1993/12/08 21:45:16 bjaspan
+ * display badauth errors, improve arg handling
+ *
+ * Revision 1.1 1993/11/03 23:53:58 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <arpa/inet.h> /* inet_ntoa */
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <rpc/auth_gssapi.h>
+#include <sys/param.h> /* MAXHOSTNAMELEN */
+#include "rpc_test.h"
+
+#ifdef linux
+/*
+ For some reason, Linux's rpcgen names the server function
+ differently from the client function. I suppose this is useful if
+ you want to include them both in the same library or something, but
+ not useful at all if you want to link the client code directly to
+ the server code for testing, instead of going through the RPC layer.
+ */
+#define rpc_test_echo_1 rpc_test_echo_1_svc
+#endif
+
+extern void rpc_test_prog_1();
+
+extern int svc_debug_gssapi, misc_debug_gssapi;
+
+void rpc_test_badauth(OM_uint32 major, OM_uint32 minor,
+ struct sockaddr_in *addr, void *data);
+void log_badauth_display_status(OM_uint32 major, OM_uint32 minor);
+void log_badauth_display_status_1(OM_uint32 code, int type, int rec);
+static void rpc_test_badverf(gss_name_t client, gss_name_t server,
+ struct svc_req *rqst, struct rpc_msg *msg,
+ caddr_t data);
+
+#ifndef SERVICE_NAME
+#define SERVICE_NAME "host"
+#endif
+
+main(int argc, char **argv)
+{
+ auth_gssapi_name names[2];
+ register SVCXPRT *transp;
+
+ names[0].name = SERVICE_NAME;
+ names[0].type = (gss_OID) gss_nt_service_name;
+ names[1].name = 0;
+ names[1].type = 0;
+
+ switch (argc) {
+ case 3:
+ misc_debug_gssapi = atoi(argv[2]);
+ case 2:
+ svc_debug_gssapi = atoi(argv[1]);
+ case 1:
+ break;
+ default:
+ fprintf(stderr, "Usage: server [svc-debug] [misc-debug]\n");
+ exit(1);
+ }
+
+ (void) pmap_unset(RPC_TEST_PROG, RPC_TEST_VERS_1);
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL) {
+ fprintf(stderr, "cannot create tcp service.");
+ exit(1);
+ }
+ if (!svc_register(transp, RPC_TEST_PROG, RPC_TEST_VERS_1,
+ rpc_test_prog_1, IPPROTO_TCP)) {
+ fprintf(stderr,
+ "unable to register (RPC_TEST_PROG, RPC_TEST_VERS_1, tcp).");
+ exit(1);
+ }
+
+ if (_svcauth_gssapi_set_names(names, 0) == FALSE) {
+ fprintf(stderr, "unable to set gssapi names\n");
+ exit(1);
+ }
+
+ _svcauth_gssapi_set_log_badauth_func(rpc_test_badauth, NULL);
+ _svcauth_gssapi_set_log_badverf_func(rpc_test_badverf, NULL);
+
+ printf("running\n");
+
+ svc_run();
+ fprintf(stderr, "svc_run returned");
+ exit(1);
+ /* NOTREACHED */
+}
+
+char **rpc_test_echo_1(char **arg, struct svc_req *h)
+{
+ static char *res = NULL;
+
+ if (res)
+ free(res);
+ res = (char *) malloc(strlen(*arg) + strlen("Echo: ") + 1);
+ sprintf(res, "Echo: %s", *arg);
+ return &res;
+}
+
+static void rpc_test_badverf(gss_name_t client, gss_name_t server,
+ struct svc_req *rqst, struct rpc_msg *msg,
+ caddr_t data)
+{
+ OM_uint32 minor_stat;
+ gss_OID type;
+ gss_buffer_desc client_name, server_name;
+
+ (void) gss_display_name(&minor_stat, client, &client_name, &type);
+ (void) gss_display_name(&minor_stat, server, &server_name, &type);
+
+ printf("rpc_test server: bad verifier from %s at %s:%d for %s\n",
+ client_name.value,
+ inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr),
+ ntohs(rqst->rq_xprt->xp_raddr.sin_port),
+ server_name.value);
+
+ (void) gss_release_buffer(&minor_stat, &client_name);
+ (void) gss_release_buffer(&minor_stat, &server_name);
+}
+
+/*
+ * Function: log_badauth
+ *
+ * Purpose: Callback from GSS-API Sun RPC for authentication
+ * failures/errors.
+ *
+ * Arguments:
+ * major (r) GSS-API major status
+ * minor (r) GSS-API minor status
+ * addr (r) originating address
+ * data (r) arbitrary data (NULL), not used
+ *
+ * Effects:
+ *
+ * Logs the GSS-API error to stdout.
+ */
+void rpc_test_badauth(OM_uint32 major, OM_uint32 minor,
+ struct sockaddr_in *addr, void *data)
+{
+ char *a;
+
+ /* Authentication attempt failed: <IP address>, <GSS-API error */
+ /* strings> */
+
+ a = inet_ntoa(addr->sin_addr);
+
+ printf("rpc_test server: Authentication attempt failed: %s", a);
+ log_badauth_display_status(major, minor);
+ printf("\n");
+}
+
+void log_badauth_display_status(OM_uint32 major, OM_uint32 minor)
+{
+ log_badauth_display_status_1(major, GSS_C_GSS_CODE, 0);
+ log_badauth_display_status_1(minor, GSS_C_MECH_CODE, 0);
+}
+
+void log_badauth_display_status_1(OM_uint32 code, int type, int rec)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc msg;
+ int msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ gssstat = gss_display_status(&minor_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg);
+ if (gssstat != GSS_S_COMPLETE) {
+ if (!rec) {
+ log_badauth_display_status_1(gssstat,GSS_C_GSS_CODE,1);
+ log_badauth_display_status_1(minor_stat,
+ GSS_C_MECH_CODE, 1);
+ } else
+ printf("GSS-API authentication error %s: "
+ "recursive failure!\n", msg);
+ return;
+ }
+
+ printf(", %s", (char *)msg.value);
+ (void) gss_release_buffer(&minor_stat, &msg);
+
+ if (!msg_ctx)
+ break;
+ }
+}
+
+
+#if 0
+
+/* this hack is no longer necessary, since the library supports it
+ internally */
+
+/* This is a hack to change the default keytab name */
+
+#include <krb5/krb5.h>
+extern char *krb5_defkeyname;
+
+krb5_error_code
+krb5_kt_default_name(char *name, int namesize)
+{
+ char *ktname;
+
+ if ((ktname = getenv("KRB5KTNAME")) == NULL)
+ ktname = krb5_defkeyname;
+
+ if (namesize < strlen(ktname)+1)
+ return(KRB5_CONFIG_NOTENUFSPACE);
+
+ strcpy(name, ktname);
+
+ return(0);
+}
+
+#endif
diff --git a/src/lib/rpc/unit-test/testsuite/Makefile b/src/lib/rpc/unit-test/testsuite/Makefile
new file mode 100644
index 000000000..8a2cccdc2
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/Makefile
@@ -0,0 +1,24 @@
+#
+# $Id$
+#
+
+TOP = ../../..
+include $(TOP)/config.mk/template
+
+export RPC_TEST_SRVTAB := /tmp/rpc_test_v5srvtab
+
+unit-test:: unit-test-setup unit-test-body unit-test-cleanup
+
+unit-test-setup::
+ $(START_SERVERS)
+ ./rpc_test_setup.sh
+
+unit-test-body::
+ $(RUNTEST) SERVER=../server CLIENT=../client --tool rpc_test
+
+unit-test-cleanup::
+ $(STOP_SERVERS)
+ -rm -f /tmp/rpc_test_v5srvtab /tmp/krb5cc_rpc_test_fullrun
+
+clean::
+ $(CLEAN) rpc_test.log rpc_test.plog rpc_test.sum rpc_test.psum
diff --git a/src/lib/rpc/unit-test/testsuite/config/unix.exp b/src/lib/rpc/unit-test/testsuite/config/unix.exp
new file mode 100644
index 000000000..030837d49
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/config/unix.exp
@@ -0,0 +1,79 @@
+#
+# $Id$
+#
+
+set kill /bin/kill
+set sleep /bin/sleep
+set kinit $env(TOP)/install/bin/kinit
+set kdestroy $env(TOP)/install/bin/kdestroy
+
+set hostname [exec hostname]
+
+proc rpc_test_version {} {
+ global CLIENT
+ global SERVER
+
+ clone_output "$CLIENT version <unknown>"
+ clone_output "$SERVER version <unknown>"
+}
+
+proc rpc_test_load {} {
+ #
+}
+
+# rpc_test_exit -- clean up and exit
+proc rpc_test_exit {} {
+ global server_id
+ global server_pid
+ global server_started
+ global kill
+
+ if {[catch {
+ expect {
+ -i $server_id
+ eof {
+ fail "server exited!"
+ verbose $expect_out(buffer) 1
+ }
+ timeout { pass "server survived" }
+ }
+ } tmp]} {
+ fail "server exited! (expect failed)"
+ }
+}
+
+#
+# rpc_test_start -- start the rpc_test server running
+#
+proc rpc_test_start { } {
+ global SERVER
+ global server_id
+ global server_pid
+ global server_started
+ global env
+
+ set env(KRB5KTNAME) FILE:$env(RPC_TEST_SRVTAB)
+
+ verbose "% $SERVER" 1
+ set server_pid [spawn $SERVER]
+ set server_id $spawn_id
+
+ unset env(KRB5KTNAME)
+
+ set timeout 30
+
+ expect {
+ "running" { }
+ eof {
+ fail "server exited!"
+ verbose $expect_out(buffer) 1
+ }
+ timeout {
+ fail "server didn't start in $timeout seconds"
+ verbose $expect_out(buffer) 1
+ }
+ }
+
+}
+
+rpc_test_start
diff --git a/src/lib/rpc/unit-test/testsuite/helpers.exp b/src/lib/rpc/unit-test/testsuite/helpers.exp
new file mode 100644
index 000000000..1a37ad512
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/helpers.exp
@@ -0,0 +1,128 @@
+if {[info commands exp_version] != {}} {
+ set exp_version_4 [regexp {^4} [exp_version]]
+} else {
+ set exp_version_4 [regexp {^4} [expect_version]]
+}
+
+# Backward compatibility until we're using expect 5 everywhere
+if {$exp_version_4} {
+ global wait_error_index wait_errno_index wait_status_index
+ set wait_error_index 0
+ set wait_errno_index 1
+ set wait_status_index 1
+} else {
+ set wait_error_index 2
+ set wait_errno_index 3
+ set wait_status_index 3
+}
+
+
+proc kinit {princ pass lifetime} {
+ global kinit
+ global wait_error_index wait_errno_index wait_status_index
+
+ spawn -noecho $kinit -l $lifetime $princ
+ expect {
+ -re "Password for $princ.*: " { send "$pass\n" }
+ timeout { error "Timeout waiting for kinit"; close }
+ }
+ expect { eof {} }
+
+ set ret [wait]
+ if {[lindex $ret $wait_error_index] == -1} {
+ error \
+ "wait(kinit $princ) returned error [lindex $ret $wait_errno_index]"
+ } else {
+ if {[lindex $ret $wait_status_index] != 0} {
+ error \
+ "kinit $princ failed with [lindex $ret $wait_status_index]"
+ }
+ }
+}
+
+proc flush_server {} {
+ global server_id
+ global expect_out
+
+ verbose "flushing server output" 1
+
+ while {1} {
+ set timeout 5
+
+ expect {
+ -i $server_id
+ -re "^.+$" {
+ verbose "server output: $expect_out(buffer)"
+ }
+ timeout { break }
+ }
+ }
+}
+
+proc start_client {testname ccname user password lifetime count
+ {target ""}} {
+ global env
+ global CLIENT
+ global hostname
+ global spawn_id
+ global verbose
+
+ if {$target == ""} {
+ set target "server@$hostname"
+ }
+
+ set env(KRB5CCNAME) FILE:/tmp/krb5cc_rpc_test_$ccname
+ kinit $user $password $lifetime
+
+ if {$verbose > 0} {
+ spawn $CLIENT -a 1 -s 1 -m 1 $hostname $target $count
+ } else {
+ spawn $CLIENT $hostname $target $count
+ }
+
+ verbose "$testname: client $ccname started"
+
+ unset env(KRB5CCNAME)
+}
+
+proc eof_client {testname ccname id status} {
+ verbose "$testname: eof'ing for client $ccname" 1
+
+ expect {
+ -i $id
+ eof { verbose $expect_out(buffer) 1 }
+ timeout {
+ fail "$testname: timeout waiting for client $ccname to exit"
+ }
+ }
+ wait_client $testname $ccname $id $status
+}
+
+
+proc wait_client {testname ccname id status} {
+ global env
+ global kill
+ global kdestroy
+ global wait_error_index wait_errno_index wait_status_index
+
+ verbose "$testname: waiting for client $ccname" 1
+
+ set ret [wait -i $id]
+ if {[lindex $ret $wait_error_index] == -1} {
+ fail \
+ "$testname: wait $ccname returned error [lindex $ret $wait_errno_index]"
+ } else {
+ if {[lindex $ret $wait_status_index] == $status} {
+ pass "$testname: client $ccname"
+ } else {
+ fail "$testname: client $ccname: unexpected return status [lindex $ret $wait_status_index], should be $status."
+ }
+ }
+
+ set env(KRB5CCNAME) FILE:/tmp/krb5cc_rpc_test_$ccname
+ if {[catch "exec $kdestroy"] != 0} {
+ error "$testname: cannot destroy client $ccname ccache"
+ }
+
+ unset env(KRB5CCNAME)
+}
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp
new file mode 100644
index 000000000..d80bae6da
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp
@@ -0,0 +1,21 @@
+set timeout 40
+
+load_lib "helpers.exp"
+
+global spawn_id
+
+start_client expire 1 testuser notathena 20m 100
+set client1_id $spawn_id
+flush_server
+
+start_client expire 2 testuser notathena 40m 300
+set client2_id $spawn_id
+flush_server
+
+start_client expire 3 testuser notathena 60m 500
+set client3_id $spawn_id
+flush_server
+
+eof_client expire 1 $client1_id 0
+eof_client expire 2 $client2_id 0
+eof_client expire 3 $client3_id 0
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp
new file mode 100644
index 000000000..6e8acf80e
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp
@@ -0,0 +1,95 @@
+set timeout 120
+
+load_lib "helpers.exp"
+
+global spawn_id
+global server_id
+
+# Start the client and do a full run
+start_client "full run" fullrun testuser notathena 8 1026
+set client_id $spawn_id
+
+#
+# test: did we get 11 dots?
+#
+verbose "Starting RPC echo test. This will take about 50 seconds.\n"
+
+set ver_line "rpc_test server: bad verifier\[^\r\n\]*\n"
+
+set dots 0
+set server_lines 0
+while {1} {
+ set oldtimeout $timeout
+ set timeout 5
+ while {1} {
+ expect {
+ -i $server_id
+ -re $ver_line {
+ verbose "Got line from server."
+ incr server_lines
+ }
+ default {
+ break
+ }
+ }
+ }
+ set timeout $oldtimeout
+ expect {
+ -i $client_id
+ . {
+ incr dots
+ verbose "$expect_out(buffer)" 1
+ if ($dots==11) { break }
+ }
+ eof {
+ #
+ # test: was the exit status right?
+ #
+ wait_client "full run" fullrun $client_id 0
+ break
+ }
+
+ timeout {
+ verbose "Timeout waiting for dot\n" 1
+ fail "full run: timeout waiting for dot"
+ break
+ }
+
+ }
+}
+if {$dots==11} {
+ pass "fullrun: echo test"
+} else {
+ fail "fullrun: echo test: expected 11 dots, got $dots"
+}
+
+#
+# test: server logged four bad verifiers?
+#
+verbose "full run: checking server output"
+
+# Small timeout, since the server should have already printed everything
+set timeout 5
+
+while {$server_lines < 4} {
+ expect {
+ -i $server_id
+ -re $ver_line {
+ incr server_lines
+ }
+ -re ".+\r\n" {
+ verbose "Unexpected server output: $expect_out(buffer)"
+ }
+ default {
+ break
+ }
+ }
+}
+
+if {$server_lines == 4} {
+ pass "fullrun: bad verifiers"
+} else {
+ fail "fullrun: expected four bad verifiers, got $server_lines"
+}
+
+flush_server
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp
new file mode 100644
index 000000000..f9d53052d
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp
@@ -0,0 +1,27 @@
+set timeout 30
+
+load_lib "helpers.exp"
+
+global spawn_id
+global server_id
+global hostname
+
+start_client "gss err" gsserr testuser notathena 8 1026 notserver@$hostname
+
+eof_client "gss err" gsserr $spawn_id 2
+
+#
+# test: server logged an authentication attempted failed?
+#
+verbose "gss err: checking server output"
+
+expect {
+ -i $server_id
+ -re "rpc_test server: Authent.*failed: .* Wrong princ" {
+ pass "gss err: server logged auth error"
+ }
+ eof { fail "gss err: server exited" }
+ timeout { fail "gss err: timeout waiting for server output" }
+}
+
+flush_server
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh b/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh
new file mode 100644
index 000000000..2a97af4d3
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# This script performs additional setup for the RPC unit test. It
+# assumes that gmake has put TOP and RPC_TEST_SRVTAB into the
+# environment.
+#
+# $Id$
+# $Source$
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${CLNTTCL=$TESTDIR/util/ovsec_kadm_clnt_tcl}
+DUMMY=${TCLUTIL=$TESTDIR/tcl/util.t}; export TCLUTIL
+DUMMY=${MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl}
+
+# If it's set, set it to true
+VERBOSE=${VERBOSE_TEST:+true}
+# Otherwise, set it to false
+DUMMY=${VERBOSE:=false}
+
+if $VERBOSE; then
+ REDIRECT=
+else
+ REDIRECT='>/dev/null'
+fi
+
+PATH=$TOP/install/admin:$PATH; export PATH
+
+CANON_HOST=`perl -e 'chop($_=\`hostname\`);($n,$a,$t,$l,@a)=gethostbyname($_);($_)=gethostbyaddr($a[0],$t); print;'`
+export CANON_HOST
+
+eval $CLNTTCL <<'EOF' $REDIRECT
+source $env(TCLUTIL)
+set h $env(CANON_HOST)
+puts stdout [ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle]
+puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal server/$h] {OVSEC_KADM_PRINCIPAL} admin]
+puts stdout [ovsec_kadm_randkey_principal $server_handle server/$h key]
+puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal notserver/$h] {OVSEC_KADM_PRINCIPAL} admin]
+puts stdout [ovsec_kadm_randkey_principal $server_handle notserver/$h key]
+puts stdout [ovsec_kadm_destroy $server_handle]
+EOF
+
+rm -f $RPC_TEST_SRVTAB
+
+eval $MAKE_KEYTAB -princ server/$CANON_HOST $RPC_TEST_SRVTAB $REDIRECT
+
+grep -s "$CANON_HOST SECURE-TEST.OV.COM" /etc/krb.realms
+if [ $? != 0 ]; then
+ eval echo \"Adding \$CANON_HOST SECURE-TEST.OV.COM to /etc/krb.realms\" $REDIRECT
+ ed /etc/krb.realms <<EOF >/dev/null
+1i
+$CANON_HOST SECURE-TEST.OV.COM
+.
+w
+q
+EOF
+fi
diff --git a/src/lib/rpc/xdr.c b/src/lib/rpc/xdr.c
new file mode 100644
index 000000000..7f4418162
--- /dev/null
+++ b/src/lib/rpc/xdr.c
@@ -0,0 +1,674 @@
+/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
+#endif
+
+/*
+ * xdr.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ *
+ * These are the "generic" xdr routines used to serialize and de-serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+#include <string.h>
+char *malloc();
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE ((rpc_int32) 0)
+#define XDR_TRUE ((rpc_int32) 1)
+#define LASTUNSIGNED ((unsigned int) 0-1)
+
+/*
+ * for unit alignment
+ */
+static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+
+/*
+ * Free a data structure using XDR
+ * Not a filter, but a convenient utility nonetheless
+ */
+void
+xdr_free(proc, objp)
+ xdrproc_t proc;
+ char *objp;
+{
+ XDR x;
+
+ x.x_op = XDR_FREE;
+ (*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(/* xdrs, addr */)
+ /* XDR *xdrs; */
+ /* caddr_t addr; */
+{
+
+ return (TRUE);
+}
+
+/*
+ * XDR integers
+ */
+bool_t
+xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+{
+
+#ifdef lint
+ (void) (xdr_short(xdrs, (short *)ip));
+ return (xdr_long(xdrs, (rpc_int32 *)ip));
+#else
+ if (sizeof (int) >= 4) {
+ long l;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ l = *ip;
+ return (xdr_long(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!xdr_long(xdrs, &l)) {
+ return (FALSE);
+ }
+ *ip = l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ } else {
+ return (xdr_short(xdrs, (short *)ip));
+ }
+#endif
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ unsigned int *up;
+{
+#ifdef lint
+ (void) (xdr_short(xdrs, (short *)up));
+ return (xdr_u_long(xdrs, (rpc_u_int32 *)up));
+#else
+ if (sizeof (unsigned int) >= 4) {
+ unsigned long l;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ l = *up;
+ return (xdr_u_long(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!xdr_u_long(xdrs, &l)) {
+ return (FALSE);
+ }
+ *up = l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ } else {
+ return (xdr_short(xdrs, (short *)up));
+ }
+#endif
+}
+
+/*
+ * XDR long integers
+ * same as xdr_u_long - open coded to save a proc call!
+ */
+bool_t
+xdr_long(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (sizeof (long) > 4) {
+ /* See if the dereferenced value fits in 4 bytes. If not, return FALSE.
+ * Check by loading value into a rpc_int32, then loading back and comparing
+ * results.
+ */
+ rpc_int32 i = (int) *lp;
+ long l = i;
+ if (l != *lp) {
+ return (FALSE);
+ }
+ }
+ return (XDR_PUTLONG(xdrs, lp));
+ }
+ if (xdrs->x_op == XDR_DECODE)
+ return (XDR_GETLONG(xdrs, lp));
+
+ if (xdrs->x_op == XDR_FREE)
+ return (TRUE);
+
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ * same as xdr_long - open coded to save a proc call!
+ */
+bool_t
+xdr_u_long(xdrs, ulp)
+ register XDR *xdrs;
+ unsigned long *ulp;
+{
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (sizeof (unsigned long) > 4) {
+ /* See if the dereferenced value fits in 4 bytes. If not, return FALSE.
+ * Check by loading value into a rpc_int32, then loading back and comparing
+ * results.
+ */
+ unsigned int ui = *ulp;
+ unsigned long ul = ui;
+ if (ul != *ulp) {
+ return (FALSE);
+ }
+ }
+ return (XDR_PUTLONG(xdrs, ulp));
+ }
+ if (xdrs->x_op == XDR_DECODE) {
+ return (XDR_GETLONG(xdrs, (long *)ulp));
+ }
+ if (xdrs->x_op == XDR_FREE)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(xdrs, sp)
+ register XDR *xdrs;
+ short *sp;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *sp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *sp = (short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(xdrs, usp)
+ register XDR *xdrs;
+ unsigned short *usp;
+{
+ unsigned long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (unsigned long) *usp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *usp = (unsigned short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR a char
+ */
+bool_t
+xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+{
+ int i;
+
+ i = (*cp);
+ if (!xdr_int(xdrs, &i)) {
+ return (FALSE);
+ }
+ *cp = i;
+ return (TRUE);
+}
+
+/*
+ * XDR an unsigned char
+ */
+bool_t
+xdr_u_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+{
+ unsigned int u;
+
+ u = (*cp);
+ if (!xdr_u_int(xdrs, &u)) {
+ return (FALSE);
+ }
+ *cp = u;
+ return (TRUE);
+}
+
+/*
+ * XDR booleans
+ */
+bool_t
+xdr_bool(xdrs, bp)
+ register XDR *xdrs;
+ bool_t *bp;
+{
+ long lb;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ lb = *bp ? XDR_TRUE : XDR_FALSE;
+ return (XDR_PUTLONG(xdrs, &lb));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &lb)) {
+ return (FALSE);
+ }
+ *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+{
+#ifndef lint
+ enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
+
+ /*
+ * enums are treated as ints
+ */
+ if (sizeof (enum sizecheck) == sizeof (rpc_int32)) {
+ return (xdr_int32(xdrs, (rpc_int32 *)ep));
+ } else if (sizeof (enum sizecheck) == sizeof (short)) {
+ return (xdr_short(xdrs, (short *)ep));
+ } else {
+ return (FALSE);
+ }
+#else
+ (void) (xdr_short(xdrs, (short *)ep));
+ return (xdr_long(xdrs, (long *)ep));
+#endif
+}
+
+/*
+ * XDR opaque data
+ * Allows the specification of a fixed size sequence of opaque bytes.
+ * cp points to the opaque object and cnt gives the byte length.
+ */
+bool_t
+xdr_opaque(xdrs, cp, cnt)
+ register XDR *xdrs;
+ caddr_t cp;
+ register unsigned int cnt;
+{
+ register unsigned int rndup;
+ static crud[BYTES_PER_XDR_UNIT];
+
+ /*
+ * if no data we are done
+ */
+ if (cnt == 0)
+ return (TRUE);
+
+ /*
+ * round byte count to full xdr units
+ */
+ rndup = cnt % BYTES_PER_XDR_UNIT;
+ if (rndup > 0)
+ rndup = BYTES_PER_XDR_UNIT - rndup;
+
+ if (xdrs->x_op == XDR_DECODE) {
+ if (!XDR_GETBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_GETBYTES(xdrs, crud, rndup));
+ }
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+ }
+
+ if (xdrs->x_op == XDR_FREE) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * XDR counted bytes
+ * *cpp is a pointer to the bytes, *sizep is the count.
+ * If *cpp is NULL maxsize bytes are allocated
+ */
+bool_t
+xdr_bytes(xdrs, cpp, sizep, maxsize)
+ register XDR *xdrs;
+ char **cpp;
+ register unsigned int *sizep;
+ unsigned int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ register unsigned int nodesize;
+
+ /*
+ * first deal with the length since xdr bytes are counted
+ */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ nodesize = *sizep;
+ if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL) {
+ *cpp = sp = (char *)mem_alloc(nodesize);
+ }
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_bytes: out of memory\n");
+ return (FALSE);
+ }
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, nodesize));
+
+ case XDR_FREE:
+ if (sp != NULL) {
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ }
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * Implemented here due to commonality of the object.
+ */
+bool_t
+xdr_netobj(xdrs, np)
+ XDR *xdrs;
+ struct netobj *np;
+{
+
+ return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+}
+
+bool_t
+xdr_int32(xdrs, ip)
+ XDR *xdrs;
+ rpc_int32 *ip;
+{
+ long l;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ l = *ip;
+ return (xdr_long(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!xdr_long(xdrs, &l)) {
+ return (FALSE);
+ }
+ *ip = l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+}
+
+xdr_u_int32(xdrs, up)
+ XDR *xdrs;
+ rpc_u_int32 *up;
+{
+ unsigned long ul;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul = *up;
+ return (xdr_u_long(xdrs, &ul));
+
+ case XDR_DECODE:
+ if (!xdr_u_long(xdrs, &ul)) {
+ return (FALSE);
+ }
+ *up = ul;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+}
+
+/*
+ * XDR a descriminated union
+ * Support routine for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer. The routine gets
+ * the discriminant value and then searches the array of xdrdiscrims
+ * looking for that value. It calls the procedure given in the xdrdiscrim
+ * to handle the discriminant. If there is no specific routine a default
+ * routine may be called.
+ * If there is no specific or default routine an error is returned.
+ */
+bool_t
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+ register XDR *xdrs;
+ enum_t *dscmp; /* enum to decide which arm to work on */
+ char *unp; /* the union itself */
+ struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
+ xdrproc_t dfault; /* default xdr routine */
+{
+ register enum_t dscm;
+
+ /*
+ * we deal with the discriminator; it's an enum
+ */
+ if (! xdr_enum(xdrs, dscmp)) {
+ return (FALSE);
+ }
+ dscm = *dscmp;
+
+ /*
+ * search choices for a value that matches the discriminator.
+ * if we find one, execute the xdr routine for that value.
+ */
+ for (; choices->proc != NULL_xdrproc_t; choices++) {
+ if (choices->value == dscm)
+ return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
+ }
+
+ /*
+ * no match - execute the default xdr routine if there is one
+ */
+ return ((dfault == NULL_xdrproc_t) ? FALSE :
+ (*dfault)(xdrs, unp, LASTUNSIGNED));
+}
+
+
+/*
+ * Non-portable xdr primitives.
+ * Care should be taken when moving these routines to new architectures.
+ */
+
+
+/*
+ * XDR null terminated ASCII strings
+ * xdr_string deals with "C strings" - arrays of bytes that are
+ * terminated by a NULL character. The parameter cpp references a
+ * pointer to storage; If the pointer is null, then the necessary
+ * storage is allocated. The last parameter is the max allowed length
+ * of the string as specified by a protocol.
+ */
+bool_t
+xdr_string(xdrs, cpp, maxsize)
+ register XDR *xdrs;
+ char **cpp;
+ unsigned int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ unsigned int size;
+ unsigned int nodesize;
+
+ /*
+ * first deal with the length since xdr strings are counted-strings
+ */
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ if (sp == NULL) {
+ return(TRUE); /* already free */
+ }
+ /* fall through... */
+ case XDR_ENCODE:
+ size = strlen(sp);
+ break;
+ }
+ if (! xdr_u_int(xdrs, &size)) {
+ return (FALSE);
+ }
+ if (size > maxsize) {
+ return (FALSE);
+ }
+ nodesize = size + 1;
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL)
+ *cpp = sp = (char *)mem_alloc(nodesize);
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_string: out of memory\n");
+ return (FALSE);
+ }
+ sp[size] = 0;
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, size));
+
+ case XDR_FREE:
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * Wrapper for xdr_string that can be called directly from
+ * routines like clnt_call
+ */
+bool_t
+xdr_wrapstring(xdrs, cpp)
+ XDR *xdrs;
+ char **cpp;
+{
+ if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/src/lib/rpc/xdr.h b/src/lib/rpc/xdr.h
new file mode 100644
index 000000000..9f0819b61
--- /dev/null
+++ b/src/lib/rpc/xdr.h
@@ -0,0 +1,276 @@
+/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)xdr.h 1.19 87/04/22 SMI */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __XDR_HEADER__
+#define __XDR_HEADER__
+
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation. Library supplied
+ * routines provide for the conversion on built-in C data types. These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ * bool_t
+ * xdrproc(xdrs, argresp)
+ * XDR *xdrs;
+ * <type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted. argresp is a pointer to the structure to be
+ * converted. The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null. This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations. XDR_ENCODE causes the type to be encoded into the
+ * stream. XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+ XDR_ENCODE=0,
+ XDR_DECODE=1,
+ XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT (4)
+#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+ * BYTES_PER_XDR_UNIT)
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded. If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ * bool_t (*xdrproc_t)(XDR *, caddr_t *);
+ */
+typedef bool_t (*xdrproc_t)();
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular impelementation.
+ */
+typedef struct {
+ enum xdr_op x_op; /* operation; fast additional param */
+ struct xdr_ops {
+ bool_t (*x_getlong)(); /* get a long from underlying stream */
+ bool_t (*x_putlong)(); /* put a long to " */
+ bool_t (*x_getbytes)();/* get some bytes from " */
+ bool_t (*x_putbytes)();/* put some bytes to " */
+ unsigned int (*x_getpostn)();/* returns bytes off from beginning */
+ bool_t (*x_setpostn)();/* lets you reposition the stream */
+ rpc_int32 * (*x_inline)(); /* buf quick ptr to buffered data */
+ void (*x_destroy)(); /* free privates of this xdr_stream */
+ } *x_ops;
+ caddr_t x_public; /* users' data */
+ caddr_t x_private; /* pointer to private data */
+ caddr_t x_base; /* private used for position info */
+ int x_handy; /* extra private word */
+} XDR;
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR *xdrs;
+ * rpc_int32 *longp;
+ * caddr_t addr;
+ * unsigned int len;
+ * unsigned int pos;
+ */
+#define XDR_GETLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+#define XDR_GETBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define XDR_INLINE(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define xdr_inline(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define XDR_DESTROY(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+#define xdr_destroy(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * a entry with a null procedure pointer. The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value. If a match is found the associated xdr routine
+ * is called to handle that part of the union. If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+ int value;
+ xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitve data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned. The standard way to use these
+ * is to say:
+ * if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ * return (FALSE);
+ * <<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_LONG(buf) ((long)ntohl((rpc_u_int32)*(buf)++))
+#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (rpc_int32)htonl((rpc_u_int32)v))
+
+#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_LONG(buf) ((rpc_u_int32)IXDR_GET_LONG(buf))
+#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf))
+
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+extern bool_t xdr_void();
+extern bool_t xdr_int(XDR *, int *);
+extern bool_t xdr_u_int(XDR *, unsigned int *);
+extern bool_t xdr_long(XDR *, long *);
+extern bool_t xdr_u_long(XDR *, unsigned long *);
+extern bool_t xdr_short(XDR *, short *);
+extern bool_t xdr_u_short(XDR *, unsigned short *);
+extern bool_t xdr_bool(XDR *, bool_t *);
+extern bool_t xdr_enum(XDR *, enum_t *);
+extern bool_t xdr_array(XDR *, caddr_t *, unsigned int*, unsigned int, unsigned int, xdrproc_t);
+extern bool_t xdr_bytes(XDR *, char **, unsigned int *, unsigned int);
+extern bool_t xdr_opaque(XDR *, caddr_t, unsigned int);
+extern bool_t xdr_string(XDR *, char **, unsigned int);
+extern bool_t xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t);
+extern bool_t xdr_char(XDR *, char *);
+extern bool_t xdr_u_char(XDR *, char *);
+extern bool_t xdr_vector(XDR *, char *, unsigned int, unsigned int, xdrproc_t);
+extern bool_t xdr_float(XDR *, float *);
+extern bool_t xdr_double(XDR *, double *);
+extern bool_t xdr_reference(XDR *, caddr_t *, unsigned int, xdrproc_t);
+extern bool_t xdr_pointer(XDR *, char **, unsigned int, xdrproc_t);
+extern bool_t xdr_wrapstring(XDR *, char **);
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 1024
+struct netobj {
+ unsigned int n_len;
+ char *n_bytes;
+};
+typedef struct netobj netobj;
+extern bool_t xdr_netobj(XDR *, struct netobj *);
+
+extern bool_t xdr_int32(XDR *, rpc_int32 *);
+extern bool_t xdr_u_int32(XDR *, rpc_u_int32 *);
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+extern void xdrmem_create(); /* XDR using memory buffers */
+extern void xdrstdio_create(); /* XDR using stdio library */
+extern void xdrrec_create(); /* XDR pseudo records for tcp */
+extern void xdralloc_create(); /* XDR allocating memory buffer */
+extern void xdralloc_release(); /* destroy xdralloc, save buf */
+extern bool_t xdrrec_endofrecord(); /* make end of xdr record */
+extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */
+extern bool_t xdrrec_eof(); /* true if no more input */
+extern caddr_t xdralloc_getdata(); /* get buffer from xdralloc */
+
+#endif /* !__XDR_HEADER__ */
diff --git a/src/lib/rpc/xdr_alloc.c b/src/lib/rpc/xdr_alloc.c
new file mode 100644
index 000000000..37ae71e82
--- /dev/null
+++ b/src/lib/rpc/xdr_alloc.c
@@ -0,0 +1,173 @@
+/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.6 1996/07/22 20:41:21 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.5.4.1 1996/07/18 04:19:49 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.5.2.1 1996/06/20 23:40:30 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.5 1996/05/12 06:19:25 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.4 1995/12/13 14:03:14 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.3 1993/12/09 18:57:25 bjaspan
+ * [secure-releng/833] misc bugfixes to admin library
+ *
+ * Revision 1.3 1993/12/06 21:23:08 bjaspan
+ * add xdralloc_release
+ *
+ * Revision 1.2 1993/10/26 21:13:19 bjaspan
+ * add casts for correctness
+ *
+ * Revision 1.1 1993/10/19 03:11:39 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <dyn.h>
+
+static bool_t xdralloc_putlong();
+static bool_t xdralloc_putbytes();
+static unsigned int xdralloc_getpos();
+static rpc_int32 * xdralloc_inline();
+static void xdralloc_destroy();
+static bool_t xdralloc_notsup();
+
+static struct xdr_ops xdralloc_ops = {
+ xdralloc_notsup,
+ xdralloc_putlong,
+ xdralloc_notsup,
+ xdralloc_putbytes,
+ xdralloc_getpos,
+ xdralloc_notsup,
+ xdralloc_inline,
+ xdralloc_destroy,
+};
+
+/*
+ * The procedure xdralloc_create initializes a stream descriptor for a
+ * memory buffer.
+ */
+void xdralloc_create(xdrs, op)
+ register XDR *xdrs;
+ enum xdr_op op;
+{
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdralloc_ops;
+ xdrs->x_private = (caddr_t) DynCreate(sizeof(char), -4);
+ /* not allowed to fail */
+}
+
+caddr_t xdralloc_getdata(xdrs)
+ XDR *xdrs;
+{
+ return (caddr_t) DynGet((DynObject) xdrs->x_private, 0);
+}
+
+void xdralloc_release(xdrs)
+ XDR *xdrs;
+{
+ DynRelease((DynObject) xdrs->x_private);
+}
+
+static void xdralloc_destroy(xdrs)
+ XDR *xdrs;
+{
+ DynDestroy((DynObject) xdrs->x_private);
+}
+
+static bool_t xdralloc_notsup()
+{
+ return FALSE;
+}
+
+static bool_t xdralloc_putlong(xdrs, lp)
+ register XDR *xdrs;
+ rpc_int32 *lp;
+{
+ int l = htonl((rpc_u_int32) *(int *)lp);
+
+ if (DynInsert((DynObject) xdrs->x_private,
+ DynSize((DynObject) xdrs->x_private), &l,
+ sizeof(int)) != DYN_OK)
+ return FALSE;
+ return (TRUE);
+}
+
+static bool_t xdralloc_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register unsigned int len;
+{
+ if (DynInsert((DynObject) xdrs->x_private,
+ DynSize((DynObject) xdrs->x_private),
+ addr, len) != DYN_OK)
+ return FALSE;
+ return TRUE;
+}
+
+static unsigned int xdralloc_getpos(xdrs)
+ register XDR *xdrs;
+{
+ return DynSize((DynObject) xdrs->x_private);
+}
+
+
+static rpc_int32 *xdralloc_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ return (rpc_int32 *) 0;
+}
diff --git a/src/lib/rpc/xdr_array.c b/src/lib/rpc/xdr_array.c
new file mode 100644
index 000000000..09bd50abd
--- /dev/null
+++ b/src/lib/rpc/xdr_array.c
@@ -0,0 +1,153 @@
+/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_array.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * arrays. See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((unsigned int)0-1)
+
+
+/*
+ * XDR an array of arbitrary elements
+ * *addrp is a pointer to the array, *sizep is the number of elements.
+ * If addrp is NULL (*sizep * elsize) bytes are allocated.
+ * elsize is the size (in bytes) of each element, and elproc is the
+ * xdr procedure to call to handle each element of the array.
+ */
+bool_t
+xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
+ register XDR *xdrs;
+ caddr_t *addrp; /* array pointer */
+ unsigned int *sizep; /* number of elements */
+ unsigned int maxsize; /* max numberof elements */
+ unsigned int elsize; /* size in bytes of each element */
+ xdrproc_t elproc; /* xdr routine to handle each element */
+{
+ register unsigned int i;
+ register caddr_t target = *addrp;
+ register unsigned int c; /* the actual element count */
+ register bool_t stat = TRUE;
+ register unsigned int nodesize;
+
+ /* like strings, arrays are really counted arrays */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ c = *sizep;
+ if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+ nodesize = c * elsize;
+
+ /*
+ * if we are deserializing, we may need to allocate an array.
+ * We also save time by checking for a null array if we are freeing.
+ */
+ if (target == NULL)
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (c == 0)
+ return (TRUE);
+ *addrp = target = mem_alloc(nodesize);
+ if (target == NULL) {
+ (void) fprintf(stderr,
+ "xdr_array: out of memory\n");
+ return (FALSE);
+ }
+ memset(target, 0, nodesize);
+ break;
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+
+ /*
+ * now we xdr each element of array
+ */
+ for (i = 0; (i < c) && stat; i++) {
+ stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+ target += elsize;
+ }
+
+ /*
+ * the array may need freeing
+ */
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(*addrp, nodesize);
+ *addrp = NULL;
+ }
+ return (stat);
+}
+
+/*
+ * xdr_vector():
+ *
+ * XDR a fixed length array. Unlike variable-length arrays,
+ * the storage of fixed length arrays is static and unfreeable.
+ * > basep: base of the array
+ * > size: size of the array
+ * > elemsize: size of each element
+ * > xdr_elem: routine to XDR each element
+ */
+bool_t
+xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
+ register XDR *xdrs;
+ register char *basep;
+ register unsigned int nelem;
+ register unsigned int elemsize;
+ register xdrproc_t xdr_elem;
+{
+ register unsigned int i;
+ register char *elptr;
+
+ elptr = basep;
+ for (i = 0; i < nelem; i++) {
+ if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+ return(FALSE);
+ }
+ elptr += elemsize;
+ }
+ return(TRUE);
+}
+
diff --git a/src/lib/rpc/xdr_float.c b/src/lib/rpc/xdr_float.c
new file mode 100644
index 000000000..0c153c472
--- /dev/null
+++ b/src/lib/rpc/xdr_float.c
@@ -0,0 +1,293 @@
+/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_float.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "floating point" xdr routines used to (de)serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * NB: Not portable.
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+#ifdef IGNORE
+
+#ifdef vax
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct ieee_single {
+ unsigned int mantissa: 23;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+};
+
+/* Vax single precision floating point */
+struct vax_single {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS 0x81
+#define IEEE_SNG_BIAS 0x7f
+
+static struct sgl_limits {
+ struct vax_single s;
+ struct ieee_single ieee;
+} sgl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
+ { 0x0, 0xff, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
+ { 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+#endif /* vax */
+
+bool_t
+xdr_float(xdrs, fp)
+ register XDR *xdrs;
+ register float *fp;
+{
+#if defined(vax)
+ struct ieee_single is;
+ struct vax_single vs, *vsp;
+ struct sgl_limits *lim;
+ int i;
+#endif
+ long lg;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#if !defined(vax)
+ lg = * (int_32 *) fp;
+ return (XDR_PUTLONG(xdrs, &lg));
+#else
+ vs = *((struct vax_single *)fp);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((vs.mantissa2 == lim->s.mantissa2) &&
+ (vs.exp == lim->s.exp) &&
+ (vs.mantissa1 == lim->s.mantissa1)) {
+ is = lim->ieee;
+ goto shipit;
+ }
+ }
+ is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+ is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
+ shipit:
+ is.sign = vs.sign;
+ return (XDR_PUTLONG(xdrs, (rpc_int32 *)&is));
+#endif
+
+ case XDR_DECODE:
+#if !defined(vax)
+ if (!(XDR_GETLONG(xdrs, &lg))) {
+ return (FALSE);
+ }
+ *fp = (float) ((int) lg);
+ return (TRUE);
+#else
+ vsp = (struct vax_single *)fp;
+ if (!XDR_GETLONG(xdrs, (rpc_int32 *)&is))
+ return (FALSE);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((is.exp == lim->ieee.exp) &&
+ (is.mantissa == lim->ieee.mantissa)) {
+ *vsp = lim->s;
+ goto doneit;
+ }
+ }
+ vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+ vsp->mantissa2 = is.mantissa;
+ vsp->mantissa1 = (is.mantissa >> 16);
+ doneit:
+ vsp->sign = is.sign;
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+
+#ifdef vax
+/* What IEEE double precision floating point looks like on a Vax */
+struct ieee_double {
+ unsigned int mantissa1 : 20;
+ unsigned int exp : 11;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 32;
+};
+
+/* Vax double precision floating point */
+struct vax_double {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+ unsigned int mantissa3 : 16;
+ unsigned int mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS 0x81
+#define IEEE_DBL_BIAS 0x3ff
+#define MASK(nbits) ((1 << nbits) - 1)
+
+static struct dbl_limits {
+ struct vax_double d;
+ struct ieee_double ieee;
+} dbl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
+ { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
+ { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+
+#endif /* vax */
+
+
+bool_t
+xdr_double(xdrs, dp)
+ register XDR *xdrs;
+ double *dp;
+{
+ register rpc_int32 *lp;
+#if defined(vax)
+ struct ieee_double id;
+ struct vax_double vd;
+ register struct dbl_limits *lim;
+ int i;
+#endif
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#if !defined(vax)
+ lp = (rpc_int32 *)dp;
+ if (sizeof(rpc_int32) == sizeof(long)) {
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+ } else {
+ long lg1 = *lp++;;
+ long lg2 = *lp;
+ return (XDR_PUTLONG(xdrs, &lg1) && XDR_PUTLONG(xdrs, &lg2));
+ }
+#else
+ vd = *((struct vax_double *)dp);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((vd.mantissa4 == lim->d.mantissa4) &&
+ (vd.mantissa3 == lim->d.mantissa3) &&
+ (vd.mantissa2 == lim->d.mantissa2) &&
+ (vd.mantissa1 == lim->d.mantissa1) &&
+ (vd.exp == lim->d.exp)) {
+ id = lim->ieee;
+ goto shipit;
+ }
+ }
+ id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+ id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
+ id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
+ (vd.mantissa3 << 13) |
+ ((vd.mantissa4 >> 3) & MASK(13));
+ shipit:
+ id.sign = vd.sign;
+ lp = (rpc_int32 *)&id;
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#endif
+
+ case XDR_DECODE:
+#if !defined(vax)
+ lp = (rpc_int32 *)dp;
+ if (sizeof(rpc_int32) == sizeof(long)) {
+ return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
+ } else {
+ long lg1, lg2;
+ bool_t flag =
+ (XDR_GETLONG(xdrs, &lg1) && XDR_GETLONG(xdrs, &lg2));
+ *lp++ = lg1;
+ *lp = lg2;
+ return flag;
+ }
+#else
+ lp = (rpc_int32 *)&id;
+ if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
+ return (FALSE);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((id.mantissa2 == lim->ieee.mantissa2) &&
+ (id.mantissa1 == lim->ieee.mantissa1) &&
+ (id.exp == lim->ieee.exp)) {
+ vd = lim->d;
+ goto doneit;
+ }
+ }
+ vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+ vd.mantissa1 = (id.mantissa1 >> 13);
+ vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
+ (id.mantissa2 >> 29);
+ vd.mantissa3 = (id.mantissa2 >> 13);
+ vd.mantissa4 = (id.mantissa2 << 3);
+ doneit:
+ vd.sign = id.sign;
+ *dp = *((double *)&vd);
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+#endif /* IGNORE */
diff --git a/src/lib/rpc/xdr_mem.c b/src/lib/rpc/xdr_mem.c
new file mode 100644
index 000000000..39c0df203
--- /dev/null
+++ b/src/lib/rpc/xdr_mem.c
@@ -0,0 +1,188 @@
+/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_mem.h, XDR implementation using memory buffers.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * If you have some data to be interpreted as external data representation
+ * or to be converted to external data representation in a memory buffer,
+ * then this is the package for you.
+ *
+ */
+
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+#include <stdio.h>
+
+static bool_t xdrmem_getlong();
+static bool_t xdrmem_putlong();
+static bool_t xdrmem_getbytes();
+static bool_t xdrmem_putbytes();
+static unsigned int xdrmem_getpos();
+static bool_t xdrmem_setpos();
+static rpc_int32 * xdrmem_inline();
+static void xdrmem_destroy();
+
+static struct xdr_ops xdrmem_ops = {
+ xdrmem_getlong,
+ xdrmem_putlong,
+ xdrmem_getbytes,
+ xdrmem_putbytes,
+ xdrmem_getpos,
+ xdrmem_setpos,
+ xdrmem_inline,
+ xdrmem_destroy
+};
+
+/*
+ * The procedure xdrmem_create initializes a stream descriptor for a
+ * memory buffer.
+ */
+void
+xdrmem_create(xdrs, addr, size, op)
+ register XDR *xdrs;
+ caddr_t addr;
+ unsigned int size;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrmem_ops;
+ xdrs->x_private = xdrs->x_base = addr;
+ xdrs->x_handy = size;
+}
+
+static void
+xdrmem_destroy(/*xdrs*/)
+ /*XDR *xdrs;*/
+{
+}
+
+static bool_t
+xdrmem_getlong(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(rpc_int32)) < 0)
+ return (FALSE);
+ *lp = (long)ntohl(*((rpc_u_int32 *)(xdrs->x_private)));
+ xdrs->x_private += sizeof(rpc_int32);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(rpc_int32)) < 0)
+ return (FALSE);
+ *(rpc_int32 *)xdrs->x_private = (rpc_int32)htonl((rpc_u_int32)(*lp));
+ xdrs->x_private += sizeof(rpc_int32);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register unsigned int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memmove(addr, xdrs->x_private, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register unsigned int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memmove(xdrs->x_private, addr, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static unsigned int
+xdrmem_getpos(xdrs)
+ register XDR *xdrs;
+{
+/*
+ * 11/3/95 - JRG - Rather than recast everything for 64 bit, just convert
+ * pointers to longs, then cast to int.
+ */
+ return (unsigned int)((unsigned long)xdrs->x_private - (unsigned long)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(xdrs, pos)
+ register XDR *xdrs;
+ unsigned int pos;
+{
+ register caddr_t newaddr = xdrs->x_base + pos;
+ register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
+
+ if ((long)newaddr > (long)lastaddr)
+ return (FALSE);
+ xdrs->x_private = newaddr;
+ xdrs->x_handy = (int)((long)lastaddr - (long)newaddr);
+ return (TRUE);
+}
+
+static rpc_int32 *
+xdrmem_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ rpc_int32 *buf = 0;
+
+ if (xdrs->x_handy >= len) {
+ xdrs->x_handy -= len;
+ buf = (rpc_int32 *) xdrs->x_private;
+ xdrs->x_private += len;
+ }
+ return (buf);
+}
diff --git a/src/lib/rpc/xdr_rec.c b/src/lib/rpc/xdr_rec.c
new file mode 100644
index 000000000..99ce9235a
--- /dev/null
+++ b/src/lib/rpc/xdr_rec.c
@@ -0,0 +1,596 @@
+/* @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
+ * layer above tcp (for rpc's use).
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These routines interface XDRSTREAMS to a tcp/ip connection.
+ * There is a record marking layer between the xdr stream
+ * and the tcp transport level. A record is composed on one or more
+ * record fragments. A record fragment is a thirty-two bit header followed
+ * by n bytes of data, where n is contained in the header. The header
+ * is represented as a htonl(rpc_u_int32). Thegh order bit encodes
+ * whether or not the fragment is the last fragment of the record
+ * (1 => fragment is last, 0 => more fragments to follow.
+ * The other 31 bits encode the byte length of the fragment.
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+
+static unsigned int fix_buf_size();
+static bool_t flush_out();
+static bool_t get_input_bytes();
+static bool_t set_input_fragment();
+static bool_t skip_input_bytes();
+
+static bool_t xdrrec_getlong();
+static bool_t xdrrec_putlong();
+static bool_t xdrrec_getbytes();
+static bool_t xdrrec_putbytes();
+static unsigned int xdrrec_getpos();
+static bool_t xdrrec_setpos();
+static rpc_int32 * xdrrec_inline();
+static void xdrrec_destroy();
+
+static struct xdr_ops xdrrec_ops = {
+ xdrrec_getlong,
+ xdrrec_putlong,
+ xdrrec_getbytes,
+ xdrrec_putbytes,
+ xdrrec_getpos,
+ xdrrec_setpos,
+ xdrrec_inline,
+ xdrrec_destroy
+};
+
+/*
+ * A record is composed of one or more record fragments.
+ * A record fragment is a two-byte header followed by zero to
+ * 2**32-1 bytes. The header is treated as an unsigned 32 bit integer and is
+ * encode/decoded to the network via htonl/ntohl. The low order 31 bits
+ * are a byte count of the fragment. The highest order bit is a boolean:
+ * 1 => this fragment is the last fragment of the record,
+ * 0 => this fragment is followed by more fragment(s).
+ *
+ * The fragment/record machinery is not general; it is constructed to
+ * meet the needs of xdr and rpc based on tcp.
+ */
+
+#define LAST_FRAG ((rpc_u_int32)(1 << 31))
+
+typedef struct rec_strm {
+ caddr_t tcp_handle;
+ caddr_t the_buffer;
+ /*
+ * out-goung bits
+ */
+ int (*writeit)();
+ caddr_t out_base; /* output buffer (points to frag header) */
+ caddr_t out_finger; /* next output position */
+ caddr_t out_boundry; /* data cannot up to this address */
+ rpc_u_int32 *frag_header; /* beginning of curren fragment */
+ bool_t frag_sent; /* true if buffer sent in middle of record */
+ /*
+ * in-coming bits
+ */
+ int (*readit)();
+ rpc_u_int32 in_size; /* fixed size of the input buffer */
+ caddr_t in_base;
+ caddr_t in_finger; /* location of next byte to be had */
+ caddr_t in_boundry; /* can read up to this location */
+ rpc_int32 fbtbc; /* fragment bytes to be consumed */
+ bool_t last_frag;
+ unsigned int sendsize;
+ unsigned int recvsize;
+} RECSTREAM;
+
+
+/*
+ * Create an xdr handle for xdrrec
+ * xdrrec_create fills in xdrs. Sendsize and recvsize are
+ * send and recv buffer sizes (0 => use default).
+ * tcp_handle is an opaque handle that is passed as the first parameter to
+ * the procedures readit and writeit. Readit and writeit are read and
+ * write respectively. They are like the system
+ * calls expect that they take an opaque handle rather than an fd.
+ */
+void
+xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
+ register XDR *xdrs;
+ register unsigned int sendsize;
+ register unsigned int recvsize;
+ caddr_t tcp_handle;
+ int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
+ int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
+{
+ register RECSTREAM *rstrm =
+ (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+
+ if (rstrm == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ /*
+ * This is bad. Should rework xdrrec_create to
+ * return a handle, and in this case return NULL
+ */
+ return;
+ }
+ /*
+ * adjust sizes and allocate buffer quad byte aligned
+ */
+ rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+ rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+ rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
+ if (rstrm->the_buffer == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ return;
+ }
+ for (rstrm->out_base = rstrm->the_buffer;
+ /* Pointer arithmetic - long cast allowed... */
+ (unsigned long)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
+ rstrm->out_base++);
+ rstrm->in_base = rstrm->out_base + sendsize;
+ /*
+ * now the rest ...
+ */
+ xdrs->x_ops = &xdrrec_ops;
+ xdrs->x_private = (caddr_t)rstrm;
+ rstrm->tcp_handle = tcp_handle;
+ rstrm->readit = readit;
+ rstrm->writeit = writeit;
+ rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+ rstrm->frag_header = (rpc_u_int32 *)rstrm->out_base;
+ rstrm->out_finger += sizeof(rpc_u_int32);
+ rstrm->out_boundry += sendsize;
+ rstrm->frag_sent = FALSE;
+ rstrm->in_size = recvsize;
+ rstrm->in_boundry = rstrm->in_base;
+ rstrm->in_finger = (rstrm->in_boundry += recvsize);
+ rstrm->fbtbc = 0;
+ rstrm->last_frag = TRUE;
+}
+
+
+/*
+ * The reoutines defined below are the xdr ops which will go into the
+ * xdr handle filled in by xdrrec_create.
+ */
+
+static bool_t
+xdrrec_getlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register rpc_int32 *buflp = (rpc_int32 *)(rstrm->in_finger);
+ int mylong;
+
+ /* first try the inline, fast case */
+ if ((rstrm->fbtbc >= sizeof(rpc_int32)) &&
+ (((long)rstrm->in_boundry - (long)buflp) >= sizeof(rpc_int32))) {
+ *lp = (long)ntohl((rpc_u_int32)(*buflp));
+ rstrm->fbtbc -= sizeof(rpc_int32);
+ rstrm->in_finger += sizeof(rpc_int32);
+ } else {
+ if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(rpc_int32)))
+ return (FALSE);
+ *lp = (long)ntohl((unsigned int)mylong);
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register rpc_int32 *dest_lp = ((rpc_int32 *)(rstrm->out_finger));
+
+ if ((rstrm->out_finger += sizeof(rpc_int32)) > rstrm->out_boundry) {
+ /*
+ * this case should almost never happen so the code is
+ * inefficient
+ */
+ rstrm->out_finger -= sizeof(rpc_int32);
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ dest_lp = ((rpc_int32 *)(rstrm->out_finger));
+ rstrm->out_finger += sizeof(rpc_int32);
+ }
+ *dest_lp = (rpc_int32)htonl((rpc_u_int32)(*lp));
+ return (TRUE);
+}
+
+static bool_t /* must manage buffers, fragments, and records */
+xdrrec_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register unsigned int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = rstrm->fbtbc;
+ if (current == 0) {
+ if (rstrm->last_frag)
+ return (FALSE);
+ if (! set_input_fragment(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ if (! get_input_bytes(rstrm, addr, current))
+ return (FALSE);
+ addr += current;
+ rstrm->fbtbc -= current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register unsigned int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = (int) ((long)rstrm->out_boundry -
+ (long)rstrm->out_finger);
+ current = (len < current) ? len : current;
+ memmove(rstrm->out_finger, addr, current);
+ rstrm->out_finger += current;
+ addr += current;
+ len -= current;
+ if (rstrm->out_finger == rstrm->out_boundry) {
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+static unsigned int
+xdrrec_getpos(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ register int pos;
+
+/* 11/5/95 JRG HELP! lseek() can't take a pointer as the first arg
+ * This code must have always failed, and the failure let the arithmetic
+ * calculations proceed
+ */
+#ifdef __osf__
+ pos = -1;
+#else
+ pos = lseek((int)rstrm->tcp_handle, (long) 0, 1);
+#endif
+ if (pos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ pos += rstrm->out_finger - rstrm->out_base;
+ break;
+
+ case XDR_DECODE:
+ pos -= rstrm->in_boundry - rstrm->in_finger;
+ break;
+
+ default:
+ pos = (unsigned int) -1;
+ break;
+ }
+ return ((unsigned int) pos);
+}
+
+static bool_t
+xdrrec_setpos(xdrs, pos)
+ register XDR *xdrs;
+ unsigned int pos;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ unsigned int currpos = xdrrec_getpos(xdrs);
+ int delta = currpos - pos;
+ caddr_t newpos;
+
+ if ((int)currpos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ newpos = rstrm->out_finger - delta;
+ if ((newpos > (caddr_t)(rstrm->frag_header)) &&
+ (newpos < rstrm->out_boundry)) {
+ rstrm->out_finger = newpos;
+ return (TRUE);
+ }
+ break;
+
+ case XDR_DECODE:
+ newpos = rstrm->in_finger - delta;
+ if ((delta < (int)(rstrm->fbtbc)) &&
+ (newpos <= rstrm->in_boundry) &&
+ (newpos >= rstrm->in_base)) {
+ rstrm->in_finger = newpos;
+ rstrm->fbtbc -= delta;
+ return (TRUE);
+ }
+ break;
+ }
+ return (FALSE);
+}
+
+static rpc_int32 *
+xdrrec_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ rpc_int32 * buf = NULL;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
+ buf = (rpc_int32 *) rstrm->out_finger;
+ rstrm->out_finger += len;
+ }
+ break;
+
+ case XDR_DECODE:
+ if ((len <= rstrm->fbtbc) &&
+ ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
+ buf = (rpc_int32 *) rstrm->in_finger;
+ rstrm->fbtbc -= len;
+ rstrm->in_finger += len;
+ }
+ break;
+ }
+ return (buf);
+}
+
+static void
+xdrrec_destroy(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+ mem_free(rstrm->the_buffer,
+ rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+ mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
+}
+
+
+/*
+ * Exported routines to manage xdr records
+ */
+
+/*
+ * Before reading (deserializing from the stream, one should always call
+ * this procedure to guarantee proper record alignment.
+ */
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (FALSE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (FALSE);
+ }
+ rstrm->last_frag = FALSE;
+ return (TRUE);
+}
+
+/*
+ * Look ahead fuction.
+ * Returns TRUE iff there is no more input in the buffer
+ * after consuming the rest of the current record.
+ */
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (TRUE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (TRUE);
+ }
+ if (rstrm->in_finger == rstrm->in_boundry)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * The client must tell the package when an end-of-record has occurred.
+ * The second paraemters tells whether the record should be flushed to the
+ * (output) tcp stream. (This let's the package support batched or
+ * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
+ */
+bool_t
+xdrrec_endofrecord(xdrs, sendnow)
+ XDR *xdrs;
+ bool_t sendnow;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register rpc_u_int32 len; /* fragment length */
+
+ if (sendnow || rstrm->frag_sent ||
+ ((long)rstrm->out_finger + sizeof(unsigned int) >=
+ (long)rstrm->out_boundry)) {
+ rstrm->frag_sent = FALSE;
+ return (flush_out(rstrm, TRUE));
+ }
+ len = (long)(rstrm->out_finger) - (long)(rstrm->frag_header) -
+ sizeof(unsigned int);
+ *(rstrm->frag_header) = htonl((unsigned int)len | LAST_FRAG);
+ rstrm->frag_header = (rpc_u_int32 *)rstrm->out_finger;
+ rstrm->out_finger += sizeof(unsigned int);
+ return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(rstrm, eor)
+ register RECSTREAM *rstrm;
+ bool_t eor;
+{
+ register rpc_u_int32 eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ register rpc_u_int32 len = (unsigned long)(rstrm->out_finger) -
+ (unsigned long)(rstrm->frag_header) - sizeof(rpc_u_int32);
+
+ *(rstrm->frag_header) = htonl(len | eormask);
+ len = (unsigned long)(rstrm->out_finger) - (unsigned long)(rstrm->out_base);
+ if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+ != (int)len)
+ return (FALSE);
+ rstrm->frag_header = (rpc_u_int32 *)rstrm->out_base;
+ rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(rpc_u_int32);
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+fill_input_buf(rstrm)
+ register RECSTREAM *rstrm;
+{
+ register caddr_t where;
+ unsigned int i;
+ register int len;
+
+ where = rstrm->in_base;
+ i = (unsigned int)((unsigned long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
+ where += i;
+ len = rstrm->in_size - i;
+ if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
+ return (FALSE);
+ rstrm->in_finger = where;
+ where += len;
+ rstrm->in_boundry = where;
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+get_input_bytes(rstrm, addr, len)
+ register RECSTREAM *rstrm;
+ register caddr_t addr;
+ register int len;
+{
+ register int current;
+
+ while (len > 0) {
+ current = (int)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ memmove(addr, rstrm->in_finger, current);
+ rstrm->in_finger += current;
+ addr += current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t /* next two bytes of the input stream are treated as a header */
+set_input_fragment(rstrm)
+ register RECSTREAM *rstrm;
+{
+ rpc_u_int32 header;
+
+ if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+ return (FALSE);
+ header = (int)ntohl(header);
+ rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+ rstrm->fbtbc = header & (~LAST_FRAG);
+ return (TRUE);
+}
+
+static bool_t /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(rstrm, cnt)
+ register RECSTREAM *rstrm;
+ rpc_int32 cnt;
+{
+ register int current;
+
+ while (cnt > 0) {
+ current = (int)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (cnt < current) ? cnt : current;
+ rstrm->in_finger += current;
+ cnt -= current;
+ }
+ return (TRUE);
+}
+
+static unsigned int
+fix_buf_size(s)
+ register unsigned int s;
+{
+
+ if (s < 100)
+ s = 4000;
+ return (RNDUP(s));
+}
diff --git a/src/lib/rpc/xdr_reference.c b/src/lib/rpc/xdr_reference.c
new file mode 100644
index 000000000..ebf14b68e
--- /dev/null
+++ b/src/lib/rpc/xdr_reference.c
@@ -0,0 +1,132 @@
+/* @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
+#endif
+
+/*
+ * xdr_reference.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * "pointers". See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((unsigned int)0-1)
+
+/*
+ * XDR an indirect pointer
+ * xdr_reference is for recursively translating a structure that is
+ * referenced by a pointer inside the structure that is currently being
+ * translated. pp references a pointer to storage. If *pp is null
+ * the necessary storage is allocated.
+ * size is the sizeof the referneced structure.
+ * proc is the routine to handle the referenced structure.
+ */
+bool_t
+xdr_reference(xdrs, pp, size, proc)
+ register XDR *xdrs;
+ caddr_t *pp; /* the pointer to work on */
+ unsigned int size; /* size of the object pointed to */
+ xdrproc_t proc; /* xdr routine to handle the object */
+{
+ register caddr_t loc = *pp;
+ register bool_t stat;
+
+ if (loc == NULL)
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ return (TRUE);
+
+ case XDR_DECODE:
+ *pp = loc = (caddr_t) mem_alloc(size);
+ if (loc == NULL) {
+ (void) fprintf(stderr,
+ "xdr_reference: out of memory\n");
+ return (FALSE);
+ }
+ memset(loc, 0, (int)size);
+ break;
+ }
+
+ stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(loc, size);
+ *pp = NULL;
+ }
+ return (stat);
+}
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ * What's sent is actually a union:
+ *
+ * union object_pointer switch (boolean b) {
+ * case TRUE: object_data data;
+ * case FALSE: void nothing;
+ * }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
+ register XDR *xdrs;
+ char **objpp;
+ unsigned int obj_size;
+ xdrproc_t xdr_obj;
+{
+
+ bool_t more_data;
+
+ more_data = (*objpp != NULL);
+ if (! xdr_bool(xdrs,&more_data)) {
+ return (FALSE);
+ }
+ if (! more_data) {
+ *objpp = NULL;
+ return (TRUE);
+ }
+ return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
diff --git a/src/lib/rpc/xdr_stdio.c b/src/lib/rpc/xdr_stdio.c
new file mode 100644
index 000000000..6d59ad5c6
--- /dev/null
+++ b/src/lib/rpc/xdr_stdio.c
@@ -0,0 +1,189 @@
+/* @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * xdr_stdio.c, XDR implementation on standard i/o file.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements a XDR on a stdio stream.
+ * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
+ * from the stream.
+ */
+
+#include <rpc/types.h>
+#include <stdio.h>
+#include <rpc/xdr.h>
+
+static bool_t xdrstdio_getlong();
+static bool_t xdrstdio_putlong();
+static bool_t xdrstdio_getbytes();
+static bool_t xdrstdio_putbytes();
+static unsigned int xdrstdio_getpos();
+static bool_t xdrstdio_setpos();
+static rpc_int32 * xdrstdio_inline();
+static void xdrstdio_destroy();
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static struct xdr_ops xdrstdio_ops = {
+ xdrstdio_getlong, /* deseraialize a long int */
+ xdrstdio_putlong, /* seraialize a long int */
+ xdrstdio_getbytes, /* deserialize counted bytes */
+ xdrstdio_putbytes, /* serialize counted bytes */
+ xdrstdio_getpos, /* get offset in the stream */
+ xdrstdio_setpos, /* set offset in the stream */
+ xdrstdio_inline, /* prime stream for inline macros */
+ xdrstdio_destroy /* destroy stream */
+};
+
+/*
+ * Initialize a stdio xdr stream.
+ * Sets the xdr stream handle xdrs for use on the stream file.
+ * Operation flag is set to op.
+ */
+void
+xdrstdio_create(xdrs, file, op)
+ register XDR *xdrs;
+ FILE *file;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrstdio_ops;
+ xdrs->x_private = (caddr_t)file;
+ xdrs->x_handy = 0;
+ xdrs->x_base = 0;
+}
+
+/*
+ * Destroy a stdio xdr stream.
+ * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
+ */
+static void
+xdrstdio_destroy(xdrs)
+ register XDR *xdrs;
+{
+ (void)fflush((FILE *)xdrs->x_private);
+ /* xx should we close the file ?? */
+}
+
+static bool_t
+xdrstdio_getlong(xdrs, lp)
+ XDR *xdrs;
+ register long *lp;
+{
+ rpc_int32 tmp;
+ if (fread((caddr_t)&tmp,
+ sizeof(rpc_int32), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+#ifndef mc68000
+ *lp = ntohl(tmp);
+#endif
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+
+#ifndef mc68000
+ rpc_int32 mycopy = htonl((rpc_int32)*lp);
+#endif
+ if (fwrite((caddr_t)&mycopy, sizeof(rpc_int32), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ unsigned int len;
+{
+
+ if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ unsigned int len;
+{
+
+ if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static unsigned int
+xdrstdio_getpos(xdrs)
+ XDR *xdrs;
+{
+
+ return ((unsigned int) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(xdrs, pos)
+ XDR *xdrs;
+ unsigned int pos;
+{
+
+ return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
+ FALSE : TRUE);
+}
+
+static rpc_int32 *
+xdrstdio_inline(xdrs, len)
+ XDR *xdrs;
+ unsigned int len;
+{
+
+ /*
+ * Must do some work to implement this: must insure
+ * enough data in the underlying stdio buffer,
+ * that the buffer is aligned so that we can indirect through a
+ * long *, and stuff this pointer in xdrs->x_buf. Doing
+ * a fread or fwrite to a scratch buffer would defeat
+ * most of the gains to be had here and require storage
+ * management on this buffer, so we don't do this.
+ */
+ return (NULL);
+}