Add kadmin functionality for string attributes
authorGreg Hudson <ghudson@mit.edu>
Wed, 21 Sep 2011 16:29:00 +0000 (16:29 +0000)
committerGreg Hudson <ghudson@mit.edu>
Wed, 21 Sep 2011 16:29:00 +0000 (16:29 +0000)
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25215 dc483132-0cff-0310-8789-dd5450dbe970

21 files changed:
doc/rst_source/krb_admins/admin_commands/kadmin_local.rst
src/include/kdb.h
src/kadmin/cli/kadmin.M
src/kadmin/cli/kadmin.c
src/kadmin/cli/kadmin.h
src/kadmin/cli/kadmin_ct.ct
src/kadmin/server/kadm_rpc_svc.c
src/kadmin/server/ovsec_kadmd.c
src/kadmin/server/server_stubs.c
src/lib/kadm5/admin.h
src/lib/kadm5/admin_xdr.h
src/lib/kadm5/clnt/client_principal.c
src/lib/kadm5/clnt/client_rpc.c
src/lib/kadm5/clnt/libkadm5clnt_mit.exports
src/lib/kadm5/kadm_rpc.h
src/lib/kadm5/kadm_rpc_xdr.c
src/lib/kadm5/misc_free.c
src/lib/kadm5/srv/libkadm5srv_mit.exports
src/lib/kadm5/srv/svr_principal.c
src/tests/Makefile.in
src/tests/t_stringattr.py [new file with mode: 0644]

index eab77e0c373bba69c436fc7344c6cb63980e88c0..ae6b1434c669647ffc066267b96d3d46ba90cde3 100644 (file)
@@ -562,6 +562,43 @@ list_principals
 
 .. _list_principals_end:
 
+.. _get_strings:
+
+get_strings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+       **get_strings** *principal*
+              Displays string attributes on *principal*.
+             String attributes are used to supply per-principal configuration to some KDC plugin modules.
+
+              Alias::
+
+                     getstr
+
+.. _set_string:
+
+set_string
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+       **set_string** *principal* *key* *value*
+              Sets a string attribute on *principal*.
+
+              Alias::
+
+                     setstr
+
+.. _del_string:
+
+del_string
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+       **del_string** *principal* *key*
+              Deletes a string attribute from *principal*.
+
+              Alias::
+
+                     delstr
+
 .. _add_policy:
 
 add_policy
index 31f48b1515f3e5b7c8381b58264a123416c506fc..809722eda3f7b4309da003307484965d9640378e 100644 (file)
@@ -243,7 +243,7 @@ typedef struct __krb5_key_salt_tuple {
 #define KRB5_TL_MKEY_AUX                0x000a
 
 /* String attributes may not always be represented in tl-data.  kadmin clients
- * must use the modify_strings and get_strings RPCs. */
+ * must use the get_strings and set_string RPCs. */
 #define KRB5_TL_STRING_ATTRS            0x000b
 
 #define KRB5_TL_PAC_LOGON_INFO          0x0100 /* NDR encoded validation info */
index f847c8235d098490eff8c60e87fa9a5e50cfc86d..4dd10e6d33796bd0e7766b617d561e8922d402c4 100644 (file)
@@ -672,6 +672,28 @@ kadmin:
 .RE
 .fi
 .TP
+\fBget_strings\fP \fIprincipal\fP
+displays string attributes on
+.IR principal .
+String attributes are used to supply per-principal configuration to
+some KDC plugin modules.  Alias
+.BR getstrs .
+.fi
+.TP
+\fBset_string\fP \fIprincipal\fP \fIkey\fP \fIvalue\fP
+sets a string attribute on
+.IR principal .
+Alias
+.BR setstr .
+.fi
+.TP
+\fBdel_string\fP \fIprincipal\fP \fIkey\fP
+deletes a string attribute from
+.IR principal .
+Alias
+.BR delstr .
+.fi
+.TP
 \fBadd_policy\fP [\fIoptions\fP] \fIpolicy\fP
 adds the named policy to the policy database.  Requires the
 .I add
index baaac0bab356c3a243723b6ba2ef968c1cc88dfd..539091f846eae75c5ea989fe490df1dba61131fa 100644 (file)
@@ -1898,3 +1898,130 @@ cleanup:
     free(canon);
     return;
 }
+
+void
+kadmin_getstrings(int argc, char *argv[])
+{
+    kadm5_ret_t retval;
+    char *pname, *canon = NULL;
+    krb5_principal princ = NULL;
+    krb5_string_attr *strings = NULL;
+    int count, i;
+
+    if (argc != 2) {
+        fprintf(stderr, _("usage: get_strings principal\n"));
+        return;
+    }
+    pname = argv[1];
+
+    retval = kadmin_parse_name(pname, &princ);
+    if (retval) {
+        com_err("get_strings", retval, _("while parsing principal"));
+        return;
+    }
+
+    retval = krb5_unparse_name(context, princ, &canon);
+    if (retval) {
+        com_err("get_strings", retval, _("while canonicalizing principal"));
+        goto cleanup;
+    }
+
+    retval = kadm5_get_strings(handle, princ, &strings, &count);
+    if (retval) {
+        com_err("get_strings", retval,
+                _("while getting attributes for principal \"%s\""), canon);
+        goto cleanup;
+    }
+
+    if (count == 0)
+        printf(_("(No string attributes.)\n"));
+    for (i = 0; i < count; i++)
+        printf("%s: %s\n", strings[i].key, strings[i].value);
+    kadm5_free_strings(handle, strings, count);
+
+cleanup:
+    krb5_free_principal(context, princ);
+    free(canon);
+    return;
+}
+
+void
+kadmin_setstring(int argc, char *argv[])
+{
+    kadm5_ret_t retval;
+    char *pname, *canon = NULL, *key, *value;
+    krb5_principal princ = NULL;
+
+    if (argc != 4) {
+        fprintf(stderr, _("usage: set_string principal key value\n"));
+        return;
+    }
+    pname = argv[1];
+    key = argv[2];
+    value = argv[3];
+
+    retval = kadmin_parse_name(pname, &princ);
+    if (retval) {
+        com_err("set_string", retval, _("while parsing principal"));
+        return;
+    }
+
+    retval = krb5_unparse_name(context, princ, &canon);
+    if (retval) {
+        com_err("set_string", retval, _("while canonicalizing principal"));
+        goto cleanup;
+    }
+
+    retval = kadm5_set_string(handle, princ, key, value);
+    if (retval) {
+        com_err("set_string", retval,
+                _("while setting attribute on principal \"%s\""), canon);
+        goto cleanup;
+    }
+
+    printf(_("Attribute set for principal \"%s\".\n"), canon);
+cleanup:
+    krb5_free_principal(context, princ);
+    free(canon);
+    return;
+}
+
+void
+kadmin_delstring(int argc, char *argv[])
+{
+    kadm5_ret_t retval;
+    char *pname, *canon = NULL, *key;
+    krb5_principal princ = NULL;
+
+    if (argc != 3) {
+        fprintf(stderr, _("usage: del_string principal key\n"));
+        return;
+    }
+    pname = argv[1];
+    key = argv[2];
+
+    retval = kadmin_parse_name(pname, &princ);
+    if (retval) {
+        com_err("delstring", retval, _("while parsing principal"));
+        return;
+    }
+
+    retval = krb5_unparse_name(context, princ, &canon);
+    if (retval) {
+        com_err("del_string", retval, _("while canonicalizing principal"));
+        goto cleanup;
+    }
+
+    retval = kadm5_set_string(handle, princ, key, NULL);
+    if (retval) {
+        com_err("del_string", retval,
+                _("while deleting attribute from principal \"%s\""), canon);
+        goto cleanup;
+    }
+
+    printf(_("Attribute removed from principal \"%s\".\n"), canon);
+cleanup:
+    krb5_free_principal(context, princ);
+    free(canon);
+    return;
+}
index 6d87040359004dff9f8ca03ab24410cbb42a1951..7afa0c9283ea108ae90adc0be8ba066992129449 100644 (file)
@@ -53,6 +53,9 @@ extern void kadmin_getprivs(int argc, char *argv[]);
 extern void kadmin_keytab_add(int argc, char *argv[]);
 extern void kadmin_keytab_remove(int argc, char *argv[]);
 extern void kadmin_purgekeys(int argc, char *argv[]);
+extern void kadmin_getstrings(int argc, char *argv[]);
+extern void kadmin_setstring(int argc, char *argv[]);
+extern void kadmin_delstring(int argc, char *argv[]);
 
 #include "autoconf.h"
 
index 86ac96e7083db1617740b5a21be862791c9dc305..705e41840e3f967af9abaa9e878f5aa7a3600b9e 100644 (file)
@@ -80,6 +80,15 @@ request kadmin_unlock, "Release exclusive database lock",
 request kadmin_purgekeys, "Purge previously retained old keys from a principal",
        purgekeys;
 
+request kadmin_getstrings, "Show string attributes on a principal",
+       get_strings, getstrs;
+
+request kadmin_setstring, "Set a string attribute on a principal",
+       set_string, setstr;
+
+request kadmin_delstring, "Delete a string attribute on a principal",
+       del_string, delstr;
+
 # list_requests is generic -- unrelated to Kerberos
 request        ss_list_requests, "List available requests.",
        list_requests, lr, "?";
index a9bccf5999afb1234daff172b5a3a8c242a01592..a75bdb89d3c28c95963e731372a22695cab4e2be 100644 (file)
@@ -213,6 +213,18 @@ void kadm_1(rqstp, transp)
          local = (char *(*)()) purgekeys_2_svc;
          break;
 
+     case GET_STRINGS:
+         xdr_argument = xdr_gstrings_arg;
+         xdr_result = xdr_gstrings_ret;
+         local = (char *(*)()) get_strings_2_svc;
+         break;
+
+     case SET_STRING:
+         xdr_argument = xdr_sstring_arg;
+         xdr_result = xdr_generic_ret;
+         local = (char *(*)()) set_string_2_svc;
+         break;
+
      default:
          krb5_klog_syslog(LOG_ERR, "Invalid KADM5 procedure number: %s, %d",
                 inet_ntoa(rqstp->rq_xprt->xp_raddr.sin_addr),
index 63d1787cbc1b9ca4e2732ce3ba88d449cd0e92c8..f38f209f14e79cbb639bebc5900655b004af62a2 100644 (file)
@@ -746,7 +746,9 @@ void log_badverf(gss_name_t client_name, gss_name_t server_name,
         {19, "CHPASS_PRINCIPAL3"},
         {20, "CHRAND_PRINCIPAL3"},
         {21, "SETKEY_PRINCIPAL3"},
-        {22, "PURGEKEYS"}
+        {22, "PURGEKEYS"},
+        {23, "GET_STRINGS"},
+        {24, "SET_STRING"}
     };
 #define NPROCNAMES (sizeof (proc_names) / sizeof (struct procnames))
     OM_uint32 minor;
index 6a2ed75511a2b6602c36c3c0993c42ead91f05f3..8dbe756d695604e0fab55a3551f753d24ab48953 100644 (file)
@@ -1604,6 +1604,118 @@ exit_func:
     return &ret;
 }
 
+gstrings_ret *
+get_strings_2_svc(gstrings_arg *arg, struct svc_req *rqstp)
+{
+    static gstrings_ret             ret;
+    char                            *prime_arg;
+    gss_buffer_desc                 client_name,
+        service_name;
+    OM_uint32                       minor_stat;
+    kadm5_server_handle_t           handle;
+    const char                      *errmsg = NULL;
+
+    xdr_free(xdr_gstrings_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+        goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle)))
+        goto exit_func;
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+        ret.code = KADM5_FAILURE;
+        goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+        ret.code = KADM5_BAD_PRINCIPAL;
+        goto exit_func;
+    }
+
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+                                                       rqst2name(rqstp),
+                                                       ACL_LIST, NULL, NULL)) {
+        ret.code = KADM5_AUTH_LIST;
+        log_unauth("kadm5_get_strings", prime_arg,
+                   &client_name, &service_name, rqstp);
+    } else {
+        ret.code = kadm5_get_strings((void *)handle, arg->princ, &ret.strings,
+                                     &ret.count);
+        if (ret.code != 0)
+            errmsg = krb5_get_error_message(handle->context, ret.code);
+
+        log_done("kadm5_get_strings", prime_arg, errmsg,
+                 &client_name, &service_name, rqstp);
+
+        if (errmsg != NULL)
+            krb5_free_error_message(handle->context, errmsg);
+    }
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    free_server_handle(handle);
+    return &ret;
+}
+
+generic_ret *
+set_string_2_svc(sstring_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;
+    const char                      *errmsg = NULL;
+
+    xdr_free(xdr_generic_ret, &ret);
+
+    if ((ret.code = new_server_handle(arg->api_version, rqstp, &handle)))
+        goto exit_func;
+
+    if ((ret.code = check_handle((void *)handle)))
+        goto exit_func;
+
+    ret.api_version = handle->api_version;
+
+    if (setup_gss_names(rqstp, &client_name, &service_name) < 0) {
+        ret.code = KADM5_FAILURE;
+        goto exit_func;
+    }
+    if (krb5_unparse_name(handle->context, arg->princ, &prime_arg)) {
+        ret.code = KADM5_BAD_PRINCIPAL;
+        goto exit_func;
+    }
+
+    if (CHANGEPW_SERVICE(rqstp) || !kadm5int_acl_check(handle->context,
+                                                       rqst2name(rqstp),
+                                                       ACL_LIST, NULL, NULL)) {
+        ret.code = KADM5_AUTH_LIST;
+        log_unauth("kadm5_mod_strings", prime_arg,
+                   &client_name, &service_name, rqstp);
+    } else {
+        ret.code = kadm5_set_string((void *)handle, arg->princ, arg->key,
+                                    arg->value);
+        if (ret.code != 0)
+            errmsg = krb5_get_error_message(handle->context, ret.code);
+
+        log_done("kadm5_mod_strings", prime_arg, errmsg,
+                 &client_name, &service_name, rqstp);
+
+        if (errmsg != NULL)
+            krb5_free_error_message(handle->context, errmsg);
+    }
+    free(prime_arg);
+    gss_release_buffer(&minor_stat, &client_name);
+    gss_release_buffer(&minor_stat, &service_name);
+exit_func:
+    free_server_handle(handle);
+    return &ret;
+}
+
 generic_ret *init_2_svc(krb5_ui_4 *arg, struct svc_req *rqstp)
 {
     static generic_ret         ret;
index 7bcc7fcbc98cfdd24274819ccd88dbfae6f1436c..d1a76f737d39ef4c516fc35c37d3898dd1b532ed 100644 (file)
@@ -513,6 +513,20 @@ kadm5_ret_t    kadm5_purgekeys(void *server_handle,
                                krb5_principal principal,
                                int keepkvno);
 
+kadm5_ret_t    kadm5_get_strings(void *server_handle,
+                                 krb5_principal principal,
+                                 krb5_string_attr **strings_out,
+                                 int *count_out);
+
+kadm5_ret_t    kadm5_set_string(void *server_handle,
+                                krb5_principal principal,
+                                const char *key,
+                                const char *value);
+
+kadm5_ret_t    kadm5_free_strings(void *server_handle,
+                                  krb5_string_attr *strings,
+                                  int count);
+
 KADM5INT_END_DECLS
 
 #endif /* __KADM5_ADMIN_H__ */
index 927a0e5b0ae534f5fb50f6f32a898c111f10e831..e46d5429d8c731f3731b9be861e3570c8ac14fa1 100644 (file)
@@ -56,6 +56,9 @@ bool_t      xdr_gpols_arg(XDR *xdrs, gpols_arg *objp);
 bool_t      xdr_gpols_ret(XDR *xdrs, gpols_ret *objp);
 bool_t      xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp);
 bool_t      xdr_purgekeys_arg(XDR *xdrs, purgekeys_arg *objp);
+bool_t      xdr_gstrings_arg(XDR *xdrs, gstrings_arg *objp);
+bool_t      xdr_gstrings_ret(XDR *xdrs, gstrings_ret *objp);
+bool_t      xdr_sstring_arg(XDR *xdrs, sstring_arg *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);
@@ -63,4 +66,5 @@ bool_t            xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp);
 bool_t      xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp);
 bool_t     xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp);
 bool_t      xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
+bool_t      xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp);
 bool_t      xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
index 41324be804811ff8cadeb3bc54231059a88556b6..6af2a17519eaddde28f4dba1c13d4cbb9c5d0c9f 100644 (file)
@@ -482,3 +482,51 @@ kadm5_purgekeys(void *server_handle,
         eret();
     return r->code;
 }
+
+kadm5_ret_t
+kadm5_get_strings(void *server_handle, krb5_principal principal,
+                  krb5_string_attr **strings_out, int *count_out)
+{
+    gstrings_arg arg;
+    gstrings_ret *r;
+    kadm5_server_handle_t handle = server_handle;
+
+    *strings_out = NULL;
+    *count_out = 0;
+    CHECK_HANDLE(server_handle);
+    if (principal == NULL)
+        return EINVAL;
+
+    arg.princ = principal;
+    arg.api_version = handle->api_version;
+    r = get_strings_2(&arg, handle->clnt);
+    if (r == NULL)
+        eret();
+    if (r->code == 0) {
+        *strings_out = r->strings;
+        *count_out = r->count;
+    }
+    return r->code;
+}
+
+kadm5_ret_t
+kadm5_set_string(void *server_handle, krb5_principal principal,
+                 const char *key, const char *value)
+{
+    sstring_arg arg;
+    generic_ret *r;
+    kadm5_server_handle_t handle = server_handle;
+
+    CHECK_HANDLE(server_handle);
+    if (principal == NULL || key == NULL)
+        return EINVAL;
+
+    arg.princ = principal;
+    arg.key = (char *)key;
+    arg.value = (char *)value;
+    arg.api_version = handle->api_version;
+    r = set_string_2(&arg, handle->clnt);
+    if (r == NULL)
+        eret();
+    return r->code;
+}
index 95417a60ce80682b41d5a2be315c59f5dda4e7ea..e11346d82ac2142bf4fdedec216e569bb5bd5708 100644 (file)
@@ -341,3 +341,33 @@ purgekeys_2(purgekeys_arg *argp, CLIENT *clnt)
      }
      return (&clnt_res);
 }
+
+gstrings_ret *
+get_strings_2(gstrings_arg *argp, CLIENT *clnt)
+{
+     static gstrings_ret clnt_res;
+
+     memset(&clnt_res, 0, sizeof(clnt_res));
+     if (clnt_call(clnt, GET_STRINGS,
+                  (xdrproc_t) xdr_gstrings_arg, (caddr_t) argp,
+                  (xdrproc_t) xdr_gstrings_ret, (caddr_t) &clnt_res,
+                  TIMEOUT) != RPC_SUCCESS) {
+         return (NULL);
+     }
+     return (&clnt_res);
+}
+
+generic_ret *
+set_string_2(sstring_arg *argp, CLIENT *clnt)
+{
+     static generic_ret clnt_res;
+
+     memset(&clnt_res, 0, sizeof(clnt_res));
+     if (clnt_call(clnt, SET_STRING,
+                  (xdrproc_t) xdr_sstring_arg, (caddr_t) argp,
+                  (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+                  TIMEOUT) != RPC_SUCCESS) {
+         return (NULL);
+     }
+     return (&clnt_res);
+}
index 249a3c774c1ee48d05db15a2524f2ff30092376f..4732766ae9f6dde3ab34c68e3e107c230e928884 100644 (file)
@@ -16,6 +16,7 @@ kadm5_free_key_data
 kadm5_free_name_list
 kadm5_free_policy_ent
 kadm5_free_principal_ent
+kadm5_free_strings
 kadm5_get_admin_service_name
 kadm5_get_config_params
 kadm5_get_policies
@@ -23,6 +24,7 @@ kadm5_get_policy
 kadm5_get_principal
 kadm5_get_principals
 kadm5_get_privs
+kadm5_get_strings
 kadm5_init
 kadm5_init_anonymous
 kadm5_init_krb5_context
@@ -36,6 +38,7 @@ kadm5_purgekeys
 kadm5_randkey_principal
 kadm5_randkey_principal_3
 kadm5_rename_principal
+kadm5_set_string
 kadm5_setkey_principal
 kadm5_setkey_principal_3
 kadm5_setv4key_principal
index 1aa98d0fda7497826340166d7a8c85812ebda9ca..d5e9e7f0779cc1859bb5070991452245dc0b270f 100644 (file)
@@ -207,6 +207,28 @@ struct purgekeys_arg {
 };
 typedef struct purgekeys_arg purgekeys_arg;
 
+struct gstrings_arg {
+       krb5_ui_4 api_version;
+       krb5_principal princ;
+};
+typedef struct gstrings_arg gstrings_arg;
+
+struct gstrings_ret {
+       krb5_ui_4 api_version;
+       kadm5_ret_t code;
+       krb5_string_attr *strings;
+       int count;
+};
+typedef struct gstrings_ret gstrings_ret;
+
+struct sstring_arg {
+       krb5_ui_4 api_version;
+       krb5_principal princ;
+       char *key;
+       char *value;
+};
+typedef struct sstring_arg sstring_arg;
+
 #define KADM 2112
 #define KADMVERS 2
 #define CREATE_PRINCIPAL 1
@@ -275,6 +297,12 @@ extern  generic_ret * setkey_principal3_2_svc(setkey3_arg *, struct svc_req *);
 #define PURGEKEYS 22
 extern  generic_ret * purgekeys_2(purgekeys_arg *, CLIENT *);
 extern  generic_ret * purgekeys_2_svc(purgekeys_arg *, struct svc_req *);
+#define GET_STRINGS 23
+extern  gstrings_ret * get_strings_2(gstrings_arg *, CLIENT *);
+extern  gstrings_ret * get_strings_2_svc(gstrings_arg *, struct svc_req *);
+#define SET_STRING 24
+extern  generic_ret * set_string_2(sstring_arg *, CLIENT *);
+extern  generic_ret * set_string_2_svc(sstring_arg *, struct svc_req *);
 
 extern bool_t xdr_cprinc_arg ();
 extern bool_t xdr_cprinc3_arg ();
@@ -312,6 +340,10 @@ extern bool_t xdr_gpols_arg ();
 extern bool_t xdr_gpols_ret ();
 extern bool_t xdr_getprivs_ret ();
 extern bool_t xdr_purgekeys_arg ();
+extern bool_t xdr_gstrings_arg ();
+extern bool_t xdr_gstrings_ret ();
+extern bool_t xdr_sstring_arg ();
+extern bool_t xdr_krb5_string_attr ();
 
 
 #endif /* __KADM_RPC_H__ */
index 0b14ff8f52135eeba2b9524fd75e4e0303c632b0..0b0253a5c55c2bec6c713e4a0ba758c1fe8165d8 100644 (file)
@@ -971,6 +971,62 @@ xdr_purgekeys_arg(XDR *xdrs, purgekeys_arg *objp)
        return (TRUE);
 }
 
+bool_t
+xdr_gstrings_arg(XDR *xdrs, gstrings_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_gstrings_ret(XDR *xdrs, gstrings_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->strings,
+                              (unsigned int *) &objp->count, ~0,
+                              sizeof(krb5_string_attr),
+                              xdr_krb5_string_attr)) {
+                       return (FALSE);
+               }
+       }
+
+       return (TRUE);
+}
+
+bool_t
+xdr_sstring_arg(XDR *xdrs, sstring_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->key)) {
+               return (FALSE);
+       }
+       if (!xdr_nullstring(xdrs, &objp->value)) {
+               return (FALSE);
+       }
+
+       return (TRUE);
+}
+
 bool_t
 xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
 {
@@ -1063,3 +1119,16 @@ xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp)
       return FALSE;
    return TRUE;
 }
+
+bool_t
+xdr_krb5_string_attr(XDR *xdrs, krb5_string_attr *objp)
+{
+       if (!xdr_nullstring(xdrs, &objp->key))
+               return FALSE;
+       if (!xdr_nullstring(xdrs, &objp->value))
+               return FALSE;
+       if (xdrs->x_op == XDR_DECODE &&
+           (objp->key == NULL || objp->value == NULL))
+               return FALSE;
+       return TRUE;
+}
index 4d38c0f991c263709745062af959956f37703fe0..1d70791995e10d53e1257ac8ce923524a09c103e 100644 (file)
@@ -89,3 +89,22 @@ kadm5_free_principal_ent(void *server_handle, kadm5_principal_ent_t val)
     }
     return KADM5_OK;
 }
+
+kadm5_ret_t
+kadm5_free_strings(void *server_handle, krb5_string_attr *strings,
+                   int count)
+{
+    int i;
+
+    _KADM5_CHECK_HANDLE(server_handle);
+
+    if (!strings)
+        return KADM5_OK;
+
+    for (i = 0; i < count; i++) {
+        free(strings[i].key);
+        free(strings[i].value);
+    }
+    free(strings);
+    return KADM5_OK;
+}
index 49a1b880310451feeb9e0fb48e9b7139b2320d89..44311ee26014de860904491fcb29f563085f560a 100644 (file)
@@ -26,6 +26,7 @@ kadm5_free_key_data
 kadm5_free_name_list
 kadm5_free_policy_ent
 kadm5_free_principal_ent
+kadm5_free_strings
 kadm5_get_config_params
 kadm5_get_policies
 kadm5_get_policy
@@ -33,6 +34,7 @@ kadm5_get_principal
 kadm5_get_principal_keys
 kadm5_get_principals
 kadm5_get_privs
+kadm5_get_strings
 kadm5_init
 kadm5_init_anonymous
 kadm5_init_krb5_context
@@ -47,6 +49,7 @@ kadm5_purgekeys
 kadm5_randkey_principal
 kadm5_randkey_principal_3
 kadm5_rename_principal
+kadm5_set_string
 kadm5_setkey_principal
 kadm5_setkey_principal_3
 kadm5_setv4key_principal
@@ -105,6 +108,8 @@ xdr_gprinc_arg
 xdr_gprinc_ret
 xdr_gprincs_arg
 xdr_gprincs_ret
+xdr_gstrings_arg
+xdr_gstrings_ret
 xdr_kadm5_policy_ent_rec
 xdr_kadm5_principal_ent_rec
 xdr_kadm5_ret_t
@@ -120,6 +125,7 @@ xdr_krb5_kvno
 xdr_krb5_octet
 xdr_krb5_principal
 xdr_krb5_salttype
+xdr_krb5_string_attr
 xdr_krb5_timestamp
 xdr_krb5_tl_data
 xdr_krb5_ui_2
@@ -135,5 +141,6 @@ xdr_rprinc_arg
 xdr_setkey3_arg
 xdr_setkey_arg
 xdr_setv4key_arg
+xdr_sstring_arg
 xdr_ui_4
 kadm5_init_iprop
index 464d5e8e45e9b7eec07ab57d0f4c33fb7ade0ca4..a9d0cdb88b7a39e97d464986f71d4fc0ac2a15ce 100644 (file)
@@ -2307,3 +2307,55 @@ done:
     kdb_free_entry(handle, kdb, &adb);
     return ret;
 }
+
+kadm5_ret_t
+kadm5_get_strings(void *server_handle, krb5_principal principal,
+                  krb5_string_attr **strings_out, int *count_out)
+{
+    kadm5_server_handle_t handle = server_handle;
+    kadm5_ret_t ret;
+    krb5_db_entry *kdb = NULL;
+
+    *strings_out = NULL;
+    *count_out = 0;
+    CHECK_HANDLE(server_handle);
+    if (principal == NULL)
+        return EINVAL;
+
+    ret = kdb_get_entry(handle, principal, &kdb, NULL);
+    if (ret)
+        return ret;
+
+    ret = krb5_dbe_get_strings(handle->context, kdb, strings_out, count_out);
+    kdb_free_entry(handle, kdb, NULL);
+    return ret;
+}
+
+kadm5_ret_t
+kadm5_set_string(void *server_handle, krb5_principal principal,
+                 const char *key, const char *value)
+{
+    kadm5_server_handle_t handle = server_handle;
+    kadm5_ret_t ret;
+    krb5_db_entry *kdb;
+    osa_princ_ent_rec adb;
+
+    CHECK_HANDLE(server_handle);
+    if (principal == NULL || key == NULL)
+        return EINVAL;
+
+    ret = kdb_get_entry(handle, principal, &kdb, &adb);
+    if (ret)
+        return ret;
+
+    ret = krb5_dbe_set_string(handle->context, kdb, key, value);
+    if (ret)
+        goto done;
+
+    kdb->mask = KADM5_TL_DATA;
+    ret = kdb_put_entry(handle, kdb, &adb);
+
+done:
+    kdb_free_entry(handle, kdb, &adb);
+    return ret;
+}
index 0d6f0b7950c81f1853929668dbef307675fcc3d5..6578d330987f3ba68b93198bd5a33b52a21aaa4e 100644 (file)
@@ -69,6 +69,7 @@ check-pytests::
        $(RUNPYTEST) $(srcdir)/t_renew.py $(PYTESTFLAGS)
        $(RUNPYTEST) $(srcdir)/t_renprinc.py $(PYTESTFLAGS)
        $(RUNPYTEST) $(srcdir)/t_cccol.py $(PYTESTFLAGS)
+       $(RUNPYTEST) $(srcdir)/t_stringattr.py $(PYTESTFLAGS)
 
 clean::
        $(RM) kdc.conf
diff --git a/src/tests/t_stringattr.py b/src/tests/t_stringattr.py
new file mode 100644 (file)
index 0000000..392ab6c
--- /dev/null
@@ -0,0 +1,56 @@
+# Copyright (C) 2011 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.  Furthermore if you modify this software you must label
+# your software as modified software and not distribute it in such a
+# fashion that it might be confused with the original M.I.T. software.
+# 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.
+
+#!/usr/bin/python
+from k5test import *
+
+def run_kadmin(query):
+    global realm
+    return realm.run_as_master([kadmin, '-c', realm.ccache, '-q', query])
+
+realm = K5Realm(create_host=False, get_creds=False)
+
+realm.kinit(realm.admin_princ, password('admin'), flags=['-S', 'kadmin/admin'])
+
+output = run_kadmin('getstrs user')
+if '(No string attributes.)' not in output:
+    fail('Empty attribute query')
+
+output = run_kadmin('setstr user attr1 value1')
+if 'Attribute set for principal' not in output:
+    fail('Setting attr1')
+output = run_kadmin('setstr user attr2 value2')
+if 'Attribute set for principal' not in output:
+    fail('Setting attr2')
+output = run_kadmin('delstr user attr1')
+if 'Attribute removed from principal' not in output:
+    fail('Deleting attr1')
+output = run_kadmin('setstr user attr3 value3')
+if 'Attribute set for principal' not in output:
+    fail('Setting attr3')
+
+output = run_kadmin('getstrs user')
+if 'attr2: value2' not in output or 'attr3: value3' not in output or \
+        'attr1:' in output:
+    fail('Final attribute query')
+
+success('KDB string attributes.')