summaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorMarc Horowitz <marc@mit.edu>1996-07-22 20:49:46 +0000
committerMarc Horowitz <marc@mit.edu>1996-07-22 20:49:46 +0000
commitedf8b4d8a6a665c2aa150993cd813ea6c5cf12e1 (patch)
tree6c2974a97b448c040fa4a31708ec5e02f187526c /src/lib
parent013bb1391582ed9e653ae706e398ddb8d08cfcc9 (diff)
downloadkrb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.gz
krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.xz
krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.zip
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. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@8774 dc483132-0cff-0310-8789-dd5450dbe970
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 210d8cf517..c7e7fb6b1a 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 aebd96c6a9..80c359eb35 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 f8637a6e79..c6f7072903 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 9c98263a2a..c4fb8c0860 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 0ad7c89bd8..036bd46930 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 c27788dc2f..b874a951c5 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 ee150e11f4..164582c647 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 d434599140..a3b2a14110 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 9c90244f24..c9e940962a 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 79b5fbbe2e..c4db91375c 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 ad0b17f203..4dd91d25fd 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 2b2e6002bf..28cc4ca417 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 a882f61392..e0bb28d447 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 91d958d125..ddeed4227e 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 0000000000..7072329b75
--- /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 fe22827967..88c0547880 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 0000000000..38d73f429e
--- /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 0000000000..d367ef31ec
--- /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 0000000000..01e814bcb4
--- /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 cf144495f8..e715834d92 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 896b950b15..900834f40d 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 6b19092db8..d601ceef2f 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 91bb544ede..8843a7ff6a 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 e440d907a3..027d2a765f 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 72631341ba..63f5528598 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 73a09c111e..a996733e68 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 d5061fa149..4a18efeea2 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 79d41b71da..09ed412472 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 526e6dddb7..b2d6ce1116 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 19b94f452d..75a534220d 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 d5fc0695f3..a055318932 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 3bc42e603d..76f1489b77 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 fded9afa8a..5b5ff74fa6 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 a9cbcae066..77f520035f 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 326d3fc7c8..143f7a6245 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 180cc2ef59..fba8a684ba 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 2e73cacfee..5dd91064f7 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 53c4f46918..7ccc4b8288 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 0f26773b19..54a126518b 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 e184557558..feec0bc712 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 450081d97c..71182f22b4 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 ee44132ae3..5c2c6f43a8 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 d802ecdd00..c1d1bfa72a 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 0f78de2199..bc53b4434d 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 2b671680ae..686384216a 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 c8499212fb..5e57463441 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 e3e01bf4ec..f9811c347c 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 fe61eb01af..948346dc6c 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 4e5c78bd1a..254d516807 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 1b4288c0cc..70d2d4d7bd 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 0000000000..f22e9d6337
--- /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 80affbd271..4639108d51 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 297699fe18..df301987b7 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 40ff0d2d31..56f56d060d 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 32e697acef..d5ec7bcc72 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 ca52a60af2..818de191f2 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 5acfd5c678..2a8cd0dd03 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 c3b6ebf4b4..0177f40d48 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 da71fa4f4c..546521e1bf 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 0b46d0e5e7..ee3e1aafa0 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 89028270e3..bf49de41da 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 ed60922d51..14f3652452 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 67bcda6db1..ed9293f778 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 33ee8fb8c2..0e73056404 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 0000000000..8c47d0fa67
--- /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 e82cfbba0a..22b8c5bdb7 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 6e9e4d64ee..ac07e19810 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 d4512c41c7..9556ac4503 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 0000000000..a10d351d16
--- /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 0000000000..ef500d3f26
--- /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 0000000000..6b078f7776
--- /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 0000000000..b73553575a
--- /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 0000000000..3948025719
--- /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 0000000000..4c6f8a66de
--- /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 0000000000..627a6b4104
--- /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 0000000000..ff0117bac8
--- /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 0000000000..8ee9aab30c
--- /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 0000000000..944fb04b3e
--- /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 0000000000..1e98430dbb
--- /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 0000000000..d73837e679
--- /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 0000000000..3e4f48f7ab
--- /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 0000000000..2f36f76fa7
--- /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 0000000000..dbf610ce30
--- /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 0000000000..0322549982
--- /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 0000000000..895777a6ed
--- /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 0000000000..bfc1c3a3c6
--- /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 0000000000..5a246158eb
--- /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 0000000000..c419227223
--- /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 0000000000..547844a2c9
--- /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 0000000000..d6c7f0bfb2
--- /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 0000000000..f81cf7471b
--- /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 0000000000..93ea199e26
--- /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 0000000000..6466673a8a
--- /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 0000000000..a398997d6c
--- /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 0000000000..446a38de1c
--- /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 0000000000..b0f97e6cb9
--- /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 0000000000..6cce9391ee
--- /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 0000000000..924fb9a23e
--- /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 0000000000..cfe28a4117
--- /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 0000000000..6118282df3
--- /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 0000000000..16a7f4e402
--- /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 0000000000..9dfc8daba7
--- /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 0000000000..6c0bcef037
--- /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 0000000000..53abe94dd2
--- /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 0000000000..653f6d896e
--- /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 0000000000..415f6d7d7f
--- /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 0000000000..1a900a380f
--- /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 0000000000..24f101ce5a
--- /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 0000000000..47904de1b5
--- /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 0000000000..8828929337
--- /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 0000000000..df2bf4c47b
--- /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 0000000000..19c9000212
--- /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 0000000000..5c76a1ebc5
--- /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 0000000000..74e2521157
--- /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 0000000000..6f9671fcfb
--- /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 0000000000..172084c20f
--- /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 0000000000..208bedeb3c
--- /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 0000000000..12fa3b9d16
--- /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 0000000000..dbf4f1cbc1
--- /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 0000000000..12c300793a
--- /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 0000000000..31b8447861
--- /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 0000000000..7f349b02cd
--- /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 0000000000..bb52301df3
--- /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 0000000000..329e7886ab
--- /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 0000000000..05937055eb
--- /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 0000000000..5df5dcfc94
--- /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 0000000000..67f8457b6a
--- /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 0000000000..c4bc2bed18
--- /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 0000000000..259cd8f031
--- /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 0000000000..56e4129552
--- /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 0000000000..67ab80060d
--- /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 0000000000..88aed8bca9
--- /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 0000000000..3efdfa9b90
--- /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 0000000000..b0ea04630d
--- /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 0000000000..653d1222a8
--- /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 0000000000..808f0b401c
--- /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 0000000000..95a57dc201
--- /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 0000000000..fe157e880b
--- /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 0000000000..ff41c17b9b
--- /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 0000000000..486d1a6ab3
--- /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 0000000000..4f91b33bb2
--- /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 0000000000..5de25d6fe0
--- /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 0000000000..97a99e0baa
--- /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 0000000000..07e2e62dbf
--- /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 0000000000..5e24e08b02
--- /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 0000000000..c3dfd18df5
--- /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 0000000000..d693a2ac1e
--- /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 0000000000..e9a681f935
--- /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 0000000000..0db69c3a18
--- /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 0000000000..593d673207
--- /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 0000000000..593d673207
--- /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 0000000000..ced1d183d6
--- /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 0000000000..823dd222bf
--- /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 0000000000..7ca43d44fe
--- /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 0000000000..110514de8b
--- /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 0000000000..cff3423861
--- /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 0000000000..8d7e2fecef
--- /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 0000000000..18b435dd12
--- /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 0000000000..5bcbd62523
--- /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 fa274c12ae..4e5440cc91 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 7b1176d890..ba683222a4 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 ec7f93ec1a..e480603e4c 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 0928eba2a1..54316dde09 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 e42e31f9d3..3931389f47 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 5953d6dd25..044ce4c7fe 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 58112dcccc..39c3974343 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 a8f27c4746..dd8aadc743 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 75d2f0d3ea..721ce1e5ef 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 433c1c9da8..29eb54fe2c 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 0000000000..a78d05c37c
--- /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 0000000000..9426bb94c7
--- /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 0000000000..d64c77e223
--- /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 0000000000..4b0a40ccc0
--- /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 0000000000..5e2a8633a4
--- /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 0000000000..0ffe96d188
--- /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 0000000000..9092149a55
--- /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 0000000000..bd7b6e5a3f
--- /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 0000000000..90f3bb8be1
--- /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 0000000000..b41e442fc9
--- /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 0000000000..4b54f1db69
--- /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 0000000000..36770f2989
--- /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 0000000000..875aeefb64
--- /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 0000000000..442a96d44d
--- /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 0000000000..f111c2e147
--- /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 0000000000..63eef49f0f
--- /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 0000000000..d05dbaa7e1
--- /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 0000000000..0d8f7a4df7
--- /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 0000000000..c573897f73
--- /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 0000000000..000b9683df
--- /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 0000000000..6084638d3d
--- /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 0000000000..fa4c54e784
--- /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 0000000000..e48d5b1e92
--- /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 0000000000..d209a15274
--- /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 0000000000..f6b6374b55
--- /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 0000000000..7218777ccf
--- /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 0000000000..dfb00dcc55
--- /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 0000000000..472b2a46db
--- /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 0000000000..40b764880c
--- /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 0000000000..1dffffe17b
--- /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 0000000000..4f76580f4e
--- /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 0000000000..5f48f2a283
--- /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 0000000000..6a23767639
--- /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 0000000000..2ea22120e9
--- /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 0000000000..d0280aaa09
--- /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 0000000000..370e79ff98
--- /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 0000000000..75cead0875
--- /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 0000000000..d252d6acdf
--- /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 0000000000..66b10c5fbc
--- /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 0000000000..6fea605e67
--- /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 0000000000..cb4d877a74
--- /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 0000000000..2114d6249e
--- /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 0000000000..281d7cba48
--- /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 0000000000..4d59631445
--- /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 0000000000..2f0a66dc85
--- /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 0000000000..07cf59ab8b
--- /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 0000000000..1ff21588cf
--- /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 0000000000..1170ecec83
--- /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 0000000000..d43aa2425c
--- /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 0000000000..2a22e57224
--- /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 0000000000..e20a29b192
--- /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 0000000000..d44c7f5d88
--- /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 0000000000..619a9ce204
--- /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 0000000000..31853cb354
--- /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 0000000000..bcf2700e5e
--- /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 0000000000..e9ae27c979
--- /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 0000000000..d98b2df0ba
--- /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 0000000000..8a2cccdc2d
--- /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 0000000000..030837d49a
--- /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 0000000000..1a37ad512a
--- /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 0000000000..d80bae6dae
--- /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 0000000000..6e8acf80e8
--- /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 0000000000..f9d53052de
--- /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 0000000000..2a97af4d3c
--- /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 0000000000..7f44181620
--- /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 0000000000..9f0819b61a
--- /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 0000000000..37ae71e823
--- /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 0000000000..09bd50abd1
--- /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 0000000000..0c153c4723
--- /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 0000000000..39c0df203b
--- /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 0000000000..99ce9235aa
--- /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 0000000000..ebf14b68e3
--- /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 0000000000..6d59ad5c6e
--- /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);
+}