Skip to content

Commit

Permalink
Improve profile final flag support
Browse files Browse the repository at this point in the history
When parsing a file, ignore sections appearing after a final-flagged
section of the same name.  Adjust the meaning of group_level in the
parser state so that it is 1 inside of top-level sections instead of
0, and simplify the addition of top-level sections to the tree by
relying on profile_add_node()'s section merging.

Make the final flag work for relations as well as sections.  Check it
while parsing via a new check_final parameter in profile_add_node(),
and during iteration.

Output final flags for relations in dump_profile().  Make the final
flag available to it via a new output parameter in
profile_find_node_relation().

ticket: 9120
  • Loading branch information
greghudson committed Apr 20, 2024
1 parent fc54edd commit f951625
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 53 deletions.
16 changes: 10 additions & 6 deletions doc/admin/conf_files/krb5_conf.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,6 @@ or::
baz = quux
}

Placing a '\*' after the closing bracket of a section name indicates
that the section is *final*, meaning that if the same section appears
within a later file specified in **KRB5_CONFIG**, it will be ignored.
A subsection can be marked as final by placing a '\*' after either the
tag name or the closing brace.

The krb5.conf file can include other files using either of the
following directives at the beginning of a line::

Expand All @@ -58,6 +52,16 @@ section header. Starting in release 1.17, files are read in
alphanumeric order; in previous releases, they may be read in any
order.

Placing a '\*' after the closing bracket of a section name indicates
that the section is *final*, meaning that if the same section appears
again later, it will be ignored. A subsection can be marked as final
by placing a '\*' after either the tag name or the closing brace. A
relation can be marked as final by placing a '\*' after the tag name.
Prior to release 1.22, only sections and subsections can be marked as
final, and the flag only causes values to be ignored if they appear in
later files specified in **KRB5_CONFIG**, not if they appear later
within the same file or an included file.

The krb5.conf file can specify that configuration should be obtained
from a loadable module, rather than the file itself, using the
following directive at the beginning of a line before any section
Expand Down
8 changes: 8 additions & 0 deletions src/util/profile/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ F2=$(srcdir)/final2.ini
F3=$(srcdir)/final3.ini
F4=$(srcdir)/final4.ini
F5=$(srcdir)/final5.ini
F6=$(srcdir)/final6.ini
QUERY=query section subsection key
check-unix-final: test_profile
$(RM) final.out
Expand All @@ -148,6 +149,13 @@ check-unix-final: test_profile
(echo; $(RUN_TEST) ./test_profile $(F3):$(F1) $(QUERY)) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F4):$(F1) $(QUERY)) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F5):$(F1) $(QUERY)) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query a ab) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query a ac) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query b ba) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query b bb bba) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query c ca caa) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query c cb cba) >> final.out
(echo; $(RUN_TEST) ./test_profile $(F6) query c cc) >> final.out
cmp final.out $(srcdir)/final.expected
$(RM) final.out

Expand Down
18 changes: 17 additions & 1 deletion src/util/profile/final.expected
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,26 @@ value1
value1

value2
value1

value3

value4

value5

1
2

1

1
2

1

1

1

1
2
4 changes: 1 addition & 3 deletions src/util/profile/final2.ini
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# In this variant the relation is marked final. There is parsing
# support for this but no iteration or dumping support, so the marker
# currently has no effect.
# In this variant the relation is marked final.
[section]
subsection = {
key* = value2
Expand Down
45 changes: 45 additions & 0 deletions src/util/profile/final6.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# A profile exercising suppression of final-flagged sections,
# subsections, and relations within the same file.

[a]
ab = 1
ab* = 2
ab = 3
ab* = 4
ac* = 1

[a]
ac = 2
ac* = 3
ac = 4

[b]*
ba = 1
ba* = 2
bb = {
bba = 1
}

[b]
ba = 3
bb = {
bba = 2
}

[c]
ca* = {
caa* = 1
}
cb = {
cba = 1
}*
cc = 1

[c]
ca = {
caa = 2
}
cb* = {
cba = 2
}
cc = 2
4 changes: 2 additions & 2 deletions src/util/profile/prof_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ errcode_t profile_verify_node

errcode_t profile_add_node
(struct profile_node *section,
const char *name, const char *value,
const char *name, const char *value, int check_final,
struct profile_node **ret_node);

errcode_t profile_make_node_final
Expand All @@ -168,7 +168,7 @@ errcode_t profile_find_node
errcode_t profile_find_node_relation
(struct profile_node *section,
const char *name, void **state,
char **ret_name, char **value);
char **ret_name, char **value, int *ret_final);

errcode_t profile_find_node_subsection
(struct profile_node *section,
Expand Down
78 changes: 42 additions & 36 deletions src/util/profile/prof_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@
#define STATE_GET_OBRACE 3

struct parse_state {
int state;
int group_level;
int state;
int group_level;
int discard; /* group_level of a final-flagged section */
struct profile_node *root_section;
struct profile_node *current_section;
};
Expand Down Expand Up @@ -78,7 +79,6 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
errcode_t retval;
struct profile_node *node;
int do_subsection = 0;
void *iter = 0;

if (*line == 0)
return 0;
Expand All @@ -90,24 +90,22 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
if (ch == 0)
return 0;
if (ch == '[') {
if (state->group_level > 0)
if (state->group_level > 1)
return PROF_SECTION_NOTOP;
cp++;
p = strchr(cp, ']');
if (p == NULL)
return PROF_SECTION_SYNTAX;
*p = '\0';
retval = profile_find_node_subsection(state->root_section,
cp, &iter, 0,
&state->current_section);
if (retval == PROF_NO_SECTION) {
retval = profile_add_node(state->root_section,
cp, 0,
&state->current_section);
if (retval)
return retval;
} else if (retval)
retval = profile_add_node(state->root_section, cp, NULL, 0,
&state->current_section);
if (retval)
return retval;
state->group_level = 1;
/* If we previously saw this section name with the final flag,
* discard values until the next top-level section. */
state->discard = profile_is_node_final(state->current_section) ?
1 : 0;

/*
* Finish off the rest of the line.
Expand Down Expand Up @@ -135,6 +133,9 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
if (retval)
return retval;
state->group_level--;
/* Check if we are done discarding values from a subsection. */
if (state->group_level < state->discard)
state->discard = 0;
return 0;
}
/*
Expand Down Expand Up @@ -180,21 +181,29 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
p = strchr(tag, '*');
if (p)
*p = '\0';
retval = profile_add_node(state->current_section,
tag, 0, &state->current_section);
if (retval)
return retval;
if (p)
profile_make_node_final(state->current_section);
state->group_level++;
if (!state->discard) {
retval = profile_add_node(state->current_section, tag, NULL, 0,
&state->current_section);
if (retval)
return retval;
/* If we previously saw this subsection with the final flag,
* discard values until the subsection is done. */
if (profile_is_node_final(state->current_section))
state->discard = state->group_level;
if (p)
profile_make_node_final(state->current_section);
}
return 0;
}
p = strchr(tag, '*');
if (p)
*p = '\0';
profile_add_node(state->current_section, tag, value, &node);
if (p)
profile_make_node_final(node);
if (!state->discard) {
profile_add_node(state->current_section, tag, value, 1, &node);
if (p && node)
profile_make_node_final(node);
}
return 0;
}

Expand All @@ -209,7 +218,7 @@ static errcode_t parse_include_file(const char *filename,
/* Create a new state so that fragments are syntactically independent but
* share a root section. */
state.state = STATE_INIT_COMMENT;
state.group_level = 0;
state.group_level = state.discard = 0;
state.root_section = root_section;
state.current_section = NULL;

Expand Down Expand Up @@ -407,7 +416,7 @@ errcode_t profile_parse_file(FILE *f, struct profile_node **root,

/* Initialize parsing state with a new root node. */
state.state = STATE_INIT_COMMENT;
state.group_level = 0;
state.group_level = state.discard = 0;
state.current_section = NULL;
retval = profile_create_node("(root)", 0, &state.root_section);
if (retval)
Expand Down Expand Up @@ -513,7 +522,7 @@ static void output_quoted_string(char *str, void (*cb)(const char *,void *),
static void dump_profile(struct profile_node *root, int level,
void (*cb)(const char *, void *), void *data)
{
int i;
int i, final;
struct profile_node *p;
void *iter;
long retval;
Expand All @@ -522,22 +531,19 @@ static void dump_profile(struct profile_node *root, int level,
iter = 0;
do {
retval = profile_find_node_relation(root, 0, &iter,
&name, &value);
&name, &value, &final);
if (retval)
break;
for (i=0; i < level; i++)
cb("\t", data);
if (need_double_quotes(value)) {
cb(name, data);
cb(" = ", data);
cb(name, data);
cb(final ? "*" : "", data);
cb(" = ", data);
if (need_double_quotes(value))
output_quoted_string(value, cb, data);
cb(EOL, data);
} else {
cb(name, data);
cb(" = ", data);
else
cb(value, data);
cb(EOL, data);
}
cb(EOL, data);
} while (iter != 0);

iter = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/util/profile/prof_set.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ profile_add_relation(profile_t profile, const char **names,
retval = profile_find_node(section, *cpp, 0, 1,
&state, &section);
if (retval == PROF_NO_SECTION)
retval = profile_add_node(section, *cpp, 0, &section);
retval = profile_add_node(section, *cpp, NULL, 0, &section);
if (retval) {
k5_mutex_unlock(&profile->first_file->data->lock);
return retval;
Expand All @@ -289,7 +289,7 @@ profile_add_relation(profile_t profile, const char **names,
}
}

retval = profile_add_node(section, *cpp, new_value, 0);
retval = profile_add_node(section, *cpp, new_value, 0, NULL);
if (retval) {
k5_mutex_unlock(&profile->first_file->data->lock);
return retval;
Expand Down
19 changes: 16 additions & 3 deletions src/util/profile/prof_tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,12 @@ errcode_t profile_verify_node(struct profile_node *node)
}

/*
* Add a node to a particular section
* Add a node to a particular section. If check_final is true, don't add the
* node if we find a final node for the same name.
*/
errcode_t profile_add_node(struct profile_node *section, const char *name,
const char *value, struct profile_node **ret_node)
const char *value, int check_final,
struct profile_node **ret_node)
{
errcode_t retval;
struct profile_node *p, *last, *new;
Expand All @@ -174,6 +176,12 @@ errcode_t profile_add_node(struct profile_node *section, const char *name,
/* Found duplicate subsection, so don't make a new one. */
*ret_node = p;
return 0;
} else if (check_final && cmp == 0 && p->final) {
/* This key already exists with the final flag and we were asked
* to check it, so don't add this node. */
if (ret_node)
*ret_node = NULL;
return 0;
}
}
retval = profile_create_node(name, value, &new);
Expand Down Expand Up @@ -326,7 +334,8 @@ errcode_t profile_find_node(struct profile_node *section, const char *name,
*/
errcode_t profile_find_node_relation(struct profile_node *section,
const char *name, void **state,
char **ret_name, char **value)
char **ret_name, char **value,
int *ret_final)
{
struct profile_node *p;
errcode_t retval;
Expand All @@ -340,6 +349,8 @@ errcode_t profile_find_node_relation(struct profile_node *section,
*value = p->value;
if (ret_name)
*ret_name = p->name;
if (ret_final)
*ret_final = p->final;
}
return 0;
}
Expand Down Expand Up @@ -569,6 +580,8 @@ errcode_t profile_node_iterator(void **iter_p,
}
if (p->deleted)
continue;
if (p->final)
iter->flags |= PROFILE_ITER_FINAL_SEEN;
break;
}
iter->num++;
Expand Down

0 comments on commit f951625

Please sign in to comment.