]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Unify KDB principal flag conversion functions 292/head
authorTom Yu <tlyu@mit.edu>
Thu, 2 Jul 2015 20:16:07 +0000 (16:16 -0400)
committerTom Yu <tlyu@mit.edu>
Thu, 9 Jul 2015 12:38:56 +0000 (08:38 -0400)
These changes unify the KDB principal flag specifiers used by kadmin,
kdc.conf default_principal_flags, and kadm5.acl.  Each of those
interfaces will now accept any of the historically accepted input
forms of any of those interfaces.  Additionally, accept flag
specifiers in the forms that kadmin prints, as well as hexadecimal
numbers.

Replace krb5_string_to_flags() with krb5_flagspec_to_mask().  The
latter has a pseudo-ternary output, allowing different pointers for
flags to set versus flags to clear.  Additional functionality includes
parsing hexadecimal numbers for flag settings.

Remove krb5_input_flag_to_string(), which nothing in the tree used,
and probably hasn't ever worked properly due to long-standing gaps in
the flag number sequence.

Remove krb5_flags_to_string(), which nothing in the tree used.
Verbose flag output can be added back through another interface if
there is demand.

Add krb5_flagnum_to_string(), which produces a string representation
of a flag number.  Additional functionality includes output of
hexadecimal numbers for unknown flags.

Add krb5_flags_to_strings(), which produces an array of strings
describing the flags, using the output from krb5_flagnum_to_string().

ticket: 8215

src/include/adm_proto.h
src/kadmin/cli/kadmin.c
src/lib/kadm5/admin_internal.h
src/lib/kadm5/alt_prof.c
src/lib/kadm5/clnt/Makefile.in
src/lib/kadm5/clnt/libkadm5clnt_mit.exports
src/lib/kadm5/srv/Makefile.in
src/lib/kadm5/srv/libkadm5srv_mit.exports
src/lib/kadm5/srv/server_acl.c
src/lib/kadm5/str_conv.c
src/plugins/kdb/test/kdb_test.c

index 3758f5ffe625070afcb2d0d947bf04aa0196b71f..e99a84d6f86be90c28b84b70e54741154bb3df0a 100644 (file)
@@ -72,10 +72,10 @@ krb5_error_code krb5_aprof_get_int32(krb5_pointer, const char **,
 krb5_error_code krb5_aprof_finish(krb5_pointer);
 
 /* str_conv.c */
-krb5_error_code krb5_string_to_flags(char *, const char *, const char *,
-                                     krb5_flags *);
-krb5_error_code krb5_flags_to_string(krb5_flags, const char *, char *, size_t);
-krb5_error_code krb5_input_flag_to_string (int, char *, size_t);
+krb5_error_code krb5_flagspec_to_mask(const char *,
+                                      krb5_flags *, krb5_flags *);
+krb5_error_code krb5_flagnum_to_string(int, char **);
+krb5_error_code krb5_flags_to_strings(krb5_int32, char ***);
 
 /* keysalt.c */
 krb5_boolean krb5_keysalt_is_present(krb5_key_salt_tuple *, krb5_int32,
index defc0fe9f4aaeede2fe53b932546715e2734a48d..c9cc0b050380fb4299a066ae56fecaea644196b0 100644 (file)
 #include <time.h>
 #include "kadmin.h"
 
-/* special struct to convert flag names for principals
-   to actual krb5_flags for a principal */
-struct pflag {
-    char *flagname;             /* name of flag as typed to CLI */
-    size_t flaglen;             /* length of string (not counting -,+) */
-    krb5_flags theflag;         /* actual principal flag to set/clear */
-    int set;                    /* 0 means clear, 1 means set (on '-') */
-};
-
-static struct pflag flags[] = {
-    {"allow_postdated",     15,     KRB5_KDB_DISALLOW_POSTDATED,    1 },
-    {"allow_forwardable",   17,     KRB5_KDB_DISALLOW_FORWARDABLE,  1 },
-    {"allow_tgs_req",       13,     KRB5_KDB_DISALLOW_TGT_BASED,    1 },
-    {"allow_renewable",     15,     KRB5_KDB_DISALLOW_RENEWABLE,    1 },
-    {"allow_proxiable",     15,     KRB5_KDB_DISALLOW_PROXIABLE,    1 },
-    {"allow_dup_skey",      14,     KRB5_KDB_DISALLOW_DUP_SKEY,     1 },
-    {"allow_tix",            9,     KRB5_KDB_DISALLOW_ALL_TIX,      1 },
-    {"requires_preauth",    16,     KRB5_KDB_REQUIRES_PRE_AUTH,     0 },
-    {"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 },
-    {"support_desmd5",      14,     KRB5_KDB_SUPPORT_DESMD5,        0 },
-    {"ok_as_delegate",      14,     KRB5_KDB_OK_AS_DELEGATE,        0 },
-    {"ok_to_auth_as_delegate", 22,  KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, 0 },
-    {"no_auth_data_required", 21,   KRB5_KDB_NO_AUTH_DATA_REQUIRED, 0 },
-};
-
-static char *prflags[] = {
-    "DISALLOW_POSTDATED",       /* 0x00000001 */
-    "DISALLOW_FORWARDABLE",     /* 0x00000002 */
-    "DISALLOW_TGT_BASED",       /* 0x00000004 */
-    "DISALLOW_RENEWABLE",       /* 0x00000008 */
-    "DISALLOW_PROXIABLE",       /* 0x00000010 */
-    "DISALLOW_DUP_SKEY",        /* 0x00000020 */
-    "DISALLOW_ALL_TIX",         /* 0x00000040 */
-    "REQUIRES_PRE_AUTH",        /* 0x00000080 */
-    "REQUIRES_HW_AUTH",         /* 0x00000100 */
-    "REQUIRES_PWCHANGE",        /* 0x00000200 */
-    "UNKNOWN_0x00000400",       /* 0x00000400 */
-    "UNKNOWN_0x00000800",       /* 0x00000800 */
-    "DISALLOW_SVR",             /* 0x00001000 */
-    "PWCHANGE_SERVICE",         /* 0x00002000 */
-    "SUPPORT_DESMD5",           /* 0x00004000 */
-    "NEW_PRINC",                /* 0x00008000 */
-    "UNKNOWN_0x00010000",       /* 0x00010000 */
-    "UNKNOWN_0x00020000",       /* 0x00020000 */
-    "UNKNOWN_0x00040000",       /* 0x00040000 */
-    "UNKNOWN_0x00080000",       /* 0x00080000 */
-    "OK_AS_DELEGATE",           /* 0x00100000 */
-    "OK_TO_AUTH_AS_DELEGATE",   /* 0x00200000 */
-    "NO_AUTH_DATA_REQUIRED",    /* 0x00400000 */
-};
-
 static krb5_boolean script_mode = FALSE;
 int exit_status = 0;
 char *def_realm = NULL;
@@ -1005,8 +951,7 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
                         krb5_boolean *nokey, krb5_key_salt_tuple **ks_tuple,
                         int *n_ks_tuple, char *caller)
 {
-    int i, attrib_set;
-    size_t j;
+    int i;
     time_t date;
     time_t now;
     krb5_error_code retval;
@@ -1019,7 +964,6 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
     *randkey = FALSE;
     *nokey = FALSE;
     for (i = 1; i < argc - 1; i++) {
-        attrib_set = 0;
         if (!strcmp("-x",argv[i])) {
             if (++i > argc - 2)
                 return -1;
@@ -1127,29 +1071,12 @@ kadmin_parse_princ_args(int argc, char *argv[], kadm5_principal_ent_t oprinc,
             }
             continue;
         }
-        for (j = 0; j < sizeof(flags) / sizeof(struct pflag); j++) {
-            if (strlen(argv[i]) == flags[j].flaglen + 1 &&
-                !strcmp(flags[j].flagname,
-                        &argv[i][1] /* strip off leading + or - */)) {
-                if ((flags[j].set && argv[i][0] == '-') ||
-                    (!flags[j].set && argv[i][0] == '+')) {
-                    oprinc->attributes |= flags[j].theflag;
-                    *mask |= KADM5_ATTRIBUTES;
-                    attrib_set++;
-                    break;
-                } else if ((flags[j].set && argv[i][0] == '+') ||
-                           (!flags[j].set && argv[i][0] == '-')) {
-                    oprinc->attributes &= ~flags[j].theflag;
-                    *mask |= KADM5_ATTRIBUTES;
-                    attrib_set++;
-                    break;
-                } else {
-                    return -1;
-                }
-            }
-        }
-        if (!attrib_set)
-            return -1;          /* nothing was parsed */
+        retval = krb5_flagspec_to_mask(argv[i], &oprinc->attributes,
+                                       &oprinc->attributes);
+        if (retval)
+            return -1;
+        else
+            *mask |= KADM5_ATTRIBUTES;
     }
     if (i != argc - 1)
         return -1;
@@ -1423,8 +1350,8 @@ kadmin_getprinc(int argc, char *argv[])
     krb5_error_code retval;
     const char *polname, *noexist;
     char *canon = NULL, *princstr = NULL, *modprincstr = NULL;
+    char **sp = NULL, **attrstrs = NULL;
     int i;
-    size_t j;
 
     if (!(argc == 2 || (argc == 3 && !strcmp("-terse", argv[1])))) {
         error(_("usage: get_principal [-terse] principal\n"));
@@ -1504,10 +1431,16 @@ kadmin_getprinc(int argc, char *argv[])
         printf(_("MKey: vno %d\n"), dprinc.mkvno);
 
         printf(_("Attributes:"));
-        for (j = 0; j < sizeof(prflags) / sizeof(char *); j++) {
-            if (dprinc.attributes & (krb5_flags) 1 << j)
-                printf(" %s", prflags[j]);
+        retval = krb5_flags_to_strings(dprinc.attributes, &attrstrs);
+        if (retval) {
+            com_err("get_principal", retval, _("while printing flags"));
+            return;
+        }
+        for (sp = attrstrs; sp != NULL && *sp != NULL; sp++) {
+            printf(" %s", *sp);
+            free(*sp);
         }
+        free(attrstrs);
         printf("\n");
         polname = (dprinc.policy != NULL) ? dprinc.policy : _("[none]");
         noexist = (dprinc.policy != NULL && !policy_exists(dprinc.policy)) ?
index ec604b2b3ca93fca1abe499e95963489b68c4d54..faf8e9c3623a340f81db17409944017a91c86e41 100644 (file)
@@ -74,8 +74,4 @@ krb5_string_to_keysalts(const 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__ */
index db45d13c1a37be1b9c8b056168931c9dea6eb0f1..a1570931092725959c572adc0f224d9831405c46 100644 (file)
@@ -689,7 +689,7 @@ krb5_error_code kadm5_get_config_params(krb5_context context,
                     ep++;
             }
             /* Convert this flag. */
-            if (krb5_string_to_flags(sp, "+", "-", &params.flags))
+            if (krb5_flagspec_to_mask(sp, &params.flags, &params.flags))
                 break;
             sp = ep;
         }
index 28d66aeac6aac9ff6b87c399017ff98e10402427..93012410dc0cdc280f7ef95607645f30c92b1c64 100644 (file)
@@ -3,7 +3,7 @@ BUILDTOP=$(REL)..$(S)..$(S)..
 LOCALINCLUDES = -I$(BUILDTOP)/include/kadm5
 
 LIBBASE=kadm5clnt_mit
-LIBMAJOR=9
+LIBMAJOR=10
 LIBMINOR=0
 STOBJLISTS=../OBJS.ST OBJS.ST
 SHLIB_EXPDEPS=\
index f6f93b96a20a4c0fcda1a746132a080dffa4b34c..b7d0ec52c072a9d4019fc51ccac48710c0fda51e 100644 (file)
@@ -50,16 +50,16 @@ krb5_aprof_get_int32
 krb5_aprof_get_string
 krb5_aprof_getvals
 krb5_aprof_init
-krb5_flags_to_string
+krb5_flagnum_to_string
+krb5_flagspec_to_mask
+krb5_flags_to_strings
 krb5_free_key_data_contents
-krb5_input_flag_to_string
 krb5_keysalt_is_present
 krb5_keysalt_iterate
 krb5_klog_close
 krb5_klog_init
 krb5_klog_reopen
 krb5_klog_syslog
-krb5_string_to_flags
 krb5_string_to_keysalts
 xdr_chpass3_arg
 xdr_chpass_arg
index 26c52374868bd5243001eaf3b0b5292ec1d5cb33..3fd4b9e522f74d1a4d5cd12d72547c02abbecf5b 100644 (file)
@@ -9,7 +9,7 @@ DEFINES = @HESIOD_DEFS@
 ##DOSLIBNAME = libkadm5srv.lib
 
 LIBBASE=kadm5srv_mit
-LIBMAJOR=9
+LIBMAJOR=10
 LIBMINOR=0
 STOBJLISTS=../OBJS.ST OBJS.ST
 
index 8602e76587d897c2739242d8032299cd3bd19f38..86af3715f74ffe321e722c64500a04218787cc7a 100644 (file)
@@ -65,16 +65,16 @@ krb5_aprof_get_string_all
 krb5_aprof_getvals
 krb5_aprof_init
 krb5_copy_key_data_contents
-krb5_flags_to_string
+krb5_flagnum_to_string
+krb5_flagspec_to_mask
+krb5_flags_to_strings
 krb5_free_key_data_contents
-krb5_input_flag_to_string
 krb5_keysalt_is_present
 krb5_keysalt_iterate
 krb5_klog_close
 krb5_klog_init
 krb5_klog_reopen
 krb5_klog_syslog
-krb5_string_to_flags
 krb5_string_to_keysalts
 master_db
 master_princ
index 64f738540893aa70224c730908fdab9a3ffded1f..b6c2bb292afa483125bad13fcb98838968964830 100644 (file)
@@ -265,7 +265,7 @@ kadm5int_acl_parse_line(lp)
  * kadm5int_acl_parse_restrictions() - Parse optional restrictions field
  *
  * Allowed restrictions are:
- *      [+-]flagname            (recognized by krb5_string_to_flags)
+ *      [+-]flagname            (recognized by krb5_flagspec_to_mask)
  *                              flag is forced to indicated value
  *      -clearpolicy            policy is forced clear
  *      -policy pol             policy is forced to be "pol"
@@ -283,7 +283,6 @@ kadm5int_acl_parse_restrictions(s, rpp)
     char                *sp = NULL, *tp, *ap, *save;
     static const char   *delims = "\t\n\f\v\r ,";
     krb5_deltat         dt;
-    krb5_flags          flag;
     krb5_error_code     code;
 
     DPRINT(DEBUG_CALLS, acl_debug_level,
@@ -297,18 +296,11 @@ kadm5int_acl_parse_restrictions(s, rpp)
             code = ENOMEM;
         } else {
             memset(*rpp, 0, sizeof(**rpp));
+            (*rpp)->forbid_attrs = ~(krb5_flags)0;
             for (tp = strtok_r(sp, delims, &save); tp;
                  tp = strtok_r(NULL, delims, &save)) {
-                flag = 0;
-                if (!krb5_string_to_flags(tp, "+", "-", &flag)) {
-                    /* OK, but was it in the positive or negative sense? */
-                    if (flag) {
-                        (*rpp)->require_attrs |= flag;
-                    } else {
-                        flag = ~0;
-                        (void) krb5_string_to_flags(tp, "+", "-", &flag);
-                        (*rpp)->forbid_attrs |= ~flag;
-                    }
+                if (!krb5_flagspec_to_mask(tp, &(*rpp)->require_attrs,
+                                           &(*rpp)->forbid_attrs)) {
                     (*rpp)->mask |= KADM5_ATTRIBUTES;
                 } else if (!strcmp(tp, "-clearpolicy")) {
                     (*rpp)->mask |= KADM5_POLICY_CLR;
@@ -396,7 +388,7 @@ kadm5int_acl_impose_restrictions(kcontext, recp, maskp, rp)
 
     if (rp->mask & KADM5_ATTRIBUTES) {
         recp->attributes |= rp->require_attrs;
-        recp->attributes &= ~(rp->forbid_attrs);
+        recp->attributes &= rp->forbid_attrs;
         *maskp |= KADM5_ATTRIBUTES;
     }
     if (rp->mask & KADM5_POLICY_CLR) {
index 30c395101f5134188264e7dae16914510ec9793e..fd9a1d178afbae98ca4b7794389d635216e0915c 100644 (file)
 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /* lib/kadm5/str_conv.c */
 /*
- * Copyright 1995 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
+ * Copyright (C) 1995-2015 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.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
  *
- * 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.
- */
-
-/* Convert between strings and Kerberos internal data. */
-
-/*
- * Table of contents:
+ * * Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
  *
- * String decoding:
- * ----------------
- * krb5_string_to_flags()       - Convert string to krb5_flags.
+ * * Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in
+ *   the documentation and/or other materials provided with the
+ *   distribution.
  *
- * String encoding:
- * ----------------
- * krb5_flags_to_string()       - Convert krb5_flags to string.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+/* Convert between strings and Kerberos internal data. */
+
 #include "k5-int.h"
 #include "admin_internal.h"
 #include "adm_proto.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
- */
+#include <ctype.h>
 
 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_ok_as_delegate_in[]     = "ok-as-delegate";
-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_ok_to_auth_as_delegate_in[] = "ok-to-auth-as-delegate";
-static const char flags_no_auth_data_required_in[] = "no-auth-data-required";
-static const char flags_pdate_out[]     = N_("Not Postdateable");
-static const char flags_fwd_out[]       = N_("Not Forwardable");
-static const char flags_tgtbased_out[]  = N_("No TGT-based requests");
-static const char flags_renew_out[]     = N_("Not renewable");
-static const char flags_proxy_out[]     = N_("Not proxiable");
-static const char flags_dup_skey_out[]  = N_("No DUP_SKEY requests");
-static const char flags_tickets_out[]   = N_("All Tickets Disallowed");
-static const char flags_preauth_out[]   = N_("Preauthentication required");
-static const char flags_hwauth_out[]    = N_("HW authentication required");
-static const char flags_ok_as_delegate_out[]    = N_("OK as Delegate");
-static const char flags_pwchange_out[]  = N_("Password Change required");
-static const char flags_service_out[]   = N_("Service Disabled");
-static const char flags_pwsvc_out[]     = N_("Password Changing Service");
-static const char flags_md5_out[]       = N_("RSA-MD5 supported");
-static const char flags_ok_to_auth_as_delegate_out[] = N_("Protocol transition with delegation allowed");
-static const char flags_no_auth_data_required_out[] = N_("No authorization data required");
-static const char flags_default_neg[]   = "-";
-static const char flags_default_sep[]   = " ";
-
-/*
- * Lookup tables.
- */
+struct flag_table_row {
+    const char *spec;           /* Input specifier string */
+    krb5_flags flag;            /* Flag */
+    int invert;                 /* Whether to invert the sense */
+};
 
-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_OK_AS_DELEGATE,      1,      flags_ok_as_delegate_in, flags_ok_as_delegate_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     },
-    { KRB5_KDB_OK_TO_AUTH_AS_DELEGATE,  1,  flags_ok_to_auth_as_delegate_in, flags_ok_to_auth_as_delegate_out },
-    { KRB5_KDB_NO_AUTH_DATA_REQUIRED,   1,  flags_no_auth_data_required_in, flags_no_auth_data_required_out }
+static const struct flag_table_row ftbl[] = {
+    {"allow_postdated",         KRB5_KDB_DISALLOW_POSTDATED,    1},
+    {"postdateable",            KRB5_KDB_DISALLOW_POSTDATED,    1},
+    {"disallow_postdated",      KRB5_KDB_DISALLOW_POSTDATED,    0},
+    {"allow_forwardable",       KRB5_KDB_DISALLOW_FORWARDABLE,  1},
+    {"forwardable",             KRB5_KDB_DISALLOW_FORWARDABLE,  1},
+    {"disallow_forwardable",    KRB5_KDB_DISALLOW_FORWARDABLE,  0},
+    {"allow_tgs_req",           KRB5_KDB_DISALLOW_TGT_BASED,    1},
+    {"tgt_based",               KRB5_KDB_DISALLOW_TGT_BASED,    1},
+    {"disallow_tgt_based",      KRB5_KDB_DISALLOW_TGT_BASED,    0},
+    {"allow_renewable",         KRB5_KDB_DISALLOW_RENEWABLE,    1},
+    {"renewable",               KRB5_KDB_DISALLOW_RENEWABLE,    1},
+    {"disallow_renewable",      KRB5_KDB_DISALLOW_RENEWABLE,    0},
+    {"allow_proxiable",         KRB5_KDB_DISALLOW_PROXIABLE,    1},
+    {"proxiable",               KRB5_KDB_DISALLOW_PROXIABLE,    1},
+    {"disallow_proxiable",      KRB5_KDB_DISALLOW_PROXIABLE,    0},
+    {"allow_dup_skey",          KRB5_KDB_DISALLOW_DUP_SKEY,     1},
+    {"dup_skey",                KRB5_KDB_DISALLOW_DUP_SKEY,     1},
+    {"disallow_dup_skey",       KRB5_KDB_DISALLOW_DUP_SKEY,     0},
+    {"allow_tickets",           KRB5_KDB_DISALLOW_ALL_TIX,      1},
+    {"allow_tix",               KRB5_KDB_DISALLOW_ALL_TIX,      1},
+    {"disallow_all_tix",        KRB5_KDB_DISALLOW_ALL_TIX,      0},
+    {"preauth",                 KRB5_KDB_REQUIRES_PRE_AUTH,     0},
+    {"requires_pre_auth",       KRB5_KDB_REQUIRES_PRE_AUTH,     0},
+    {"requires_preauth",        KRB5_KDB_REQUIRES_PRE_AUTH,     0},
+    {"hwauth",                  KRB5_KDB_REQUIRES_HW_AUTH,      0},
+    {"requires_hw_auth",        KRB5_KDB_REQUIRES_HW_AUTH,      0},
+    {"requires_hwauth",         KRB5_KDB_REQUIRES_HW_AUTH,      0},
+    {"needchange",              KRB5_KDB_REQUIRES_PWCHANGE,     0},
+    {"pwchange",                KRB5_KDB_REQUIRES_PWCHANGE,     0},
+    {"requires_pwchange",       KRB5_KDB_REQUIRES_PWCHANGE,     0},
+    {"allow_svr",               KRB5_KDB_DISALLOW_SVR,          1},
+    {"service",                 KRB5_KDB_DISALLOW_SVR,          1},
+    {"disallow_svr",            KRB5_KDB_DISALLOW_SVR,          0},
+    {"password_changing_service", KRB5_KDB_PWCHANGE_SERVICE,    0},
+    {"pwchange_service",        KRB5_KDB_PWCHANGE_SERVICE,      0},
+    {"pwservice",               KRB5_KDB_PWCHANGE_SERVICE,      0},
+    {"md5",                     KRB5_KDB_SUPPORT_DESMD5,        0},
+    {"support_desmd5",          KRB5_KDB_SUPPORT_DESMD5,        0},
+    {"new_princ",               KRB5_KDB_NEW_PRINC,             0},
+    {"ok_as_delegate",          KRB5_KDB_OK_AS_DELEGATE,        0},
+    {"ok_to_auth_as_delegate",  KRB5_KDB_OK_TO_AUTH_AS_DELEGATE, 0},
+    {"no_auth_data_required",   KRB5_KDB_NO_AUTH_DATA_REQUIRED, 0},
 };
-static const int flags_table_nents = sizeof(flags_table)/
-    sizeof(flags_table[0]);
+#define NFTBL (sizeof(ftbl) / sizeof(ftbl[0]))
 
+static const char *outflags[] = {
+    "DISALLOW_POSTDATED",       /* 0x00000001 */
+    "DISALLOW_FORWARDABLE",     /* 0x00000002 */
+    "DISALLOW_TGT_BASED",       /* 0x00000004 */
+    "DISALLOW_RENEWABLE",       /* 0x00000008 */
+    "DISALLOW_PROXIABLE",       /* 0x00000010 */
+    "DISALLOW_DUP_SKEY",        /* 0x00000020 */
+    "DISALLOW_ALL_TIX",         /* 0x00000040 */
+    "REQUIRES_PRE_AUTH",        /* 0x00000080 */
+    "REQUIRES_HW_AUTH",         /* 0x00000100 */
+    "REQUIRES_PWCHANGE",        /* 0x00000200 */
+    NULL,                       /* 0x00000400 */
+    NULL,                       /* 0x00000800 */
+    "DISALLOW_SVR",             /* 0x00001000 */
+    "PWCHANGE_SERVICE",         /* 0x00002000 */
+    "SUPPORT_DESMD5",           /* 0x00004000 */
+    "NEW_PRINC",                /* 0x00008000 */
+    NULL,                       /* 0x00010000 */
+    NULL,                       /* 0x00020000 */
+    NULL,                       /* 0x00040000 */
+    NULL,                       /* 0x00080000 */
+    "OK_AS_DELEGATE",           /* 0x00100000 */
+    "OK_TO_AUTH_AS_DELEGATE",   /* 0x00200000 */
+    "NO_AUTH_DATA_REQUIRED",    /* 0x00400000 */
+};
+#define NOUTFLAGS (sizeof(outflags) / sizeof(outflags[0]))
 
-krb5_error_code
-krb5_string_to_flags(string, positive, negative, flagsp)
-    char        * string;
-    const char  * positive;
-    const char  * negative;
-    krb5_flags  * flagsp;
+/*
+ * Given s, which is a normalized flagspec with the prefix stripped off, and
+ * req_neg indicating whether the flagspec is negated, update the toset and
+ * toclear masks.
+ */
+static krb5_error_code
+raw_flagspec_to_mask(const char *s, int req_neg, krb5_flags *toset,
+                     krb5_flags *toclear)
 {
-    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;
+    int found = 0, invert = 0;
+    size_t i;
+    krb5_flags flag;
+    unsigned long ul;
 
-    cpos = 0;
-    sense = 1;
-    /* First check for positive or negative sense */
-    if (!strncasecmp(neg, string, nsize)) {
-        sense = 0;
-        cpos += (int) nsize;
+    for (i = 0; !found && i < NFTBL; i++) {
+        if (strcmp(s, ftbl[i].spec) != 0)
+            continue;
+        /* Found a match */
+        found = 1;
+        invert = ftbl[i].invert;
+        flag = ftbl[i].flag;
     }
-    else if (psize && !strncasecmp(positive, string, psize)) {
-        cpos += (int) psize;
+    /* Accept hexadecimal numbers. */
+    if (!found && strncmp(s, "0x", 2) == 0) {
+        /* Assume that krb5_flags are 32 bits long. */
+        ul = strtoul(s, NULL, 16) & 0xffffffff;
+        flag = (krb5_flags)ul;
+        found = 1;
     }
+    if (!found)
+        return EINVAL;
+    if (req_neg)
+        invert = !invert;
+    if (invert)
+        *toclear &= ~flag;
+    else
+        *toset |= flag;
+    return 0;
+}
+
+/*
+ * Update the toset and toclear flag masks according to flag specifier string
+ * spec, which is of the form {+|-}flagname.  toset and toclear can point to
+ * the same flag word.
+ */
+krb5_error_code
+krb5_flagspec_to_mask(const char *spec, krb5_flags *toset, krb5_flags *toclear)
+{
+    int req_neg = 0;
+    char *copy, *cp, *s;
+    krb5_error_code retval;
 
-    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;
+    s = copy = strdup(spec);
+    if (s == NULL)
+        return ENOMEM;
 
-            break;
-        }
+    if (*s == '-') {
+        req_neg = 1;
+        s++;
+    } else if (*s == '+')
+        s++;
+
+    for (cp = s; *cp != '\0'; cp++) {
+        /* Transform hyphens to underscores.*/
+        if (*cp == '-')
+            *cp = '_';
+        /* Downcase. */
+        if (isupper((unsigned char)*cp))
+            *cp = tolower((unsigned char)*cp);
     }
-    return((found) ? 0 : EINVAL);
+    retval = raw_flagspec_to_mask(s, req_neg, toset, toclear);
+    free(copy);
+    return retval;
 }
 
+/*
+ * Copy the flag name of flagnum to outstr.
+ */
 krb5_error_code
-krb5_flags_to_string(flags, sep, buffer, buflen)
-    krb5_flags  flags;
-    const char  * sep;
-    char        * buffer;
-    size_t      buflen;
+krb5_flagnum_to_string(int flagnum, char **outstr)
 {
-    int                 i;
-    krb5_flags          pflags;
-    const char          *sepstring;
-    struct k5buf        buf;
+    const char *s = NULL;
 
-    pflags = 0;
-    sepstring = (sep) ? sep : flags_default_sep;
-    k5_buf_init_fixed(&buf, buffer, buflen);
-    /* Blast through the table matching all we can */
-    for (i=0; i<flags_table_nents; i++) {
-        if (flags & flags_table[i].fl_flags) {
-            if (buf.len > 0)
-                k5_buf_add(&buf, sepstring);
-            k5_buf_add(&buf, _(flags_table[i].fl_output));
-            /* Keep track of what we matched */
-            pflags |= flags_table[i].fl_flags;
-        }
+    *outstr = NULL;
+    if ((unsigned int)flagnum < NOUTFLAGS) {
+        s = outflags[flagnum];
     }
-    if (k5_buf_status(&buf) != 0)
-        return(ENOMEM);
-
-    /* See if there's any leftovers */
-    if (flags & ~pflags)
-        return(EINVAL);
-
-    return(0);
+    if (s == NULL)
+        /* Assume that krb5_flags are 32 bits long. */
+        asprintf(outstr, "0x%08lx", 1UL<<flagnum);
+    else
+        *outstr = strdup(s);
+    if (*outstr == NULL)
+        return ENOMEM;
+    return 0;
 }
 
+/*
+ * Create a null-terminated array of string representations of flags.  Store a
+ * null pointer into outarray if there would be no strings.
+ */
 krb5_error_code
-krb5_input_flag_to_string(flag, buffer, buflen)
-    int         flag;
-    char        * buffer;
-    size_t      buflen;
+krb5_flags_to_strings(krb5_int32 flags, char ***outarray)
 {
-    if(flag < 0 || flag >= flags_table_nents) return ENOENT; /* End of list */
-    if(strlcpy(buffer, flags_table[flag].fl_specifier, buflen) >= buflen)
-        return ENOMEM;
-    return  0;
+    char **a = NULL, **a_new = NULL, **ap;
+    size_t amax = 0, i;
+    krb5_error_code retval;
+
+    *outarray = NULL;
+
+    /* Assume that krb5_flags are 32 bits long. */
+    for (i = 0; i < 32; i++) {
+        if (!(flags & (1UL << i)))
+            continue;
+
+        a_new = realloc(a, (amax + 2) * sizeof(*a));
+        if (a_new == NULL) {
+            retval = ENOMEM;
+            goto cleanup;
+        }
+        a = a_new;
+        retval = krb5_flagnum_to_string(i, &a[amax++]);
+        if (retval)
+            goto cleanup;
+        a[amax] = NULL;
+    }
+    *outarray = a;
+    return 0;
+cleanup:
+    for (ap = a; ap != NULL && *ap != NULL; ap++) {
+        free(ap);
+    }
+    free(a);
+    return retval;
 }
 
 /*
index acb1d76a0885976911ecc9cd6425dfbb01a1e1f0..5c61c23b100cd9063f2700eaad6f928b3b0edba1 100644 (file)
@@ -324,8 +324,10 @@ test_get_principal(krb5_context context, krb5_const_principal search_for,
     check(krb5_parse_name(context, ename, &ent->princ));
 
     flagstr = get_string(h, "princs", ename, "flags");
-    if (flagstr != NULL)
-        check(krb5_string_to_flags(flagstr, "+", "-", &ent->attributes));
+    if (flagstr != NULL) {
+        check(krb5_flagspec_to_mask(flagstr, &ent->attributes,
+                                    &ent->attributes));
+    }
     free(flagstr);
 
     ent->max_life = get_duration(h, "princs", ename, "maxlife");