|
|
1756dc |
From 3935dd9f2ac3aab9027783e45f499401476f52cd Mon Sep 17 00:00:00 2001
|
|
|
1756dc |
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
|
|
|
1756dc |
Date: Mon, 19 Nov 2018 15:04:42 +0100
|
|
|
1756dc |
Subject: [PATCH 09/15] lib: add authselect_profile_features to list supported
|
|
|
1756dc |
features
|
|
|
1756dc |
|
|
|
1756dc |
The feature list is automatically obtained from profile's template files.
|
|
|
1756dc |
|
|
|
1756dc |
Related to:
|
|
|
1756dc |
https://github.com/pbrezina/authselect/issues/107
|
|
|
1756dc |
---
|
|
|
1756dc |
include/authselect.h | 12 +++++
|
|
|
1756dc |
src/lib/authselect_profile.c | 51 ++++++++++++++++++++++
|
|
|
1756dc |
src/lib/util/string_array.c | 36 +++++++++++++++
|
|
|
1756dc |
src/lib/util/string_array.h | 20 +++++++++
|
|
|
1756dc |
src/lib/util/template.c | 85 ++++++++++++++++++++++++++++++++++--
|
|
|
1756dc |
src/lib/util/template.h | 11 +++++
|
|
|
1756dc |
6 files changed, 211 insertions(+), 4 deletions(-)
|
|
|
1756dc |
|
|
|
1756dc |
diff --git a/include/authselect.h b/include/authselect.h
|
|
|
1756dc |
index d52d460e38132cf81e8a03b88a530c634a2c8937..462f54291e8283d5778005ac1747dd03258584be 100644
|
|
|
1756dc |
--- a/include/authselect.h
|
|
|
1756dc |
+++ b/include/authselect.h
|
|
|
1756dc |
@@ -273,6 +273,18 @@ char **
|
|
|
1756dc |
authselect_profile_nsswitch_maps(const struct authselect_profile *profile,
|
|
|
1756dc |
const char **features);
|
|
|
1756dc |
|
|
|
1756dc |
+/**
|
|
|
1756dc |
+ * List features supported by the profile.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * It is necessary to free the returned pointer with @authselect_array_free.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @param profile Pointer to structure obtained by @authselect_profile.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @return NULL-terminated array of supported features, NULL on error.
|
|
|
1756dc |
+ */
|
|
|
1756dc |
+char **
|
|
|
1756dc |
+authselect_profile_features(const struct authselect_profile *profile);
|
|
|
1756dc |
+
|
|
|
1756dc |
/**
|
|
|
1756dc |
* Free authconfig_profile structure obtained by @authselect_profile.
|
|
|
1756dc |
*
|
|
|
1756dc |
diff --git a/src/lib/authselect_profile.c b/src/lib/authselect_profile.c
|
|
|
1756dc |
index 8a12a082802fbc4f3c8cb3af7379ad26372dcc0c..d0cf17b8b7a414a41427c88039687725dcf1a560 100644
|
|
|
1756dc |
--- a/src/lib/authselect_profile.c
|
|
|
1756dc |
+++ b/src/lib/authselect_profile.c
|
|
|
1756dc |
@@ -115,6 +115,57 @@ authselect_profile_nsswitch_maps(const struct authselect_profile *profile,
|
|
|
1756dc |
return maps;
|
|
|
1756dc |
}
|
|
|
1756dc |
|
|
|
1756dc |
+_PUBLIC_ char **
|
|
|
1756dc |
+authselect_profile_features(const struct authselect_profile *profile)
|
|
|
1756dc |
+{
|
|
|
1756dc |
+ char **features;
|
|
|
1756dc |
+ char **array;
|
|
|
1756dc |
+ errno_t ret;
|
|
|
1756dc |
+ int i;
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (profile == NULL) {
|
|
|
1756dc |
+ return NULL;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ features = string_array_create(10);
|
|
|
1756dc |
+ if (features == NULL) {
|
|
|
1756dc |
+ ERROR("Unable to create array (out of memory)");
|
|
|
1756dc |
+ return NULL;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ struct authselect_generated files[] = PROFILE_FILES(profile->files);
|
|
|
1756dc |
+
|
|
|
1756dc |
+ for (i = 0; files[i].path != NULL; i++) {
|
|
|
1756dc |
+ array = template_list_features(files[i].content);
|
|
|
1756dc |
+ if (array == NULL) {
|
|
|
1756dc |
+ ERROR("Unable to obtain feature list (out of memory)");
|
|
|
1756dc |
+ ret = ENOMEM;
|
|
|
1756dc |
+ goto done;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ features = string_array_concat(features, array, true);
|
|
|
1756dc |
+ string_array_free(array);
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (features == NULL) {
|
|
|
1756dc |
+ ERROR("Unable to obtain feature list (out of memory)");
|
|
|
1756dc |
+ ret = ENOMEM;
|
|
|
1756dc |
+ goto done;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ string_array_sort(features);
|
|
|
1756dc |
+
|
|
|
1756dc |
+ ret = EOK;
|
|
|
1756dc |
+
|
|
|
1756dc |
+done:
|
|
|
1756dc |
+ if (ret != EOK) {
|
|
|
1756dc |
+ string_array_free(features);
|
|
|
1756dc |
+ return NULL;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ return features;
|
|
|
1756dc |
+}
|
|
|
1756dc |
+
|
|
|
1756dc |
_PUBLIC_ void
|
|
|
1756dc |
authselect_profile_free(struct authselect_profile *profile)
|
|
|
1756dc |
{
|
|
|
1756dc |
diff --git a/src/lib/util/string_array.c b/src/lib/util/string_array.c
|
|
|
1756dc |
index a074e23ee504792da7f1a9262e15c549de5747d3..43e30d0008b5709f97da9c43f8f2c28ef2475df5 100644
|
|
|
1756dc |
--- a/src/lib/util/string_array.c
|
|
|
1756dc |
+++ b/src/lib/util/string_array.c
|
|
|
1756dc |
@@ -159,3 +159,39 @@ string_array_del_value(char **array, const char *value)
|
|
|
1756dc |
|
|
|
1756dc |
return array;
|
|
|
1756dc |
}
|
|
|
1756dc |
+
|
|
|
1756dc |
+char **
|
|
|
1756dc |
+string_array_concat(char **to, char **items, bool unique)
|
|
|
1756dc |
+{
|
|
|
1756dc |
+ int i;
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (items == NULL) {
|
|
|
1756dc |
+ return to;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ for (i = 0; items[i] != NULL; i++) {
|
|
|
1756dc |
+ to = string_array_add_value(to, items[i], unique);
|
|
|
1756dc |
+ if (to == NULL) {
|
|
|
1756dc |
+ return NULL;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ return to;
|
|
|
1756dc |
+}
|
|
|
1756dc |
+
|
|
|
1756dc |
+static int
|
|
|
1756dc |
+string_array_sort_callback(const void *a, const void *b)
|
|
|
1756dc |
+{
|
|
|
1756dc |
+ return strcmp(*(char* const*)a, *(char* const*)b);
|
|
|
1756dc |
+}
|
|
|
1756dc |
+
|
|
|
1756dc |
+void
|
|
|
1756dc |
+string_array_sort(char **array)
|
|
|
1756dc |
+{
|
|
|
1756dc |
+ if (array == NULL) {
|
|
|
1756dc |
+ return;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ qsort(array, string_array_count(array), sizeof(char *),
|
|
|
1756dc |
+ string_array_sort_callback);
|
|
|
1756dc |
+}
|
|
|
1756dc |
diff --git a/src/lib/util/string_array.h b/src/lib/util/string_array.h
|
|
|
1756dc |
index 9545685b2553228a109ab51e7c6a0fd16698fa3e..06aa46c008058163e5557d51e18258fa4e9a1523 100644
|
|
|
1756dc |
--- a/src/lib/util/string_array.h
|
|
|
1756dc |
+++ b/src/lib/util/string_array.h
|
|
|
1756dc |
@@ -118,4 +118,24 @@ string_array_add_value(char **array, const char *value, bool unique);
|
|
|
1756dc |
char **
|
|
|
1756dc |
string_array_del_value(char **array, const char *value);
|
|
|
1756dc |
|
|
|
1756dc |
+/**
|
|
|
1756dc |
+ * Concatenate two array. Array @items values will be appended to arra @to.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @param to NULL-terminated destination array.
|
|
|
1756dc |
+ * @param items NULL-terminated array to be appended into @to.
|
|
|
1756dc |
+ * @param unique If true, value will not be added if it is already present.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @return Array or NULL if reallocation fails.
|
|
|
1756dc |
+ */
|
|
|
1756dc |
+char **
|
|
|
1756dc |
+string_array_concat(char **to, char **items, bool unique);
|
|
|
1756dc |
+
|
|
|
1756dc |
+/**
|
|
|
1756dc |
+ * Alphabetically sort a NULL-terminated string array.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @param array NULL-terminated string array.
|
|
|
1756dc |
+ */
|
|
|
1756dc |
+void
|
|
|
1756dc |
+string_array_sort(char **array);
|
|
|
1756dc |
+
|
|
|
1756dc |
#endif /* _STRING_ARRAY_H_ */
|
|
|
1756dc |
diff --git a/src/lib/util/template.c b/src/lib/util/template.c
|
|
|
1756dc |
index e38d1d7f1db2c90f1281e97f3ebbdd9d9d1a935d..fb373c0fd83e04c6c78d5f57d3d8e50e54c0377b 100644
|
|
|
1756dc |
--- a/src/lib/util/template.c
|
|
|
1756dc |
+++ b/src/lib/util/template.c
|
|
|
1756dc |
@@ -325,10 +325,27 @@ template_process_matches(const char *match_string,
|
|
|
1756dc |
return ret;
|
|
|
1756dc |
}
|
|
|
1756dc |
|
|
|
1756dc |
- *_op = op;
|
|
|
1756dc |
- *_feature = feature;
|
|
|
1756dc |
- *_if_true = if_true;
|
|
|
1756dc |
- *_if_false = if_false;
|
|
|
1756dc |
+ if (_op != NULL) {
|
|
|
1756dc |
+ *_op = op;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (_feature != NULL) {
|
|
|
1756dc |
+ *_feature = feature;
|
|
|
1756dc |
+ } else {
|
|
|
1756dc |
+ free(feature);
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (_if_true != NULL) {
|
|
|
1756dc |
+ *_if_true = if_true;
|
|
|
1756dc |
+ } else {
|
|
|
1756dc |
+ free(if_true);
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (_if_false != NULL) {
|
|
|
1756dc |
+ *_if_false = if_false;
|
|
|
1756dc |
+ } else {
|
|
|
1756dc |
+ free(if_false);
|
|
|
1756dc |
+ }
|
|
|
1756dc |
|
|
|
1756dc |
return EOK;
|
|
|
1756dc |
}
|
|
|
1756dc |
@@ -478,6 +495,66 @@ template_generate_preamble()
|
|
|
1756dc |
return preamble;
|
|
|
1756dc |
}
|
|
|
1756dc |
|
|
|
1756dc |
+char **
|
|
|
1756dc |
+template_list_features(const char *template)
|
|
|
1756dc |
+{
|
|
|
1756dc |
+ regmatch_t m[RE_MATCHES];
|
|
|
1756dc |
+ const char *match_string;
|
|
|
1756dc |
+ char **features;
|
|
|
1756dc |
+ char *feature;
|
|
|
1756dc |
+ regex_t regex;
|
|
|
1756dc |
+ errno_t ret;
|
|
|
1756dc |
+ int reret;
|
|
|
1756dc |
+
|
|
|
1756dc |
+ features = string_array_create(10);
|
|
|
1756dc |
+ if (features == NULL) {
|
|
|
1756dc |
+ return NULL;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (template == NULL) {
|
|
|
1756dc |
+ return features;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ reret = regcomp(®ex, OP_RE, REG_EXTENDED | REG_NEWLINE);
|
|
|
1756dc |
+ if (reret != REG_NOERROR) {
|
|
|
1756dc |
+ ERROR("Unable to compile regular expression: regex error %d", reret);
|
|
|
1756dc |
+ ret = EFAULT;
|
|
|
1756dc |
+ goto done;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ match_string = template;
|
|
|
1756dc |
+ while ((reret = regexec(®ex, match_string, RE_MATCHES, m, 0)) == REG_NOERROR) {
|
|
|
1756dc |
+ ret = template_process_matches(match_string, m, NULL, &feature,
|
|
|
1756dc |
+ NULL, NULL);
|
|
|
1756dc |
+ if (ret != EOK) {
|
|
|
1756dc |
+ ERROR("Unable to process match [%d]: %s", ret, strerror(ret));
|
|
|
1756dc |
+ goto done;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ features = string_array_add_value(features, feature, true);
|
|
|
1756dc |
+ free(feature);
|
|
|
1756dc |
+
|
|
|
1756dc |
+ match_string += m[0].rm_eo;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ if (reret != REG_NOMATCH) {
|
|
|
1756dc |
+ ERROR("Unable to search string: regex error %d", reret);
|
|
|
1756dc |
+ ret = EFAULT;
|
|
|
1756dc |
+ goto done;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ ret = EOK;
|
|
|
1756dc |
+
|
|
|
1756dc |
+done:
|
|
|
1756dc |
+ if (ret != EOK) {
|
|
|
1756dc |
+ string_array_free(features);
|
|
|
1756dc |
+ return NULL;
|
|
|
1756dc |
+ }
|
|
|
1756dc |
+
|
|
|
1756dc |
+ regfree(®ex);
|
|
|
1756dc |
+ return features;
|
|
|
1756dc |
+}
|
|
|
1756dc |
+
|
|
|
1756dc |
errno_t
|
|
|
1756dc |
template_write(const char *filepath,
|
|
|
1756dc |
const char *content,
|
|
|
1756dc |
diff --git a/src/lib/util/template.h b/src/lib/util/template.h
|
|
|
1756dc |
index 57e076c257a8cdcbc9c2c8f4f5266b4c21f27941..1c412dcf15a7f0d5a5897b78b8b52ff67b7c3f95 100644
|
|
|
1756dc |
--- a/src/lib/util/template.h
|
|
|
1756dc |
+++ b/src/lib/util/template.h
|
|
|
1756dc |
@@ -37,6 +37,17 @@ char *
|
|
|
1756dc |
template_generate(const char *template,
|
|
|
1756dc |
const char **features);
|
|
|
1756dc |
|
|
|
1756dc |
+/**
|
|
|
1756dc |
+ * Find all features available withint the @template and return them in
|
|
|
1756dc |
+ * NULL-terminated array.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @param template Template.
|
|
|
1756dc |
+ *
|
|
|
1756dc |
+ * @return List of features in NULL-terminated array or NULL on error.
|
|
|
1756dc |
+ */
|
|
|
1756dc |
+char **
|
|
|
1756dc |
+template_list_features(const char *template);
|
|
|
1756dc |
+
|
|
|
1756dc |
/**
|
|
|
1756dc |
* Write generated file preamble together with its content to a file.
|
|
|
1756dc |
* If the file does not exist, it is created, otherwise its content
|
|
|
1756dc |
--
|
|
|
1756dc |
2.17.2
|
|
|
1756dc |
|