From: Barry Jaspan Date: Wed, 23 Apr 1997 19:53:16 +0000 (+0000) Subject: add kadm5_setkey_principal X-Git-Tag: krb5-1.1-beta1~1151 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=47a32a44d71b8433300739dbd3b6899c12b53227;p=krb5.git add kadm5_setkey_principal git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@10072 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c index 1beed3e10..a4c1711f5 100644 --- a/src/kadmin/cli/kadmin.c +++ b/src/kadmin/cli/kadmin.c @@ -55,7 +55,8 @@ static struct pflag flags[] = { {"requires_hwauth", 15, KRB5_KDB_REQUIRES_HW_AUTH, 0}, {"needchange", 10, KRB5_KDB_REQUIRES_PWCHANGE, 0}, {"allow_svr", 9, KRB5_KDB_DISALLOW_SVR, 1}, -{"password_changing_service", 25, KRB5_KDB_PWCHANGE_SERVICE, 0 } +{"password_changing_service", 25, KRB5_KDB_PWCHANGE_SERVICE, 0 }, +{"support_desmd5", 14, KRB5_KDB_SUPPORT_DESMD5, 0 } }; static char *prflags[] = { @@ -72,7 +73,9 @@ static char *prflags[] = { "UNKNOWN_0x00000400", /* 0x00000400 */ "UNKNOWN_0x00000800", /* 0x00000800 */ "DISALLOW_SVR", /* 0x00001000 */ - "PWCHANGE_SERVICE" /* 0x00002000 */ + "PWCHANGE_SERVICE", /* 0x00002000 */ + "SUPPORT_DESMD5", /* 0x00004000 */ + "NEW_PRINC", /* 0x00008000 */ }; char *getenv(); diff --git a/src/kadmin/server/ChangeLog b/src/kadmin/server/ChangeLog index e36f94d8c..ea9cbdb73 100644 --- a/src/kadmin/server/ChangeLog +++ b/src/kadmin/server/ChangeLog @@ -1,3 +1,7 @@ +Mon Mar 31 17:42:03 1997 Barry Jaspan + + * kadm_rpc_svc.c, server_stubs.c: add support for setkey_principal + Tue Feb 4 20:59:31 1997 Tom Yu * Makefile.in: diff --git a/src/kadmin/server/kadm_rpc_svc.c b/src/kadmin/server/kadm_rpc_svc.c index 9128821d5..c4b6ebc59 100644 --- a/src/kadmin/server/kadm_rpc_svc.c +++ b/src/kadmin/server/kadm_rpc_svc.c @@ -5,6 +5,9 @@ * $Source$ * * $Log$ + * Revision 1.13 1997/04/23 19:53:11 bjaspan + * add kadm5_setkey_principal + * * Revision 1.12 1996/07/22 20:28:53 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 @@ -173,6 +176,12 @@ void kadm_1(rqstp, transp) xdr_result = xdr_generic_ret; local = (char *(*)()) chpass_principal_1; break; + + case SETKEY_PRINCIPAL: + xdr_argument = xdr_setkey_arg; + xdr_result = xdr_generic_ret; + local = (char *(*)()) setkey_principal_1; + break; case CHRAND_PRINCIPAL: xdr_argument = xdr_chrand_arg; @@ -223,7 +232,7 @@ void kadm_1(rqstp, transp) break; default: - krb5_klog_syslog(LOG_ERR, "Invalid OVSEC_KADM procedure number: %s, %d", + krb5_klog_syslog(LOG_ERR, "Invalid KADM5 procedure number: %s, %d", inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr), rqstp->rq_proc); svcerr_noproc(transp); diff --git a/src/kadmin/server/server_stubs.c b/src/kadmin/server/server_stubs.c index 8107160af..1d04c03d9 100644 --- a/src/kadmin/server/server_stubs.c +++ b/src/kadmin/server/server_stubs.c @@ -611,6 +611,61 @@ chpass_principal_1(chpass_arg *arg, struct svc_req *rqstp) return &ret; } +generic_ret * +setkey_principal_1(setkey_arg *arg, struct svc_req *rqstp) +{ + static generic_ret ret; + char *prime_arg; + gss_buffer_desc client_name, + service_name; + OM_uint32 minor_stat; + kadm5_server_handle_t handle; + + xdr_free(xdr_generic_ret, &ret); + + if (ret.code = new_server_handle(arg->api_version, rqstp, &handle)) + return &ret; + + if (ret.code = check_handle((void *)handle)) { + free_server_handle(handle); + return &ret; + } + + ret.api_version = handle->api_version; + + if (setup_gss_names(rqstp, &client_name, &service_name) < 0) { + ret.code = KADM5_FAILURE; + return &ret; + } + krb5_unparse_name(handle->context, arg->princ, &prime_arg); + + if (!(CHANGEPW_SERVICE(rqstp)) && + acl_check(handle->context, rqstp->rq_clntcred, + ACL_SETKEY, arg->princ)) { + ret.code = kadm5_setkey_principal((void *)handle, arg->princ, + arg->keyblocks, arg->n_keys); + } else { + krb5_klog_syslog(LOG_NOTICE, LOG_UNAUTH, "kadm5_setkey_principal", + prime_arg, client_name.value, service_name.value, + inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr)); + ret.code = KADM5_AUTH_SETKEY; + } + + if(ret.code != KADM5_AUTH_SETKEY) { + krb5_klog_syslog(LOG_NOTICE, LOG_DONE, "kadm5_setkey_principal", + prime_arg, ((ret.code == 0) ? "success" : + error_message(ret.code)), + client_name.value, service_name.value, + inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr)); + } + + free_server_handle(handle); + free(prime_arg); + gss_release_buffer(&minor_stat, &client_name); + gss_release_buffer(&minor_stat, &service_name); + return &ret; +} + chrand_ret * chrand_principal_1(chrand_arg *arg, struct svc_req *rqstp) { diff --git a/src/kadmin/testing/proto/ChangeLog b/src/kadmin/testing/proto/ChangeLog index 1ee19274c..175aede60 100644 --- a/src/kadmin/testing/proto/ChangeLog +++ b/src/kadmin/testing/proto/ChangeLog @@ -1,3 +1,7 @@ +Mon Mar 31 17:42:33 1997 Barry Jaspan + + * krb5.conf.proto: add support for setkey_principal (support more enctypes) + Tue Oct 15 16:24:33 1996 Barry Jaspan * krb5.conf.proto: s/localhost/__LOCALHOST__/ diff --git a/src/kadmin/testing/proto/kdc.conf.proto b/src/kadmin/testing/proto/kdc.conf.proto index 1797b5a8e..18cd54438 100644 --- a/src/kadmin/testing/proto/kdc.conf.proto +++ b/src/kadmin/testing/proto/kdc.conf.proto @@ -11,6 +11,6 @@ dict_file = __K5ROOT__/ovsec_adm.dict kadmind_port = 1751 master_key_type = des-cbc-crc - supported_enctypes = des-cbc-crc:normal des-cbc-crc:v4 + supported_enctypes = des-cbc-crc:normal des-cbc-crc:v4 des-cbc-md5:normal des-cbc-raw:normal } diff --git a/src/kadmin/testing/util/ChangeLog b/src/kadmin/testing/util/ChangeLog index f011d939a..cb0960fba 100644 --- a/src/kadmin/testing/util/ChangeLog +++ b/src/kadmin/testing/util/ChangeLog @@ -1,3 +1,7 @@ +Mon Mar 31 17:43:06 1997 Barry Jaspan + + * Makefile.in: be more verbose if Tcl is unavailable + Wed Feb 5 22:57:53 1997 Tom Yu * Makefile.in: diff --git a/src/kadmin/testing/util/Makefile.in b/src/kadmin/testing/util/Makefile.in index cc5835836..6c6cf630b 100644 --- a/src/kadmin/testing/util/Makefile.in +++ b/src/kadmin/testing/util/Makefile.in @@ -14,7 +14,9 @@ DO_ALL=@DO_ALL@ all:: all-$(DO_ALL) all-:: - @echo "Tcl is not installed on this system. The kadm5 test suite cannot be run." + @echo "+++" + @echo "+++ WARNING: Tcl not available. The kadm5 tests will not be run." + @echo "+++" all-tcl:: $(CLNTPROG) $(SRVPROG) diff --git a/src/lib/kadm5/ChangeLog b/src/lib/kadm5/ChangeLog index 2aa7cc99b..dc016db57 100644 --- a/src/lib/kadm5/ChangeLog +++ b/src/lib/kadm5/ChangeLog @@ -1,3 +1,8 @@ +Mon Mar 31 17:41:11 1997 Barry Jaspan + + * kadm_err.et, kadm_rpc.h, kadm_rpc_xdr.c: add support for + setkey_principal + Thu Jan 16 19:01:00 1997 Tom Yu * Makefile.in (all-prerecurse): Update to use double-colon rules. diff --git a/src/lib/kadm5/clnt/ChangeLog b/src/lib/kadm5/clnt/ChangeLog index 0497aba54..3635a324f 100644 --- a/src/lib/kadm5/clnt/ChangeLog +++ b/src/lib/kadm5/clnt/ChangeLog @@ -1,3 +1,8 @@ +Mon Mar 31 17:40:48 1997 Barry Jaspan + + * client_principal.c, client_rpc.c: add support for + setkey_principal + Sat Feb 22 01:35:19 1997 Sam Hartman * Makefile.in (SHLIB_EXPDEPS): s/.so/$(SHLIBEXT) diff --git a/src/lib/kadm5/clnt/client_principal.c b/src/lib/kadm5/clnt/client_principal.c index 14cd55d80..adcbb291f 100644 --- a/src/lib/kadm5/clnt/client_principal.c +++ b/src/lib/kadm5/clnt/client_principal.c @@ -261,6 +261,31 @@ kadm5_chpass_principal(void *server_handle, return r->code; } +kadm5_ret_t +kadm5_setkey_principal(void *server_handle, + krb5_principal princ, + krb5_keyblock *keyblocks, + int n_keys) +{ + setkey_arg arg; + generic_ret *r; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + arg.princ = princ; + arg.keyblocks = keyblocks; + arg.n_keys = n_keys; + arg.api_version = handle->api_version; + + if(princ == NULL || keyblocks == NULL) + return EINVAL; + r = setkey_principal_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, diff --git a/src/lib/kadm5/clnt/client_rpc.c b/src/lib/kadm5/clnt/client_rpc.c index 547844a2c..ecb5943b3 100644 --- a/src/lib/kadm5/clnt/client_rpc.c +++ b/src/lib/kadm5/clnt/client_rpc.c @@ -106,6 +106,20 @@ chpass_principal_1(argp, clnt) return (&res); } +generic_ret * +setkey_principal_1(argp, clnt) + setkey_arg *argp; + CLIENT *clnt; +{ + static generic_ret res; + + memset((char *)&res, 0, sizeof(res)); + if (clnt_call(clnt, SETKEY_PRINCIPAL, xdr_setkey_arg, argp, xdr_generic_ret, &res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); + } + return (&res); +} + chrand_ret * chrand_principal_1(argp, clnt) chrand_arg *argp; diff --git a/src/lib/kadm5/kadm_err.et b/src/lib/kadm5/kadm_err.et index fbddc237d..a43a9b557 100644 --- a/src/lib/kadm5/kadm_err.et +++ b/src/lib/kadm5/kadm_err.et @@ -54,4 +54,6 @@ error_code KADM5_GSS_ERROR, "GSS-API (or Kerberos) error" error_code KADM5_BAD_TL_TYPE, "Programmer error! Illegal tagged data list type" error_code KADM5_MISSING_CONF_PARAMS, "Required parameters in kdc.conf missing" error_code KADM5_BAD_SERVER_NAME, "Bad krb5 admin server hostname" +error_code KADM5_AUTH_SETKEY, "Operation requires ``set-key'' privilege" +error_code KADM5_SETKEY_DUP_ENCTYPES, "Multiple values for single or folded enctype" end diff --git a/src/lib/kadm5/kadm_rpc.h b/src/lib/kadm5/kadm_rpc.h index b0f97e6cb..82bf3d57c 100644 --- a/src/lib/kadm5/kadm_rpc.h +++ b/src/lib/kadm5/kadm_rpc.h @@ -66,6 +66,15 @@ struct chpass_arg { typedef struct chpass_arg chpass_arg; bool_t xdr_chpass_arg(); +struct setkey_arg { + krb5_ui_4 api_version; + krb5_principal princ; + krb5_keyblock *keyblocks; + int n_keys; +}; +typedef struct setkey_arg setkey_arg; +bool_t xdr_setkey_arg(); + struct chrand_arg { krb5_ui_4 api_version; krb5_principal princ; @@ -202,4 +211,6 @@ extern generic_ret *init_1(); extern gprincs_ret *get_princs_1(); #define GET_POLS ((krb5_ui_4) 15) extern gpols_ret *get_pols_1(); +#define SETKEY_PRINCIPAL ((krb5_ui_4) 16) +extern generic_ret *setkey_principal_1(); diff --git a/src/lib/kadm5/kadm_rpc_xdr.c b/src/lib/kadm5/kadm_rpc_xdr.c index 67b94c921..fd253043d 100644 --- a/src/lib/kadm5/kadm_rpc_xdr.c +++ b/src/lib/kadm5/kadm_rpc_xdr.c @@ -585,6 +585,23 @@ xdr_chpass_arg(XDR *xdrs, chpass_arg *objp) return (TRUE); } +bool_t +xdr_setkey_arg(XDR *xdrs, setkey_arg *objp) +{ + if (!xdr_ui_4(xdrs, &objp->api_version)) { + return (FALSE); + } + if (!xdr_krb5_principal(xdrs, &objp->princ)) { + return (FALSE); + } + if (!xdr_array(xdrs, (caddr_t *) &objp->keyblocks, + (unsigned int *) &objp->n_keys, ~0, + sizeof(krb5_keyblock), xdr_krb5_keyblock)) { + return (FALSE); + } + return (TRUE); +} + bool_t xdr_chrand_arg(XDR *xdrs, chrand_arg *objp) { diff --git a/src/lib/kadm5/srv/ChangeLog b/src/lib/kadm5/srv/ChangeLog index d462a0d77..fcca8b1a3 100644 --- a/src/lib/kadm5/srv/ChangeLog +++ b/src/lib/kadm5/srv/ChangeLog @@ -1,3 +1,8 @@ +Mon Mar 31 17:40:24 1997 Barry Jaspan + + * server_acl.c, server_acl.h, svr_pricipal.c: add support for + setkey_principal + Sun Mar 9 13:40:33 1997 Tom Yu * svr_principal.c (add_to_history): Don't call realloc() on a NULL diff --git a/src/lib/kadm5/srv/server_acl.c b/src/lib/kadm5/srv/server_acl.c index 6f5c01499..35da5dd80 100644 --- a/src/lib/kadm5/srv/server_acl.c +++ b/src/lib/kadm5/srv/server_acl.c @@ -56,6 +56,7 @@ static const aop_t acl_op_table[] = { { 'c', ACL_CHANGEPW }, { 'i', ACL_INQUIRE }, { 'l', ACL_LIST }, + { 's', ACL_SETKEY }, { 'x', ACL_ALL_MASK }, { '*', ACL_ALL_MASK }, { '\0', 0 } diff --git a/src/lib/kadm5/srv/server_acl.h b/src/lib/kadm5/srv/server_acl.h index 9dfc8daba..4323d6319 100644 --- a/src/lib/kadm5/srv/server_acl.h +++ b/src/lib/kadm5/srv/server_acl.h @@ -56,6 +56,7 @@ #define ACL_INQUIRE 32 /* #define ACL_EXTRACT 64 */ #define ACL_LIST 128 +#define ACL_SETKEY 256 #define ACL_RENAME (ACL_ADD+ACL_DELETE) #define ACL_ALL_MASK (ACL_ADD | \ diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 5ff1b4976..e7bfe0394 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -86,6 +86,21 @@ static krb5_tl_data *dup_tl_data(krb5_tl_data *tl) return n; } +/* This is in lib/kdb/kdb_cpw.c, but is static */ +static void cleanup_key_data(context, count, data) + krb5_context context; + int count; + krb5_key_data * data; +{ + int i, j; + + for (i = 0; i < count; i++) + for (j = 0; j < data[i].key_data_ver; j++) + if (data[i].key_data_length[j]) + free(data[i].key_data_contents[j]); + free(data); +} + kadm5_ret_t kadm5_create_principal(void *server_handle, kadm5_principal_ent_t entry, long mask, @@ -1246,6 +1261,133 @@ done: return ret; } +kadm5_ret_t +kadm5_setkey_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; + int i, kvno, ret, last_pwd, have_pol = 0; + int deskeys; + kadm5_server_handle_t handle = server_handle; + + CHECK_HANDLE(server_handle); + + if (principal == NULL || keyblocks == NULL) + return EINVAL; + if (hist_princ && /* this will be NULL when initializing the databse */ + ((krb5_principal_compare(handle->context, + principal, hist_princ)) == TRUE)) + return KADM5_PROTECT_PRINCIPAL; + + for (i = 0, deskeys = 0; i < n_keys; i++) { + if (keyblocks[i].enctype == ENCTYPE_DES_CBC_MD4 || + keyblocks[i].enctype == ENCTYPE_DES_CBC_MD5 || + keyblocks[i].enctype == ENCTYPE_DES_CBC_RAW || + keyblocks[i].enctype == ENCTYPE_DES_CBC_CRC) + deskeys++; + if (deskeys > 1) + return KADM5_SETKEY_DUP_ENCTYPES; + } + + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) + return(ret); + + for (kvno = 0, i=0; i kvno) + kvno = kdb.key_data[i].key_data_kvno; + + if (kdb.key_data != NULL) + cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data); + + kdb.key_data = (krb5_key_data*)malloc(n_keys*sizeof(krb5_key_data)); + if (kdb.key_data == NULL) + return ENOMEM; + memset(kdb.key_data, 0, n_keys*sizeof(krb5_key_data)); + kdb.n_key_data = n_keys; + + for (i = 0; i < n_keys; i++) { + if (ret = krb5_dbekd_encrypt_key_data(handle->context, + &master_encblock, + &keyblocks[i], NULL, + kvno + 1, + &kdb.key_data[i])) + return ret; + } + + kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE; + + if (ret = krb5_timeofday(handle->context, &now)) + goto done; + + if ((adb.aux_attributes & KADM5_POLICY)) { + if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, + &pol)) != KADM5_OK) + goto done; + have_pol = 1; + +#if 0 + /* + * The spec says this check is overridden if the caller has + * modify privilege. The admin server therefore makes this + * check itself (in chpass_principal_wrapper, misc.c). A + * local caller implicitly has all authorization bits. + */ + if (ret = krb5_dbe_lookup_last_pwd_change(handle->context, + &kdb, &last_pwd)) + goto done; + if((now - last_pwd) < pol.pw_min_life && + !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) { + ret = KADM5_PASS_TOOSOON; + goto done; + } +#endif +#if 0 + /* + * Should we be checking/updating pw history here? + */ + if(pol.pw_history_num > 1) { + if(adb.admin_history_kvno != hist_kvno) { + ret = KADM5_BAD_HIST_KEY; + goto done; + } + + if (ret = check_pw_reuse(handle->context, + &hist_encblock, + kdb.n_key_data, kdb.key_data, + adb.old_key_len, adb.old_keys)) + goto done; + } +#endif + + if (pol.pw_max_life) + kdb.pw_expiration = now + pol.pw_max_life; + else + kdb.pw_expiration = 0; + } else { + kdb.pw_expiration = 0; + } + + if (ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now)) + goto done; + + if ((ret = kdb_put_entry(handle, &kdb, &adb))) + goto done; + + ret = KADM5_OK; +done: + kdb_free_entry(handle, &kdb, &adb); + if (have_pol) + kadm5_free_policy_ent(handle->lhandle, &pol); + + return ret; +} + /* * 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 diff --git a/src/lib/kadm5/unit-test/ChangeLog b/src/lib/kadm5/unit-test/ChangeLog index 7ec91fa00..4401065c9 100644 --- a/src/lib/kadm5/unit-test/ChangeLog +++ b/src/lib/kadm5/unit-test/ChangeLog @@ -1,3 +1,7 @@ +Mon Mar 31 17:39:52 1997 Barry Jaspan + + * Makefile.in, setkey-test.c: add support for setkey + Wed Mar 12 15:49:46 1997 Barry Jaspan * Makefile.in (unit-test-server-body): depend on test-randkey, not diff --git a/src/lib/kadm5/unit-test/Makefile.in b/src/lib/kadm5/unit-test/Makefile.in index 656a6ea2b..dd0522c80 100644 --- a/src/lib/kadm5/unit-test/Makefile.in +++ b/src/lib/kadm5/unit-test/Makefile.in @@ -4,6 +4,7 @@ PROG_RPATH=$(KRB5_LIBDIR) all:: init-test destroy-test client-handle-test client-iter-test all:: randkey-test server-handle-test lock-test server-iter-test +all:: server-setkey-test client-setkey-test # # The client-side test programs. @@ -28,6 +29,10 @@ client-iter-test: iter-test.o $(KADMLCNT_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o client-iter-test iter-test.o \ $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) +client-setkey-test: setkey-test.o $(KADMCLNT_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o client-setkey-test setkey-test.o \ + $(KADMCLNT_LIBS) $(KRB5_BASE_LIBS) + # # The server-side test programs. # @@ -48,6 +53,13 @@ server-iter-test: iter-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) $(CC_LINK) -o server-iter-test iter-test.o \ $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) +setkey-test.o: $(SRCTOP)/lib/kadm5/unit-test/setkey-test.c + $(CC) $(CFLAGS) -UUSE_KADM5_API_VERSION -DUSE_KADM5_API_VERSION=2 -c $(SRCTOP)/lib/kadm5/unit-test/setkey-test.c + +server-setkey-test: setkey-test.o $(KADMSRV_DEPLIBS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o server-setkey-test setkey-test.o \ + $(KADMSRV_LIBS) $(KRB5_BASE_LIBS) + # # The unit-test targets # diff --git a/src/lib/kadm5/unit-test/setkey-test.c b/src/lib/kadm5/unit-test/setkey-test.c new file mode 100644 index 000000000..e329fce25 --- /dev/null +++ b/src/lib/kadm5/unit-test/setkey-test.c @@ -0,0 +1,212 @@ +#include +#include +#include + +krb5_keyblock test1[] = { + 0, ENCTYPE_DES_CBC_CRC, 0, 0, + -1, +}; +krb5_keyblock test2[] = { + 0, ENCTYPE_DES_CBC_RAW, 0, 0, + -1, +}; +krb5_keyblock test3[] = { + 0, ENCTYPE_DES_CBC_MD5, 0, 0, + -1, +}; + +krb5_keyblock *tests[] = { + test1, test2, test3, NULL +}; + +int keyblocks_equal(krb5_keyblock *kb1, krb5_keyblock *kb2) +{ + return (kb1->enctype == kb2->enctype && + kb1->length == kb2->length && + memcmp(kb1->contents, kb2->contents, kb1->length) == 0); +} + +krb5_data tgtname = { + 0, + KRB5_TGS_NAME_SIZE, + KRB5_TGS_NAME +}; + +unsigned int ktypes[] = { 0, 0 }; + +extern krb5_kt_ops krb5_ktf_writable_ops; + +main(int argc, char **argv) +{ + krb5_context context; + krb5_keytab kt; + krb5_keytab_entry ktent; + krb5_encrypt_block eblock; + krb5_creds my_creds; + kadm5_principal_ent_rec princ_ent; + krb5_principal princ, server; + char pw[16]; + char *whoami, *principal, *authprinc; + krb5_data pwdata; + void *handle; + int ret, i, test, encnum; + + whoami = argv[0]; + + if (argc != 2 && argc != 3) { + fprintf(stderr, "Usage: %s principal [authuser]\n", whoami); + exit(1); + } + principal = argv[1]; + authprinc = argv[2] ? argv[2] : argv[0]; + + /* + * Setup. Initialize data structures, open keytab, open connection + * to kadm5 server. + */ + + memset((char *) &context, 0, sizeof(context)); + krb5_init_context(&context); + + ret = krb5_parse_name(context, principal, &princ); + if (ret) { + com_err(whoami, ret, "while parsing principal name %s", principal); + exit(1); + } + + if((ret = krb5_build_principal_ext(context, &server, + krb5_princ_realm(kcontext, princ)->length, + krb5_princ_realm(kcontext, princ)->data, + tgtname.length, tgtname.data, + krb5_princ_realm(kcontext, princ)->length, + krb5_princ_realm(kcontext, princ)->data, + 0))) { + com_err(whoami, ret, "while building server name"); + exit(1); + } + + /* register the WRFILE keytab type */ + if (ret = krb5_kt_register(context, &krb5_ktf_writable_ops)) { + com_err(whoami, ret, + "while registering writable key table functions"); + exit(1); + } + + ret = krb5_kt_default(context, &kt); + if (ret) { + com_err(whoami, ret, "while opening keytab"); + exit(1); + } + + ret = kadm5_init(authprinc, NULL, KADM5_ADMIN_SERVICE, NULL, + KADM5_STRUCT_VERSION, KADM5_API_VERSION_2, + &handle); + if (ret) { + com_err(whoami, ret, "while initializing connection"); + exit(1); + } + + /* these pw's don't need to be secure, just different every time */ + srandom(getpid() ^ time(0)); + pwdata.data = pw; + pwdata.length = sizeof(pw); + + /* + * For each test: + * + * For each enctype in the test, construct a random password/key. + * Assign all keys to principal with kadm5_setkey_principal. Add + * each key to the keytab, and acquire an initial ticket with the + * keytab (XXX can I specify the enctype & kvno explicitly?). If + * krb5_get_in_tkt_with_keytab succeeds, then the keys were set + * successfully. + */ + for (test = 0; tests[test] != NULL; test++) { + krb5_keyblock *testp = tests[test]; + printf("+ Test %d:\n", test); + + for (encnum = 0; testp[encnum].magic != -1; encnum++) { + for (i = 0; i < sizeof(pw); i++) + pw[i] = (random() % 26) + '0'; /* XXX */ + + krb5_use_enctype(context, &eblock, testp[encnum].enctype); + if (ret = krb5_string_to_key(context, &eblock, &testp[encnum], + &pwdata, NULL)) { + com_err(whoami, ret, "while converting string to key"); + exit(1); + } + } + + /* now, encnum == # of keyblocks in testp */ + ret = kadm5_setkey_principal(handle, princ, testp, encnum); + if (ret) { + com_err(whoami, ret, "while setting keys"); + exit(1); + } + + ret = kadm5_get_principal(handle, princ, &princ_ent, KADM5_KVNO); + if (ret) { + com_err(whoami, ret, "while retrieving principal"); + exit(1); + } + + for (encnum = 0; testp[encnum].magic != -1; encnum++) { + printf("+ enctype %d\n", testp[encnum].enctype); + + memset((char *) &ktent, 0, sizeof(ktent)); + ktent.principal = princ; + ktent.key = testp[encnum]; + ktent.vno = princ_ent.kvno; + + ret = krb5_kt_add_entry(context, kt, &ktent); + if (ret) { + com_err(whoami, ret, "while adding keytab entry"); + exit(1); + } + + memset((char *)&my_creds, 0, sizeof(my_creds)); + my_creds.client = princ; + my_creds.server = server; + + ktypes[0] = testp[encnum].enctype; + ret = krb5_get_in_tkt_with_keytab(context, + 0 /* options */, + NULL /* addrs */, + ktypes, + NULL /* preauth */, + kt, 0, + &my_creds, 0); + if (ret) { + com_err(whoami, ret, "while acquiring initial ticket"); + exit(1); + } + + /* since I can't specify enctype explicitly ... */ + ret = krb5_kt_remove_entry(context, kt, &ktent); + if (ret) { + com_err(whoami, ret, "while removing keytab entry"); + exit(1); + } + } + } + + ret = krb5_kt_close(context, kt); + if (ret) { + com_err(whoami, ret, "while closing keytab"); + exit(1); + } + + ret = kadm5_destroy(handle); + if (ret) { + com_err(whoami, ret, "while closing kadmin connection"); + exit(1); + } + + return 0; +} + + + + + +